langflower 0.0.8 → 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.
Files changed (221) hide show
  1. package/package.json +2 -2
  2. package/ui-dist/{chunk-Y6VMBLSJ.js → chunk-7UMVYN3A.js} +1 -1
  3. package/ui-dist/{chunk-6DQ2XSRW.js → chunk-MDGXX73Z.js} +3 -3
  4. package/ui-dist/index.html +2 -2
  5. package/ui-dist/main-Z7CPFXFA.js +313 -0
  6. package/ui-dist/styles-2TMDAUD7.css +1 -0
  7. package/vendor/common-nodes/dist/ai/chat-completion-stream.d.ts +2 -0
  8. package/vendor/common-nodes/dist/ai/critique/node.d.ts +246 -0
  9. package/vendor/common-nodes/dist/ai/critique/node.js +2 -2
  10. package/vendor/common-nodes/dist/ai/fake-llm/node.d.ts +246 -0
  11. package/vendor/common-nodes/dist/ai/features/chat-completion-stream.d.ts +53 -0
  12. package/vendor/common-nodes/dist/ai/features/chat-completion-stream.js +1 -0
  13. package/vendor/common-nodes/dist/ai/features/llm-loop/autokick-recovery.d.ts +13 -0
  14. package/vendor/common-nodes/dist/ai/features/llm-loop/autokick-recovery.js +17 -0
  15. package/vendor/common-nodes/dist/ai/features/llm-loop/classify-llm-failure.d.ts +2 -0
  16. package/vendor/common-nodes/dist/ai/features/llm-loop/classify-llm-failure.js +113 -0
  17. package/vendor/common-nodes/dist/ai/features/llm-loop/dead-loop-detector.d.ts +28 -0
  18. package/vendor/common-nodes/dist/ai/features/llm-loop/dead-loop-detector.js +194 -0
  19. package/vendor/common-nodes/dist/ai/features/llm-loop/live-get-tools.d.ts +9 -0
  20. package/vendor/common-nodes/dist/ai/features/llm-loop/live-get-tools.js +21 -0
  21. package/vendor/common-nodes/dist/ai/features/llm-loop/llm-loop-reducer.d.ts +2 -0
  22. package/vendor/common-nodes/dist/ai/features/llm-loop/llm-loop-reducer.js +204 -0
  23. package/vendor/common-nodes/dist/ai/features/llm-loop/llm-loop-types.d.ts +120 -0
  24. package/vendor/common-nodes/dist/ai/features/llm-loop/llm-loop-types.js +39 -0
  25. package/vendor/common-nodes/dist/ai/features/llm-loop/normalize-llm-recovery-policy.d.ts +2 -0
  26. package/vendor/common-nodes/dist/ai/features/llm-loop/normalize-llm-recovery-policy.js +59 -0
  27. package/vendor/common-nodes/dist/ai/features/llm-loop/operators/normalize-tool-result.d.ts +1 -0
  28. package/vendor/common-nodes/dist/ai/features/llm-loop/operators/normalize-tool-result.js +7 -0
  29. package/vendor/common-nodes/dist/ai/features/llm-loop/operators/observe-provider-stream.d.ts +43 -0
  30. package/vendor/common-nodes/dist/ai/features/llm-loop/operators/observe-provider-stream.js +96 -0
  31. package/vendor/common-nodes/dist/ai/features/llm-loop/run-agent-loop.d.ts +29 -0
  32. package/vendor/common-nodes/dist/ai/features/llm-loop/run-agent-loop.js +44 -0
  33. package/vendor/common-nodes/dist/ai/features/llm-loop/run-llm-loop.d.ts +74 -0
  34. package/vendor/common-nodes/dist/ai/features/llm-loop/run-llm-loop.js +658 -0
  35. package/vendor/common-nodes/dist/ai/features/llm-role-preset.d.ts +69 -0
  36. package/vendor/common-nodes/dist/ai/features/llm-role-preset.js +265 -0
  37. package/vendor/common-nodes/dist/ai/features/llm-session/llm-session-shell.d.ts +141 -0
  38. package/vendor/common-nodes/dist/ai/features/llm-session/llm-session-shell.js +193 -0
  39. package/vendor/common-nodes/dist/ai/features/llm-session/run-session-machine.d.ts +21 -0
  40. package/vendor/common-nodes/dist/ai/features/llm-session/run-session-machine.js +118 -0
  41. package/vendor/common-nodes/dist/ai/features/openai/context-length-error.d.ts +14 -0
  42. package/vendor/common-nodes/dist/ai/features/openai/context-length-error.js +63 -0
  43. package/vendor/common-nodes/dist/ai/features/openai/create-chat-completion-stream.d.ts +19 -0
  44. package/vendor/common-nodes/dist/ai/features/openai/create-chat-completion-stream.js +182 -0
  45. package/vendor/common-nodes/dist/ai/features/openai/list-provider-models.d.ts +28 -0
  46. package/vendor/common-nodes/dist/ai/features/openai/list-provider-models.js +52 -0
  47. package/vendor/common-nodes/dist/ai/features/openai/llm-context-compaction.d.ts +31 -0
  48. package/vendor/common-nodes/dist/ai/features/openai/llm-context-compaction.js +326 -0
  49. package/vendor/common-nodes/dist/ai/features/openai/normalize-compaction-params.d.ts +14 -0
  50. package/vendor/common-nodes/dist/ai/features/openai/normalize-compaction-params.js +21 -0
  51. package/vendor/common-nodes/dist/ai/features/openai/prepare-chat-completion.d.ts +30 -0
  52. package/vendor/common-nodes/dist/ai/features/openai/prepare-chat-completion.js +132 -0
  53. package/vendor/common-nodes/dist/ai/features/path-choice/control-tools.d.ts +20 -0
  54. package/vendor/common-nodes/dist/ai/features/path-choice/control-tools.js +70 -0
  55. package/vendor/common-nodes/dist/ai/features/path-choice/run-reactive-path-choice-loop.d.ts +32 -0
  56. package/vendor/common-nodes/dist/ai/features/path-choice/run-reactive-path-choice-loop.js +93 -0
  57. package/vendor/common-nodes/dist/ai/features/prompt/build-effective-system-prompt.d.ts +9 -0
  58. package/vendor/common-nodes/dist/ai/features/prompt/build-effective-system-prompt.js +21 -0
  59. package/vendor/common-nodes/dist/ai/features/prompt/normalize-max-iterations.d.ts +13 -0
  60. package/vendor/common-nodes/dist/ai/features/prompt/normalize-max-iterations.js +23 -0
  61. package/vendor/common-nodes/dist/ai/features/prompt/resolve-chat-provider-model.d.ts +10 -0
  62. package/vendor/common-nodes/dist/ai/features/prompt/resolve-chat-provider-model.js +8 -0
  63. package/vendor/common-nodes/dist/ai/features/run-host-services.d.ts +54 -0
  64. package/vendor/common-nodes/dist/ai/features/run-host-services.js +29 -0
  65. package/vendor/common-nodes/dist/ai/features/scripted-chat-completion-stream.d.ts +17 -0
  66. package/vendor/common-nodes/dist/ai/features/scripted-chat-completion-stream.js +61 -0
  67. package/vendor/common-nodes/dist/ai/features/sub-agent-protocol.d.ts +40 -0
  68. package/vendor/common-nodes/dist/ai/features/sub-agent-protocol.js +44 -0
  69. package/vendor/common-nodes/dist/ai/features/ui-schema/llm-compaction-ui-schema.d.ts +14 -0
  70. package/vendor/common-nodes/dist/ai/features/ui-schema/llm-compaction-ui-schema.js +18 -0
  71. package/vendor/common-nodes/dist/ai/features/ui-schema/llm-panel-ui-schema.d.ts +80 -0
  72. package/vendor/common-nodes/dist/ai/features/ui-schema/llm-panel-ui-schema.js +76 -0
  73. package/vendor/common-nodes/dist/ai/features/ui-schema/llm-recovery-ui-schema.d.ts +113 -0
  74. package/vendor/common-nodes/dist/ai/features/ui-schema/llm-recovery-ui-schema.js +131 -0
  75. package/vendor/common-nodes/dist/ai/features/wait-for-subagent-result.d.ts +7 -0
  76. package/vendor/common-nodes/dist/ai/features/wait-for-subagent-result.js +31 -0
  77. package/vendor/common-nodes/dist/ai/llm-loop/autokick-recovery.d.ts +13 -0
  78. package/vendor/common-nodes/dist/ai/llm-loop/autokick-recovery.js +17 -0
  79. package/vendor/common-nodes/dist/ai/llm-loop/dead-loop-detector.d.ts +28 -0
  80. package/vendor/common-nodes/dist/ai/llm-loop/dead-loop-detector.js +194 -0
  81. package/vendor/common-nodes/dist/ai/llm-loop/llm-loop-reducer.js +36 -0
  82. package/vendor/common-nodes/dist/ai/llm-loop/llm-loop-types.d.ts +35 -0
  83. package/vendor/common-nodes/dist/ai/llm-loop/llm-loop-types.js +19 -0
  84. package/vendor/common-nodes/dist/ai/llm-loop/normalize-llm-recovery-policy.js +52 -9
  85. package/vendor/common-nodes/dist/ai/llm-loop/operators/observe-provider-stream.d.ts +8 -2
  86. package/vendor/common-nodes/dist/ai/llm-loop/operators/observe-provider-stream.js +43 -13
  87. package/vendor/common-nodes/dist/ai/llm-loop/run-llm-loop.d.ts +3 -5
  88. package/vendor/common-nodes/dist/ai/llm-loop/run-llm-loop.js +116 -1
  89. package/vendor/common-nodes/dist/ai/llm-recovery-ui-schema.d.ts +82 -0
  90. package/vendor/common-nodes/dist/ai/llm-recovery-ui-schema.js +95 -0
  91. package/vendor/common-nodes/dist/ai/llm-session-shell.d.ts +4 -9
  92. package/vendor/common-nodes/dist/ai/llm-session-shell.js +2 -4
  93. package/vendor/common-nodes/dist/ai/nodes/critique/node.d.ts +588 -0
  94. package/vendor/common-nodes/dist/ai/nodes/critique/node.js +227 -0
  95. package/vendor/common-nodes/dist/ai/nodes/fake-llm/node.d.ts +571 -0
  96. package/vendor/common-nodes/dist/ai/nodes/fake-llm/node.js +201 -0
  97. package/vendor/common-nodes/dist/ai/nodes/openai-llm/node.d.ts +587 -0
  98. package/vendor/common-nodes/dist/ai/nodes/openai-llm/node.js +84 -0
  99. package/vendor/common-nodes/dist/ai/nodes/review/node.d.ts +593 -0
  100. package/vendor/common-nodes/dist/ai/nodes/review/node.js +227 -0
  101. package/vendor/common-nodes/dist/ai/nodes/sub-agent/node.d.ts +630 -0
  102. package/vendor/common-nodes/dist/ai/nodes/sub-agent/node.js +417 -0
  103. package/vendor/common-nodes/dist/ai/openai/create-chat-completion-stream.js +6 -0
  104. package/vendor/common-nodes/dist/ai/openai/prepare-chat-completion.d.ts +2 -0
  105. package/vendor/common-nodes/dist/ai/openai/prepare-chat-completion.js +18 -0
  106. package/vendor/common-nodes/dist/ai/openai-llm/node.d.ts +246 -0
  107. package/vendor/common-nodes/dist/ai/review/node.d.ts +246 -0
  108. package/vendor/common-nodes/dist/ai/review/node.js +2 -2
  109. package/vendor/common-nodes/dist/ai/sub-agent/node.d.ts +246 -0
  110. package/vendor/common-nodes/dist/ai/sub-agent/node.js +2 -2
  111. package/vendor/common-nodes/dist/catalog.js +9 -5
  112. package/vendor/common-nodes/dist/compile-custom-nodes/node.d.ts +21 -0
  113. package/vendor/common-nodes/dist/compile-custom-nodes/node.js +45 -0
  114. package/vendor/common-nodes/dist/crawl/crawl/node.js +1 -1
  115. package/vendor/common-nodes/dist/crawl/fetch-url/node.js +1 -1
  116. package/vendor/common-nodes/dist/flow/repeat/node.js +6 -1
  117. package/vendor/common-nodes/dist/langflower-tools/emit-registration-tools.d.ts +18 -0
  118. package/vendor/common-nodes/dist/langflower-tools/emit-registration-tools.js +29 -0
  119. package/vendor/common-nodes/dist/langflower-tools/node.d.ts +20 -0
  120. package/vendor/common-nodes/dist/langflower-tools/node.js +77 -0
  121. package/vendor/common-nodes/dist/mcp/mcp-http/node.d.ts +4 -4
  122. package/vendor/common-nodes/dist/mcp/mcp-http/node.js +9 -10
  123. package/vendor/common-nodes/dist/mcp/mcp-stdio/node.d.ts +4 -4
  124. package/vendor/common-nodes/dist/mcp/mcp-stdio/node.js +9 -10
  125. package/vendor/common-nodes/dist/text/append-file/node.js +1 -1
  126. package/vendor/common-nodes/dist/text/read-file/node.js +1 -1
  127. package/vendor/common-nodes/dist/text/write-file/node.js +1 -1
  128. package/vendor/common-nodes/dist/tools/collect-agent-tool-handles.d.ts +4 -4
  129. package/vendor/common-nodes/dist/tools/collect-agent-tool-handles.js +3 -11
  130. package/vendor/common-nodes/dist/tools/inventory-tool-round.d.ts +1 -11
  131. package/vendor/common-nodes/dist/tools/inventory-tool-round.js +0 -84
  132. package/vendor/common-nodes/dist/tools/tool-collection/node.d.ts +20 -0
  133. package/vendor/common-nodes/dist/tools/tool-collection/node.js +42 -0
  134. package/vendor/common-nodes/package.json +9 -13
  135. package/vendor/compiler/dist/compile-project-nodes.d.ts +2 -1
  136. package/vendor/compiler/dist/compile-project-nodes.js +35 -6
  137. package/vendor/compiler/dist/resolve-host-types.d.ts +0 -5
  138. package/vendor/compiler/dist/resolve-host-types.js +0 -8
  139. package/vendor/compiler/package.json +1 -1
  140. package/vendor/node-sdk/dist/node-factory/define-llm-node/default-llm-ports.d.ts +3 -7
  141. package/vendor/node-sdk/dist/node-factory/define-llm-node/default-llm-ports.js +4 -44
  142. package/vendor/node-sdk/dist/node-factory/define-llm-node/define-llm-node.d.ts +4 -6
  143. package/vendor/node-sdk/dist/node-factory/define-llm-node/define-llm-node.js +4 -6
  144. package/vendor/node-sdk/dist/node-factory/define-llm-node/llm-inventory-wire.d.ts +1 -0
  145. package/vendor/node-sdk/dist/node-factory/define-llm-node/llm-inventory-wire.js +1 -0
  146. package/vendor/node-sdk/dist/node-factory/define-llm-node/recovery-notice.d.ts +8 -0
  147. package/vendor/node-sdk/dist/node-factory/define-llm-node/recovery-notice.js +14 -0
  148. package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-handle.d.ts +3 -4
  149. package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-handle.js +1 -1
  150. package/vendor/node-sdk/dist/node-factory/define-reactive-node/types.d.ts +2 -4
  151. package/vendor/node-sdk/dist/node-factory/define-reactive-node/ui-schema-inference.d.ts +1 -1
  152. package/vendor/node-sdk/package.json +1 -1
  153. package/vendor/runtime/dist/port-feed-override.d.ts +13 -0
  154. package/vendor/runtime/dist/port-feed-override.js +21 -0
  155. package/vendor/runtime/dist/port-signal-from-response.d.ts +15 -0
  156. package/vendor/runtime/dist/port-signal-from-response.js +48 -0
  157. package/vendor/runtime/dist/runtime-editor.d.ts +5 -1
  158. package/vendor/runtime/dist/runtime-editor.js +19 -0
  159. package/vendor/runtime/dist/runtime-runner.d.ts +8 -3
  160. package/vendor/runtime/dist/runtime-runner.js +108 -87
  161. package/vendor/runtime/dist/runtime.d.ts +3 -1
  162. package/vendor/runtime/dist/runtime.js +1 -0
  163. package/vendor/runtime/dist/testing/workflows/workflow-events.d.ts +10 -6
  164. package/vendor/runtime/dist/testing/workflows/workflow-events.js +21 -31
  165. package/vendor/runtime/dist/types.d.ts +52 -40
  166. package/vendor/runtime/dist/types.js +5 -1
  167. package/vendor/runtime/package.json +1 -1
  168. package/vendor/server/dist/bridge/attach-langflower-bridge.js +3 -2
  169. package/vendor/server/dist/bridge/bridge-event-log.js +17 -102
  170. package/vendor/server/dist/bridge/build-execution-context.d.ts +5 -2
  171. package/vendor/server/dist/bridge/build-execution-context.js +48 -8
  172. package/vendor/server/dist/bridge/forward-runner-event.d.ts +1 -1
  173. package/vendor/server/dist/bridge/forward-runner-event.js +7 -12
  174. package/vendor/server/dist/bridge/get-live-wired-tools.d.ts +13 -0
  175. package/vendor/server/dist/bridge/get-live-wired-tools.js +83 -0
  176. package/vendor/server/dist/bridge/langflower-tools-rpc.d.ts +7 -0
  177. package/vendor/server/dist/bridge/langflower-tools-rpc.js +29 -0
  178. package/vendor/server/dist/bridge/wire-custom-palette-handlers.d.ts +2 -1
  179. package/vendor/server/dist/bridge/wire-custom-palette-handlers.js +3 -5
  180. package/vendor/server/dist/bridge/wire-runner-handlers.js +17 -10
  181. package/vendor/server/dist/bridge/wire-workflow-handlers.js +23 -9
  182. package/vendor/server/dist/checkpoint/run-checkpoint-session.d.ts +1 -1
  183. package/vendor/server/dist/checkpoint/run-checkpoint-session.js +10 -9
  184. package/vendor/server/dist/palette/compile-and-hot-swap-custom-nodes.d.ts +10 -0
  185. package/vendor/server/dist/palette/compile-and-hot-swap-custom-nodes.js +23 -0
  186. package/vendor/server/dist/session/reset-session-execution-feed.d.ts +6 -0
  187. package/vendor/server/dist/session/reset-session-execution-feed.js +8 -0
  188. package/vendor/server/dist/workflow/apply-editor-mutation.d.ts +5 -0
  189. package/vendor/server/dist/workflow/apply-editor-mutation.js +32 -0
  190. package/vendor/server/skeleton/instructions.md +9 -5
  191. package/vendor/server/skeleton/nodes/my-nodes/README.md +4 -3
  192. package/vendor/server/skeleton/nodes/my-nodes/package.json +1 -1
  193. package/vendor/server/skeleton/skills/langflower-helper/SKILL.md +82 -38
  194. package/vendor/server/skeleton/skills/langflower-helper/architecture.md +29 -10
  195. package/vendor/server/skeleton/skills/langflower-helper/layout.md +16 -15
  196. package/vendor/server/skeleton/skills/langflower-node-writer/SKILL.md +19 -9
  197. package/vendor/server/skeleton/skills/langflower-workflow-writer/SKILL.md +23 -15
  198. package/vendor/server/skeleton/workflows/kb-create.json +15 -43
  199. package/vendor/server/skeleton/workflows/kb-navigate.json +8 -22
  200. package/vendor/server/skeleton/workflows/simple-coder.json +18 -46
  201. package/vendor/server/skeleton/workflows/starter.json +35 -22
  202. package/vendor/shared/dist/execution/derive-run-settle-outcome.d.ts +1 -1
  203. package/vendor/shared/dist/execution/derive-run-settle-outcome.js +4 -3
  204. package/vendor/shared/dist/execution/derive-run-settle-outcome.test.js +18 -15
  205. package/vendor/shared/dist/langflower-bus-config.d.ts +6 -14
  206. package/vendor/shared/dist/langflower-bus-config.js +4 -12
  207. package/vendor/shared/dist/langflower-config/resolve-wired-tool-options.js +6 -0
  208. package/vendor/shared/dist/langflower-config/resolve-wired-tool-options.test.js +30 -0
  209. package/vendor/shared/dist/langflower-ws-waits.d.ts +9 -14
  210. package/vendor/shared/dist/langflower-ws-waits.js +14 -14
  211. package/vendor/websocket-bridge/dist/bridge-codec.d.ts +1 -0
  212. package/vendor/websocket-bridge/dist/bridge-codec.js +11 -11
  213. package/vendor/websocket-bridge/dist/bridge-frame.js +1 -1
  214. package/vendor/websocket-bridge/dist/bridge-subjects.d.ts +1 -1
  215. package/vendor/websocket-bridge/dist/bridge-subjects.js +2 -2
  216. package/vendor/websocket-bridge/dist/bridge-types.d.ts +13 -1
  217. package/vendor/websocket-bridge/dist/create-client.js +3 -3
  218. package/vendor/websocket-bridge/dist/create-server.js +12 -6
  219. package/vendor/websocket-bridge/package.json +8 -0
  220. package/ui-dist/main-ECEWAM6V.js +0 -311
  221. package/ui-dist/styles-EOXODOI7.css +0 -1
@@ -4,6 +4,7 @@ export { bypassOutputPortId, parseBypassOutputPortId } from './bypass-ports.js';
4
4
  export { RuntimeEditor } from './runtime-editor.js';
5
5
  export { graphHasCycle } from './runtime-helpers.js';
6
6
  export { RuntimeRunner } from './runtime-runner.js';
7
+ export { isPortErrorTelemetry, isPortPendingTelemetry, isPortTelemetry, isPortValueTelemetry, isRuntimeDone, } from './types.js';
7
8
  export class RuntimeFacade {
8
9
  editor;
9
10
  runner;
@@ -1,20 +1,24 @@
1
+ import { type EdgeId, type PortTelemetry, type RunId, type RuntimeEdge, type RuntimeRunnerEvent } from '../../types.js';
1
2
  import { RuntimeEditor } from '../../runtime-editor.js';
2
3
  import { RuntimeRunner } from '../../runtime-runner.js';
3
4
  import { type RuntimeOptions } from '../../runtime.js';
4
- import type { RunId, RuntimeEdge, RuntimeRunnerEvent } from '../../types.js';
5
5
  export type RuntimeHarness = {
6
6
  readonly editor: RuntimeEditor;
7
7
  readonly runner: RuntimeRunner;
8
8
  };
9
9
  export declare function createRuntimeHarness(options?: RuntimeOptions): RuntimeHarness;
10
10
  export declare function wireEdge(editor: RuntimeEditor, edge: Omit<RuntimeEdge, 'edgeId'>): void;
11
- export type OutputEmittedEvent = Extract<RuntimeRunnerEvent, {
12
- kind: 'output-emitted';
13
- }>;
14
- export declare function outputValues(events: readonly RuntimeRunnerEvent[], nodeId: string, portId: string, runId?: string): unknown[];
15
- export declare function waitForOutput(runtime: RuntimeRunner | RuntimeHarness, nodeId: string, portId: string, runId?: string): Promise<OutputEmittedEvent>;
11
+ export type OutputEmittedEvent = PortTelemetry & {
12
+ readonly 0: 'out';
13
+ };
14
+ export declare function outputValues(events: readonly RuntimeRunnerEvent[], nodeId: string, portId: string, _runId?: string): unknown[];
15
+ export declare function waitForOutput(runtime: RuntimeRunner | RuntimeHarness, nodeId: string, portId: string, _runId?: string): Promise<OutputEmittedEvent>;
16
16
  export declare function runAndCollectEvents(runtime: RuntimeRunner | RuntimeHarness, startRun: () => string, settleMs?: number): Promise<{
17
17
  readonly runId: string;
18
18
  readonly events: readonly RuntimeRunnerEvent[];
19
19
  }>;
20
20
  export declare function noDoneWithin(runtime: RuntimeRunner | RuntimeHarness, ms: number, runId?: RunId): Promise<boolean>;
21
+ export declare const edgeIdsFromPortEvent: (event: PortTelemetry) => readonly EdgeId[];
22
+ export declare const portDirLabel: (event: PortTelemetry) => "input-received" | "output-emitted";
23
+ export declare const dtoHas: (dtos: readonly unknown[], key: "pending" | "value" | "error" | "inactive") => boolean;
24
+ export declare const dtoIndex: (dtos: readonly unknown[], key: "pending" | "value" | "error" | "inactive") => number;
@@ -1,4 +1,5 @@
1
1
  import { filter, firstValueFrom } from 'rxjs';
2
+ import { isPortValueTelemetry, isRuntimeDone, } from '../../types.js';
2
3
  import { RuntimeEditor } from '../../runtime-editor.js';
3
4
  import { RuntimeRunner } from '../../runtime-runner.js';
4
5
  export function createRuntimeHarness(options) {
@@ -17,27 +18,23 @@ export function wireEdge(editor, edge) {
17
18
  throw new Error(`Failed to wire ${edge.fromNodeId}.${edge.fromPort[0]} → ${edge.toNodeId}.${edge.toPort[0]}`);
18
19
  }
19
20
  }
20
- function isOutputEmitted(event) {
21
- return event.kind === 'output-emitted' && event.state === 'value';
22
- }
23
- export function outputValues(events, nodeId, portId, runId) {
21
+ const isOutputValue = (event) => isPortValueTelemetry(event) && event[0] === 'out';
22
+ export function outputValues(events, nodeId, portId, _runId) {
24
23
  return events
25
- .filter((event) => isOutputEmitted(event) &&
26
- event.nodeId === nodeId &&
27
- event.portId === portId &&
28
- (runId === undefined || event.runId === runId))
29
- .map((event) => event.value);
24
+ .filter((event) => isOutputValue(event) &&
25
+ event[1] === nodeId &&
26
+ event[2] === portId)
27
+ .map((event) => event[3].value);
30
28
  }
31
- export async function waitForOutput(runtime, nodeId, portId, runId) {
32
- return waitForOutputMatching(runtime, nodeId, portId, () => true, runId);
29
+ export async function waitForOutput(runtime, nodeId, portId, _runId) {
30
+ return waitForOutputMatching(runtime, nodeId, portId, () => true, _runId);
33
31
  }
34
- async function waitForOutputMatching(runtime, nodeId, portId, predicate, runId) {
32
+ async function waitForOutputMatching(runtime, nodeId, portId, predicate, _runId) {
35
33
  const runner = resolveRunner(runtime);
36
- return firstValueFrom(runner.events$.pipe(filter((event) => isOutputEmitted(event) &&
37
- event.nodeId === nodeId &&
38
- event.portId === portId &&
39
- (runId === undefined || event.runId === runId) &&
40
- predicate(event.value))));
34
+ return firstValueFrom(runner.events$.pipe(filter((event) => isOutputValue(event) &&
35
+ event[1] === nodeId &&
36
+ event[2] === portId &&
37
+ predicate(event[3].value))));
41
38
  }
42
39
  export async function runAndCollectEvents(runtime, startRun, settleMs = 50) {
43
40
  const events = [];
@@ -52,26 +49,19 @@ export async function runAndCollectEvents(runtime, startRun, settleMs = 50) {
52
49
  subscription.unsubscribe();
53
50
  return { runId, events };
54
51
  }
55
- async function collectEventsForMs(runtime, ms) {
56
- const events = [];
57
- const runner = resolveRunner(runtime);
58
- const subscription = runner.events$.subscribe((event) => {
59
- events.push(event);
60
- });
61
- await new Promise((resolve) => {
62
- setTimeout(resolve, ms);
63
- });
64
- subscription.unsubscribe();
65
- return events;
66
- }
67
52
  export async function noDoneWithin(runtime, ms, runId) {
68
53
  const runner = resolveRunner(runtime);
69
54
  const result = await Promise.race([
70
- firstValueFrom(runner.events$.pipe(filter((event) => event.kind === 'done' &&
71
- (runId === undefined || event.runId === runId)))).then(() => 'done'),
55
+ firstValueFrom(runner.events$.pipe(filter((event) => isRuntimeDone(event) &&
56
+ event.length === 2 &&
57
+ (runId === undefined || event[1] === runId)))).then(() => 'done'),
72
58
  new Promise((resolve) => {
73
59
  setTimeout(() => resolve('timeout'), ms);
74
60
  }),
75
61
  ]);
76
62
  return result === 'timeout';
77
63
  }
64
+ export const edgeIdsFromPortEvent = (event) => event[5];
65
+ export const portDirLabel = (event) => event[0] === 'out' ? 'output-emitted' : 'input-received';
66
+ export const dtoHas = (dtos, key) => dtos.some((dto) => typeof dto === 'object' && dto !== null && key in dto);
67
+ export const dtoIndex = (dtos, key) => dtos.findIndex((dto) => typeof dto === 'object' && dto !== null && key in dto);
@@ -1,4 +1,4 @@
1
- import type { StatefulConnection, StatefulObservable } from '@rx-evo/stateful-observable';
1
+ import type { ResponseDto, StatefulConnection, StatefulObservable } from '@rx-evo/stateful-observable';
2
2
  import type { Observable } from 'rxjs';
3
3
  import type { GraphCluster } from './runtime-helpers.js';
4
4
  export type RuntimeWireType = string & {
@@ -83,7 +83,7 @@ export type MetaFromStatefulObservable<T extends StatefulObservable<unknown, unk
83
83
  *
84
84
  * ## Errors
85
85
  * Node handlers surface failures via RxJS / `StatefulObservable` (`catchError`,
86
- * port `error$`). Runner telemetry emits `output-emitted` with `state: 'error'`
86
+ * port `error$`). Runner telemetry emits `ResponseDto` `{ error }`
87
87
  * on the source; wiring then drops `ResponseError` so edges do not cascade
88
88
  * error chrome to downstream nodes.
89
89
  *
@@ -118,45 +118,41 @@ export type MetaFromStatefulObservable<T extends StatefulObservable<unknown, unk
118
118
  * optional {@link RuntimeNode.stopsRun} completion.
119
119
  */
120
120
  export type RuntimeRunnerStatus = 'idle' | 'running' | 'stopped';
121
- export type RuntimePortSignalState = 'pending' | 'value' | 'error';
122
- export type RuntimeOutputEmittedEvent = {
123
- readonly kind: 'output-emitted';
124
- readonly runId: RunId;
125
- readonly nodeId: NodeId;
126
- readonly portId: string | symbol;
127
- readonly portIdx: number;
128
- readonly edgeIds: EdgeId[];
129
- readonly state: RuntimePortSignalState;
130
- readonly value: unknown;
131
- /** Resolved author feed contract carried with the runtime fact. */
132
- readonly feed?: RuntimeFeedPortMeta;
121
+ /**
122
+ * Port signal tuple — `portDir` `'out'` = output emitted, `'in'` = input received.
123
+ * Slot 3 is `@rx-evo` {@link ResponseDto} (JSON-safe pending / inactive / error /
124
+ * value). No per-frame `runId`; session snapshots own run correlation.
125
+ */
126
+ export type PortTelemetry = readonly [
127
+ portDir: 'in' | 'out',
128
+ nodeId: NodeId,
129
+ portId: string,
130
+ response: ResponseDto<unknown>,
131
+ portIdx: number,
132
+ edgeIds: readonly EdgeId[],
133
+ /** Absent feed meta — use `null` (never `undefined`; JSON arrays drop undefined). */
134
+ feed: RuntimeFeedPortMeta | null
135
+ ];
136
+ /** Run ended — `runId` at index 1 when replay needs explicit correlation. */
137
+ export type RuntimeDoneTelemetry = readonly ['done'] | readonly ['done', RunId];
138
+ export type RuntimeRunnerEvent = PortTelemetry | RuntimeDoneTelemetry;
139
+ export declare const isPortTelemetry: (event: RuntimeRunnerEvent) => event is PortTelemetry;
140
+ export declare const isPortValueTelemetry: (event: RuntimeRunnerEvent) => event is PortTelemetry & {
141
+ readonly 3: Extract<ResponseDto<unknown>, {
142
+ value: unknown;
143
+ }>;
133
144
  };
134
- export type RuntimeInputReceivedEvent = {
135
- readonly kind: 'input-received';
136
- readonly runId: RunId;
137
- readonly nodeId: NodeId;
138
- readonly portId: string | symbol;
139
- readonly portIdx: number;
140
- readonly edgeIds: EdgeId[];
141
- readonly state: RuntimePortSignalState;
142
- readonly value: unknown;
143
- /** Resolved author feed contract carried with the runtime fact. */
144
- readonly feed?: RuntimeFeedPortMeta;
145
+ export declare const isPortErrorTelemetry: (event: RuntimeRunnerEvent) => event is PortTelemetry & {
146
+ readonly 3: Extract<ResponseDto<unknown>, {
147
+ error: unknown;
148
+ }>;
145
149
  };
146
- export type RuntimeRunnerEvent = RuntimeOutputEmittedEvent | RuntimeInputReceivedEvent | {
147
- /**
148
- * Run ended naturally — sets {@link RuntimeRunnerStatus} to `'idle'`.
149
- *
150
- * Emitted when:
151
- * - the graph is **empty** on {@link RuntimeRunner.start}, or
152
- * - a node with {@link RuntimeNode.stopsRun} emits on a watched output.
153
- *
154
- * Otherwise the run stays `'running'` until
155
- * {@link RuntimeRunner.interrupt}.
156
- */
157
- readonly kind: 'done';
158
- readonly runId: RunId;
150
+ export declare const isPortPendingTelemetry: (event: RuntimeRunnerEvent) => event is PortTelemetry & {
151
+ readonly 3: {
152
+ readonly pending: true;
153
+ };
159
154
  };
155
+ export declare const isRuntimeDone: (event: RuntimeRunnerEvent) => event is RuntimeDoneTelemetry;
160
156
  /** Seed value pushed into an input port slot on {@link RuntimeRunner.start}. */
161
157
  export type RuntimeSeedPortValue = {
162
158
  readonly portId: string | symbol;
@@ -255,6 +251,10 @@ export type RuntimeOptions = {
255
251
  */
256
252
  readonly log?: boolean;
257
253
  };
254
+ export type SwapNodeResult = {
255
+ readonly node: RuntimeNode;
256
+ readonly droppedEdges: readonly RuntimeEdge[];
257
+ };
258
258
  export type RuntimeEditorApi = {
259
259
  /**
260
260
  * Register a node and its port observables (handler already bound).
@@ -288,6 +288,15 @@ export type RuntimeEditorApi = {
288
288
  * graph is locked. Does not cascade-remove other edges.
289
289
  */
290
290
  replaceEdge(edge: Omit<RuntimeEdge, 'edgeId'>): RuntimeEdge | false;
291
+ /**
292
+ * Replace the live instance at `nodeId` with `next`. Keeps `nodeId`.
293
+ * Drops incident edges whose ports vanished or whose wire types are no
294
+ * longer compatible (same rules as {@link addEdge}).
295
+ *
296
+ * Allowed while the graph is locked. Does not call {@link addNode} /
297
+ * {@link removeNode}. Returns `false` when disposed or `nodeId` is missing.
298
+ */
299
+ swapNode(nodeId: NodeId, next: Omit<RuntimeNode, 'nodeId'>): SwapNodeResult | false;
291
300
  /** Must fail while runner status is `'running'`.
292
301
  *
293
302
  * return false while running or node not found
@@ -314,7 +323,9 @@ export type RuntimeEditorApi = {
314
323
  export type RuntimeRunnerApi = {
315
324
  /**
316
325
  * Wire every cluster that does not contain a {@link RuntimeNode.chatEntry}
317
- * node, seed source inputs, set status to `'running'`.
326
+ * node. Assigns `runId` and sets `'running'` **synchronously**, then wires
327
+ * ports on a microtask so callers (WS `runner.started`) can fence before
328
+ * any `runner.port` telemetry.
318
329
  *
319
330
  * Chat-entry clusters are omitted — start them via
320
331
  * {@link RuntimeRunnerApi.pushIntoInput}. When every cluster is chat-entry
@@ -331,7 +342,8 @@ export type RuntimeRunnerApi = {
331
342
  start(initialPayload?: Readonly<Record<string, ReadonlyArray<RuntimeSeedPortValue>>>, runId?: RunId): RunId | false;
332
343
  /**
333
344
  * Run-from-node: wire the weakly connected cluster containing `nodeId`
334
- * (orphan nodes elsewhere on the canvas are not wired).
345
+ * (orphan nodes elsewhere on the canvas are not wired). Same runId /
346
+ * `'running'` sync + microtask wiring as {@link RuntimeRunnerApi.start}.
335
347
  *
336
348
  * Run stays `'running'` until {@link RuntimeRunnerApi.interrupt} or a
337
349
  * {@link RuntimeNode.stopsRun} node in scope emits.
@@ -1 +1,5 @@
1
- export {};
1
+ export const isPortTelemetry = (event) => Array.isArray(event) && (event[0] === 'in' || event[0] === 'out');
2
+ export const isPortValueTelemetry = (event) => isPortTelemetry(event) && 'value' in event[3];
3
+ export const isPortErrorTelemetry = (event) => isPortTelemetry(event) && 'error' in event[3];
4
+ export const isPortPendingTelemetry = (event) => isPortTelemetry(event) && 'pending' in event[3];
5
+ export const isRuntimeDone = (event) => Array.isArray(event) && event[0] === 'done';
@@ -15,7 +15,7 @@
15
15
  }
16
16
  },
17
17
  "dependencies": {
18
- "@rx-evo/stateful-observable": "^0.5.2",
18
+ "@rx-evo/stateful-observable": "^0.6.0",
19
19
  "rxjs": "^7.8.1"
20
20
  },
21
21
  "files": [
@@ -1,3 +1,4 @@
1
+ import { isRuntimeDone } from '@langflower/runtime';
1
2
  import { deriveExecutionProgressStatus, terminalExecutionProgressStatus, } from '@langflower/shared/langflower.js';
2
3
  import { Subscription } from 'rxjs';
3
4
  import { RunCheckpointSession } from '../checkpoint/run-checkpoint-session.js';
@@ -36,7 +37,7 @@ export const attachLangflowerBridge = (bridge, context, options = {}) => {
36
37
  // miss them (`events$` is a non-replaying Subject). Late clients get the
37
38
  // backlog via `executionFeed.snapshot`. See FOUND_BUGS pending race.
38
39
  rootSubscription.add(session.runtime.runner.events$.subscribe((event) => {
39
- if (event.kind === 'done' && onRunSettled !== undefined) {
40
+ if (isRuntimeDone(event) && onRunSettled !== undefined) {
40
41
  const progress = deriveExecutionProgressStatus('idle', session.runtime.runner.eventLog);
41
42
  const status = terminalExecutionProgressStatus(progress);
42
43
  if (status !== null) {
@@ -59,7 +60,7 @@ export const attachLangflowerBridge = (bridge, context, options = {}) => {
59
60
  // 3. Intent handlers (bus namespaces)
60
61
  rootSubscription.add(wireWorkflowHandlers(bridge, context, session));
61
62
  rootSubscription.add(wirePaletteHandlers(bridge, context));
62
- rootSubscription.add(wireCustomPaletteHandlers(bridge, context));
63
+ rootSubscription.add(wireCustomPaletteHandlers(bridge, context, session));
63
64
  rootSubscription.add(wireConfigHandlers(bridge, context, session, draftController, {
64
65
  onEffectiveConfig: (config) => {
65
66
  applyServerLogsGate(diagnosticLog.setEnabled, config);
@@ -2,67 +2,22 @@ import { randomUUID } from 'node:crypto';
2
2
  import { promises as fs } from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import { langflowerWsConfig } from '@langflower/shared/langflower.js';
5
+ import { encodeBridgeFrame } from '@langflower/websocket-bridge/bridge-codec';
5
6
  import { Subscription } from 'rxjs';
6
- const REDACTED = '[REDACTED]';
7
- const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
8
- const isSecretKey = (key) => {
9
- const normalized = key.toLowerCase();
10
- return (normalized.includes('apikey') ||
11
- normalized.includes('authorization') ||
12
- normalized.includes('cookie') ||
13
- normalized.includes('token') ||
14
- normalized.includes('password') ||
15
- normalized.includes('secret') ||
16
- normalized.includes('credential'));
17
- };
18
- const sanitize = (value, seen = new WeakSet()) => {
19
- if (value === null ||
20
- typeof value === 'string' ||
21
- typeof value === 'number' ||
22
- typeof value === 'boolean') {
23
- return value;
24
- }
25
- if (typeof value === 'bigint') {
26
- return `${value}n`;
27
- }
28
- if (typeof value === 'undefined') {
29
- return '[undefined]';
30
- }
31
- if (typeof value === 'symbol' || typeof value === 'function') {
32
- return `[${typeof value}]`;
33
- }
34
- if (value instanceof Error) {
35
- return {
36
- name: value.name,
37
- message: value.message,
38
- };
39
- }
40
- if (value instanceof Date) {
41
- return value.toISOString();
42
- }
43
- if (typeof value === 'object') {
44
- if (seen.has(value)) {
45
- return '[circular]';
46
- }
47
- seen.add(value);
48
- }
49
- if (Array.isArray(value)) {
50
- return value.map((entry) => sanitize(entry, seen));
51
- }
52
- if (isRecord(value)) {
53
- return Object.fromEntries(Object.entries(value).map(([key, entry]) => [
54
- key,
55
- isSecretKey(key) ? REDACTED : sanitize(entry, seen),
56
- ]));
57
- }
58
- return String(value);
59
- };
60
7
  const toSafeTimestamp = (date) => date.toISOString().replaceAll(':', '-').replaceAll('.', '-');
61
- const asObservable = (value) => isRecord(value) && typeof value.subscribe === 'function'
8
+ const asObservable = (value) => typeof value === 'object' &&
9
+ value !== null &&
10
+ typeof value.subscribe === 'function'
62
11
  ? value
63
12
  : undefined;
64
- const asInboundEvent = (value) => isRecord(value) && typeof value.clientId === 'string' && 'payload' in value
65
- ? { clientId: value.clientId, payload: value.payload }
13
+ const asInboundEvent = (value) => typeof value === 'object' &&
14
+ value !== null &&
15
+ typeof value.clientId === 'string' &&
16
+ 'payload' in value
17
+ ? {
18
+ clientId: value.clientId,
19
+ payload: value.payload,
20
+ }
66
21
  : undefined;
67
22
  const logPath = (projectDir) => path.join(projectDir, '.langflower', 'logs', `${toSafeTimestamp(new Date())}-${process.pid}-${randomUUID()}.log`);
68
23
  export const attachBridgeEventLog = (bridge, projectDir, subscriptions, options = {}) => {
@@ -81,15 +36,11 @@ export const attachBridgeEventLog = (bridge, projectDir, subscriptions, options
81
36
  const message = error instanceof Error ? error.message : String(error);
82
37
  process.stderr.write(`Langflower diagnostic logging disabled: ${message}\n`);
83
38
  };
84
- const write = (record) => {
39
+ const writeFrame = (transportDir, busType, payload) => {
85
40
  if (!enabled || !acceptingWrites || closed) {
86
41
  return;
87
42
  }
88
- const line = `${JSON.stringify(sanitize({
89
- schemaVersion: 1,
90
- timestamp: new Date().toISOString(),
91
- ...record,
92
- }))}\n`;
43
+ const line = `${encodeBridgeFrame(transportDir, busType, payload)}\n`;
93
44
  writeQueue = writeQueue.then(async () => {
94
45
  if (!enabled || !acceptingWrites) {
95
46
  return;
@@ -118,13 +69,7 @@ export const attachBridgeEventLog = (bridge, projectDir, subscriptions, options
118
69
  subscriptions.add(channel.subscribe((value) => {
119
70
  const event = asInboundEvent(value);
120
71
  if (event !== undefined) {
121
- write({
122
- kind: 'frame',
123
- direction: 'inbound',
124
- clientId: event.clientId,
125
- type,
126
- payload: event.payload,
127
- });
72
+ writeFrame('in', type, event.payload);
128
73
  }
129
74
  }));
130
75
  }
@@ -134,30 +79,10 @@ export const attachBridgeEventLog = (bridge, projectDir, subscriptions, options
134
79
  continue;
135
80
  }
136
81
  subscriptions.add(channel.subscribe((payload) => {
137
- write({
138
- kind: 'frame',
139
- direction: 'outbound',
140
- scope: 'broadcast',
141
- type,
142
- payload,
143
- });
82
+ writeFrame('out', type, payload);
144
83
  }));
145
84
  }
146
- subscriptions.add(bridge.status$.subscribe((status) => {
147
- write({ kind: 'status', status });
148
- }));
149
- subscriptions.add(bridge.errors$.subscribe((error) => {
150
- write({
151
- kind: 'error',
152
- error: {
153
- code: error.code,
154
- message: error.message,
155
- ...('cause' in error ? { cause: error.cause } : {}),
156
- },
157
- });
158
- }));
159
85
  subscriptions.add(bridge.connections$.subscribe((client) => {
160
- write({ kind: 'connection', clientId: client.id });
161
86
  const clientSubscriptions = new Subscription();
162
87
  subscriptions.add(clientSubscriptions);
163
88
  const clientChannels = client;
@@ -167,29 +92,19 @@ export const attachBridgeEventLog = (bridge, projectDir, subscriptions, options
167
92
  continue;
168
93
  }
169
94
  clientSubscriptions.add(channel.subscribe((payload) => {
170
- write({
171
- kind: 'frame',
172
- direction: 'outbound',
173
- scope: 'client',
174
- clientId: client.id,
175
- type,
176
- payload,
177
- });
95
+ writeFrame('out', type, payload);
178
96
  }));
179
97
  }
180
98
  clientSubscriptions.add(client.disconnected$.subscribe(() => {
181
- write({ kind: 'disconnection', clientId: client.id });
182
99
  clientSubscriptions.unsubscribe();
183
100
  }));
184
101
  }));
185
- write({ kind: 'server-started' });
186
102
  return {
187
103
  filePath,
188
104
  setEnabled: (nextEnabled) => {
189
105
  enabled = nextEnabled;
190
106
  },
191
107
  writeServerClosing: () => {
192
- write({ kind: 'server-closing' });
193
108
  closed = true;
194
109
  },
195
110
  flush: async () => {
@@ -1,4 +1,5 @@
1
- import { type ExecutionContext } from '@langflower/node-sdk';
1
+ import type { LangflowerBusRequest } from '@langflower/common-nodes/ai/run-host-services';
2
+ import { type ExecutionContext, type ToolHandle } from '@langflower/node-sdk';
2
3
  import type { LlmExecutionCaps } from '@langflower/node-sdk/llm';
3
4
  import type { McpHandle } from '@langflower/node-sdk/mcp';
4
5
  import type { RuntimeSeedPortValue } from '@langflower/runtime';
@@ -16,6 +17,8 @@ type BuildHarnessHooks = {
16
17
  readonly nodeId: string;
17
18
  readonly requestPermission: LangflowerSession['permissionAsks']['requestPermission'];
18
19
  readonly emitPermissionAsk: (payload: RunnerPermissionAskPayload) => void;
20
+ readonly requestLangflowerBus?: LangflowerBusRequest;
21
+ readonly getLiveWiredTools?: (agentNodeId: string) => readonly ToolHandle[];
19
22
  };
20
23
  export declare const buildExecutionContext: (context: ExecutionContextDeps, runId: string, node: WorkflowGraphNode, hooks?: BuildHarnessHooks, preloadedConfig?: LangflowerConfig, runMcpHandles?: readonly McpHandle[]) => Promise<ExecutionContext<never, LlmExecutionCaps>>;
21
24
  /**
@@ -24,5 +27,5 @@ export declare const buildExecutionContext: (context: ExecutionContextDeps, runI
24
27
  * which would put the Observable in value$ instead of error$.
25
28
  */
26
29
  export declare const applyObservableContextSeeds: (session: LangflowerSession, seeds: Readonly<Record<string, ReadonlyArray<RuntimeSeedPortValue>>>) => Record<string, ReadonlyArray<RuntimeSeedPortValue>>;
27
- export declare const buildContextSeeds: (session: LangflowerSession, context: ExecutionContextDeps, runId: string, emitPermissionAsk: (payload: RunnerPermissionAskPayload) => void) => Promise<Record<string, ReadonlyArray<RuntimeSeedPortValue>>>;
30
+ export declare const buildContextSeeds: (session: LangflowerSession, context: ExecutionContextDeps, runId: string, emitPermissionAsk: (payload: RunnerPermissionAskPayload) => void, requestLangflowerBus?: LangflowerBusRequest, getLiveWiredTools?: (agentNodeId: string) => readonly ToolHandle[]) => Promise<Record<string, ReadonlyArray<RuntimeSeedPortValue>>>;
28
31
  export {};
@@ -28,6 +28,13 @@ const createToolHarness = (options) => {
28
28
  : {}),
29
29
  });
30
30
  };
31
+ const LIVE_WIRED_TOOLS_NODE_TYPES = new Set([
32
+ 'common-openai-llm',
33
+ 'common-fake-llm',
34
+ 'common-review',
35
+ 'common-critique',
36
+ 'common-sub-agent',
37
+ ]);
31
38
  export const buildExecutionContext = async (context, runId, node, hooks, preloadedConfig, runMcpHandles) => {
32
39
  const rolePreset = parseLlmRolePreset(node.params.rolePreset);
33
40
  const skillId = resolveEffectiveSkillId(rolePreset, node.params.skillId);
@@ -66,8 +73,9 @@ export const buildExecutionContext = async (context, runId, node, hooks, preload
66
73
  webFetch,
67
74
  };
68
75
  const enabledToolIds = toolPermissionsToEnabledIds(toolPermissions);
69
- const toolHandles = wrapBuiltinToolHandles(harness, enabledToolIds, permission);
70
- const mcpHandles = filterMcpHandlesByIds(runMcpHandles ?? [], parseEnabledMcpIds(node.params.enabledMcpIds));
76
+ const builtinHandles = wrapBuiltinToolHandles(harness, enabledToolIds, permission);
77
+ const mcpTools = filterMcpHandlesByIds(runMcpHandles ?? [], parseEnabledMcpIds(node.params.enabledMcpIds)).flatMap((handle) => handle.tools);
78
+ const toolHandles = [...builtinHandles, ...mcpTools];
71
79
  const base = {
72
80
  projectDir: context.projectDir,
73
81
  runId,
@@ -78,7 +86,6 @@ export const buildExecutionContext = async (context, runId, node, hooks, preload
78
86
  params: node.params,
79
87
  })?.uiSchema ?? []),
80
88
  ...(toolHandles.length > 0 ? { toolHandles } : {}),
81
- ...(mcpHandles.length > 0 ? { mcpHandles } : {}),
82
89
  };
83
90
  const defaultChat = parseDefaultChatModel(config.model);
84
91
  return attachRunHostServices(base, {
@@ -104,8 +111,28 @@ export const buildExecutionContext = async (context, runId, node, hooks, preload
104
111
  ...(config.harness?.allowedHosts !== undefined
105
112
  ? { allowedHosts: config.harness.allowedHosts }
106
113
  : {}),
114
+ ...(hooks?.requestLangflowerBus !== undefined &&
115
+ node.type === 'common-langflower-tools'
116
+ ? { requestLangflowerBus: hooks.requestLangflowerBus }
117
+ : {}),
118
+ ...(hooks?.getLiveWiredTools !== undefined &&
119
+ LIVE_WIRED_TOOLS_NODE_TYPES.has(node.type)
120
+ ? { getLiveWiredTools: hooks.getLiveWiredTools }
121
+ : {}),
107
122
  });
108
123
  };
124
+ /** Host `contextSymbol` vs compiled-pack duplicate (`file://` / Vitest alias). */
125
+ const contextPortLabel = String(contextSymbol);
126
+ const resolveLiveContextPortId = (session, nodeId) => {
127
+ const node = session.runtime.editor.getNode(nodeId);
128
+ if (node === false || node.inputs[contextSymbol] !== undefined) {
129
+ return contextSymbol;
130
+ }
131
+ const match = Object.getOwnPropertySymbols(node.inputs).find((portId) => String(portId) === contextPortLabel);
132
+ return match ?? contextSymbol;
133
+ };
134
+ const isContextSeedPort = (portId) => portId === contextSymbol ||
135
+ (typeof portId === 'symbol' && String(portId) === contextPortLabel);
109
136
  const ctxErrorFromFailures = (failures) => ({
110
137
  message: failures.map((failure) => failure.message).join('\n'),
111
138
  });
@@ -119,9 +146,10 @@ export const applyObservableContextSeeds = (session, seeds) => {
119
146
  for (const [nodeId, list] of Object.entries(seeds)) {
120
147
  const kept = [];
121
148
  for (const seed of list) {
122
- if (seed.portId === contextSymbol && isObservable(seed.value)) {
149
+ if (isContextSeedPort(seed.portId) && isObservable(seed.value)) {
123
150
  const node = session.runtime.editor.getNode(nodeId);
124
- const connection = node === false ? undefined : node.inputs[contextSymbol];
151
+ const portId = resolveLiveContextPortId(session, nodeId);
152
+ const connection = node === false ? undefined : node.inputs[portId];
125
153
  if (connection !== undefined) {
126
154
  connection.connect(seed.value);
127
155
  }
@@ -135,7 +163,7 @@ export const applyObservableContextSeeds = (session, seeds) => {
135
163
  }
136
164
  return valueSeeds;
137
165
  };
138
- export const buildContextSeeds = async (session, context, runId, emitPermissionAsk) => {
166
+ export const buildContextSeeds = async (session, context, runId, emitPermissionAsk, requestLangflowerBus, getLiveWiredTools) => {
139
167
  const workflow = session.activeWorkflow;
140
168
  if (workflow === null) {
141
169
  return {};
@@ -160,7 +188,7 @@ export const buildContextSeeds = async (session, context, runId, emitPermissionA
160
188
  const error = ctxErrorFromFailures(nodeFailures);
161
189
  seeds[node.id] = [
162
190
  {
163
- portId: contextSymbol,
191
+ portId: resolveLiveContextPortId(session, node.id),
164
192
  slotIndex: 0,
165
193
  value: throwError(() => error),
166
194
  },
@@ -172,8 +200,20 @@ export const buildContextSeeds = async (session, context, runId, emitPermissionA
172
200
  nodeId: node.id,
173
201
  requestPermission: session.permissionAsks.requestPermission,
174
202
  emitPermissionAsk,
203
+ ...(requestLangflowerBus !== undefined
204
+ ? { requestLangflowerBus }
205
+ : {}),
206
+ ...(getLiveWiredTools !== undefined
207
+ ? { getLiveWiredTools }
208
+ : {}),
175
209
  }, config, runMcp?.handles);
176
- seeds[node.id] = [{ portId: contextSymbol, slotIndex: 0, value: ctx }];
210
+ seeds[node.id] = [
211
+ {
212
+ portId: resolveLiveContextPortId(session, node.id),
213
+ slotIndex: 0,
214
+ value: ctx,
215
+ },
216
+ ];
177
217
  }
178
218
  return seeds;
179
219
  };
@@ -1,4 +1,4 @@
1
- import type { RuntimeRunnerEvent } from '@langflower/runtime';
1
+ import { type RuntimeRunnerEvent } from '@langflower/runtime';
2
2
  import type { LangflowerBridge } from './langflower-bridge.types.js';
3
3
  /** Fan-out runner telemetry to every connected tab (session-shared). */
4
4
  export declare const forwardRunnerEvent: (bridge: LangflowerBridge, event: RuntimeRunnerEvent) => void;
@@ -1,17 +1,12 @@
1
+ import { isPortTelemetry, isRuntimeDone, } from '@langflower/runtime';
1
2
  import { bridgeEmit } from './bridge-outbound.js';
2
3
  /** Fan-out runner telemetry to every connected tab (session-shared). */
3
4
  export const forwardRunnerEvent = (bridge, event) => {
4
- switch (event.kind) {
5
- case 'output-emitted':
6
- bridgeEmit(bridge, 'runner.output-emitted', event);
7
- break;
8
- case 'input-received':
9
- bridgeEmit(bridge, 'runner.input-received', event);
10
- break;
11
- case 'done':
12
- bridgeEmit(bridge, 'runner.done', event);
13
- break;
14
- default:
15
- break;
5
+ if (isPortTelemetry(event)) {
6
+ bridgeEmit(bridge, 'runner.port', event);
7
+ return;
8
+ }
9
+ if (isRuntimeDone(event)) {
10
+ bridgeEmit(bridge, 'runner.done', event);
16
11
  }
17
12
  };