windmill-components 1.555.1 → 1.558.1

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 (150) hide show
  1. package/package/components/AIAgentLogViewer.svelte.d.ts +3 -3
  2. package/package/components/AIProviderPicker.svelte.d.ts +3 -3
  3. package/package/components/ArgInput.svelte +2 -0
  4. package/package/components/DBManager.svelte.d.ts +3 -3
  5. package/package/components/DBManagerDrawer.svelte.d.ts +3 -3
  6. package/package/components/DBSchemaExplorer.svelte.d.ts +3 -3
  7. package/package/components/DBTable.svelte.d.ts +3 -3
  8. package/package/components/DBTableEditor.svelte +9 -12
  9. package/package/components/DBTableEditor.svelte.d.ts +3 -3
  10. package/package/components/DateTimeInput.svelte +19 -13
  11. package/package/components/DateTimeInput.svelte.d.ts +5 -0
  12. package/package/components/DucklakePicker.svelte +32 -0
  13. package/package/components/DucklakePicker.svelte.d.ts +13 -0
  14. package/package/components/Editor.svelte +1 -1
  15. package/package/components/EditorBar.svelte +14 -1
  16. package/package/components/FakeMonacoPlaceHolder.svelte +1 -1
  17. package/package/components/FlowGraphViewerStep.svelte +1 -1
  18. package/package/components/FlowPreviewContent.svelte +1 -1
  19. package/package/components/HighlightCode.svelte +21 -10
  20. package/package/components/HighlightCode.svelte.d.ts +12 -22
  21. package/package/components/InputTransformForm.svelte +9 -41
  22. package/package/components/InstanceSetting.svelte +1 -6
  23. package/package/components/ResourceEditor.svelte +1 -1
  24. package/package/components/ResourcePicker.svelte +0 -5
  25. package/package/components/apps/components/display/dbtable/AppDbExplorer.svelte +50 -34
  26. package/package/components/apps/components/display/dbtable/DbExplorerCount.svelte +7 -5
  27. package/package/components/apps/components/display/dbtable/DbExplorerCount.svelte.d.ts +2 -2
  28. package/package/components/apps/components/display/dbtable/DeleteRow.svelte +2 -2
  29. package/package/components/apps/components/display/dbtable/DeleteRow.svelte.d.ts +3 -2
  30. package/package/components/apps/components/display/dbtable/InsertRow.svelte +13 -7
  31. package/package/components/apps/components/display/dbtable/InsertRowRunnable.svelte +6 -3
  32. package/package/components/apps/components/display/dbtable/InsertRowRunnable.svelte.d.ts +2 -1
  33. package/package/components/apps/components/display/dbtable/UpdateCell.svelte +2 -2
  34. package/package/components/apps/components/display/dbtable/UpdateCell.svelte.d.ts +3 -2
  35. package/package/components/apps/components/display/dbtable/queries/count.d.ts +2 -1
  36. package/package/components/apps/components/display/dbtable/queries/count.js +28 -18
  37. package/package/components/apps/components/display/dbtable/queries/createTable.d.ts +1 -1
  38. package/package/components/apps/components/display/dbtable/queries/createTable.js +1 -1
  39. package/package/components/apps/components/display/dbtable/queries/delete.d.ts +2 -1
  40. package/package/components/apps/components/display/dbtable/queries/delete.js +19 -10
  41. package/package/components/apps/components/display/dbtable/queries/insert.d.ts +2 -1
  42. package/package/components/apps/components/display/dbtable/queries/insert.js +16 -10
  43. package/package/components/apps/components/display/dbtable/queries/select.d.ts +2 -1
  44. package/package/components/apps/components/display/dbtable/queries/select.js +20 -16
  45. package/package/components/apps/components/display/dbtable/queries/update.d.ts +2 -1
  46. package/package/components/apps/components/display/dbtable/queries/update.js +19 -10
  47. package/package/components/apps/components/display/dbtable/utils.d.ts +1 -1
  48. package/package/components/apps/components/display/dbtable/utils.js +12 -3
  49. package/package/components/apps/components/display/table/AppAggridExplorerTable.svelte +9 -1
  50. package/package/components/apps/components/display/table/AppAggridExplorerTable.svelte.d.ts +1 -0
  51. package/package/components/apps/components/display/table/AppAggridInfiniteTable.svelte +2 -1
  52. package/package/components/apps/components/display/table/AppAggridInfiniteTable.svelte.d.ts +1 -0
  53. package/package/components/apps/components/display/table/AppAggridInfiniteTableEe.svelte +2 -1
  54. package/package/components/apps/components/display/table/AppAggridInfiniteTableEe.svelte.d.ts +1 -0
  55. package/package/components/apps/components/display/table/AppAggridTable.svelte +9 -1
  56. package/package/components/apps/components/display/table/AppAggridTable.svelte.d.ts +1 -0
  57. package/package/components/apps/components/display/table/AppAggridTableEe.svelte +2 -1
  58. package/package/components/apps/components/display/table/AppAggridTableEe.svelte.d.ts +1 -0
  59. package/package/components/apps/components/helpers/RunnableComponent.svelte +3 -1
  60. package/package/components/apps/components/inputs/AppDateInput.svelte +1 -0
  61. package/package/components/apps/editor/AppEditor.svelte +6 -1
  62. package/package/components/apps/editor/AppEditorHeader.svelte +12 -8
  63. package/package/components/apps/editor/AppJobsDrawer.svelte +5 -5
  64. package/package/components/apps/editor/component/ComponentInner.svelte +4 -0
  65. package/package/components/apps/editor/component/components.d.ts +16 -0
  66. package/package/components/apps/editor/component/components.js +17 -1
  67. package/package/components/apps/editor/settingsPanel/AGChartRichEditor.svelte.d.ts +3 -3
  68. package/package/components/apps/editor/settingsPanel/CSSMigrationModal.svelte.d.ts +3 -3
  69. package/package/components/apps/editor/settingsPanel/ChartJSRichEditor.svelte.d.ts +3 -3
  70. package/package/components/apps/editor/settingsPanel/ComponentInputTypeEditor.svelte +23 -23
  71. package/package/components/apps/editor/settingsPanel/EventHandlers.svelte +7 -2
  72. package/package/components/apps/editor/settingsPanel/InputsSpecEditor.svelte +1 -0
  73. package/package/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte +2 -1
  74. package/package/components/apps/editor/settingsPanel/inputEditor/DBTableSelect.svelte.d.ts +3 -3
  75. package/package/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte +10 -0
  76. package/package/components/apps/inputType.d.ts +2 -2
  77. package/package/components/auditLogs/AuditLogsFilters.svelte.d.ts +1 -1
  78. package/package/components/common/button/ConnectionButton.svelte +12 -14
  79. package/package/components/common/button/ConnectionButton.svelte.d.ts +5 -18
  80. package/package/components/copilot/AIFormAssistant.svelte.d.ts +3 -3
  81. package/package/components/copilot/AIFormSettings.svelte.d.ts +3 -3
  82. package/package/components/copilot/FlowInlineScriptAIButton.svelte.d.ts +3 -3
  83. package/package/components/copilot/StepInputsGen.svelte +1 -1
  84. package/package/components/copilot/TestAIKey.svelte.d.ts +3 -3
  85. package/package/components/copilot/chat/AIChat.svelte.d.ts +3 -3
  86. package/package/components/copilot/chat/AIChatDisplay.svelte.d.ts +3 -3
  87. package/package/components/copilot/chat/AIChatInlineWidget.svelte.d.ts +3 -3
  88. package/package/components/copilot/chat/AIChatInput.svelte.d.ts +3 -3
  89. package/package/components/copilot/chat/AIChatMessage.svelte.d.ts +3 -3
  90. package/package/components/copilot/chat/ContextElementBadge.svelte +2 -2
  91. package/package/components/copilot/chat/flow/AIChangesWarningModal.svelte.d.ts +3 -3
  92. package/package/components/copilot/chat/flow/FlowAIButton.svelte.d.ts +3 -3
  93. package/package/components/copilot/chat/flow/FlowAIChat.svelte +4 -1
  94. package/package/components/copilot/chat/flow/FlowAIChat.svelte.d.ts +3 -3
  95. package/package/components/copilot/chat/script/CodeDisplay.svelte +30 -9
  96. package/package/components/copilot/chat/script/core.d.ts +2 -1
  97. package/package/components/copilot/chat/script/core.js +6 -1
  98. package/package/components/details/DetailPageLayout.svelte +11 -3
  99. package/package/components/details/DetailPageLayout.svelte.d.ts +1 -0
  100. package/package/components/flows/content/DynamicInputHelpBox.svelte +4 -4
  101. package/package/components/flows/content/FlowInput.svelte +1 -1
  102. package/package/components/flows/content/FlowInputsQuick.svelte +1 -1
  103. package/package/components/flows/content/FlowLoop.svelte +143 -10
  104. package/package/components/flows/conversations/FlowChatInterface.svelte +110 -0
  105. package/package/components/flows/{FlowChatInterface.svelte.d.ts → conversations/FlowChatInterface.svelte.d.ts} +1 -1
  106. package/package/components/flows/conversations/FlowChatManager.svelte.d.ts +52 -0
  107. package/package/components/flows/conversations/FlowChatManager.svelte.js +422 -0
  108. package/package/components/flows/conversations/FlowChatMessage.svelte +68 -0
  109. package/package/components/flows/{FlowChatMessage.svelte.d.ts → conversations/FlowChatMessage.svelte.d.ts} +2 -4
  110. package/package/components/flows/{FlowConversationsSidebar.svelte → conversations/FlowConversationsSidebar.svelte} +6 -6
  111. package/package/components/flows/flowInfers.js +1 -1
  112. package/package/components/flows/scheduleUtils.js +2 -1
  113. package/package/components/graph/renderers/nodes/AIToolNode.svelte.d.ts +3 -3
  114. package/package/components/graph/renderers/nodes/NewAIToolNode.svelte.d.ts +3 -3
  115. package/package/components/icons/CACertificate.svelte.d.ts +3 -3
  116. package/package/components/icons/MSSqlServerIcon.svelte.d.ts +3 -3
  117. package/package/components/icons/MSTeamsIcon.svelte.d.ts +3 -3
  118. package/package/components/icons/OracleDBIcon.svelte.d.ts +3 -3
  119. package/package/components/icons/PHPIcon.svelte.d.ts +3 -3
  120. package/package/components/icons/QRCodeIcon.svelte.d.ts +3 -3
  121. package/package/components/instanceSettings.js +11 -2
  122. package/package/components/runs/JobsLoader.svelte +3 -3
  123. package/package/components/runs/RunRow.svelte +1 -1
  124. package/package/components/schema/SchemaFormDND.svelte.d.ts +3 -3
  125. package/package/components/settings/AIUserSettings.svelte.d.ts +3 -3
  126. package/package/components/sidebar/SidebarContent.svelte +2 -2
  127. package/package/components/text_input/TextInput.svelte.d.ts +1 -1
  128. package/package/components/triggers/http/OpenAPISpecGenerator.svelte.d.ts +3 -3
  129. package/package/components/triggers/schedules/ScheduleEditorInner.svelte +42 -1
  130. package/package/components/vscode.js +16 -12
  131. package/package/components/wizards/ChartJSWizard.svelte.d.ts +3 -3
  132. package/package/components/wizards/DBExplorerWizard.svelte.d.ts +3 -3
  133. package/package/components/wizards/LoggedWizardResult.svelte +95 -0
  134. package/package/components/wizards/LoggedWizardResult.svelte.d.ts +17 -0
  135. package/package/components/workspaceSettings/AISettings.svelte.d.ts +3 -3
  136. package/package/components/workspaceSettings/DucklakeSettings.svelte +223 -89
  137. package/package/gen/core/OpenAPI.js +1 -1
  138. package/package/gen/schemas.gen.d.ts +73 -5
  139. package/package/gen/schemas.gen.js +73 -5
  140. package/package/gen/services.gen.d.ts +8 -8
  141. package/package/gen/services.gen.js +14 -12
  142. package/package/gen/types.gen.d.ts +69 -18
  143. package/package/svelte5Utils.svelte.d.ts +1 -0
  144. package/package/svelte5Utils.svelte.js +6 -0
  145. package/package/utils.js +2 -5
  146. package/package.json +11 -13
  147. package/package/components/flows/FlowChatInterface.svelte +0 -404
  148. package/package/components/flows/FlowChatMessage.svelte +0 -41
  149. package/package/components/meltComponents/Menubar.svelte.d.ts +0 -503
  150. /package/package/components/flows/{FlowConversationsSidebar.svelte.d.ts → conversations/FlowConversationsSidebar.svelte.d.ts} +0 -0
@@ -0,0 +1,422 @@
1
+ import { FlowConversationService } from '../../../gen';
2
+ import { sendUserToast } from '../../../toast';
3
+ import { waitJob } from '../../waitJob';
4
+ import { tick } from 'svelte';
5
+ class FlowChatManager {
6
+ // State
7
+ messages = $state([]);
8
+ inputMessage = $state('');
9
+ isLoading = $state(false);
10
+ isLoadingMessages = $state(false);
11
+ isWaitingForResponse = $state(false);
12
+ messagesContainer = $state(undefined);
13
+ inputElement = $state(undefined);
14
+ page = $state(1);
15
+ hasMoreMessages = $state(false);
16
+ loadingMoreMessages = $state(false);
17
+ currentEventSource = $state(undefined);
18
+ pollingInterval = $state(undefined);
19
+ // Private state
20
+ #conversationsCache = $state({});
21
+ #scrollTimeout = undefined;
22
+ #perPage = 50;
23
+ #workspace = $state(undefined);
24
+ // Options
25
+ #onRunFlow;
26
+ #createConversation;
27
+ #refreshConversations;
28
+ #conversationId = $state(undefined);
29
+ #useStreaming = $state(false);
30
+ #path = $state(undefined);
31
+ initialize(options, workspace) {
32
+ this.#onRunFlow = options.onRunFlow;
33
+ this.#createConversation = options.createConversation;
34
+ this.#refreshConversations = options.refreshConversations;
35
+ this.#conversationId = options.conversationId;
36
+ this.#useStreaming = options.useStreaming ?? false;
37
+ this.#path = options.path;
38
+ this.#workspace = workspace;
39
+ }
40
+ updateConversationId(conversationId) {
41
+ this.#conversationId = conversationId;
42
+ }
43
+ cleanup() {
44
+ if (this.currentEventSource) {
45
+ this.currentEventSource.close();
46
+ this.currentEventSource = undefined;
47
+ }
48
+ this.stopPolling();
49
+ this.isLoading = false;
50
+ this.isWaitingForResponse = false;
51
+ }
52
+ // Public methods for component to call
53
+ fillInputMessage(message) {
54
+ this.inputMessage = message;
55
+ }
56
+ focusInput() {
57
+ this.inputElement?.focus();
58
+ }
59
+ clearMessages() {
60
+ this.messages = [];
61
+ this.inputMessage = '';
62
+ this.page = 1;
63
+ }
64
+ async loadConversationMessages(conversationId) {
65
+ this.page = 1;
66
+ await this.loadMessages(true, conversationId);
67
+ }
68
+ // Message loading
69
+ async loadMessages(reset, conversationId) {
70
+ let conversationIdToUse = conversationId ?? this.#conversationId;
71
+ if (!this.#workspace || !conversationIdToUse)
72
+ return;
73
+ if (reset) {
74
+ if (this.#conversationsCache[conversationIdToUse]) {
75
+ this.messages = this.#conversationsCache[conversationIdToUse];
76
+ return;
77
+ }
78
+ this.isLoadingMessages = true;
79
+ }
80
+ else {
81
+ this.loadingMoreMessages = true;
82
+ }
83
+ const pageToFetch = reset ? 1 : this.page + 1;
84
+ try {
85
+ const previousScrollHeight = this.messagesContainer?.scrollHeight || 0;
86
+ const response = await FlowConversationService.listConversationMessages({
87
+ workspace: this.#workspace,
88
+ conversationId: conversationIdToUse,
89
+ page: pageToFetch,
90
+ perPage: this.#perPage
91
+ });
92
+ if (reset) {
93
+ this.#conversationsCache[conversationIdToUse] = response;
94
+ this.messages = response;
95
+ this.isLoadingMessages = false;
96
+ await new Promise((resolve) => setTimeout(resolve, 100));
97
+ this.scrollToBottom();
98
+ }
99
+ else {
100
+ this.messages = [...response, ...this.messages];
101
+ this.page = pageToFetch;
102
+ // Restore scroll position
103
+ await new Promise((resolve) => setTimeout(resolve, 50));
104
+ if (this.messagesContainer) {
105
+ this.messagesContainer.scrollTop =
106
+ this.messagesContainer.scrollHeight - previousScrollHeight;
107
+ }
108
+ }
109
+ this.hasMoreMessages = response.length === this.#perPage;
110
+ }
111
+ catch (error) {
112
+ console.error('Failed to load messages:', error);
113
+ sendUserToast('Failed to load messages: ' + error);
114
+ }
115
+ finally {
116
+ this.isLoadingMessages = false;
117
+ this.loadingMoreMessages = false;
118
+ }
119
+ }
120
+ handleScroll = () => {
121
+ if (this.#scrollTimeout)
122
+ clearTimeout(this.#scrollTimeout);
123
+ this.#scrollTimeout = setTimeout(() => {
124
+ if (!this.messagesContainer || !this.hasMoreMessages || this.loadingMoreMessages)
125
+ return;
126
+ if (this.messagesContainer.scrollTop <= 10) {
127
+ this.loadMessages(false);
128
+ }
129
+ }, 200);
130
+ };
131
+ scrollToBottom() {
132
+ if (this.messagesContainer) {
133
+ this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;
134
+ }
135
+ }
136
+ scrollToUserMessage(messageId) {
137
+ if (!this.messagesContainer)
138
+ return;
139
+ const messageElement = this.messagesContainer.querySelector(`[data-message-id="${messageId}"]`);
140
+ if (messageElement) {
141
+ messageElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
142
+ }
143
+ }
144
+ // Polling
145
+ async pollJobResult(jobId) {
146
+ try {
147
+ await waitJob(jobId);
148
+ }
149
+ catch (error) {
150
+ console.error('Error polling job result:', error);
151
+ }
152
+ finally {
153
+ // Do a final poll to get all messages from database
154
+ try {
155
+ if (this.#conversationId) {
156
+ await this.pollConversationMessages(this.#conversationId);
157
+ }
158
+ }
159
+ catch { }
160
+ this.cleanup();
161
+ }
162
+ }
163
+ parseStreamDeltas(streamData) {
164
+ let type = 'message';
165
+ const lines = streamData.trim().split('\n');
166
+ let content = '';
167
+ let success = true;
168
+ for (const line of lines) {
169
+ if (!line.trim())
170
+ continue;
171
+ try {
172
+ const parsed = JSON.parse(line);
173
+ if (parsed.type === 'tool_result') {
174
+ type = 'tool_result';
175
+ const toolName = parsed.function_name;
176
+ success = parsed.success;
177
+ content = success ? `Used ${toolName} tool` : `Failed to use ${toolName} tool`;
178
+ }
179
+ if (parsed.type === 'token_delta' && parsed.content) {
180
+ type = 'message';
181
+ content += parsed.content;
182
+ }
183
+ }
184
+ catch (e) {
185
+ console.error('Failed to parse stream line:', line, e);
186
+ }
187
+ }
188
+ return { type, content, success };
189
+ }
190
+ async pollConversationMessages(conversationId, isNewConversation) {
191
+ if (!this.#workspace)
192
+ return;
193
+ try {
194
+ const lastId = this.messages[this.messages.length - 1].id;
195
+ const response = await FlowConversationService.listConversationMessages({
196
+ workspace: this.#workspace,
197
+ conversationId: conversationId,
198
+ page: 1,
199
+ perPage: 50,
200
+ afterId: lastId
201
+ });
202
+ if (isNewConversation) {
203
+ await this.#refreshConversations?.();
204
+ }
205
+ const filteredResponse = response.filter((msg) => msg.message_type !== 'user');
206
+ // Add any new intermediate messages not already present
207
+ for (const msg of filteredResponse) {
208
+ if (!this.messages.find((m) => m.id === msg.id)) {
209
+ this.messages = [...this.messages, msg];
210
+ }
211
+ }
212
+ // Remove temporary messages
213
+ this.messages = this.messages.filter((msg) => !msg.id.startsWith('temp-'));
214
+ }
215
+ catch (error) {
216
+ console.error('Polling error:', error);
217
+ }
218
+ }
219
+ startPolling(conversationId, isNewConversation) {
220
+ if (this.pollingInterval)
221
+ return;
222
+ this.pollingInterval = setInterval(() => {
223
+ this.pollConversationMessages(conversationId, isNewConversation);
224
+ }, 500); // Poll every 0.5 seconds
225
+ setTimeout(() => {
226
+ this.stopPolling();
227
+ }, 2 * 60 * 1000); // Stop polling after 2 minutes
228
+ }
229
+ stopPolling() {
230
+ if (this.pollingInterval) {
231
+ clearInterval(this.pollingInterval);
232
+ this.pollingInterval = undefined;
233
+ }
234
+ }
235
+ // Message sending
236
+ async sendMessage() {
237
+ if (!this.inputMessage.trim() || this.isLoading)
238
+ return;
239
+ const isNewConversation = this.messages.length === 0;
240
+ // Reset state for new message
241
+ this.stopPolling();
242
+ // Generate a new conversation ID if we don't have one
243
+ let currentConversationId = this.#conversationId;
244
+ if (!this.#conversationId && this.#createConversation) {
245
+ const newConversationId = await this.#createConversation({ clearMessages: false });
246
+ currentConversationId = newConversationId;
247
+ }
248
+ if (!currentConversationId) {
249
+ console.error('No conversation ID found');
250
+ return;
251
+ }
252
+ // Invalidate the conversation cache
253
+ delete this.#conversationsCache[currentConversationId];
254
+ const userMessage = {
255
+ id: crypto.randomUUID(),
256
+ content: this.inputMessage.trim(),
257
+ created_at: new Date().toISOString(),
258
+ message_type: 'user',
259
+ conversation_id: currentConversationId
260
+ };
261
+ this.messages = [...this.messages, userMessage];
262
+ const messageContent = this.inputMessage.trim();
263
+ this.inputMessage = '';
264
+ this.isLoading = true;
265
+ this.isWaitingForResponse = true;
266
+ try {
267
+ await tick();
268
+ this.scrollToUserMessage(userMessage.id);
269
+ if (this.#useStreaming && this.#path) {
270
+ await this.handleStreamingMessage(messageContent, currentConversationId, isNewConversation);
271
+ }
272
+ else {
273
+ await this.handlePollingMessage(messageContent, currentConversationId, isNewConversation);
274
+ }
275
+ }
276
+ catch (error) {
277
+ console.error('Error running flow:', error);
278
+ sendUserToast('Failed to run flow: ' + error, true);
279
+ }
280
+ finally {
281
+ if (!this.#useStreaming) {
282
+ this.isLoading = false;
283
+ }
284
+ }
285
+ await tick();
286
+ this.focusInput();
287
+ }
288
+ async handleStreamingMessage(messageContent, currentConversationId, isNewConversation) {
289
+ // Close any existing EventSource
290
+ if (this.currentEventSource) {
291
+ this.currentEventSource.close();
292
+ }
293
+ // Track stream state for this message
294
+ let accumulatedContent = '';
295
+ let assistantMessageId = '';
296
+ let isCompleted = false;
297
+ try {
298
+ // Encode the payload as base64
299
+ const payload = { user_message: messageContent };
300
+ const payloadBase64 = btoa(JSON.stringify(payload));
301
+ // Build the EventSource URL
302
+ const streamUrl = `/api/w/${this.#workspace}/jobs/run_and_stream/f/${this.#path}`;
303
+ const url = new URL(streamUrl, window.location.origin);
304
+ url.searchParams.set('payload', payloadBase64);
305
+ url.searchParams.set('memory_id', currentConversationId);
306
+ url.searchParams.set('poll_delay_ms', '50');
307
+ // Create EventSource connection
308
+ const eventSource = new EventSource(url.toString());
309
+ this.currentEventSource = eventSource;
310
+ // start polling
311
+ this.startPolling(currentConversationId, isNewConversation);
312
+ eventSource.onmessage = async (event) => {
313
+ try {
314
+ const data = JSON.parse(event.data);
315
+ if (data.type === 'update') {
316
+ // Process new stream content
317
+ if (data.new_result_stream) {
318
+ // Stop polling since we are receiving last step streaming
319
+ this.stopPolling();
320
+ const { type, content: newContent, success } = this.parseStreamDeltas(data.new_result_stream);
321
+ accumulatedContent += newContent;
322
+ if (accumulatedContent.length > 0 || type === 'tool_result') {
323
+ this.isWaitingForResponse = false;
324
+ }
325
+ // Create tool message if type is tool_result
326
+ if (type === 'tool_result') {
327
+ // set last message streaming to false
328
+ this.messages = this.messages.map((msg) => msg.id === this.messages[this.messages.length - 1].id
329
+ ? { ...msg, streaming: false }
330
+ : msg);
331
+ this.messages = [
332
+ ...this.messages,
333
+ {
334
+ id: 'temp-' + crypto.randomUUID(),
335
+ content: newContent,
336
+ created_at: new Date().toISOString(),
337
+ message_type: 'tool',
338
+ conversation_id: currentConversationId,
339
+ job_id: '',
340
+ loading: false,
341
+ streaming: false,
342
+ success
343
+ }
344
+ ];
345
+ // Reset assistant message ID since we are creating a tool message
346
+ assistantMessageId = '';
347
+ accumulatedContent = '';
348
+ }
349
+ // Create message on first content
350
+ else if (type === 'message' &&
351
+ assistantMessageId.length === 0 &&
352
+ accumulatedContent.length > 0) {
353
+ assistantMessageId = 'temp-' + crypto.randomUUID();
354
+ this.messages = [
355
+ ...this.messages,
356
+ {
357
+ id: assistantMessageId,
358
+ content: accumulatedContent,
359
+ created_at: new Date().toISOString(),
360
+ message_type: 'assistant',
361
+ conversation_id: currentConversationId,
362
+ job_id: '',
363
+ loading: false,
364
+ streaming: true
365
+ }
366
+ ];
367
+ }
368
+ else {
369
+ // Update existing message
370
+ this.messages = this.messages.map((msg) => msg.id === assistantMessageId ? { ...msg, content: accumulatedContent } : msg);
371
+ }
372
+ }
373
+ // Handle completion
374
+ if (data.completed) {
375
+ isCompleted = true;
376
+ // Do a final poll to get all messages from database
377
+ if (this.#conversationId) {
378
+ await this.pollConversationMessages(this.#conversationId);
379
+ }
380
+ this.cleanup();
381
+ }
382
+ }
383
+ }
384
+ catch (error) {
385
+ console.error('Error processing stream event:', error);
386
+ }
387
+ };
388
+ eventSource.onerror = (error) => {
389
+ if (isCompleted)
390
+ return;
391
+ console.error('EventSource error:', error);
392
+ sendUserToast('Stream error occurred', true);
393
+ this.cleanup();
394
+ };
395
+ }
396
+ catch (error) {
397
+ console.error('Stream connection error:', error);
398
+ sendUserToast('Failed to connect to stream', true);
399
+ this.cleanup();
400
+ }
401
+ }
402
+ async handlePollingMessage(messageContent, currentConversationId, isNewConversation) {
403
+ const jobId = await this.#onRunFlow?.(messageContent, currentConversationId);
404
+ if (!jobId) {
405
+ console.error('No jobId returned from onRunFlow');
406
+ return;
407
+ }
408
+ if (isNewConversation) {
409
+ await this.#refreshConversations?.();
410
+ }
411
+ // Start polling for intermediate messages in non-streaming mode too
412
+ this.startPolling(currentConversationId);
413
+ this.pollJobResult(jobId);
414
+ }
415
+ handleKeyDown = (event) => {
416
+ if (event.key === 'Enter' && !event.shiftKey) {
417
+ event.preventDefault();
418
+ this.sendMessage();
419
+ }
420
+ };
421
+ }
422
+ export const createFlowChatManager = () => new FlowChatManager();
@@ -0,0 +1,68 @@
1
+ <script lang="ts">import { Markdown } from 'svelte-exmarkdown';
2
+ import { gfmPlugin } from 'svelte-exmarkdown/gfm';
3
+ import { Loader2, CheckCircle2, AlertTriangle } from 'lucide-svelte';
4
+ import CodeDisplay from '../../copilot/chat/script/CodeDisplay.svelte';
5
+ import LinkRenderer from '../../copilot/chat/LinkRenderer.svelte';
6
+ import {} from './FlowChatManager.svelte';
7
+ let { message } = $props();
8
+ </script>
9
+
10
+ <div
11
+ class={`flex ${message.message_type === 'user' ? 'justify-end' : 'justify-start'} ${message.loading || message.streaming ? 'min-h-[200px] items-start' : ''}`}
12
+ data-message-id={message.id}
13
+ >
14
+ <div
15
+ class="max-w-[90%] min-w-0 rounded-lg
16
+ {message.message_type === 'user'
17
+ ? 'bg-surface-secondary p-3'
18
+ : `bg-surface border ${message.success !== false ? 'border-gray-200 dark:border-gray-600' : '!border-red-500'}`}"
19
+ >
20
+ {#if message.step_name}
21
+ <div
22
+ class="bg-surface-secondary text-2xs text-tertiary mb-2 font-medium py-1 px-2 rounded-t-lg"
23
+ >{message.step_name}</div
24
+ >
25
+ {/if}
26
+
27
+ {#if message.message_type === 'user'}
28
+ <p class="whitespace-pre-wrap text-sm break-words">{message.content}</p>
29
+ {:else if message.loading}
30
+ <div class="flex items-center gap-2 text-tertiary">
31
+ <Loader2 size={16} class="animate-spin" />
32
+ <span>Processing...</span>
33
+ </div>
34
+ {:else if message.content}
35
+ <div
36
+ class="flex flex-row items-center gap-2 px-3 pb-3 text-sm {!message.step_name
37
+ ? 'pt-3'
38
+ : ''}"
39
+ >
40
+ {#if message.message_type === 'tool'}
41
+ {#if message.success !== false}
42
+ <CheckCircle2 class="w-3.5 h-3.5 text-green-500" />
43
+ {:else}
44
+ <AlertTriangle class="w-3.5 h-3.5 text-red-500" />
45
+ {/if}
46
+ {/if}
47
+ <div
48
+ class="prose prose-sm dark:prose-invert break-words whitespace-pre-wrap prose-headings:!text-base"
49
+ >
50
+ <Markdown
51
+ md={message.content}
52
+ plugins={[
53
+ gfmPlugin(),
54
+ {
55
+ renderer: {
56
+ pre: CodeDisplay,
57
+ a: LinkRenderer
58
+ }
59
+ }
60
+ ]}
61
+ />
62
+ </div>
63
+ </div>
64
+ {:else}
65
+ <p class="text-tertiary text-sm">No result</p>
66
+ {/if}
67
+ </div>
68
+ </div>
@@ -1,8 +1,6 @@
1
- import type { FlowConversationMessage } from '../../gen';
1
+ import { type ChatMessage } from './FlowChatManager.svelte';
2
2
  interface Props {
3
- message: FlowConversationMessage & {
4
- loading?: boolean;
5
- };
3
+ message: ChatMessage;
6
4
  }
7
5
  declare const FlowChatMessage: import("svelte").Component<Props, {}, "">;
8
6
  type FlowChatMessage = ReturnType<typeof FlowChatMessage>;
@@ -1,10 +1,10 @@
1
- <script lang="ts">import { Button } from '../common';
1
+ <script lang="ts">import { Button } from '../../common';
2
2
  import { MessageCircle, Plus, Trash2, PanelLeftClose, PanelLeftOpen, Loader2 } from 'lucide-svelte';
3
- import { workspaceStore } from '../../stores';
4
- import { FlowConversationService } from '../../gen';
5
- import { sendUserToast } from '../../toast';
6
- import CountBadge from '../common/badge/CountBadge.svelte';
7
- import InfiniteList from '../InfiniteList.svelte';
3
+ import { workspaceStore } from '../../../stores';
4
+ import { FlowConversationService } from '../../../gen';
5
+ import { sendUserToast } from '../../../toast';
6
+ import CountBadge from '../../common/badge/CountBadge.svelte';
7
+ import InfiniteList from '../../InfiniteList.svelte';
8
8
  import { untrack } from 'svelte';
9
9
  import { twMerge } from 'tailwind-merge';
10
10
  let { flowPath, selectedConversationId, onNewConversation, onSelectConversation, onDeleteConversation } = $props();
@@ -25,7 +25,7 @@ export const AI_AGENT_SCHEMA = {
25
25
  streaming: {
26
26
  type: 'boolean',
27
27
  description: 'Whether to stream the output of the AI agent.',
28
- default: false,
28
+ default: true,
29
29
  showExpr: "fields.output_type === 'text'"
30
30
  },
31
31
  messages_context_length: {
@@ -141,7 +141,8 @@ export async function saveScheduleFromCfg(scheduleCfg, edit, workspace) {
141
141
  no_flow_overlap: scheduleCfg.no_flow_overlap,
142
142
  tag: scheduleCfg.tag,
143
143
  paused_until: scheduleCfg.paused_until,
144
- cron_version: scheduleCfg.cron_version
144
+ cron_version: scheduleCfg.cron_version,
145
+ dynamic_skip: scheduleCfg.dynamic_skip
145
146
  };
146
147
  try {
147
148
  if (edit) {
@@ -19,6 +19,6 @@ import type { GraphModuleState } from '../../model';
19
19
  interface Props {
20
20
  data: AiToolN['data'];
21
21
  }
22
- declare const AiToolNode: import("svelte").Component<Props, {}, "">;
23
- type AiToolNode = ReturnType<typeof AiToolNode>;
24
- export default AiToolNode;
22
+ declare const AIToolNode: import("svelte").Component<Props, {}, "">;
23
+ type AIToolNode = ReturnType<typeof AIToolNode>;
24
+ export default AIToolNode;
@@ -2,6 +2,6 @@ import { type NewAiToolN } from '../../graphBuilder.svelte';
2
2
  interface Props {
3
3
  data: NewAiToolN['data'];
4
4
  }
5
- declare const NewAiToolNode: import("svelte").Component<Props, {}, "">;
6
- type NewAiToolNode = ReturnType<typeof NewAiToolNode>;
7
- export default NewAiToolNode;
5
+ declare const NewAIToolNode: import("svelte").Component<Props, {}, "">;
6
+ type NewAIToolNode = ReturnType<typeof NewAIToolNode>;
7
+ export default NewAIToolNode;
@@ -2,6 +2,6 @@ interface Props {
2
2
  height?: string;
3
3
  width?: string;
4
4
  }
5
- declare const CaCertificate: import("svelte").Component<Props, {}, "">;
6
- type CaCertificate = ReturnType<typeof CaCertificate>;
7
- export default CaCertificate;
5
+ declare const CACertificate: import("svelte").Component<Props, {}, "">;
6
+ type CACertificate = ReturnType<typeof CACertificate>;
7
+ export default CACertificate;
@@ -2,6 +2,6 @@ interface Props {
2
2
  height?: string;
3
3
  width?: string;
4
4
  }
5
- declare const MsSqlServerIcon: import("svelte").Component<Props, {}, "">;
6
- type MsSqlServerIcon = ReturnType<typeof MsSqlServerIcon>;
7
- export default MsSqlServerIcon;
5
+ declare const MSSqlServerIcon: import("svelte").Component<Props, {}, "">;
6
+ type MSSqlServerIcon = ReturnType<typeof MSSqlServerIcon>;
7
+ export default MSSqlServerIcon;
@@ -2,6 +2,6 @@ interface Props {
2
2
  height?: string;
3
3
  width?: string;
4
4
  }
5
- declare const MsTeamsIcon: import("svelte").Component<Props, {}, "">;
6
- type MsTeamsIcon = ReturnType<typeof MsTeamsIcon>;
7
- export default MsTeamsIcon;
5
+ declare const MSTeamsIcon: import("svelte").Component<Props, {}, "">;
6
+ type MSTeamsIcon = ReturnType<typeof MSTeamsIcon>;
7
+ export default MSTeamsIcon;
@@ -2,6 +2,6 @@ interface Props {
2
2
  height?: string;
3
3
  width?: string;
4
4
  }
5
- declare const OracleDbIcon: import("svelte").Component<Props, {}, "">;
6
- type OracleDbIcon = ReturnType<typeof OracleDbIcon>;
7
- export default OracleDbIcon;
5
+ declare const OracleDBIcon: import("svelte").Component<Props, {}, "">;
6
+ type OracleDBIcon = ReturnType<typeof OracleDBIcon>;
7
+ export default OracleDBIcon;
@@ -2,6 +2,6 @@ interface Props {
2
2
  height?: string;
3
3
  width?: string;
4
4
  }
5
- declare const PhpIcon: import("svelte").Component<Props, {}, "">;
6
- type PhpIcon = ReturnType<typeof PhpIcon>;
7
- export default PhpIcon;
5
+ declare const PHPIcon: import("svelte").Component<Props, {}, "">;
6
+ type PHPIcon = ReturnType<typeof PHPIcon>;
7
+ export default PHPIcon;
@@ -1,6 +1,6 @@
1
1
  interface Props {
2
2
  height?: number;
3
3
  }
4
- declare const QrCodeIcon: import("svelte").Component<Props, {}, "">;
5
- type QrCodeIcon = ReturnType<typeof QrCodeIcon>;
6
- export default QrCodeIcon;
4
+ declare const QRCodeIcon: import("svelte").Component<Props, {}, "">;
5
+ type QRCodeIcon = ReturnType<typeof QRCodeIcon>;
6
+ export default QRCodeIcon;
@@ -128,7 +128,7 @@ export const settings = {
128
128
  },
129
129
  {
130
130
  label: 'Private Hub base url',
131
- description: 'Base URL of your private Hub instance, without trailing slash. <a href="https://www.windmill.dev/docs/core_concepts/private_hub">Learn more</a>',
131
+ description: 'Base URL of your Private Hub instance, without trailing slash. <a href="https://www.windmill.dev/docs/core_concepts/private_hub">Learn more</a>',
132
132
  placeholder: 'https://hub.company.com',
133
133
  key: 'hub_base_url',
134
134
  fieldType: 'text',
@@ -159,6 +159,15 @@ export const settings = {
159
159
  ee_only: '',
160
160
  requiresReloadOnChange: true
161
161
  },
162
+ {
163
+ label: 'Private Hub API secret',
164
+ description: 'If access to your Private Hub is restricted, you can set the hub API secret here. <a href="https://www.windmill.dev/docs/core_concepts/private_hub">Learn more</a>',
165
+ key: 'hub_api_secret',
166
+ fieldType: 'password',
167
+ storage: 'setting',
168
+ ee_only: '',
169
+ requiresReloadOnChange: true
170
+ },
162
171
  {
163
172
  label: 'App workspace prefix',
164
173
  description: 'When enabled apps will be accessible at /a/{workspace_id}/{custom_path} instead of /a/{custom_path} allowing you to define same custom path for apps in different workspace without conflict',
@@ -285,7 +294,7 @@ export const settings = {
285
294
  label: 'PowerShell Repository PAT',
286
295
  description: 'Add private PowerShell repository Personal Access Token',
287
296
  key: 'powershell_repo_pat',
288
- fieldType: 'text',
297
+ fieldType: 'password',
289
298
  storage: 'setting',
290
299
  ee_only: ''
291
300
  }