@flowdrop/flowdrop 1.11.0 → 1.12.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/dist/api/enhanced-client.d.ts +29 -16
- package/dist/api/enhanced-client.js +0 -14
- package/dist/components/PipelineStatus.svelte +9 -12
- package/dist/components/WorkflowEditor.svelte +3 -0
- package/dist/components/interrupt/ChoicePrompt.svelte +24 -5
- package/dist/components/interrupt/ConfirmationPrompt.svelte +5 -0
- package/dist/components/interrupt/InterruptBubble.svelte +12 -0
- package/dist/components/interrupt/ReviewPrompt.svelte +20 -0
- package/dist/components/interrupt/TextInputPrompt.svelte +5 -0
- package/dist/components/nodes/GatewayNode.svelte +2 -6
- package/dist/components/nodes/WorkflowNode.svelte +2 -6
- package/dist/components/playground/ChatInput.svelte +359 -0
- package/dist/components/playground/ChatInput.svelte.d.ts +14 -0
- package/dist/components/playground/ChatPanel.svelte +100 -724
- package/dist/components/playground/ChatPanel.svelte.d.ts +9 -26
- package/dist/components/playground/ControlPanel.svelte +496 -0
- package/dist/components/playground/ControlPanel.svelte.d.ts +20 -0
- package/dist/components/playground/ExecutionConsole.svelte +163 -0
- package/dist/components/playground/ExecutionConsole.svelte.d.ts +14 -0
- package/dist/components/playground/MessageStream.svelte +283 -0
- package/dist/components/playground/MessageStream.svelte.d.ts +27 -0
- package/dist/components/playground/PipelineKanbanView.svelte +284 -0
- package/dist/components/playground/PipelineKanbanView.svelte.d.ts +11 -0
- package/dist/components/playground/PipelinePanel.svelte +204 -65
- package/dist/components/playground/PipelinePanel.svelte.d.ts +3 -1
- package/dist/components/playground/PipelineTableView.svelte +376 -0
- package/dist/components/playground/PipelineTableView.svelte.d.ts +11 -0
- package/dist/components/playground/Playground.svelte +262 -1200
- package/dist/components/playground/Playground.svelte.d.ts +0 -13
- package/dist/components/playground/PlaygroundStudio.svelte +35 -61
- package/dist/components/playground/PlaygroundStudio.svelte.d.ts +3 -1
- package/dist/components/playground/pipelineViewUtils.svelte.d.ts +22 -0
- package/dist/components/playground/pipelineViewUtils.svelte.js +77 -0
- package/dist/messages/defaults.d.ts +24 -0
- package/dist/messages/defaults.js +24 -0
- package/dist/playground/index.d.ts +6 -1
- package/dist/playground/index.js +6 -0
- package/dist/playground/mount.d.ts +3 -0
- package/dist/playground/mount.js +3 -2
- package/dist/stores/playgroundStore.svelte.d.ts +6 -0
- package/dist/stores/playgroundStore.svelte.js +21 -1
- package/dist/types/index.d.ts +28 -2
- package/dist/types/playground.d.ts +5 -2
- package/dist/types/playground.js +5 -7
- package/dist/utils/nodeStatus.js +15 -5
- package/package.json +1 -1
|
@@ -1,29 +1,16 @@
|
|
|
1
1
|
import type { Workflow } from '../../types/index.js';
|
|
2
2
|
import type { EndpointConfig } from '../../config/endpoints.js';
|
|
3
3
|
import type { PlaygroundMode, PlaygroundConfig } from '../../types/playground.js';
|
|
4
|
-
/**
|
|
5
|
-
* Component props
|
|
6
|
-
*/
|
|
7
4
|
interface Props {
|
|
8
|
-
/** Target workflow ID */
|
|
9
5
|
workflowId: string;
|
|
10
|
-
/** Pre-loaded workflow (optional, will be fetched if not provided) */
|
|
11
6
|
workflow?: Workflow;
|
|
12
|
-
/** Display mode: embedded (panel) or standalone (page) */
|
|
13
7
|
mode?: PlaygroundMode;
|
|
14
|
-
/** Resume a specific session */
|
|
15
8
|
initialSessionId?: string;
|
|
16
|
-
/** API endpoint configuration */
|
|
17
9
|
endpointConfig?: EndpointConfig;
|
|
18
|
-
/** Playground configuration options */
|
|
19
10
|
config?: PlaygroundConfig;
|
|
20
|
-
/** Callback when playground is closed (for embedded mode) */
|
|
21
11
|
onClose?: () => void;
|
|
22
|
-
/** Callback to toggle the pipeline panel (if undefined, toggle button is hidden) */
|
|
23
12
|
onTogglePanel?: () => void;
|
|
24
|
-
/** Whether the pipeline panel is currently open (for toggle button active state) */
|
|
25
13
|
isPipelinePanelOpen?: boolean;
|
|
26
|
-
/** When provided, session switches and creation navigate to a URL instead of mutating store state */
|
|
27
14
|
onSessionNavigate?: (sessionId: string) => void;
|
|
28
15
|
}
|
|
29
16
|
declare const Playground: import("svelte").Component<Props, {}, "">;
|
|
@@ -1,48 +1,5 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
PlaygroundStudio Component
|
|
3
|
-
|
|
4
|
-
Drop-in embeddable split-pane layout: PipelinePanel (left, resizable) + Playground
|
|
5
|
-
chat (right). Provides the same integrated experience as the FlowDrop demo app with a
|
|
6
|
-
single import and zero layout glue code.
|
|
7
|
-
|
|
8
|
-
@example Basic usage — workflow fetched automatically
|
|
9
|
-
```svelte
|
|
10
|
-
<script>
|
|
11
|
-
import { PlaygroundStudio, createEndpointConfig } from '@flowdrop/flowdrop/playground';
|
|
12
|
-
import '@flowdrop/flowdrop/styles';
|
|
13
|
-
</script>
|
|
14
|
-
|
|
15
|
-
<PlaygroundStudio
|
|
16
|
-
workflowId="wf-123"
|
|
17
|
-
endpointConfig={createEndpointConfig('/api/flowdrop')}
|
|
18
|
-
/>
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
@example With pre-loaded workflow and URL-based session routing
|
|
22
|
-
```svelte
|
|
23
|
-
<script>
|
|
24
|
-
import { PlaygroundStudio, createEndpointConfig } from '@flowdrop/flowdrop/playground';
|
|
25
|
-
|
|
26
|
-
let { data } = $props(); // workflow from server load
|
|
27
|
-
let sessionId = $derived($page.params.sessionId);
|
|
28
|
-
|
|
29
|
-
function handleSessionNavigate(id) {
|
|
30
|
-
goto(`/playground/${id}`);
|
|
31
|
-
}
|
|
32
|
-
</script>
|
|
33
|
-
|
|
34
|
-
<PlaygroundStudio
|
|
35
|
-
workflowId={data.workflow.id}
|
|
36
|
-
workflow={data.workflow}
|
|
37
|
-
endpointConfig={createEndpointConfig('/api/flowdrop')}
|
|
38
|
-
initialSessionId={sessionId}
|
|
39
|
-
onSessionNavigate={handleSessionNavigate}
|
|
40
|
-
/>
|
|
41
|
-
```
|
|
42
|
-
-->
|
|
43
|
-
|
|
44
1
|
<script lang="ts">
|
|
45
|
-
import { onMount } from 'svelte';
|
|
2
|
+
import { onMount, untrack } from 'svelte';
|
|
46
3
|
import Icon from '@iconify/svelte';
|
|
47
4
|
import Playground from './Playground.svelte';
|
|
48
5
|
import PipelinePanel from './PipelinePanel.svelte';
|
|
@@ -57,7 +14,7 @@
|
|
|
57
14
|
} from '../../stores/playgroundStore.svelte.js';
|
|
58
15
|
import { setEndpointConfig, workflowApi } from '../../services/api.js';
|
|
59
16
|
import { logger } from '../../utils/logger.js';
|
|
60
|
-
import type { Workflow } from '../../types/index.js';
|
|
17
|
+
import type { Workflow, PipelineViewDef } from '../../types/index.js';
|
|
61
18
|
import type { EndpointConfig } from '../../config/endpoints.js';
|
|
62
19
|
import type { PlaygroundConfig, PlaygroundMode } from '../../types/playground.js';
|
|
63
20
|
|
|
@@ -84,6 +41,8 @@
|
|
|
84
41
|
onSessionNavigate?: (sessionId: string) => void;
|
|
85
42
|
/** Called when the playground is closed (embedded / modal mode) */
|
|
86
43
|
onClose?: () => void;
|
|
44
|
+
/** Additional pipeline views injected by the consumer */
|
|
45
|
+
extraPipelineViews?: PipelineViewDef[];
|
|
87
46
|
}
|
|
88
47
|
|
|
89
48
|
let {
|
|
@@ -98,19 +57,18 @@
|
|
|
98
57
|
initialPipelineWidth = 500,
|
|
99
58
|
onSessionNavigate,
|
|
100
59
|
onClose,
|
|
60
|
+
extraPipelineViews = [],
|
|
101
61
|
}: Props = $props();
|
|
102
62
|
|
|
103
|
-
// svelte-ignore state_referenced_locally
|
|
104
63
|
let resolvedWorkflow = $state<Workflow | null>(workflowProp ?? null);
|
|
105
|
-
// svelte-ignore state_referenced_locally
|
|
106
64
|
let workflowLoading = $state(workflowProp === undefined);
|
|
107
65
|
let workflowError = $state<string | null>(null);
|
|
108
66
|
|
|
109
67
|
let splitEl = $state<HTMLElement | null>(null);
|
|
110
|
-
// svelte-ignore state_referenced_locally
|
|
111
68
|
let pipelineWidth = $state(initialPipelineWidth);
|
|
112
69
|
let isResizing = $state(false);
|
|
113
70
|
let containerWidth = $state(0);
|
|
71
|
+
let dragContainerLeft = 0;
|
|
114
72
|
|
|
115
73
|
$effect(() => {
|
|
116
74
|
if (!splitEl) return;
|
|
@@ -121,6 +79,12 @@
|
|
|
121
79
|
return () => observer.disconnect();
|
|
122
80
|
});
|
|
123
81
|
|
|
82
|
+
$effect(() => {
|
|
83
|
+
if (containerWidth > 0) {
|
|
84
|
+
pipelineWidth = clampPipelineWidth(untrack(() => pipelineWidth));
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
124
88
|
onMount(() => {
|
|
125
89
|
pipelinePanelActions.init();
|
|
126
90
|
if (initialPipelineOpen !== undefined) {
|
|
@@ -153,23 +117,36 @@
|
|
|
153
117
|
}
|
|
154
118
|
}
|
|
155
119
|
|
|
120
|
+
function clampPipelineWidth(w: number): number {
|
|
121
|
+
if (!containerWidth) return Math.max(w, 0);
|
|
122
|
+
return Math.min(Math.max(w, containerWidth - minChatWidth), containerWidth * 0.75);
|
|
123
|
+
}
|
|
124
|
+
|
|
156
125
|
function handleResizerPointerDown(e: PointerEvent) {
|
|
126
|
+
if (splitEl) dragContainerLeft = splitEl.getBoundingClientRect().left;
|
|
157
127
|
isResizing = true;
|
|
158
128
|
(e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);
|
|
159
129
|
}
|
|
160
130
|
|
|
161
131
|
function handleResizerPointerMove(e: PointerEvent) {
|
|
162
|
-
if (!isResizing
|
|
163
|
-
|
|
164
|
-
pipelineWidth = Math.min(
|
|
165
|
-
Math.max(e.clientX - rect.left, rect.width - minChatWidth),
|
|
166
|
-
rect.width * 0.75
|
|
167
|
-
);
|
|
132
|
+
if (!isResizing) return;
|
|
133
|
+
pipelineWidth = clampPipelineWidth(e.clientX - dragContainerLeft);
|
|
168
134
|
}
|
|
169
135
|
|
|
170
136
|
function handleResizerPointerUp() {
|
|
171
137
|
isResizing = false;
|
|
172
138
|
}
|
|
139
|
+
|
|
140
|
+
function handleResizerKeyDown(e: KeyboardEvent) {
|
|
141
|
+
const step = e.shiftKey ? 50 : 20;
|
|
142
|
+
if (e.key === 'ArrowLeft') {
|
|
143
|
+
e.preventDefault();
|
|
144
|
+
pipelineWidth = clampPipelineWidth(pipelineWidth - step);
|
|
145
|
+
} else if (e.key === 'ArrowRight') {
|
|
146
|
+
e.preventDefault();
|
|
147
|
+
pipelineWidth = clampPipelineWidth(pipelineWidth + step);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
173
150
|
</script>
|
|
174
151
|
|
|
175
152
|
<div class="playground-studio" class:playground-studio--resizing={isResizing} style="--playground-studio-min-chat-width: {minChatWidth}px">
|
|
@@ -188,10 +165,10 @@
|
|
|
188
165
|
latestExecutionId={getLatestExecutionId()}
|
|
189
166
|
onSelectExecution={(id) => playgroundActions.pinExecution(id)}
|
|
190
167
|
refreshTrigger={getPipelineRefreshTrigger()}
|
|
168
|
+
extraViews={extraPipelineViews}
|
|
191
169
|
/>
|
|
192
170
|
</div>
|
|
193
171
|
|
|
194
|
-
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
195
172
|
<div
|
|
196
173
|
class="playground-studio__resizer"
|
|
197
174
|
class:playground-studio__resizer--active={isResizing}
|
|
@@ -200,11 +177,13 @@
|
|
|
200
177
|
aria-valuenow={Math.round(pipelineWidth)}
|
|
201
178
|
aria-valuemin={0}
|
|
202
179
|
aria-valuemax={Math.round(containerWidth * 0.75)}
|
|
180
|
+
aria-label="Resize pipeline panel"
|
|
203
181
|
tabindex="0"
|
|
204
182
|
onpointerdown={handleResizerPointerDown}
|
|
205
183
|
onpointermove={handleResizerPointerMove}
|
|
206
184
|
onpointerup={handleResizerPointerUp}
|
|
207
185
|
onpointercancel={handleResizerPointerUp}
|
|
186
|
+
onkeydown={handleResizerKeyDown}
|
|
208
187
|
>
|
|
209
188
|
<div class="playground-studio__resizer-handle"></div>
|
|
210
189
|
</div>
|
|
@@ -271,10 +250,8 @@
|
|
|
271
250
|
overflow: hidden;
|
|
272
251
|
}
|
|
273
252
|
|
|
274
|
-
/* Pipeline pane — explicit width
|
|
253
|
+
/* Pipeline pane — explicit width driven by JS; clamping keeps it in bounds */
|
|
275
254
|
.playground-studio__pipeline {
|
|
276
|
-
min-width: calc(100% - var(--playground-studio-min-chat-width));
|
|
277
|
-
max-width: 75%;
|
|
278
255
|
overflow: hidden;
|
|
279
256
|
flex-shrink: 0;
|
|
280
257
|
}
|
|
@@ -351,9 +328,6 @@
|
|
|
351
328
|
}
|
|
352
329
|
|
|
353
330
|
@keyframes studio-spin {
|
|
354
|
-
from {
|
|
355
|
-
transform: rotate(0deg);
|
|
356
|
-
}
|
|
357
331
|
to {
|
|
358
332
|
transform: rotate(360deg);
|
|
359
333
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Workflow } from '../../types/index.js';
|
|
1
|
+
import type { Workflow, PipelineViewDef } from '../../types/index.js';
|
|
2
2
|
import type { EndpointConfig } from '../../config/endpoints.js';
|
|
3
3
|
import type { PlaygroundConfig, PlaygroundMode } from '../../types/playground.js';
|
|
4
4
|
interface Props {
|
|
@@ -24,6 +24,8 @@ interface Props {
|
|
|
24
24
|
onSessionNavigate?: (sessionId: string) => void;
|
|
25
25
|
/** Called when the playground is closed (embedded / modal mode) */
|
|
26
26
|
onClose?: () => void;
|
|
27
|
+
/** Additional pipeline views injected by the consumer */
|
|
28
|
+
extraPipelineViews?: PipelineViewDef[];
|
|
27
29
|
}
|
|
28
30
|
declare const PlaygroundStudio: import("svelte").Component<Props, {}, "">;
|
|
29
31
|
type PlaygroundStudio = ReturnType<typeof PlaygroundStudio>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { EndpointConfig } from '../../config/endpoints.js';
|
|
2
|
+
import type { NodeExecutionStatus, KanbanColumnDef } from '../../types/index.js';
|
|
3
|
+
export type NodeStatus = NodeExecutionStatus;
|
|
4
|
+
export interface NodeStatusData {
|
|
5
|
+
status: string;
|
|
6
|
+
last_executed?: string | null;
|
|
7
|
+
execution_time?: number | null;
|
|
8
|
+
error?: string | null;
|
|
9
|
+
}
|
|
10
|
+
export declare function resolveStatus(raw: NodeStatusData | undefined): NodeStatus;
|
|
11
|
+
/**
|
|
12
|
+
* Creates a reactive pipeline data fetcher.
|
|
13
|
+
* `endpointConfig` is used once to construct the API client — it must be stable.
|
|
14
|
+
* `getPipelineId` is called on every fetch so pipeline ID changes are picked up.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createPipelineDataFetcher(getPipelineId: () => string, endpointConfig: EndpointConfig): {
|
|
17
|
+
readonly nodeStatusMap: Record<string, NodeStatusData>;
|
|
18
|
+
readonly kanbanConfig: KanbanColumnDef[] | null;
|
|
19
|
+
readonly isLoading: boolean;
|
|
20
|
+
readonly isError: boolean;
|
|
21
|
+
fetchData: () => Promise<void>;
|
|
22
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { EnhancedFlowDropApiClient } from '../../api/enhanced-client.js';
|
|
2
|
+
import { logger } from '../../utils/logger.js';
|
|
3
|
+
const KNOWN_STATUSES = new Set([
|
|
4
|
+
'idle', 'pending', 'running', 'paused', 'interrupted',
|
|
5
|
+
'completed', 'skipped', 'failed', 'cancelled'
|
|
6
|
+
]);
|
|
7
|
+
export function resolveStatus(raw) {
|
|
8
|
+
if (!raw)
|
|
9
|
+
return 'pending';
|
|
10
|
+
const s = raw.status || 'pending';
|
|
11
|
+
if (!KNOWN_STATUSES.has(s)) {
|
|
12
|
+
logger.warn(`[FlowDrop] Unknown node status from server: "${s}" — falling back to "pending"`);
|
|
13
|
+
return 'pending';
|
|
14
|
+
}
|
|
15
|
+
return s;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Creates a reactive pipeline data fetcher.
|
|
19
|
+
* `endpointConfig` is used once to construct the API client — it must be stable.
|
|
20
|
+
* `getPipelineId` is called on every fetch so pipeline ID changes are picked up.
|
|
21
|
+
*/
|
|
22
|
+
export function createPipelineDataFetcher(getPipelineId, endpointConfig) {
|
|
23
|
+
const client = new EnhancedFlowDropApiClient(endpointConfig);
|
|
24
|
+
let nodeStatusMap = $state({});
|
|
25
|
+
let kanbanConfig = $state(null);
|
|
26
|
+
let isLoading = $state(false);
|
|
27
|
+
let isError = $state(false);
|
|
28
|
+
async function fetchData() {
|
|
29
|
+
try {
|
|
30
|
+
isLoading = true;
|
|
31
|
+
isError = false;
|
|
32
|
+
const data = await client.getPipelineData(getPipelineId());
|
|
33
|
+
const map = {};
|
|
34
|
+
for (const [nodeId, info] of Object.entries(data.node_statuses)) {
|
|
35
|
+
map[nodeId] = {
|
|
36
|
+
status: info.status,
|
|
37
|
+
last_executed: info.last_executed,
|
|
38
|
+
execution_time: info.execution_time,
|
|
39
|
+
error: info.error,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
nodeStatusMap = map;
|
|
43
|
+
if (data.kanban_config?.columns) {
|
|
44
|
+
// Server sends statuses as string[]; trust the server and cast at this
|
|
45
|
+
// boundary. resolveStatus() handles unknown values at read time.
|
|
46
|
+
kanbanConfig = data.kanban_config.columns.map((col) => ({
|
|
47
|
+
key: col.key,
|
|
48
|
+
label: col.label,
|
|
49
|
+
statuses: col.statuses,
|
|
50
|
+
icon: col.icon,
|
|
51
|
+
color: col.color,
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
isError = true;
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
isLoading = false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
get nodeStatusMap() {
|
|
64
|
+
return nodeStatusMap;
|
|
65
|
+
},
|
|
66
|
+
get kanbanConfig() {
|
|
67
|
+
return kanbanConfig;
|
|
68
|
+
},
|
|
69
|
+
get isLoading() {
|
|
70
|
+
return isLoading;
|
|
71
|
+
},
|
|
72
|
+
get isError() {
|
|
73
|
+
return isError;
|
|
74
|
+
},
|
|
75
|
+
fetchData
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -328,6 +328,30 @@ export declare const defaultMessages: {
|
|
|
328
328
|
n: number;
|
|
329
329
|
}) => string;
|
|
330
330
|
};
|
|
331
|
+
readonly executionConsole: {
|
|
332
|
+
readonly header: "Execution";
|
|
333
|
+
readonly noExecutionTitle: "No execution yet";
|
|
334
|
+
readonly noExecutionText: "Create or select a session below, then run your workflow to see execution output here.";
|
|
335
|
+
readonly readyTitle: "Ready to run";
|
|
336
|
+
readonly readyText: "Use the controls below to start the workflow. Output and interactive prompts will appear here.";
|
|
337
|
+
readonly newSession: "New session";
|
|
338
|
+
};
|
|
339
|
+
readonly controlPanel: {
|
|
340
|
+
readonly sessionsLabel: "Sessions";
|
|
341
|
+
readonly noSession: "No session";
|
|
342
|
+
readonly switchSession: "Switch session";
|
|
343
|
+
readonly newSession: "New session";
|
|
344
|
+
readonly pipeline: "Pipeline";
|
|
345
|
+
readonly showPipeline: "Show pipeline";
|
|
346
|
+
readonly hidePipeline: "Hide pipeline";
|
|
347
|
+
readonly refresh: "Refresh";
|
|
348
|
+
readonly refreshTitle: "Refresh status";
|
|
349
|
+
readonly logs: "Logs";
|
|
350
|
+
readonly showLogs: "Show log messages";
|
|
351
|
+
readonly hideLogs: "Hide log messages";
|
|
352
|
+
readonly deleteSession: "Delete session";
|
|
353
|
+
readonly messageStreamLabel: "Execution output";
|
|
354
|
+
};
|
|
331
355
|
};
|
|
332
356
|
readonly nodes: {
|
|
333
357
|
readonly notes: {
|
|
@@ -300,6 +300,30 @@ export const defaultMessages = {
|
|
|
300
300
|
minutesAgo: ({ n }) => `${n}m ago`,
|
|
301
301
|
hoursAgo: ({ n }) => `${n}h ago`,
|
|
302
302
|
daysAgo: ({ n }) => `${n}d ago`
|
|
303
|
+
},
|
|
304
|
+
executionConsole: {
|
|
305
|
+
header: 'Execution',
|
|
306
|
+
noExecutionTitle: 'No execution yet',
|
|
307
|
+
noExecutionText: 'Create or select a session below, then run your workflow to see execution output here.',
|
|
308
|
+
readyTitle: 'Ready to run',
|
|
309
|
+
readyText: 'Use the controls below to start the workflow. Output and interactive prompts will appear here.',
|
|
310
|
+
newSession: 'New session'
|
|
311
|
+
},
|
|
312
|
+
controlPanel: {
|
|
313
|
+
sessionsLabel: 'Sessions',
|
|
314
|
+
noSession: 'No session',
|
|
315
|
+
switchSession: 'Switch session',
|
|
316
|
+
newSession: 'New session',
|
|
317
|
+
pipeline: 'Pipeline',
|
|
318
|
+
showPipeline: 'Show pipeline',
|
|
319
|
+
hidePipeline: 'Hide pipeline',
|
|
320
|
+
refresh: 'Refresh',
|
|
321
|
+
refreshTitle: 'Refresh status',
|
|
322
|
+
logs: 'Logs',
|
|
323
|
+
showLogs: 'Show log messages',
|
|
324
|
+
hideLogs: 'Hide log messages',
|
|
325
|
+
deleteSession: 'Delete session',
|
|
326
|
+
messageStreamLabel: 'Execution output'
|
|
303
327
|
}
|
|
304
328
|
},
|
|
305
329
|
nodes: {
|
|
@@ -115,6 +115,10 @@ export { default as PlaygroundStudio } from '../components/playground/Playground
|
|
|
115
115
|
export { default as PlaygroundApp } from '../components/playground/PlaygroundApp.svelte';
|
|
116
116
|
export { default as PlaygroundModal } from '../components/playground/PlaygroundModal.svelte';
|
|
117
117
|
export { default as ChatPanel } from '../components/playground/ChatPanel.svelte';
|
|
118
|
+
export { default as MessageStream } from '../components/playground/MessageStream.svelte';
|
|
119
|
+
export { default as ChatInput } from '../components/playground/ChatInput.svelte';
|
|
120
|
+
export { default as ExecutionConsole } from '../components/playground/ExecutionConsole.svelte';
|
|
121
|
+
export { default as ControlPanel } from '../components/playground/ControlPanel.svelte';
|
|
118
122
|
export { default as PipelinePanel } from '../components/playground/PipelinePanel.svelte';
|
|
119
123
|
export { default as ExecutionList } from '../components/playground/ExecutionList.svelte';
|
|
120
124
|
export { default as SessionManager } from '../components/playground/SessionManager.svelte';
|
|
@@ -124,7 +128,7 @@ export { default as MessageBubble } from '../components/playground/MessageBubble
|
|
|
124
128
|
export { InterruptBubble, ConfirmationPrompt, ChoicePrompt, TextInputPrompt, FormPrompt, ReviewPrompt } from '../components/interrupt/index.js';
|
|
125
129
|
export { PlaygroundService, playgroundService } from '../services/playgroundService.js';
|
|
126
130
|
export { InterruptService, interruptService } from '../services/interruptService.js';
|
|
127
|
-
export { getCurrentSession, getSessions, getMessages, getIsExecuting, getCanSendMessage, getIsLoading, getError as getPlaygroundError, getCurrentWorkflow, getLastPollSequenceNumber, getSessionStatus, getMessageCount, getChatMessages, getLogMessages, getLatestMessage, getInputFields, getHasChatInput, getSessionCount, getActiveExecutionId, getPinnedExecutionId, getLatestExecutionId, playgroundActions, applyServerResponse, subscribeToSessionStatus, getCurrentSessionId, isSessionSelected, getMessagesSnapshot, getLatestSequenceNumber } from '../stores/playgroundStore.svelte.js';
|
|
131
|
+
export { getCurrentSession, getSessions, getMessages, getIsExecuting, getCanSendMessage, getIsLoading, getError as getPlaygroundError, getCurrentWorkflow, getLastPollSequenceNumber, getSessionStatus, getMessageCount, getChatMessages, getLogMessages, getLatestMessage, getInputFields, getHasChatInput, getSessionCount, getActiveExecutionId, getPinnedExecutionId, getLatestExecutionId, getShowLogs, playgroundActions, applyServerResponse, subscribeToSessionStatus, getCurrentSessionId, isSessionSelected, getMessagesSnapshot, getLatestSequenceNumber } from '../stores/playgroundStore.svelte.js';
|
|
128
132
|
export { getPipelinePanelOpen, pipelinePanelActions } from '../stores/pipelinePanelStore.svelte.js';
|
|
129
133
|
export type { PlaygroundSession, PlaygroundMessage, PlaygroundInputField, PlaygroundMessageRequest, PlaygroundMessagesResult, PlaygroundConfig, PlaygroundMode, PlaygroundSessionStatus, PlaygroundMessageRole, PlaygroundMessageLevel, PlaygroundMessageMetadata, PlaygroundApiResponse, PlaygroundSessionsResponse, PlaygroundSessionResponse, PlaygroundMessageResponse, PlaygroundMessagesApiResponse, PlaygroundExecution } from '../types/playground.js';
|
|
130
134
|
export { isChatInputNode, CHAT_INPUT_PATTERNS, defaultShouldStopPolling, defaultIsTerminalStatus, DEFAULT_STOP_POLLING_STATUSES, DEFAULT_TERMINAL_STATUSES } from '../types/playground.js';
|
|
@@ -133,4 +137,5 @@ export { isInterruptMetadata, extractInterruptMetadata, metadataToInterrupt, def
|
|
|
133
137
|
export { getInterruptsMap, getPendingInterruptIds, getPendingInterrupts, getPendingInterruptCount, getResolvedInterrupts, getIsAnySubmitting, interruptActions, getInterrupt, isInterruptPending, isInterruptSubmitting, getInterruptError, getInterruptByMessageId, interruptHasError } from '../stores/interruptStore.svelte.js';
|
|
134
138
|
export type { InterruptWithState } from '../stores/interruptStore.svelte.js';
|
|
135
139
|
export { mountPlayground, unmountPlayground, mountPlaygroundStudio, mountPlaygroundApp, type PlaygroundMountOptions, type PlaygroundStudioMountOptions, type PlaygroundAppMountOptions, type MountedPlayground } from './mount.js';
|
|
140
|
+
export type { PipelineViewDef, PipelineViewProps } from '../types/index.js';
|
|
136
141
|
export { createEndpointConfig, defaultEndpointConfig, buildEndpointUrl, type EndpointConfig } from '../config/endpoints.js';
|
package/dist/playground/index.js
CHANGED
|
@@ -118,6 +118,10 @@ export { default as PlaygroundStudio } from '../components/playground/Playground
|
|
|
118
118
|
export { default as PlaygroundApp } from '../components/playground/PlaygroundApp.svelte';
|
|
119
119
|
export { default as PlaygroundModal } from '../components/playground/PlaygroundModal.svelte';
|
|
120
120
|
export { default as ChatPanel } from '../components/playground/ChatPanel.svelte';
|
|
121
|
+
export { default as MessageStream } from '../components/playground/MessageStream.svelte';
|
|
122
|
+
export { default as ChatInput } from '../components/playground/ChatInput.svelte';
|
|
123
|
+
export { default as ExecutionConsole } from '../components/playground/ExecutionConsole.svelte';
|
|
124
|
+
export { default as ControlPanel } from '../components/playground/ControlPanel.svelte';
|
|
121
125
|
export { default as PipelinePanel } from '../components/playground/PipelinePanel.svelte';
|
|
122
126
|
export { default as ExecutionList } from '../components/playground/ExecutionList.svelte';
|
|
123
127
|
export { default as SessionManager } from '../components/playground/SessionManager.svelte';
|
|
@@ -146,6 +150,8 @@ getCurrentSession, getSessions, getMessages, getIsExecuting, getCanSendMessage,
|
|
|
146
150
|
getSessionStatus, getMessageCount, getChatMessages, getLogMessages, getLatestMessage, getInputFields, getHasChatInput, getSessionCount,
|
|
147
151
|
// Execution getters (used with PipelinePanel / PlaygroundSplit)
|
|
148
152
|
getActiveExecutionId, getPinnedExecutionId, getLatestExecutionId,
|
|
153
|
+
// UI state
|
|
154
|
+
getShowLogs,
|
|
149
155
|
// Actions
|
|
150
156
|
playgroundActions,
|
|
151
157
|
// Server response application (single update path)
|
|
@@ -48,6 +48,7 @@ import type { EndpointConfig } from '../config/endpoints.js';
|
|
|
48
48
|
import type { PlaygroundMode, PlaygroundConfig, PlaygroundSession, PlaygroundMessagesApiResponse, PlaygroundSessionStatus } from '../types/playground.js';
|
|
49
49
|
import type { PartialSettings, SettingsCategory } from '../types/settings.js';
|
|
50
50
|
import type { NavbarAction } from '../types/navbar.js';
|
|
51
|
+
import type { PipelineViewDef } from '../types/index.js';
|
|
51
52
|
/**
|
|
52
53
|
* Mount options for Playground component
|
|
53
54
|
*/
|
|
@@ -216,6 +217,8 @@ export interface PlaygroundStudioMountOptions extends PlaygroundMountOptions {
|
|
|
216
217
|
minChatWidth?: number;
|
|
217
218
|
initialPipelineWidth?: number;
|
|
218
219
|
onSessionNavigate?: (sessionId: string) => void;
|
|
220
|
+
/** Additional pipeline views injected into the view switcher */
|
|
221
|
+
pipelineViews?: PipelineViewDef[];
|
|
219
222
|
}
|
|
220
223
|
export declare function mountPlaygroundStudio(container: HTMLElement, options: PlaygroundStudioMountOptions): Promise<MountedPlayground>;
|
|
221
224
|
export interface PlaygroundAppMountOptions extends Omit<PlaygroundStudioMountOptions, 'mode'> {
|
package/dist/playground/mount.js
CHANGED
|
@@ -225,7 +225,7 @@ export function unmountPlayground(app) {
|
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
export async function mountPlaygroundStudio(container, options) {
|
|
228
|
-
const { workflowId, workflow, mode = 'standalone', initialSessionId, endpointConfig, config = {}, height, width, initialPipelineOpen, minChatWidth, initialPipelineWidth, settings: initialSettings, onClose, onSessionNavigate, onSessionStatusChange } = options;
|
|
228
|
+
const { workflowId, workflow, mode = 'standalone', initialSessionId, endpointConfig, config = {}, height, width, initialPipelineOpen, minChatWidth, initialPipelineWidth, settings: initialSettings, onClose, onSessionNavigate, onSessionStatusChange, pipelineViews } = options;
|
|
229
229
|
if (!workflowId) {
|
|
230
230
|
throw new Error('workflowId is required for mountPlaygroundStudio()');
|
|
231
231
|
}
|
|
@@ -253,7 +253,8 @@ export async function mountPlaygroundStudio(container, options) {
|
|
|
253
253
|
onSessionNavigate,
|
|
254
254
|
initialPipelineOpen,
|
|
255
255
|
minChatWidth,
|
|
256
|
-
initialPipelineWidth
|
|
256
|
+
initialPipelineWidth,
|
|
257
|
+
extraPipelineViews: pipelineViews
|
|
257
258
|
}
|
|
258
259
|
});
|
|
259
260
|
return buildMountedPlayground(svelteApp, workflowId, config, onSessionStatusChange);
|
|
@@ -89,6 +89,10 @@ export declare function getActiveExecutionId(): string | null;
|
|
|
89
89
|
* Pass to PipelinePanel's refreshTrigger prop.
|
|
90
90
|
*/
|
|
91
91
|
export declare function getPipelineRefreshTrigger(): number;
|
|
92
|
+
/**
|
|
93
|
+
* Whether log messages should be shown in the execution console
|
|
94
|
+
*/
|
|
95
|
+
export declare function getShowLogs(): boolean;
|
|
92
96
|
/**
|
|
93
97
|
* Playground store actions for modifying state
|
|
94
98
|
*/
|
|
@@ -183,6 +187,8 @@ export declare const playgroundActions: {
|
|
|
183
187
|
*/
|
|
184
188
|
switchSession: (sessionId: string) => void;
|
|
185
189
|
pinExecution(executionId: string | null): void;
|
|
190
|
+
setShowLogs(value: boolean): void;
|
|
191
|
+
toggleShowLogs(): void;
|
|
186
192
|
};
|
|
187
193
|
/**
|
|
188
194
|
* Apply a server response to the store. All message and status updates from
|
|
@@ -43,6 +43,8 @@ let _lastPollSequenceNumber = $state(null);
|
|
|
43
43
|
let _pinnedExecutionId = $state(null);
|
|
44
44
|
/** Incremented on every message batch that should trigger a pipeline re-fetch */
|
|
45
45
|
let _pipelineRefreshTrigger = $state(0);
|
|
46
|
+
/** Whether log messages are visible in the execution console */
|
|
47
|
+
let _showLogs = $state(true);
|
|
46
48
|
/** Latest execution ID derived from current session's executions list */
|
|
47
49
|
const _latestExecutionId = $derived(_currentSession?.executions?.at(-1)?.id ?? null);
|
|
48
50
|
/** Active execution: pinned if set, otherwise latest */
|
|
@@ -237,6 +239,12 @@ export function getActiveExecutionId() {
|
|
|
237
239
|
export function getPipelineRefreshTrigger() {
|
|
238
240
|
return _pipelineRefreshTrigger;
|
|
239
241
|
}
|
|
242
|
+
/**
|
|
243
|
+
* Whether log messages should be shown in the execution console
|
|
244
|
+
*/
|
|
245
|
+
export function getShowLogs() {
|
|
246
|
+
return _showLogs;
|
|
247
|
+
}
|
|
240
248
|
// =========================================================================
|
|
241
249
|
// Helper Functions
|
|
242
250
|
// =========================================================================
|
|
@@ -345,7 +353,11 @@ export const playgroundActions = {
|
|
|
345
353
|
// so we only need to check and update the tail entry.
|
|
346
354
|
// 'idle' means the run finished normally (server returns 'idle' post-completion,
|
|
347
355
|
// not 'completed'), so map it to 'completed' for the execution entry.
|
|
348
|
-
const terminalExecutionStatus = status === 'failed'
|
|
356
|
+
const terminalExecutionStatus = status === 'failed'
|
|
357
|
+
? 'failed'
|
|
358
|
+
: status === 'completed' || status === 'idle'
|
|
359
|
+
? 'completed'
|
|
360
|
+
: null;
|
|
349
361
|
if (terminalExecutionStatus && _currentSession?.executions?.length) {
|
|
350
362
|
const execs = [..._currentSession.executions];
|
|
351
363
|
const last = execs[execs.length - 1];
|
|
@@ -405,6 +417,8 @@ export const playgroundActions = {
|
|
|
405
417
|
* @param message - The message to add
|
|
406
418
|
*/
|
|
407
419
|
addMessage: (message) => {
|
|
420
|
+
if (_messages.some(m => m.id === message.id))
|
|
421
|
+
return;
|
|
408
422
|
const seq = message.sequenceNumber ?? 0;
|
|
409
423
|
let lo = 0, hi = _messages.length;
|
|
410
424
|
while (lo < hi) {
|
|
@@ -500,6 +514,12 @@ export const playgroundActions = {
|
|
|
500
514
|
},
|
|
501
515
|
pinExecution(executionId) {
|
|
502
516
|
_pinnedExecutionId = executionId;
|
|
517
|
+
},
|
|
518
|
+
setShowLogs(value) {
|
|
519
|
+
_showLogs = value;
|
|
520
|
+
},
|
|
521
|
+
toggleShowLogs() {
|
|
522
|
+
_showLogs = !_showLogs;
|
|
503
523
|
}
|
|
504
524
|
};
|
|
505
525
|
// =========================================================================
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Core types for the Workflow Library
|
|
3
3
|
*/
|
|
4
|
+
import type { Component } from 'svelte';
|
|
4
5
|
import type { Node, Edge, XYPosition } from '@xyflow/svelte';
|
|
5
6
|
import { ConnectionLineType } from '@xyflow/svelte';
|
|
6
7
|
import type { EndpointConfig } from '../config/endpoints.js';
|
|
@@ -1168,7 +1169,32 @@ export type WorkflowsResponse = ApiResponse<Workflow[]>;
|
|
|
1168
1169
|
/**
|
|
1169
1170
|
* Node execution status enum
|
|
1170
1171
|
*/
|
|
1171
|
-
export type NodeExecutionStatus = 'idle' | 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | 'skipped';
|
|
1172
|
+
export type NodeExecutionStatus = 'idle' | 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | 'skipped' | 'paused' | 'interrupted';
|
|
1173
|
+
export interface KanbanColumnDef {
|
|
1174
|
+
key: string;
|
|
1175
|
+
label: string;
|
|
1176
|
+
statuses: NodeExecutionStatus[];
|
|
1177
|
+
icon?: string;
|
|
1178
|
+
color?: string;
|
|
1179
|
+
}
|
|
1180
|
+
/** Props passed to every pipeline view component, built-in or custom. */
|
|
1181
|
+
export interface PipelineViewProps {
|
|
1182
|
+
pipelineId: string | null;
|
|
1183
|
+
workflow: Workflow;
|
|
1184
|
+
endpointConfig: EndpointConfig;
|
|
1185
|
+
refreshTrigger?: number;
|
|
1186
|
+
}
|
|
1187
|
+
/** A custom view injected into the PipelinePanel view switcher. */
|
|
1188
|
+
export interface PipelineViewDef {
|
|
1189
|
+
/** Unique key — must not clash with built-ins: 'graph' | 'kanban' | 'table' */
|
|
1190
|
+
key: string;
|
|
1191
|
+
/** Label shown in the toggle button tooltip */
|
|
1192
|
+
label: string;
|
|
1193
|
+
/** Iconify icon name, e.g. 'mdi:chart-bar' */
|
|
1194
|
+
icon: string;
|
|
1195
|
+
/** Svelte component that receives PipelineViewProps */
|
|
1196
|
+
component: Component<PipelineViewProps>;
|
|
1197
|
+
}
|
|
1172
1198
|
/**
|
|
1173
1199
|
* Node execution tracking information
|
|
1174
1200
|
*/
|
|
@@ -1191,7 +1217,7 @@ export interface NodeExecutionInfo {
|
|
|
1191
1217
|
/**
|
|
1192
1218
|
* Workflow execution status
|
|
1193
1219
|
*/
|
|
1194
|
-
export type ExecutionStatus = 'idle' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
1220
|
+
export type ExecutionStatus = 'idle' | 'running' | 'completed' | 'failed' | 'cancelled' | 'paused' | 'interrupted';
|
|
1195
1221
|
/**
|
|
1196
1222
|
* Workflow execution result
|
|
1197
1223
|
*/
|
|
@@ -12,7 +12,10 @@ import type { ConfigProperty } from './index.js';
|
|
|
12
12
|
*/
|
|
13
13
|
export type PlaygroundSessionStatus = 'idle' | 'running' | 'awaiting_input' | 'completed' | 'failed';
|
|
14
14
|
/**
|
|
15
|
-
* Statuses that stop polling by default
|
|
15
|
+
* Statuses that stop polling by default.
|
|
16
|
+
* Only truly-dormant sessions stop polling — completed/failed/awaiting_input
|
|
17
|
+
* sessions on async servers can still generate messages after the status change,
|
|
18
|
+
* so polling continues until the session is explicitly idle.
|
|
16
19
|
*/
|
|
17
20
|
export declare const DEFAULT_STOP_POLLING_STATUSES: PlaygroundSessionStatus[];
|
|
18
21
|
/**
|
|
@@ -273,7 +276,7 @@ export interface PlaygroundConfig {
|
|
|
273
276
|
/**
|
|
274
277
|
* Determines if polling should stop for a given session status.
|
|
275
278
|
* Override to customize which statuses pause polling.
|
|
276
|
-
* @default defaultShouldStopPolling (stops on idle
|
|
279
|
+
* @default defaultShouldStopPolling (stops only on idle)
|
|
277
280
|
*/
|
|
278
281
|
shouldStopPolling?: (status: PlaygroundSessionStatus) => boolean;
|
|
279
282
|
/**
|
package/dist/types/playground.js
CHANGED
|
@@ -7,14 +7,12 @@
|
|
|
7
7
|
* @module types/playground
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
|
-
* Statuses that stop polling by default
|
|
10
|
+
* Statuses that stop polling by default.
|
|
11
|
+
* Only truly-dormant sessions stop polling — completed/failed/awaiting_input
|
|
12
|
+
* sessions on async servers can still generate messages after the status change,
|
|
13
|
+
* so polling continues until the session is explicitly idle.
|
|
11
14
|
*/
|
|
12
|
-
export const DEFAULT_STOP_POLLING_STATUSES = [
|
|
13
|
-
'idle',
|
|
14
|
-
'completed',
|
|
15
|
-
'failed',
|
|
16
|
-
'awaiting_input'
|
|
17
|
-
];
|
|
15
|
+
export const DEFAULT_STOP_POLLING_STATUSES = ['idle'];
|
|
18
16
|
/**
|
|
19
17
|
* Statuses that are considered terminal by default (clears isExecuting)
|
|
20
18
|
*/
|