langflower 0.1.3 → 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.
- package/README.md +567 -129
- package/dist/{chunk-WV2YWHOC.js → chunk-26UB55E5.js} +44 -4
- package/dist/{chunk-AO33IM2J.js → chunk-2LE3E2QP.js} +24 -23
- package/dist/{chunk-NIRPHJLO.js → chunk-3Z7Q6SQ5.js} +501 -242
- package/dist/{chunk-CVTPGIZE.js → chunk-RZUZX6PW.js} +2 -4
- package/dist/index.js +43935 -44199
- package/docs/public/extending.md +21 -3
- package/docs/public/getting-started.md +2 -1
- package/docs/public/how-it-works.md +2 -2
- package/docs/public/launcher.md +13 -12
- package/package.json +1 -1
- package/ui-dist/{chunk-EZTB7Q33.js → chunk-HEF6F5HN.js} +3 -3
- package/ui-dist/{chunk-BKIP5WRK.js → chunk-IASSR2ON.js} +1 -1
- package/ui-dist/index.html +2 -2
- package/ui-dist/main-NBS6BFBP.js +323 -0
- package/ui-dist/styles-M2URERWI.css +1 -0
- package/vendor/node-sdk/dist/node-factory/define-llm-node/default-llm-ports.js +1 -1
- package/vendor/node-sdk/dist/node-factory/define-llm-node/define-llm-node.d.ts +9 -21
- package/vendor/node-sdk/dist/node-factory/define-llm-node/define-llm-node.js +9 -3
- package/vendor/node-sdk/dist/node-factory/define-llm-node/recovery-notice.d.ts +0 -1
- package/vendor/node-sdk/dist/node-factory/define-llm-node/recovery-notice.js +0 -9
- package/vendor/node-sdk/dist/node-factory/define-node/define-node.d.ts +5 -1
- package/vendor/node-sdk/dist/node-factory/define-node/define-node.js +6 -3
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/capabilities.d.ts +128 -0
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/capabilities.js +25 -0
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/define-reactive-node.d.ts +29 -17
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/define-reactive-node.js +14 -6
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/io-helpers.d.ts +19 -5
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/io-helpers.js +4 -3
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/port-meta.d.ts +6 -1
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/types.d.ts +40 -22
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/types.js +2 -0
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/ui-schema-inference.d.ts +1 -1
- package/vendor/node-sdk/dist/node-factory/define-tool-registrations/define-tool-registrations.d.ts +13 -25
- package/vendor/node-sdk/dist/node-factory/define-tool-registrations/define-tool-registrations.js +9 -8
- package/vendor/node-sdk/dist/testing/create-node-harness.d.ts +9 -2
- package/vendor/node-sdk/dist/testing/create-node-harness.js +6 -2
- package/vendor/node-sdk/package.json +5 -0
- package/vendor/runtime/dist/bypass-ports.d.ts +0 -6
- package/vendor/runtime/dist/bypass-ports.js +0 -7
- package/vendor/runtime/dist/runtime-editor.d.ts +1 -1
- package/vendor/runtime/dist/runtime-editor.js +1 -1
- package/vendor/runtime/dist/runtime-helpers.d.ts +0 -1
- package/vendor/runtime/dist/runtime-helpers.js +0 -33
- package/vendor/runtime/dist/runtime-runner.d.ts +4 -0
- package/vendor/runtime/dist/runtime-runner.js +60 -36
- package/vendor/runtime/dist/runtime.d.ts +0 -1
- package/vendor/runtime/dist/runtime.js +0 -1
- package/vendor/runtime/dist/types.d.ts +27 -17
- package/vendor/server/skeleton/instructions.md +6 -0
- package/vendor/server/skeleton/nodes/my-nodes/README.md +19 -1
- package/vendor/server/skeleton/schemas/langflower-config.schema.json +1 -1
- package/vendor/server/skeleton/skills/langflower-helper/SKILL.md +35 -12
- package/vendor/server/skeleton/skills/langflower-helper/layout.md +6 -4
- package/vendor/server/skeleton/skills/langflower-node-writer/SKILL.md +47 -3
- package/vendor/server/skeleton/skills/langflower-workflow-writer/SKILL.md +29 -17
- package/vendor/server/skeleton/workflows/advanced-coder.json +24 -2
- package/vendor/server/skeleton/workflows/kb-create.json +24 -16
- package/vendor/server/skeleton/workflows/kb-manual-search.json +1 -1
- package/vendor/server/skeleton/workflows/kb-navigate.json +24 -2
- package/vendor/server/skeleton/workflows/kb-rag.json +1 -0
- package/vendor/server/skeleton/workflows/simple-coder.json +3 -0
- package/vendor/server/skeleton/workflows/starter.json +2 -0
- package/ui-dist/main-JJURZFKA.js +0 -318
- package/ui-dist/styles-VA3HMZK7.css +0 -1
- package/vendor/node-sdk/dist/node-factory/define-llm-node/llm-inventory-wire.d.ts +0 -5
- package/vendor/node-sdk/dist/node-factory/define-llm-node/llm-inventory-wire.js +0 -5
- package/vendor/node-sdk/dist/node-factory/define-llm-node/llm.d.ts +0 -3
- package/vendor/node-sdk/dist/node-factory/define-llm-node/llm.js +0 -2
- package/vendor/node-sdk/dist/node-factory/define-mcp/define-mcp.d.ts +0 -50
- package/vendor/node-sdk/dist/node-factory/define-mcp/define-mcp.js +0 -60
- package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-handle.d.ts +0 -15
- package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-handle.js +0 -2
- package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-server-config.d.ts +0 -17
- package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-server-config.js +0 -2
- package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-transport.d.ts +0 -20
- package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-transport.js +0 -2
- package/vendor/node-sdk/dist/node-factory/define-mcp/mcp.d.ts +0 -3
- package/vendor/node-sdk/dist/node-factory/define-mcp/mcp.js +0 -2
- package/vendor/node-sdk/dist/node-factory/define-node/test/samples/gate-node.d.ts +0 -20
- package/vendor/node-sdk/dist/node-factory/define-node/test/samples/gate-node.js +0 -22
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/chat-completion-stream.d.ts +0 -50
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/chat-completion-stream.js +0 -2
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/crawl-context.d.ts +0 -22
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/crawl-context.js +0 -2
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/create-embedding.d.ts +0 -6
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/create-embedding.js +0 -2
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/define-tool-registrations.d.ts +0 -52
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/define-tool-registrations.js +0 -52
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/kb-context.d.ts +0 -111
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/kb-context.js +0 -2
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/memory-context.d.ts +0 -12
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/memory-context.js +0 -2
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/project-files-context.d.ts +0 -10
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/project-files-context.js +0 -2
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/project-harness.d.ts +0 -56
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/project-harness.js +0 -2
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/agent-node.d.ts +0 -29
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/agent-node.js +0 -60
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/combine-node.d.ts +0 -29
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/combine-node.js +0 -26
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/constant-node.d.ts +0 -29
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/constant-node.js +0 -21
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/delay-node.d.ts +0 -29
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/delay-node.js +0 -27
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/finish-node.d.ts +0 -17
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/finish-node.js +0 -21
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/hitl-node.d.ts +0 -21
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/hitl-node.js +0 -43
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/join-node.d.ts +0 -29
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/join-node.js +0 -31
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/preview-node.d.ts +0 -17
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/preview-node.js +0 -19
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/router-node.d.ts +0 -18
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/router-node.js +0 -12
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/tool-registration.d.ts +0 -36
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/tool-registration.js +0 -2
- package/vendor/node-sdk/dist/node-factory/define-tool-registrations/tool-registration.d.ts +0 -46
- package/vendor/node-sdk/dist/node-factory/define-tool-registrations/tool-registration.js +0 -2
|
@@ -4,7 +4,7 @@ import type { StatefulObservable } from '@rx-evo/stateful-observable';
|
|
|
4
4
|
*
|
|
5
5
|
* Intentionally owned here (not imported from `@langflower/runtime`) so custom
|
|
6
6
|
* node packs peer only on `@langflower/node-sdk` (+ rxjs /
|
|
7
|
-
* stateful-observable). See [ADR-027](../../../../docs/ADR.md#adr-027--author-sdk-owns-port-types-no-production-runtime-dep).
|
|
7
|
+
* stateful-observable). See [ADR-027](../../../../docs/architecture/ADR.md#adr-027--author-sdk-owns-port-types-no-production-runtime-dep).
|
|
8
8
|
* Structural parity with runtime is locked by `runtime-parity.types.test.ts`.
|
|
9
9
|
*/
|
|
10
10
|
/** Same brand as runtime `RuntimeWireType` so bypass maps stay assignable. */
|
|
@@ -36,6 +36,11 @@ export type FeedRole = 'none' | 'reasoning' | 'progress' | 'draft' | 'tool' | 's
|
|
|
36
36
|
export type FeedPortMeta = {
|
|
37
37
|
readonly role?: FeedRole;
|
|
38
38
|
readonly streaming?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Runtime stamps this from the node-level `feedVisitBoundary` flag.
|
|
41
|
+
* Authors set `feedVisitBoundary` on the definition, not this field.
|
|
42
|
+
*/
|
|
43
|
+
readonly closesPreviousVisit?: true;
|
|
39
44
|
};
|
|
40
45
|
/**
|
|
41
46
|
* Typed metadata on every `statefulConnection` / `statefulObservable` `meta`.
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import type { combineStatefulObservables, StatefulConnection, StatefulObservable } from '@rx-evo/stateful-observable';
|
|
2
|
+
import type { CapsFor, LlmRequiredCapabilityId, NodeCapabilityId } from './capabilities.js';
|
|
2
3
|
import type { ResolveSecret } from './resolve-secret.js';
|
|
3
|
-
import type { ToolHandle } from '../define-tool-registrations/tool-handle.js';
|
|
4
4
|
import type { CtxError } from './ctx-error.js';
|
|
5
5
|
import { configureOutput, InputConfig, makeInput, OutputConfig } from './io-helpers.js';
|
|
6
6
|
import type { PortMeta, WireType } from './port-meta.js';
|
|
7
|
-
import type { AssertConstUISchema, ParamsFromUISchema,
|
|
8
|
-
|
|
9
|
-
* Identity + panel + keyed secret lookup. Host I/O (files/kb/crawl/…) is
|
|
10
|
-
* owned by specialized common-nodes internally — not part of the author
|
|
11
|
-
* ExecutionContext API. LLM inventory arrives via {@link LlmExecutionCaps}
|
|
12
|
-
* (`toolHandles`). {@link resolveSecret} looks up one id (`lf_secret:ID` /
|
|
13
|
-
* `env:ID`); authors cannot list the bag.
|
|
14
|
-
*/
|
|
15
|
-
export type ExecutionContext<UI extends readonly UISchemaConstItem[] = readonly UISchemaConstItem[], Caps extends object = Record<string, never>> = {
|
|
7
|
+
import type { AssertConstUISchema, ParamsFromUISchema, UISchemaConstItem } from './ui-schema-inference.js';
|
|
8
|
+
type ExecutionContextHostFields<UI extends readonly UISchemaConstItem[] = readonly UISchemaConstItem[]> = {
|
|
16
9
|
readonly projectDir: string;
|
|
17
10
|
readonly runId: string;
|
|
18
11
|
readonly nodeId: string;
|
|
19
12
|
readonly params: ParamsFromUISchema<UI>;
|
|
20
|
-
readonly uiSchema:
|
|
13
|
+
readonly uiSchema: UI;
|
|
21
14
|
readonly resolveSecret: ResolveSecret;
|
|
22
|
-
readonly amendInput?: (patch: Readonly<Record<string, unknown>>) => void;
|
|
23
|
-
} & Caps;
|
|
24
|
-
/** Caps for {@link defineLlmNode} — outside world via ToolHandle only. */
|
|
25
|
-
export type LlmExecutionCaps = {
|
|
26
|
-
readonly toolHandles?: readonly ToolHandle[];
|
|
27
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* Identity + panel + keyed secret lookup. Host I/O (files/kb/crawl/…) is
|
|
18
|
+
* owned by specialized common-nodes internally — not part of the author
|
|
19
|
+
* ExecutionContext API. Declared capabilities arrive via {@link CapsFor}
|
|
20
|
+
* (`requires` on the definition). {@link resolveSecret} looks up one id
|
|
21
|
+
* (`lf_secret:ID` / `env:ID`); authors cannot list the bag.
|
|
22
|
+
* Do not restore `amendInput` or other host-mutation / I/O fields here —
|
|
23
|
+
* keyed by `assertExecutionContextHostKeys` below.
|
|
24
|
+
*/
|
|
25
|
+
export type ExecutionContext<UI extends readonly UISchemaConstItem[] = readonly UISchemaConstItem[], Caps extends object = Record<string, never>> = ExecutionContextHostFields<UI> & Caps;
|
|
26
|
+
/** Caps for {@link defineLlmNode} — LLM set from {@link CapsFor}. */
|
|
27
|
+
export type LlmExecutionCaps = CapsFor<readonly LlmRequiredCapabilityId[]>;
|
|
28
28
|
type ReactiveNodeBindResult = {
|
|
29
29
|
readonly inputs: InputConfig[];
|
|
30
30
|
readonly outputs: OutputConfig[];
|
|
@@ -33,8 +33,9 @@ type ReactiveNodeBindResult = {
|
|
|
33
33
|
export type DefinedReactiveNodeConfig<UI extends readonly UISchemaConstItem[] = readonly UISchemaConstItem[], Caps extends object = Record<string, never>> = {
|
|
34
34
|
/**
|
|
35
35
|
* Stable catalog / persisted workflow id (`WorkflowNodePersisted.type`).
|
|
36
|
-
* Server resolves the definition with
|
|
37
|
-
* keys the common-nodes
|
|
36
|
+
* Server resolves the definition with
|
|
37
|
+
* `resolveDefinition({ type, params })` and keys the common-nodes
|
|
38
|
+
* catalog by `type`.
|
|
38
39
|
*/
|
|
39
40
|
readonly type: string;
|
|
40
41
|
/**
|
|
@@ -63,10 +64,21 @@ export type DefinedReactiveNodeConfig<UI extends readonly UISchemaConstItem[] =
|
|
|
63
64
|
*/
|
|
64
65
|
readonly description?: string;
|
|
65
66
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
67
|
+
* Canvas box used when the node has no persisted width: the editor locks
|
|
68
|
+
* both axes instead of auto-sizing, so payload cannot grow the node.
|
|
69
|
+
* Omitted → canvas auto-sizes. Persisted operator resize always wins.
|
|
70
|
+
*/
|
|
71
|
+
readonly defaultCanvasSize?: {
|
|
72
|
+
readonly width: number;
|
|
73
|
+
readonly height: number;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* When `true`, the first work-log frame from this node **closes the
|
|
77
|
+
* previous visit**, so a delegating node gets its own feed card instead of
|
|
78
|
+
* continuing the caller's. Omitted/`false` → frames follow the normal
|
|
79
|
+
* `feed.streaming` visit rules. Used by `common-sub-agent`.
|
|
68
80
|
*/
|
|
69
|
-
readonly
|
|
81
|
+
readonly feedVisitBoundary?: boolean;
|
|
70
82
|
/**
|
|
71
83
|
* When `true` on the live instance, the first **value** emission on any
|
|
72
84
|
* watched output schedules `RuntimeRunner.finishRun` (`done` → `idle`).
|
|
@@ -87,6 +99,12 @@ export type DefinedReactiveNodeConfig<UI extends readonly UISchemaConstItem[] =
|
|
|
87
99
|
* `false`. Used by `common-chat-input`.
|
|
88
100
|
*/
|
|
89
101
|
readonly chatEntry?: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Host capabilities this node needs. Copied onto
|
|
104
|
+
* {@link ReactiveNodeDefinition.requires} (default `[]`). `bind` sees
|
|
105
|
+
* {@link CapsFor} fields as non-optional.
|
|
106
|
+
*/
|
|
107
|
+
readonly requires?: readonly NodeCapabilityId[];
|
|
90
108
|
/**
|
|
91
109
|
* Router bypass base port id → wire type. Runtime materializes each key
|
|
92
110
|
* as a multi-input base; channel outputs (`ch`, `ch@1`, …) are slot views
|
|
@@ -122,8 +140,8 @@ export type ReactiveNodeInstance<UI extends readonly UISchemaConstItem[] = reado
|
|
|
122
140
|
readonly bypassPorts: Record<string, WireType>;
|
|
123
141
|
readonly stopsRun?: boolean;
|
|
124
142
|
readonly chatEntry?: boolean;
|
|
143
|
+
readonly feedVisitBoundary?: boolean;
|
|
125
144
|
readonly emitOncePerActivation?: boolean;
|
|
126
|
-
readonly skipExecutionTelemetry?: boolean;
|
|
127
145
|
readonly ctxConnection: StatefulConnection<ExecutionContext<UI, Caps>, CtxError, PortMeta>;
|
|
128
146
|
};
|
|
129
147
|
export {};
|
|
@@ -5,7 +5,7 @@ export type UISchemaConstItem = {
|
|
|
5
5
|
readonly type: string;
|
|
6
6
|
readonly label?: string;
|
|
7
7
|
readonly default?: unknown;
|
|
8
|
-
readonly placement?: 'panel'
|
|
8
|
+
readonly placement?: 'panel';
|
|
9
9
|
/** Number field constraints — same semantics as canvas inline `{ type: 'number' }`. */
|
|
10
10
|
readonly min?: number;
|
|
11
11
|
readonly max?: number;
|
package/vendor/node-sdk/dist/node-factory/define-tool-registrations/define-tool-registrations.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import { type ToolHandler } from './tool-handle.js';
|
|
1
|
+
import { type ToolHandle, type ToolHandler } from './tool-handle.js';
|
|
2
|
+
type RegistrationTool = {
|
|
3
|
+
readonly toolId: string;
|
|
4
|
+
readonly name?: string;
|
|
5
|
+
readonly description: string;
|
|
6
|
+
readonly inputSchema: object;
|
|
7
|
+
readonly handler: ToolHandler;
|
|
8
|
+
};
|
|
9
|
+
/** Map domain registrations onto wire {@link ToolHandle}s. */
|
|
10
|
+
export declare const toToolHandles: (tools: readonly RegistrationTool[]) => readonly ToolHandle[];
|
|
2
11
|
/**
|
|
3
12
|
* Purpose utility atop {@link defineReactiveNode}: emit a `tools` pack as
|
|
4
13
|
* {@link ToolHandle}[]. Config still takes domain `handler`s; factory maps
|
|
@@ -21,27 +30,6 @@ export declare const defineToolRegistrations: (config: {
|
|
|
21
30
|
readonly displayName: string;
|
|
22
31
|
readonly category?: string;
|
|
23
32
|
readonly description?: string;
|
|
24
|
-
readonly
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
readonly name?: string;
|
|
28
|
-
readonly description: string;
|
|
29
|
-
readonly inputSchema: object;
|
|
30
|
-
readonly handler: ToolHandler;
|
|
31
|
-
}[];
|
|
32
|
-
}) => {
|
|
33
|
-
readonly emitOncePerActivation: boolean;
|
|
34
|
-
readonly stopsRun: boolean;
|
|
35
|
-
readonly chatEntry: boolean;
|
|
36
|
-
readonly uiSchema: readonly [];
|
|
37
|
-
readonly bypassPorts: Record<string, import("../define-reactive-node/port-meta.js").WireType>;
|
|
38
|
-
readonly inputsConfigs: readonly [import("../define-reactive-node/io-helpers.js").InputPortMeta<import("../define-reactive-node/types.js").ExecutionContext<readonly [], Record<string, never>>>, ...import("../define-reactive-node/io-helpers.js").InputPortMeta<unknown>[]];
|
|
39
|
-
readonly outputsConfigs: (import("../define-reactive-node/io-helpers.js").OutputParams & import("../define-reactive-node/port-meta.js").PortMeta)[];
|
|
40
|
-
readonly getInstance: () => import("../define-reactive-node/types.js").ReactiveNodeInstance<readonly [], Record<string, never>>;
|
|
41
|
-
readonly paletteSecondary?: true;
|
|
42
|
-
readonly description?: string;
|
|
43
|
-
readonly type: string;
|
|
44
|
-
readonly displayName: string;
|
|
45
|
-
readonly category: string | undefined;
|
|
46
|
-
readonly icon: string | undefined;
|
|
47
|
-
};
|
|
33
|
+
readonly tools: readonly RegistrationTool[];
|
|
34
|
+
}) => import("../define-reactive-node/define-reactive-node.js").ReactiveNodeDefinition;
|
|
35
|
+
export {};
|
package/vendor/node-sdk/dist/node-factory/define-tool-registrations/define-tool-registrations.js
CHANGED
|
@@ -2,6 +2,14 @@ import { statefulObservable } from '@rx-evo/stateful-observable';
|
|
|
2
2
|
import { of } from 'rxjs';
|
|
3
3
|
import { defineReactiveNode } from '../define-reactive-node/define-reactive-node.js';
|
|
4
4
|
import { TOOL_HANDLE_WIRE_TYPE, } from './tool-handle.js';
|
|
5
|
+
/** Map domain registrations onto wire {@link ToolHandle}s. */
|
|
6
|
+
export const toToolHandles = (tools) => tools.map((tool) => ({
|
|
7
|
+
toolId: tool.toolId,
|
|
8
|
+
name: tool.name ?? tool.toolId,
|
|
9
|
+
description: tool.description,
|
|
10
|
+
inputSchema: tool.inputSchema,
|
|
11
|
+
invoke: tool.handler,
|
|
12
|
+
}));
|
|
5
13
|
/**
|
|
6
14
|
* Purpose utility atop {@link defineReactiveNode}: emit a `tools` pack as
|
|
7
15
|
* {@link ToolHandle}[]. Config still takes domain `handler`s; factory maps
|
|
@@ -26,17 +34,10 @@ export const defineToolRegistrations = (config) => defineReactiveNode({
|
|
|
26
34
|
...(config.description !== undefined
|
|
27
35
|
? { description: config.description }
|
|
28
36
|
: {}),
|
|
29
|
-
...(config.icon !== undefined ? { icon: config.icon } : {}),
|
|
30
37
|
uiSchema: [],
|
|
31
38
|
bind(_ctx, { configureOutput }) {
|
|
32
39
|
const tools$ = statefulObservable({
|
|
33
|
-
loader: () => of(config.tools
|
|
34
|
-
toolId: tool.toolId,
|
|
35
|
-
name: tool.name ?? tool.toolId,
|
|
36
|
-
description: tool.description,
|
|
37
|
-
inputSchema: tool.inputSchema,
|
|
38
|
-
invoke: tool.handler,
|
|
39
|
-
}))),
|
|
40
|
+
loader: () => of(toToolHandles(config.tools)),
|
|
40
41
|
});
|
|
41
42
|
return {
|
|
42
43
|
inputs: [],
|
|
@@ -2,7 +2,7 @@ import type { ReactiveNodeDefinition, ReactiveNodeInstance } from '../node-facto
|
|
|
2
2
|
import { type UISchemaConstItem } from '../node-factory/define-reactive-node/ui-schema-inference.js';
|
|
3
3
|
type HarnessUi = readonly UISchemaConstItem[];
|
|
4
4
|
type HarnessInstance = ReactiveNodeInstance<HarnessUi, object>;
|
|
5
|
-
|
|
5
|
+
type NodeHarnessBaseOptions = {
|
|
6
6
|
readonly projectDir?: string;
|
|
7
7
|
readonly runId?: string;
|
|
8
8
|
readonly nodeId?: string;
|
|
@@ -12,6 +12,13 @@ export type NodeHarnessOptions = {
|
|
|
12
12
|
/** Env map for `env:ID`. Omitted → `process.env`. */
|
|
13
13
|
readonly env?: Readonly<Record<string, string | undefined>>;
|
|
14
14
|
};
|
|
15
|
+
export type NodeHarnessOptions<Caps extends object = Record<string, never>> = [
|
|
16
|
+
keyof Caps
|
|
17
|
+
] extends [never] ? NodeHarnessBaseOptions & {
|
|
18
|
+
readonly caps?: Caps;
|
|
19
|
+
} : NodeHarnessBaseOptions & {
|
|
20
|
+
readonly caps: Caps;
|
|
21
|
+
};
|
|
15
22
|
export type CollectedPort<T> = {
|
|
16
23
|
readonly values: readonly T[];
|
|
17
24
|
readonly stop: () => void;
|
|
@@ -30,5 +37,5 @@ export type NodeHarness = {
|
|
|
30
37
|
* Subscribe with `next` or `collect` **before** `send` when the graph can
|
|
31
38
|
* emit synchronously.
|
|
32
39
|
*/
|
|
33
|
-
export declare const createNodeHarness: (definition: Pick<ReactiveNodeDefinition, "getInstance" | "uiSchema">, options?: NodeHarnessOptions) => NodeHarness;
|
|
40
|
+
export declare const createNodeHarness: <Caps extends object = Record<string, never>>(definition: Pick<ReactiveNodeDefinition, "getInstance" | "uiSchema">, options?: NodeHarnessOptions<Caps>) => NodeHarness;
|
|
34
41
|
export {};
|
|
@@ -17,7 +17,7 @@ export const createNodeHarness = (definition, options) => {
|
|
|
17
17
|
...defaultParamsFromUiSchema(uiSchema),
|
|
18
18
|
...options?.params,
|
|
19
19
|
};
|
|
20
|
-
|
|
20
|
+
const base = {
|
|
21
21
|
projectDir: options?.projectDir ?? '/tmp',
|
|
22
22
|
runId: options?.runId ?? 'test',
|
|
23
23
|
nodeId: options?.nodeId ?? 'node-1',
|
|
@@ -27,7 +27,11 @@ export const createNodeHarness = (definition, options) => {
|
|
|
27
27
|
secrets: options?.secrets ?? {},
|
|
28
28
|
...(options?.env !== undefined ? { env: options.env } : {}),
|
|
29
29
|
}),
|
|
30
|
-
}
|
|
30
|
+
};
|
|
31
|
+
const ctx = options !== undefined && options.caps !== undefined
|
|
32
|
+
? { ...base, ...options.caps }
|
|
33
|
+
: base;
|
|
34
|
+
instance.ctxConnection.connect(of(ctx));
|
|
31
35
|
const send = (portId, value) => {
|
|
32
36
|
const input = instance.inputs[portId];
|
|
33
37
|
if (input === undefined) {
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langflower/node-sdk",
|
|
3
3
|
"version": "0.1.0",
|
|
4
|
+
"description": "Author SDK for Langflower nodes (defineNode / defineReactiveNode)",
|
|
5
|
+
"license": "MIT",
|
|
4
6
|
"type": "module",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
5
10
|
"main": "./dist/node-factory/define-reactive-node/define-reactive-node.js",
|
|
6
11
|
"types": "./dist/node-factory/define-reactive-node/define-reactive-node.d.ts",
|
|
7
12
|
"exports": {
|
|
@@ -16,17 +16,12 @@ export type BypassSlot = {
|
|
|
16
16
|
readonly basePortId: string;
|
|
17
17
|
readonly slotIndex: number;
|
|
18
18
|
};
|
|
19
|
-
/** Edge `fromPort` / `toPort` shape for a bypass slot. */
|
|
20
|
-
export type BypassEdgePort = readonly [basePortId: string, slotIndex: number];
|
|
21
19
|
export declare const bypassSlot: (basePortId: string, slotIndex: number) => BypassSlot;
|
|
22
|
-
export declare const bypassSlotFromEdgePort: (port: readonly [string, number]) => BypassSlot;
|
|
23
|
-
export declare const bypassEdgePort: (slot: BypassSlot) => BypassEdgePort;
|
|
24
20
|
/**
|
|
25
21
|
* Checkpoint / outputs-map / tap key for a bypass slot (`ch`, `ch@1`, …).
|
|
26
22
|
* Resume and telemetry must look up snapshots with this id.
|
|
27
23
|
*/
|
|
28
24
|
export declare const bypassOutputPortId: (basePortId: string, slotIndex: number) => string;
|
|
29
|
-
export declare const bypassOutputPortIdFromSlot: (slot: BypassSlot) => string;
|
|
30
25
|
/** Inverse of {@link bypassOutputPortId}. */
|
|
31
26
|
export declare const parseBypassOutputPortId: (outputPortId: string) => BypassSlot;
|
|
32
27
|
/**
|
|
@@ -34,7 +29,6 @@ export declare const parseBypassOutputPortId: (outputPortId: string) => BypassSl
|
|
|
34
29
|
* materialized `ch@n` output id as the portId segment.
|
|
35
30
|
*/
|
|
36
31
|
export declare const bypassSlotKey: (nodeId: NodeId, basePortId: string, slotIndex: number) => SlotKey;
|
|
37
|
-
export declare const bypassSlotKeyFromEdgePort: (nodeId: NodeId, port: readonly [string, number]) => SlotKey;
|
|
38
32
|
/**
|
|
39
33
|
* Checkpoint / telemetry portId for a slot. Bypass bases use
|
|
40
34
|
* {@link bypassOutputPortId}; regular ports keep `portId` (slot 0).
|
|
@@ -4,17 +4,11 @@ export const bypassSlot = (basePortId, slotIndex) => ({
|
|
|
4
4
|
basePortId,
|
|
5
5
|
slotIndex,
|
|
6
6
|
});
|
|
7
|
-
export const bypassSlotFromEdgePort = (port) => bypassSlot(port[0], port[1]);
|
|
8
|
-
export const bypassEdgePort = (slot) => [
|
|
9
|
-
slot.basePortId,
|
|
10
|
-
slot.slotIndex,
|
|
11
|
-
];
|
|
12
7
|
/**
|
|
13
8
|
* Checkpoint / outputs-map / tap key for a bypass slot (`ch`, `ch@1`, …).
|
|
14
9
|
* Resume and telemetry must look up snapshots with this id.
|
|
15
10
|
*/
|
|
16
11
|
export const bypassOutputPortId = (basePortId, slotIndex) => (slotIndex === 0 ? basePortId : `${basePortId}@${slotIndex}`);
|
|
17
|
-
export const bypassOutputPortIdFromSlot = (slot) => bypassOutputPortId(slot.basePortId, slot.slotIndex);
|
|
18
12
|
/** Inverse of {@link bypassOutputPortId}. */
|
|
19
13
|
export const parseBypassOutputPortId = (outputPortId) => {
|
|
20
14
|
const at = outputPortId.lastIndexOf('@');
|
|
@@ -31,7 +25,6 @@ export const parseBypassOutputPortId = (outputPortId) => {
|
|
|
31
25
|
* materialized `ch@n` output id as the portId segment.
|
|
32
26
|
*/
|
|
33
27
|
export const bypassSlotKey = (nodeId, basePortId, slotIndex) => slotKey(nodeId, basePortId, slotIndex);
|
|
34
|
-
export const bypassSlotKeyFromEdgePort = (nodeId, port) => bypassSlotKey(nodeId, port[0], port[1]);
|
|
35
28
|
/**
|
|
36
29
|
* Checkpoint / telemetry portId for a slot. Bypass bases use
|
|
37
30
|
* {@link bypassOutputPortId}; regular ports keep `portId` (slot 0).
|
|
@@ -34,7 +34,7 @@ export declare class RuntimeEditor implements RuntimeEditorApi {
|
|
|
34
34
|
nodes: RuntimeNode[];
|
|
35
35
|
edges: RuntimeEdge[];
|
|
36
36
|
};
|
|
37
|
-
getClusterByNodeId(nodeId: NodeId): GraphCluster;
|
|
37
|
+
getClusterByNodeId(nodeId: NodeId): GraphCluster | false;
|
|
38
38
|
setLocked(locked: boolean): void;
|
|
39
39
|
dispose(): void;
|
|
40
40
|
private refreshClusters;
|
|
@@ -16,4 +16,3 @@ export declare function detectGraphClusters(nodeIds: Iterable<NodeId>, edges: re
|
|
|
16
16
|
export declare const clusterHasChatEntry: (cluster: GraphCluster, getNode: (nodeId: NodeId) => RuntimeNode | false) => boolean;
|
|
17
17
|
export declare function resolveClusterForNode(clusters: readonly GraphCluster[], nodeId: NodeId): GraphCluster;
|
|
18
18
|
export declare function collectClusterSlotKeys(nodes: ReadonlyMap<NodeId, RuntimeNode>, clusterNodeIds: ReadonlySet<NodeId>): SlotKey[];
|
|
19
|
-
export declare function graphHasCycle(edges: readonly RuntimeEdge[]): boolean;
|
|
@@ -126,36 +126,3 @@ export function collectClusterSlotKeys(nodes, clusterNodeIds) {
|
|
|
126
126
|
}
|
|
127
127
|
return keys;
|
|
128
128
|
}
|
|
129
|
-
export function graphHasCycle(edges) {
|
|
130
|
-
const adjacency = new Map();
|
|
131
|
-
for (const edge of edges) {
|
|
132
|
-
const next = adjacency.get(edge.fromNodeId) ?? [];
|
|
133
|
-
next.push(edge.toNodeId);
|
|
134
|
-
adjacency.set(edge.fromNodeId, next);
|
|
135
|
-
}
|
|
136
|
-
const visited = new Set();
|
|
137
|
-
const stack = new Set();
|
|
138
|
-
const visit = (nodeId) => {
|
|
139
|
-
if (stack.has(nodeId)) {
|
|
140
|
-
return true;
|
|
141
|
-
}
|
|
142
|
-
if (visited.has(nodeId)) {
|
|
143
|
-
return false;
|
|
144
|
-
}
|
|
145
|
-
visited.add(nodeId);
|
|
146
|
-
stack.add(nodeId);
|
|
147
|
-
for (const nextId of adjacency.get(nodeId) ?? []) {
|
|
148
|
-
if (visit(nextId)) {
|
|
149
|
-
return true;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
stack.delete(nodeId);
|
|
153
|
-
return false;
|
|
154
|
-
};
|
|
155
|
-
for (const nodeId of adjacency.keys()) {
|
|
156
|
-
if (visit(nodeId)) {
|
|
157
|
-
return true;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return false;
|
|
161
|
-
}
|
|
@@ -34,6 +34,7 @@ export declare class RuntimeRunner implements RuntimeRunnerApi {
|
|
|
34
34
|
private assertNotDisposed;
|
|
35
35
|
private setStatus;
|
|
36
36
|
private emitRunnerEvent;
|
|
37
|
+
private targetInputFeed;
|
|
37
38
|
private emitPortEvent;
|
|
38
39
|
private canPreparePushedInput;
|
|
39
40
|
private isInputOccupiedByEdge;
|
|
@@ -48,8 +49,11 @@ export declare class RuntimeRunner implements RuntimeRunnerApi {
|
|
|
48
49
|
* subscriber, which is what previously reordered events against downstream
|
|
49
50
|
* `input-received`s. Must still be subscribed/connected somewhere
|
|
50
51
|
* (downstream `connect`, or the end-node driver) to run.
|
|
52
|
+
* `tap` is telemetry only: `stopsRun` completion is a named subscribe
|
|
53
|
+
* after wrap in `wireScope`.
|
|
51
54
|
*/
|
|
52
55
|
private tapOutputPort;
|
|
56
|
+
private scheduleFinishOnSuccessValue;
|
|
53
57
|
/**
|
|
54
58
|
* Returns `source` wrapped with a `tap` that emits `input-received`
|
|
55
59
|
* telemetry for the target `(nodeId, portId, slotIndex)`. Like
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { combineStatefulObservables, serializeResponse, statefulObservable, } from '@rx-evo/stateful-observable';
|
|
2
|
-
import { BehaviorSubject, filter, merge, of, Subject, Subscription, tap, zip, } from 'rxjs';
|
|
2
|
+
import { BehaviorSubject, filter, isObservable, merge, of, Subject, Subscription, tap, zip, } from 'rxjs';
|
|
3
3
|
import { checkpointPortIdForSlot, getBypassConnection, isBypassPort, } from './bypass-ports.js';
|
|
4
4
|
import { normalizePortErrorValue } from './normalize-port-error-value.js';
|
|
5
5
|
import { edgePortSlotKey, parseSlotKey, slotKey, } from './port-meta.js';
|
|
@@ -73,8 +73,10 @@ export class RuntimeRunner {
|
|
|
73
73
|
return this.runScope(scopeNodeIds, scopeEdgeIds, initialPayload, resolvedRunId);
|
|
74
74
|
}
|
|
75
75
|
startNode(nodeId, initialPayload, runId) {
|
|
76
|
-
// Composer: resolve cluster → start scoped run
|
|
77
76
|
const cluster = this.editor.getClusterByNodeId(nodeId);
|
|
77
|
+
if (cluster === false) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
78
80
|
return this.runScope(cluster.nodeIds, cluster.edgeIds, initialPayload, runId);
|
|
79
81
|
}
|
|
80
82
|
resume(options) {
|
|
@@ -128,11 +130,8 @@ export class RuntimeRunner {
|
|
|
128
130
|
this.isInputOccupiedByEdge(cfg.nodeId, cfg.portId)) {
|
|
129
131
|
return false;
|
|
130
132
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
cluster = this.editor.getClusterByNodeId(cfg.nodeId);
|
|
134
|
-
}
|
|
135
|
-
catch {
|
|
133
|
+
const cluster = this.editor.getClusterByNodeId(cfg.nodeId);
|
|
134
|
+
if (cluster === false) {
|
|
136
135
|
return false;
|
|
137
136
|
}
|
|
138
137
|
const runId = this.runScope(cluster.nodeIds, cluster.edgeIds);
|
|
@@ -209,6 +208,10 @@ export class RuntimeRunner {
|
|
|
209
208
|
}
|
|
210
209
|
this.eventsSubject.next(event);
|
|
211
210
|
}
|
|
211
|
+
targetInputFeed = (nodeId, portId) => {
|
|
212
|
+
const node = this.editor.getNode(nodeId);
|
|
213
|
+
return node === false ? undefined : node.inputs[portId]?.meta.feed;
|
|
214
|
+
};
|
|
212
215
|
emitPortEvent(_runId, portDir, nodeId, portId, portIdx, raw, edgeIds, defaultFeed) {
|
|
213
216
|
const dto = toResponseDto(raw);
|
|
214
217
|
if (dto === null) {
|
|
@@ -217,7 +220,12 @@ export class RuntimeRunner {
|
|
|
217
220
|
const response = 'error' in dto
|
|
218
221
|
? { error: normalizePortErrorValue(dto.error) }
|
|
219
222
|
: dto;
|
|
220
|
-
const
|
|
223
|
+
const node = this.editor.getNode(nodeId);
|
|
224
|
+
const closesPreviousVisit = node !== false && node.feedVisitBoundary === true;
|
|
225
|
+
const portFeed = defaultFeed;
|
|
226
|
+
const feed = closesPreviousVisit === true
|
|
227
|
+
? { ...(portFeed ?? {}), closesPreviousVisit: true }
|
|
228
|
+
: (portFeed ?? null);
|
|
221
229
|
const portIdStr = typeof portId === 'string' ? portId : String(portId);
|
|
222
230
|
this.emitRunnerEvent([
|
|
223
231
|
portDir,
|
|
@@ -260,7 +268,7 @@ export class RuntimeRunner {
|
|
|
260
268
|
if (existing !== undefined) {
|
|
261
269
|
// Telemetry before deliver so HITL input-received precedes cascade
|
|
262
270
|
// (output-emitted / downstream input-received) in the event log.
|
|
263
|
-
this.emitPortEvent(run.runId, 'in', cfg.nodeId, cfg.portId, 0, cfg.payload, []);
|
|
271
|
+
this.emitPortEvent(run.runId, 'in', cfg.nodeId, cfg.portId, 0, cfg.payload, [], node.inputs[cfg.portId]?.meta.feed);
|
|
264
272
|
existing.source.next(cfg.payload);
|
|
265
273
|
return run.runId;
|
|
266
274
|
}
|
|
@@ -279,7 +287,7 @@ export class RuntimeRunner {
|
|
|
279
287
|
connection,
|
|
280
288
|
});
|
|
281
289
|
run.pushedInputSources.set(key, { source });
|
|
282
|
-
this.emitPortEvent(run.runId, 'in', cfg.nodeId, cfg.portId, 0, cfg.payload, []);
|
|
290
|
+
this.emitPortEvent(run.runId, 'in', cfg.nodeId, cfg.portId, 0, cfg.payload, [], connection.meta.feed);
|
|
283
291
|
source.next(cfg.payload);
|
|
284
292
|
return run.runId;
|
|
285
293
|
}
|
|
@@ -293,25 +301,16 @@ export class RuntimeRunner {
|
|
|
293
301
|
* subscriber, which is what previously reordered events against downstream
|
|
294
302
|
* `input-received`s. Must still be subscribed/connected somewhere
|
|
295
303
|
* (downstream `connect`, or the end-node driver) to run.
|
|
304
|
+
* `tap` is telemetry only: `stopsRun` completion is a named subscribe
|
|
305
|
+
* after wrap in `wireScope`.
|
|
296
306
|
*/
|
|
297
307
|
tapOutputPort(run, nodeId, portId, output, edgeIds) {
|
|
298
308
|
if (typeof output.meta.portId !== 'string')
|
|
299
309
|
return output;
|
|
300
|
-
const node = this.editor.getNode(nodeId);
|
|
301
310
|
return output
|
|
302
311
|
.pipe(tap({
|
|
303
312
|
next: (response) => {
|
|
304
|
-
|
|
305
|
-
if (emittedValue &&
|
|
306
|
-
node !== false &&
|
|
307
|
-
node.stopsRun === true) {
|
|
308
|
-
const finishRunId = run.runId;
|
|
309
|
-
queueMicrotask(() => {
|
|
310
|
-
if (this.activeRun?.runId === finishRunId) {
|
|
311
|
-
this.finishRun(finishRunId);
|
|
312
|
-
}
|
|
313
|
-
});
|
|
314
|
-
}
|
|
313
|
+
this.emitPortEvent(run.runId, 'out', nodeId, portId, 0, response, edgeIds, output.meta.feed);
|
|
315
314
|
},
|
|
316
315
|
}), filter((response) => {
|
|
317
316
|
const dto = toResponseDto(response);
|
|
@@ -319,6 +318,17 @@ export class RuntimeRunner {
|
|
|
319
318
|
}))
|
|
320
319
|
.with({ meta: output.meta });
|
|
321
320
|
}
|
|
321
|
+
scheduleFinishOnSuccessValue(runId, response) {
|
|
322
|
+
const dto = toResponseDto(response);
|
|
323
|
+
if (dto === null || !('value' in dto)) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
queueMicrotask(() => {
|
|
327
|
+
if (this.activeRun?.runId === runId) {
|
|
328
|
+
this.finishRun(runId);
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
}
|
|
322
332
|
/**
|
|
323
333
|
* Returns `source` wrapped with a `tap` that emits `input-received`
|
|
324
334
|
* telemetry for the target `(nodeId, portId, slotIndex)`. Like
|
|
@@ -331,7 +341,7 @@ export class RuntimeRunner {
|
|
|
331
341
|
return source
|
|
332
342
|
.pipe(tap({
|
|
333
343
|
next: (response) => {
|
|
334
|
-
this.emitPortEvent(run.runId, 'in', nodeId, portId, slotIndex, response, edgeIds);
|
|
344
|
+
this.emitPortEvent(run.runId, 'in', nodeId, portId, slotIndex, response, edgeIds, this.targetInputFeed(nodeId, portId));
|
|
335
345
|
},
|
|
336
346
|
}))
|
|
337
347
|
.with({ meta: source.meta });
|
|
@@ -408,7 +418,7 @@ export class RuntimeRunner {
|
|
|
408
418
|
this.flushPendingWire();
|
|
409
419
|
}
|
|
410
420
|
catch {
|
|
411
|
-
|
|
421
|
+
this.eventsSubject.next(['done', resolvedRunId]);
|
|
412
422
|
}
|
|
413
423
|
});
|
|
414
424
|
return resolvedRunId;
|
|
@@ -451,10 +461,13 @@ export class RuntimeRunner {
|
|
|
451
461
|
(meta.mode === 'single' && seed.slotIndex !== 0)) {
|
|
452
462
|
throw new Error(`Unknown seed slot ${nodeId}.${String(seed.portId)}[${seed.slotIndex}]`);
|
|
453
463
|
}
|
|
454
|
-
|
|
464
|
+
const source$ = isObservable(seed.value)
|
|
465
|
+
? seed.value
|
|
466
|
+
: of(seed.value);
|
|
467
|
+
connection.connect(source$.pipe(tap({
|
|
455
468
|
next: (value) => {
|
|
456
469
|
if (typeof seed.portId !== 'symbol') {
|
|
457
|
-
this.emitPortEvent(runId, 'in', nodeId, seed.portId, seed.slotIndex, value, []);
|
|
470
|
+
this.emitPortEvent(runId, 'in', nodeId, seed.portId, seed.slotIndex, value, [], connection.meta.feed);
|
|
458
471
|
}
|
|
459
472
|
},
|
|
460
473
|
})));
|
|
@@ -492,7 +505,7 @@ export class RuntimeRunner {
|
|
|
492
505
|
}
|
|
493
506
|
connection.connect(of(defaultValue).pipe(tap({
|
|
494
507
|
next: (value) => {
|
|
495
|
-
this.emitPortEvent(runId, 'in', nodeId, portId, 0, value, []);
|
|
508
|
+
this.emitPortEvent(runId, 'in', nodeId, portId, 0, value, [], connection.meta.feed);
|
|
496
509
|
},
|
|
497
510
|
})));
|
|
498
511
|
wiredSlotKeys.add(key);
|
|
@@ -726,7 +739,7 @@ export class RuntimeRunner {
|
|
|
726
739
|
}).with({ meta });
|
|
727
740
|
group.connection.connect(combined.pipe(tap({
|
|
728
741
|
next: (response) => {
|
|
729
|
-
this.emitPortEvent(run.runId, 'in', group.nodeId, group.portId, 0, response, group.edges.map((entry) => entry.edge.edgeId));
|
|
742
|
+
this.emitPortEvent(run.runId, 'in', group.nodeId, group.portId, 0, response, group.edges.map((entry) => entry.edge.edgeId), group.connection.meta.feed);
|
|
730
743
|
},
|
|
731
744
|
})));
|
|
732
745
|
wiredSlots.push({
|
|
@@ -734,18 +747,29 @@ export class RuntimeRunner {
|
|
|
734
747
|
connection: group.connection,
|
|
735
748
|
});
|
|
736
749
|
}
|
|
737
|
-
//
|
|
738
|
-
// shared streams
|
|
739
|
-
//
|
|
740
|
-
//
|
|
750
|
+
// Demand-pull unwired outputs *before* defaults/seeds so multi-value
|
|
751
|
+
// shared streams still deliver every chunk to ports such as LLM
|
|
752
|
+
// `reasoning` / `draftResponse`. Seeds must not emit while only
|
|
753
|
+
// edge-driven outputs are subscribed.
|
|
754
|
+
// `stopsRun` completion is this named edge (not `tap`): wired finish
|
|
755
|
+
// outputs also subscribe so teardown is not hidden in telemetry.
|
|
741
756
|
for (const key of scopeOutputKeys) {
|
|
742
|
-
|
|
757
|
+
const watched = watchedByKey.get(key);
|
|
758
|
+
if (watched === undefined) {
|
|
743
759
|
continue;
|
|
744
760
|
}
|
|
745
|
-
const
|
|
746
|
-
|
|
747
|
-
|
|
761
|
+
const { nodeId } = parseSlotKey(key);
|
|
762
|
+
const node = nodesById.get(nodeId);
|
|
763
|
+
const isUnwired = (outputEdgeIds.get(key) ?? []).length === 0;
|
|
764
|
+
const stopsRun = node?.stopsRun === true;
|
|
765
|
+
if (!isUnwired && !stopsRun) {
|
|
766
|
+
continue;
|
|
748
767
|
}
|
|
768
|
+
run.subscriptions.add(watched.subscribe((response) => {
|
|
769
|
+
if (stopsRun) {
|
|
770
|
+
this.scheduleFinishOnSuccessValue(run.runId, response);
|
|
771
|
+
}
|
|
772
|
+
}));
|
|
749
773
|
}
|
|
750
774
|
const defaultScopeNodeIds = completedNodeIds.size === 0
|
|
751
775
|
? scopeNodeIds
|
|
@@ -3,7 +3,6 @@ import { RuntimeRunner } from './runtime-runner.js';
|
|
|
3
3
|
import type { RuntimeOptions } from './types.js';
|
|
4
4
|
export { bypassOutputPortId, parseBypassOutputPortId } from './bypass-ports.js';
|
|
5
5
|
export { RuntimeEditor } from './runtime-editor.js';
|
|
6
|
-
export { graphHasCycle } from './runtime-helpers.js';
|
|
7
6
|
export type { GraphCluster } from './runtime-helpers.js';
|
|
8
7
|
export { RuntimeRunner } from './runtime-runner.js';
|
|
9
8
|
export type { MetaFromStatefulObservable, NodeId, EdgeId, RunId, PortMeta, RuntimeEdge, RuntimeEditorApi, RuntimeFeedPortMeta, RuntimeFeedRole, PortTelemetry, RuntimeDoneTelemetry, RuntimeNode, RuntimeResumeOptions, RuntimeRunnerApi, RuntimeRunnerEvent, RuntimeRunnerStatus, RuntimeSeedPortValue, RuntimeWireType, SwapNodeResult, } from './types.js';
|
|
@@ -2,7 +2,6 @@ import { RuntimeEditor } from './runtime-editor.js';
|
|
|
2
2
|
import { RuntimeRunner } from './runtime-runner.js';
|
|
3
3
|
export { bypassOutputPortId, parseBypassOutputPortId } from './bypass-ports.js';
|
|
4
4
|
export { RuntimeEditor } from './runtime-editor.js';
|
|
5
|
-
export { graphHasCycle } from './runtime-helpers.js';
|
|
6
5
|
export { RuntimeRunner } from './runtime-runner.js';
|
|
7
6
|
export { isPortErrorTelemetry, isPortPendingTelemetry, isPortTelemetry, isPortValueTelemetry, isRuntimeDone, } from './types.js';
|
|
8
7
|
export class RuntimeFacade {
|