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
@@ -0,0 +1,417 @@
1
+ import { defineLlmNode, isSteerControlPayload, toLlmRecoveryPortValue, } from '@langflower/node-sdk/llm';
2
+ import { TOOL_HANDLE_WIRE_TYPE, } from '@langflower/node-sdk';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { catchError, concat, filter, firstValueFrom, map, mergeMap, of, Subject, switchMap, take, tap, timeout, TimeoutError, } from 'rxjs';
5
+ import { llmPanelUiSchema } from '../../features/ui-schema/llm-panel-ui-schema.js';
6
+ import { llmCompactionUiSchema } from '../../features/ui-schema/llm-compaction-ui-schema.js';
7
+ import { llmRecoveryUiSchema } from '../../features/ui-schema/llm-recovery-ui-schema.js';
8
+ import { AGENT_MAX_ITERATIONS_CAP, DEFAULT_AGENT_MAX_ITERATIONS, normalizeMaxIterations, } from '../../features/prompt/normalize-max-iterations.js';
9
+ import { appendToolInventory, demuxByKind, } from '../../features/llm-session/llm-session-shell.js';
10
+ import { runAgentLoop, } from '../../features/llm-loop/run-agent-loop.js';
11
+ import { collectAgentToolHandles } from '../../../tools/collect-agent-tool-handles.js';
12
+ import { parseLlmRolePreset, resolveEffectiveSkillId, } from '../../features/llm-role-preset.js';
13
+ import { resolveChatProviderModel } from '../../features/prompt/resolve-chat-provider-model.js';
14
+ import { getRunHostServices } from '../../features/run-host-services.js';
15
+ import { buildEffectiveSystemPrompt } from '../../features/prompt/build-effective-system-prompt.js';
16
+ import { normalizeCompactionConfig } from '../../features/openai/normalize-compaction-params.js';
17
+ import { normalizeLlmRecoveryPolicy } from '../../features/llm-loop/normalize-llm-recovery-policy.js';
18
+ import { createScriptedFactory, parseScriptedTurns, } from '../../features/scripted-chat-completion-stream.js';
19
+ const normalizeSkillIds = (raw) => {
20
+ if (!Array.isArray(raw)) {
21
+ return [];
22
+ }
23
+ return raw
24
+ .map((entry) => String(entry ?? '').trim())
25
+ .filter((entry) => entry.length > 0);
26
+ };
27
+ const formatSpecialistHandleName = (displayName) => `${displayName}(subagent)`;
28
+ const slugToolId = (name, nodeId) => {
29
+ const slug = (raw) => raw
30
+ .replace(/[^a-zA-Z0-9_-]+/g, '_')
31
+ .replace(/^_+|_+$/g, '')
32
+ .slice(0, 64);
33
+ const fromName = slug(name.trim());
34
+ if (fromName.length > 0) {
35
+ return fromName;
36
+ }
37
+ const fromNode = slug(nodeId);
38
+ return fromNode.length > 0 ? fromNode : 'subagent';
39
+ };
40
+ const formatSpawnUserContent = (task, skillId) => {
41
+ if (skillId.length === 0) {
42
+ return task;
43
+ }
44
+ return `[skill:${skillId}]\n${task}`;
45
+ };
46
+ const buildSpecialistDescription = (name, description, skillIds) => {
47
+ const parts = [
48
+ `${name} is a canvas Sub-Agent — a separate specialist agent, not a regular tool (not files, shell, or MCP).`,
49
+ 'Call this tool to delegate a task; the specialist runs its own model and tools and returns a text result.',
50
+ 'Do not try to do this specialist work yourself when this tool is the right owner.',
51
+ ];
52
+ if (description.trim().length > 0) {
53
+ parts.push(description.trim());
54
+ }
55
+ if (skillIds.length > 0) {
56
+ parts.push(`Skills: ${skillIds.join(', ')}.`);
57
+ }
58
+ parts.push('Required argument: task — the assignment for this Sub-Agent.');
59
+ return parts.join(' ');
60
+ };
61
+ const buildSpecialistInputSchema = (skillIds) => {
62
+ const properties = {
63
+ task: {
64
+ type: 'string',
65
+ description: 'Task to delegate to this Sub-Agent specialist',
66
+ },
67
+ };
68
+ if (skillIds.length > 0) {
69
+ properties.skillId = {
70
+ type: 'string',
71
+ enum: [...skillIds],
72
+ description: 'Optional skill announced by this Sub-Agent Inspector selector',
73
+ };
74
+ }
75
+ return {
76
+ type: 'object',
77
+ properties,
78
+ required: ['task'],
79
+ };
80
+ };
81
+ const resolveTurnFactory = (context) => {
82
+ if (context.scriptedTurns !== undefined) {
83
+ return createScriptedFactory(context.scriptedTurns);
84
+ }
85
+ return context.factory;
86
+ };
87
+ const chatConfigError = (providerId, model, scripted) => {
88
+ if (scripted) {
89
+ return undefined;
90
+ }
91
+ if (providerId.trim().length === 0) {
92
+ return 'Error: Provider is required for Sub-Agent chat';
93
+ }
94
+ if (model.trim().length === 0) {
95
+ return 'Error: Model is required for Sub-Agent chat';
96
+ }
97
+ return undefined;
98
+ };
99
+ const EMPTY_INVOKE_RESULT = 'Error: Sub-Agent returned no content';
100
+ const finalizeInvokeText = (responseText, lastDraft, lastReasoning) => {
101
+ if (responseText.trim().length > 0) {
102
+ return responseText;
103
+ }
104
+ if (lastDraft.trim().length > 0) {
105
+ return lastDraft;
106
+ }
107
+ if (lastReasoning.trim().length > 0) {
108
+ return lastReasoning;
109
+ }
110
+ return EMPTY_INVOKE_RESULT;
111
+ };
112
+ const seedInvokeHistory = (history, context) => {
113
+ const system = {
114
+ role: 'system',
115
+ content: appendToolInventory(context.effectiveSystemPrompt, context.tools),
116
+ };
117
+ if (history.length === 0) {
118
+ return [system];
119
+ }
120
+ if (history[0]?.role === 'system') {
121
+ return [system, ...history.slice(1)];
122
+ }
123
+ return [system, ...history];
124
+ };
125
+ const reduceInvokeHistory = (history, chunk) => {
126
+ if (chunk.kind === 'historySync') {
127
+ return [...chunk.messages];
128
+ }
129
+ if (chunk.kind === 'invokeDone' && chunk.text.trim().length > 0) {
130
+ return [...history, { role: 'assistant', content: chunk.text }];
131
+ }
132
+ return history;
133
+ };
134
+ const runSubAgentTurn = (context, turn, history) => {
135
+ const fail = (text) => of({ kind: 'response', text }, {
136
+ kind: 'invokeDone',
137
+ requestId: turn.requestId,
138
+ text,
139
+ });
140
+ const scripted = context.scriptedTurns !== undefined;
141
+ const factory = resolveTurnFactory(context);
142
+ if (factory === undefined) {
143
+ return fail('Error: Sub-Agent chat is only available during server workflow runs');
144
+ }
145
+ const configError = chatConfigError(context.providerId, context.model, scripted);
146
+ if (configError !== undefined) {
147
+ return fail(configError);
148
+ }
149
+ const userContent = formatSpawnUserContent(turn.task, turn.skillId);
150
+ let lastDraft = '';
151
+ let lastReasoning = '';
152
+ return concat(of({
153
+ kind: 'historySync',
154
+ messages: [
155
+ ...history,
156
+ {
157
+ role: 'user',
158
+ content: userContent,
159
+ },
160
+ ],
161
+ }), runAgentLoop({
162
+ factory,
163
+ providerId: scripted
164
+ ? context.providerId.trim() || 'scripted'
165
+ : context.providerId,
166
+ model: scripted
167
+ ? context.model.trim() || 'scripted'
168
+ : context.model,
169
+ messages: [...history, { role: 'user', content: userContent }],
170
+ tools: context.tools,
171
+ toolCtx: context.toolCtx,
172
+ maxIterations: context.maxIterations,
173
+ compaction: context.compaction,
174
+ recovery: context.recovery,
175
+ ...(context.requestPermission !== undefined
176
+ ? { requestPermission: context.requestPermission }
177
+ : {}),
178
+ ...(context.steerControl$ !== undefined
179
+ ? { steerControl$: context.steerControl$ }
180
+ : {}),
181
+ }).pipe(mergeMap((chunk) => {
182
+ if (chunk.kind === 'reasoning' && chunk.text.length > 0) {
183
+ lastReasoning += chunk.text;
184
+ }
185
+ if (chunk.kind === 'draftResponse' && chunk.text.length > 0) {
186
+ lastDraft += chunk.text;
187
+ }
188
+ if (chunk.kind !== 'response') {
189
+ return of(chunk);
190
+ }
191
+ const text = finalizeInvokeText(chunk.text, lastDraft, lastReasoning);
192
+ return of({ kind: 'response', text }, {
193
+ kind: 'invokeDone',
194
+ requestId: turn.requestId,
195
+ text,
196
+ });
197
+ }), catchError((error) => {
198
+ const text = error instanceof Error
199
+ ? `Error: ${error.message}`
200
+ : 'Error: Sub-Agent turn failed.';
201
+ return fail(text);
202
+ })));
203
+ };
204
+ const parseInvokeTurn = (raw, skillIds) => {
205
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
206
+ return {
207
+ ok: false,
208
+ text: 'Error: Sub-Agent invoke payload is invalid.',
209
+ };
210
+ }
211
+ const record = raw;
212
+ const requestId = typeof record.requestId === 'string' && record.requestId.length > 0
213
+ ? record.requestId
214
+ : randomUUID();
215
+ const task = typeof record.task === 'string' ? record.task.trim() : '';
216
+ const skillId = typeof record.skillId === 'string' ? record.skillId.trim() : '';
217
+ if (task.length === 0) {
218
+ return {
219
+ ok: false,
220
+ text: 'Error: Sub-Agent requires a non-empty task.',
221
+ };
222
+ }
223
+ if (skillId.length > 0 && !skillIds.includes(skillId)) {
224
+ return {
225
+ ok: false,
226
+ text: `Error: Skill «${skillId}» is not announced by this Sub-Agent.`,
227
+ };
228
+ }
229
+ return { ok: true, turn: { requestId, task, skillId } };
230
+ };
231
+ /**
232
+ * Sub-Agent: ordinary OpenAI-compatible agent that announces one ToolHandle
233
+ * on `subagent-registration`. Parent invoke runs this node's in-node loop.
234
+ * @see docs/ADR.md ADR-021
235
+ */
236
+ export const subAgentNode = defineLlmNode({
237
+ type: 'common-sub-agent',
238
+ displayName: 'Sub-Agent',
239
+ category: 'AI',
240
+ description: 'OpenAI-compatible specialist agent. Wire `tools` into a parent agent; invoke runs this node in-graph.',
241
+ uiSchema: [
242
+ {
243
+ field: 'name',
244
+ type: 'string',
245
+ label: 'Name',
246
+ default: 'Sub-Agent',
247
+ },
248
+ {
249
+ field: 'description',
250
+ type: 'string',
251
+ label: 'Description',
252
+ default: '',
253
+ },
254
+ {
255
+ field: 'skillIds',
256
+ type: 'tool-id-list',
257
+ label: 'Skills',
258
+ optionsSource: 'langflower.skills',
259
+ },
260
+ ...llmPanelUiSchema,
261
+ ...llmCompactionUiSchema,
262
+ ...llmRecoveryUiSchema,
263
+ ],
264
+ bind(ctx, { makeInput, configureOutput, combineInputs }, inventory) {
265
+ const { tools, steerControl } = inventory;
266
+ const systemPrompt = makeInput('systemPrompt', {
267
+ name: 'systemPrompt',
268
+ wireType: 'string',
269
+ inline: 'text-multiline',
270
+ defaultValue: '',
271
+ });
272
+ const chunks$ = new Subject();
273
+ let latestContext;
274
+ let history = [];
275
+ let invokeTail = Promise.resolve();
276
+ const context$ = combineInputs([systemPrompt, tools, ctx], ([systemPromptValue, toolList, ec]) => {
277
+ const rolePreset = parseLlmRolePreset(ec.params.rolePreset);
278
+ const skillId = resolveEffectiveSkillId(rolePreset, ec.params.skillId);
279
+ const hostServices = getRunHostServices(ec);
280
+ const skillMarkdown = hostServices?.skillMarkdown ?? '';
281
+ const agentsMarkdown = hostServices?.agentsMarkdown ?? '';
282
+ const name = String(ec.params.name ?? 'Sub-Agent').trim();
283
+ const inspectorDescription = String(ec.params.description ?? '');
284
+ return {
285
+ prompt: '',
286
+ tools: collectAgentToolHandles({
287
+ toolHandles: ec.toolHandles,
288
+ toolsPort: toolList,
289
+ }),
290
+ ...resolveChatProviderModel(ec.params, hostServices),
291
+ skillId,
292
+ rolePreset,
293
+ skillMarkdown,
294
+ agentsMarkdown,
295
+ effectiveSystemPrompt: buildEffectiveSystemPrompt({
296
+ rolePreset,
297
+ systemPromptInput: String(systemPromptValue ?? ''),
298
+ agentsMarkdown,
299
+ skillMarkdown,
300
+ }),
301
+ toolCtx: {
302
+ projectDir: ec.projectDir,
303
+ runId: ec.runId,
304
+ ...(hostServices?.authorize !== undefined
305
+ ? { authorize: hostServices.authorize }
306
+ : {}),
307
+ ...(hostServices?.denyPaths !== undefined
308
+ ? { denyPaths: hostServices.denyPaths }
309
+ : {}),
310
+ ...(hostServices?.allowedHosts !== undefined
311
+ ? { allowedHosts: hostServices.allowedHosts }
312
+ : {}),
313
+ },
314
+ maxIterations: normalizeMaxIterations(ec.params.maxIterations, {
315
+ fallback: DEFAULT_AGENT_MAX_ITERATIONS,
316
+ maxCap: AGENT_MAX_ITERATIONS_CAP,
317
+ }),
318
+ maxFeedbackTurns: 0,
319
+ ...(hostServices?.requestPermission !== undefined
320
+ ? {
321
+ requestPermission: hostServices.requestPermission,
322
+ }
323
+ : {}),
324
+ compaction: normalizeCompactionConfig(ec.params),
325
+ recovery: normalizeLlmRecoveryPolicy(ec.params),
326
+ steerControl$: steerControl.value$.pipe(filter(isSteerControlPayload)),
327
+ factory: hostServices?.createChatCompletionStream,
328
+ scriptedTurns: parseScriptedTurns(ec.params['scriptedToolTurns']),
329
+ nodeId: ec.nodeId,
330
+ displayName: name.length > 0 ? name : 'Sub-Agent',
331
+ inspectorDescription,
332
+ skillIds: normalizeSkillIds(ec.params.skillIds),
333
+ };
334
+ });
335
+ // Inner chunks stay values. `statefulObservable({ input: chunks$ })`
336
+ // re-emits loading on every token; pipeValue fans it to all demux ports.
337
+ const cycle$ = context$.pipeValue(switchMap(() => chunks$));
338
+ const enqueueInvoke = (announced, args, _toolCtx) => {
339
+ const context = latestContext ?? announced;
340
+ const parsed = parseInvokeTurn({ ...args, requestId: randomUUID() }, announced.skillIds);
341
+ if (!parsed.ok) {
342
+ return Promise.resolve(parsed.text);
343
+ }
344
+ const run = () => {
345
+ history = seedInvokeHistory(history, context);
346
+ const timeoutMs = context.recovery.subagentTimeoutMs;
347
+ let done$ = runSubAgentTurn(context, parsed.turn, history).pipe(tap((chunk) => {
348
+ history = reduceInvokeHistory(history, chunk);
349
+ chunks$.next(chunk);
350
+ }), filter((chunk) => chunk.kind === 'invokeDone'), map((chunk) => chunk.text), take(1));
351
+ if (timeoutMs > 0) {
352
+ done$ = done$.pipe(timeout({ first: timeoutMs }), catchError((error) => of(error instanceof TimeoutError
353
+ ? `Error: Sub-Agent timed out after ${timeoutMs}ms.`
354
+ : error instanceof Error
355
+ ? `Error: ${error.message}`
356
+ : 'Error: Sub-Agent turn failed.')));
357
+ }
358
+ return firstValueFrom(done$, {
359
+ defaultValue: EMPTY_INVOKE_RESULT,
360
+ });
361
+ };
362
+ const next = invokeTail.then(run, run);
363
+ invokeTail = next.then(() => undefined, () => undefined);
364
+ return next;
365
+ };
366
+ const specialistTools$ = context$.pipeValue(tap((context) => {
367
+ latestContext = context;
368
+ }), map((context) => {
369
+ const handleName = formatSpecialistHandleName(context.displayName);
370
+ return [
371
+ {
372
+ toolId: slugToolId(handleName, context.nodeId),
373
+ name: handleName,
374
+ description: buildSpecialistDescription(handleName, context.inspectorDescription, context.skillIds),
375
+ inputSchema: buildSpecialistInputSchema(context.skillIds),
376
+ invoke: (args, toolCtx) => enqueueInvoke(context, args, toolCtx),
377
+ },
378
+ ];
379
+ }));
380
+ const reasoning$ = cycle$.pipeValue(demuxByKind('reasoning', (chunk) => chunk
381
+ .text));
382
+ const draftResponse$ = cycle$.pipeValue(demuxByKind('draftResponse', (chunk) => chunk
383
+ .text));
384
+ const toolLog$ = cycle$.pipeValue(demuxByKind('toolLog', (chunk) => chunk.text));
385
+ const recovery$ = cycle$.pipeValue(demuxByKind('recoveryNotice', (chunk) => {
386
+ const notice = chunk;
387
+ return toLlmRecoveryPortValue(notice);
388
+ }));
389
+ const response$ = cycle$.pipeValue(demuxByKind('response', (chunk) => chunk
390
+ .text));
391
+ return {
392
+ inputs: [systemPrompt],
393
+ outputs: [
394
+ configureOutput('subagent-registration', specialistTools$, {
395
+ name: 'subagent-registration',
396
+ wireType: TOOL_HANDLE_WIRE_TYPE,
397
+ }),
398
+ configureOutput('reasoning', reasoning$, {
399
+ wireType: 'string',
400
+ feed: { role: 'reasoning', streaming: true },
401
+ }),
402
+ configureOutput('draftResponse', draftResponse$, {
403
+ wireType: 'string',
404
+ feed: { role: 'draft', streaming: true },
405
+ }),
406
+ configureOutput('response', response$, {
407
+ wireType: 'string',
408
+ feed: { role: 'result' },
409
+ }),
410
+ ],
411
+ inventoryOutputs: {
412
+ toolLog$,
413
+ recovery$,
414
+ },
415
+ };
416
+ },
417
+ });
@@ -124,6 +124,12 @@ export const createChatCompletionStream = (deps) => {
124
124
  messages: toOpenAiMessages(args.messages),
125
125
  stream: true,
126
126
  ...(tools !== undefined ? { tools } : {}),
127
+ ...(args.frequency_penalty !== undefined
128
+ ? { frequency_penalty: args.frequency_penalty }
129
+ : {}),
130
+ ...(args.presence_penalty !== undefined
131
+ ? { presence_penalty: args.presence_penalty }
132
+ : {}),
127
133
  }, {
128
134
  signal: args.signal,
129
135
  }));
@@ -25,4 +25,6 @@ export declare const prepareChatCompletion: (args: {
25
25
  readonly tools?: readonly ChatCompletionToolDefinition[];
26
26
  readonly signal?: AbortSignal;
27
27
  readonly compaction?: LlmCompactionConfig;
28
+ readonly frequency_penalty?: number;
29
+ readonly presence_penalty?: number;
28
30
  }) => Promise<PreparedChatCompletion>;
@@ -7,6 +7,12 @@ const createMainStream = async (args) => args.factory({
7
7
  messages: args.messages,
8
8
  ...(args.tools.length > 0 ? { tools: args.tools } : {}),
9
9
  ...(args.signal !== undefined ? { signal: args.signal } : {}),
10
+ ...(args.frequency_penalty !== undefined
11
+ ? { frequency_penalty: args.frequency_penalty }
12
+ : {}),
13
+ ...(args.presence_penalty !== undefined
14
+ ? { presence_penalty: args.presence_penalty }
15
+ : {}),
10
16
  });
11
17
  /**
12
18
  * Proactive + compact-on-error gate before consuming a chat stream.
@@ -49,6 +55,12 @@ export const prepareChatCompletion = async (args) => {
49
55
  messages,
50
56
  tools,
51
57
  ...(args.signal !== undefined ? { signal: args.signal } : {}),
58
+ ...(args.frequency_penalty !== undefined
59
+ ? { frequency_penalty: args.frequency_penalty }
60
+ : {}),
61
+ ...(args.presence_penalty !== undefined
62
+ ? { presence_penalty: args.presence_penalty }
63
+ : {}),
52
64
  });
53
65
  return {
54
66
  ok: true,
@@ -96,6 +108,12 @@ export const prepareChatCompletion = async (args) => {
96
108
  messages,
97
109
  tools,
98
110
  ...(args.signal !== undefined ? { signal: args.signal } : {}),
111
+ ...(args.frequency_penalty !== undefined
112
+ ? { frequency_penalty: args.frequency_penalty }
113
+ : {}),
114
+ ...(args.presence_penalty !== undefined
115
+ ? { presence_penalty: args.presence_penalty }
116
+ : {}),
99
117
  });
100
118
  return {
101
119
  ok: true,