@flowdrop/flowdrop 1.11.0 → 1.13.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.
Files changed (84) hide show
  1. package/dist/api/enhanced-client.d.ts +29 -16
  2. package/dist/api/enhanced-client.js +0 -14
  3. package/dist/components/ConfigForm.svelte +1 -0
  4. package/dist/components/PipelineStatus.svelte +9 -12
  5. package/dist/components/SchemaForm.svelte +1 -0
  6. package/dist/components/WorkflowEditor.svelte +3 -0
  7. package/dist/components/form/FormAutocomplete.svelte +67 -10
  8. package/dist/components/form/FormField.svelte +21 -0
  9. package/dist/components/form/FormFieldLight.svelte +1 -0
  10. package/dist/components/interrupt/ChoicePrompt.svelte +24 -5
  11. package/dist/components/interrupt/ConfirmationPrompt.svelte +5 -0
  12. package/dist/components/interrupt/InterruptBubble.svelte +88 -17
  13. package/dist/components/interrupt/InterruptBubble.svelte.d.ts +11 -0
  14. package/dist/components/interrupt/ReviewPrompt.svelte +20 -0
  15. package/dist/components/interrupt/TextInputPrompt.svelte +5 -0
  16. package/dist/components/nodes/GatewayNode.svelte +2 -6
  17. package/dist/components/nodes/WorkflowNode.svelte +2 -6
  18. package/dist/components/playground/ChatBubble.svelte +289 -0
  19. package/dist/components/playground/ChatBubble.svelte.d.ts +10 -0
  20. package/dist/components/playground/ChatInput.svelte +359 -0
  21. package/dist/components/playground/ChatInput.svelte.d.ts +14 -0
  22. package/dist/components/playground/ChatPanel.svelte +100 -724
  23. package/dist/components/playground/ChatPanel.svelte.d.ts +9 -26
  24. package/dist/components/playground/ControlPanel.svelte +496 -0
  25. package/dist/components/playground/ControlPanel.svelte.d.ts +20 -0
  26. package/dist/components/playground/ExecutionConsole.svelte +163 -0
  27. package/dist/components/playground/ExecutionConsole.svelte.d.ts +14 -0
  28. package/dist/components/playground/HierarchyTrail.svelte +88 -0
  29. package/dist/components/playground/HierarchyTrail.svelte.d.ts +7 -0
  30. package/dist/components/playground/LogRow.svelte +178 -0
  31. package/dist/components/playground/LogRow.svelte.d.ts +8 -0
  32. package/dist/components/playground/MessageBubble.stories.svelte +89 -0
  33. package/dist/components/playground/MessageBubble.svelte +25 -737
  34. package/dist/components/playground/MessageBubble.svelte.d.ts +3 -11
  35. package/dist/components/playground/MessageCard.svelte +106 -0
  36. package/dist/components/playground/MessageCard.svelte.d.ts +10 -0
  37. package/dist/components/playground/MessageMarkdown.svelte +160 -0
  38. package/dist/components/playground/MessageMarkdown.svelte.d.ts +7 -0
  39. package/dist/components/playground/MessageNotice.svelte +120 -0
  40. package/dist/components/playground/MessageNotice.svelte.d.ts +9 -0
  41. package/dist/components/playground/MessageStream.svelte +367 -0
  42. package/dist/components/playground/MessageStream.svelte.d.ts +27 -0
  43. package/dist/components/playground/MessageTagChip.svelte +99 -0
  44. package/dist/components/playground/MessageTagChip.svelte.d.ts +7 -0
  45. package/dist/components/playground/MessageTagStrip.svelte +37 -0
  46. package/dist/components/playground/MessageTagStrip.svelte.d.ts +7 -0
  47. package/dist/components/playground/PipelineKanbanView.svelte +284 -0
  48. package/dist/components/playground/PipelineKanbanView.svelte.d.ts +11 -0
  49. package/dist/components/playground/PipelinePanel.svelte +204 -65
  50. package/dist/components/playground/PipelinePanel.svelte.d.ts +3 -1
  51. package/dist/components/playground/PipelineTableView.svelte +376 -0
  52. package/dist/components/playground/PipelineTableView.svelte.d.ts +11 -0
  53. package/dist/components/playground/Playground.svelte +262 -1200
  54. package/dist/components/playground/Playground.svelte.d.ts +0 -13
  55. package/dist/components/playground/PlaygroundStudio.svelte +113 -61
  56. package/dist/components/playground/PlaygroundStudio.svelte.d.ts +3 -1
  57. package/dist/components/playground/messageDisplay.d.ts +19 -0
  58. package/dist/components/playground/messageDisplay.js +62 -0
  59. package/dist/components/playground/pipelineViewUtils.svelte.d.ts +22 -0
  60. package/dist/components/playground/pipelineViewUtils.svelte.js +77 -0
  61. package/dist/form/autocomplete.d.ts +1 -0
  62. package/dist/form/autocomplete.js +1 -0
  63. package/dist/form/index.d.ts +17 -0
  64. package/dist/form/index.js +19 -0
  65. package/dist/messages/defaults.d.ts +29 -0
  66. package/dist/messages/defaults.js +30 -0
  67. package/dist/playground/index.d.ts +6 -1
  68. package/dist/playground/index.js +6 -0
  69. package/dist/playground/mount.d.ts +3 -0
  70. package/dist/playground/mount.js +3 -2
  71. package/dist/schemas/v1/workflow.schema.json +10 -1
  72. package/dist/services/categoriesApi.d.ts +2 -1
  73. package/dist/services/categoriesApi.js +5 -3
  74. package/dist/services/portConfigApi.d.ts +2 -1
  75. package/dist/services/portConfigApi.js +5 -3
  76. package/dist/stores/playgroundStore.svelte.d.ts +6 -0
  77. package/dist/stores/playgroundStore.svelte.js +21 -1
  78. package/dist/svelte-app.d.ts +1 -0
  79. package/dist/svelte-app.js +5 -5
  80. package/dist/types/index.d.ts +41 -2
  81. package/dist/types/playground.d.ts +81 -2
  82. package/dist/types/playground.js +19 -7
  83. package/dist/utils/nodeStatus.js +15 -5
  84. package/package.json +6 -1
@@ -1,41 +1,33 @@
1
1
  <!--
2
- MessageBubble Component
3
-
4
- Renders individual messages in the playground chat interface.
5
- Supports different message roles with distinct styling.
6
- Supports markdown rendering for message content.
7
- Supports compact mode for system messages to reduce visual noise.
8
- Styled with BEM syntax.
2
+ MessageBubble — dispatches to a per-layout component based on the server's
3
+ `display` hint (falling back to a role-based default via resolveMessageDisplay).
4
+
5
+ Each layout lives in its own file:
6
+ bubble ChatBubble
7
+ log → LogRow
8
+ notice MessageNotice
9
+ card → MessageCard
9
10
  -->
10
11
 
11
12
  <script lang="ts">
12
- import Icon from '@iconify/svelte';
13
- import { marked } from 'marked';
14
- import { sanitizeHtml } from '../../utils/sanitize.js';
15
- import type {
16
- PlaygroundMessage,
17
- PlaygroundMessageMetadata,
18
- PlaygroundMessageRole
13
+ import {
14
+ resolveMessageDisplay,
15
+ type PlaygroundMessage
19
16
  } from '../../types/playground.js';
20
- import { m } from '../../messages/index.js';
17
+ import ChatBubble from './ChatBubble.svelte';
18
+ import LogRow from './LogRow.svelte';
19
+ import MessageNotice from './MessageNotice.svelte';
20
+ import MessageCard from './MessageCard.svelte';
21
21
 
22
- /**
23
- * Component props
24
- */
25
22
  interface Props {
26
- /** The message to display */
27
23
  message: PlaygroundMessage;
28
- /** Whether to show the timestamp */
29
24
  showTimestamp?: boolean;
30
- /** Whether this is the last message (affects styling) */
31
25
  isLast?: boolean;
32
- /** Whether to render markdown content */
33
26
  enableMarkdown?: boolean;
34
27
  /**
35
28
  * Use compact display mode for system messages.
36
- * When true, system messages are rendered as minimal inline text
37
- * instead of full chat bubbles to reduce visual noise.
38
- * @default true
29
+ * When true (default), system messages without an explicit `display`
30
+ * default to the 'notice' layout instead of 'bubble'.
39
31
  */
40
32
  compactSystemMessages?: boolean;
41
33
  }
@@ -48,719 +40,15 @@
48
40
  compactSystemMessages = true
49
41
  }: Props = $props();
50
42
 
51
- /**
52
- * Determine if this message should render in compact mode.
53
- * Only system messages use compact mode when enabled.
54
- */
55
- const useCompactMode = $derived(message.role === 'system' && compactSystemMessages);
56
-
57
- /**
58
- * Render content as markdown or plain text
59
- */
60
- const renderedContent = $derived(
61
- enableMarkdown && message.role !== 'log'
62
- ? sanitizeHtml(marked.parse(message.content || '') as string)
63
- : message.content
64
- );
65
-
66
- /**
67
- * Get the icon for the message role
68
- *
69
- * @param role - The message role
70
- * @returns Iconify icon string
71
- */
72
- function getRoleIcon(role: PlaygroundMessageRole): string {
73
- switch (role) {
74
- case 'user':
75
- return 'mdi:account';
76
- case 'assistant':
77
- return 'mdi:robot';
78
- case 'system':
79
- return 'mdi:cog';
80
- case 'log':
81
- return 'mdi:console';
82
- default:
83
- return 'mdi:message';
84
- }
85
- }
86
-
87
- /**
88
- * Get the display label for the message role
89
- *
90
- * @param role - The message role
91
- * @param metadata - Optional message metadata containing userName for user messages
92
- * @returns Display label
93
- */
94
- function getRoleLabel(role: PlaygroundMessageRole, metadata?: PlaygroundMessageMetadata): string {
95
- const roles = m().playground.roles;
96
- switch (role) {
97
- case 'user':
98
- return metadata?.userName ?? roles.you;
99
- case 'assistant':
100
- return roles.assistant;
101
- case 'system':
102
- return roles.system;
103
- case 'log':
104
- return metadata?.nodeLabel ?? roles.log;
105
- default:
106
- return roles.message;
107
- }
108
- }
109
-
110
- /**
111
- * Format timestamp for display
112
- *
113
- * @param timestamp - ISO 8601 timestamp
114
- * @returns Formatted time string
115
- */
116
- function formatTimestamp(timestamp: string): string {
117
- const date = new Date(timestamp);
118
- return date.toLocaleTimeString('en-US', {
119
- hour12: false,
120
- hour: '2-digit',
121
- minute: '2-digit',
122
- second: '2-digit'
123
- });
124
- }
125
-
126
- /**
127
- * Get log level icon
128
- */
129
- function getLogLevelIcon(): string {
130
- const level = message.metadata?.level;
131
- switch (level) {
132
- case 'error':
133
- return 'mdi:alert-circle';
134
- case 'warning':
135
- return 'mdi:alert';
136
- case 'debug':
137
- return 'mdi:bug';
138
- default:
139
- return 'mdi:information';
140
- }
141
- }
142
-
143
- /**
144
- * Format duration for display
145
- */
146
- function formatDuration(ms: number): string {
147
- if (ms < 1000) {
148
- return `${ms}ms`;
149
- }
150
- return `${(ms / 1000).toFixed(2)}s`;
151
- }
43
+ const display = $derived(resolveMessageDisplay(message, { compactSystemMessages }));
152
44
  </script>
153
45
 
154
- {#if useCompactMode}
155
- <!-- Compact system message: minimal inline text without bubble -->
156
- <div
157
- class="system-notice"
158
- class:system-notice--last={isLast}
159
- class:system-notice--warning={message.metadata?.level === 'warning'}
160
- class:system-notice--error={message.metadata?.level === 'error'}
161
- class:system-notice--debug={message.metadata?.level === 'debug'}
162
- >
163
- <Icon icon={getLogLevelIcon()} class="system-notice__icon" />
164
- {#if message.metadata?.source}
165
- <span class="system-notice__source">{message.metadata.source}</span>
166
- {/if}
167
- <span class="system-notice__text">{message.content}</span>
168
- {#if showTimestamp}
169
- <span class="system-notice__timestamp">{formatTimestamp(message.timestamp)}</span>
170
- {/if}
171
- </div>
172
- {:else if message.role === 'log'}
173
- <!-- Compact log row: terminal-style entry, visually distinct from chat bubbles -->
174
- <div
175
- class="log-row"
176
- class:log-row--error={message.metadata?.level === 'error'}
177
- class:log-row--warning={message.metadata?.level === 'warning'}
178
- class:log-row--debug={message.metadata?.level === 'debug'}
179
- >
180
- <div class="log-row__level">
181
- <Icon icon={getLogLevelIcon()} />
182
- </div>
183
- <div class="log-row__body">
184
- {#if message.metadata?.source}
185
- <span class="log-row__source">{message.metadata.source}</span>
186
- {/if}
187
- <span class="log-row__node">{message.metadata?.nodeLabel ?? message.nodeId ?? 'log'}</span>
188
- <span class="log-row__text">{message.content}</span>
189
- </div>
190
- {#if showTimestamp}
191
- <span class="log-row__timestamp">{formatTimestamp(message.timestamp)}</span>
192
- {/if}
193
- </div>
46
+ {#if display === 'log'}
47
+ <LogRow {message} {showTimestamp} />
48
+ {:else if display === 'notice'}
49
+ <MessageNotice {message} {showTimestamp} {isLast} />
50
+ {:else if display === 'card'}
51
+ <MessageCard {message} {showTimestamp} {isLast} {enableMarkdown} />
194
52
  {:else}
195
- <div
196
- class="message-bubble"
197
- class:message-bubble--user={message.role === 'user'}
198
- class:message-bubble--assistant={message.role === 'assistant'}
199
- class:message-bubble--system={message.role === 'system'}
200
- class:message-bubble--last={isLast}
201
- >
202
- <!-- Avatar / Icon -->
203
- <div class="message-bubble__avatar">
204
- <Icon icon={getRoleIcon(message.role)} />
205
- </div>
206
-
207
- <!-- Content -->
208
- <div class="message-bubble__content">
209
- <!-- Header -->
210
- <div class="message-bubble__header">
211
- <span class="message-bubble__role">{getRoleLabel(message.role, message.metadata)}</span>
212
- {#if showTimestamp}
213
- <span class="message-bubble__timestamp">{formatTimestamp(message.timestamp)}</span>
214
- {/if}
215
- </div>
216
-
217
- <!-- Message Text -->
218
- <div class="message-bubble__text">
219
- {#if enableMarkdown}
220
- <!-- Markdown content - sanitized with DOMPurify to prevent XSS -->
221
- <!-- eslint-disable-next-line svelte/no-at-html-tags -->
222
- {@html renderedContent}
223
- {:else}
224
- {message.content}
225
- {/if}
226
- </div>
227
-
228
- <!-- Metadata Footer -->
229
- {#if message.metadata?.duration !== undefined || message.nodeId}
230
- <div class="message-bubble__footer">
231
- {#if message.nodeId}
232
- <span
233
- class="message-bubble__node"
234
- title={m().playground.messageTooltips.nodeId({ id: message.nodeId })}
235
- >
236
- <Icon icon="mdi:vector-square" />
237
- via {message.metadata?.nodeLabel ?? message.nodeId}
238
- </span>
239
- {/if}
240
- {#if message.metadata?.duration !== undefined}
241
- <span
242
- class="message-bubble__duration"
243
- title={m().playground.messageTooltips.executionDuration}
244
- >
245
- <Icon icon="mdi:timer-outline" />
246
- {formatDuration(message.metadata.duration)}
247
- </span>
248
- {/if}
249
- </div>
250
- {/if}
251
- </div>
252
- </div>
53
+ <ChatBubble {message} {showTimestamp} {isLast} {enableMarkdown} />
253
54
  {/if}
254
-
255
- <style>
256
- /* ============================================================
257
- Bubble container — layout only, no background
258
- ============================================================ */
259
- .message-bubble {
260
- display: flex;
261
- gap: var(--fd-space-sm);
262
- padding: 2px var(--fd-space-xl);
263
- margin-bottom: 2px;
264
- align-items: flex-end;
265
- animation: fadeIn 0.18s ease-out;
266
- }
267
-
268
- @keyframes fadeIn {
269
- from {
270
- opacity: 0;
271
- transform: translateY(6px);
272
- }
273
- to {
274
- opacity: 1;
275
- transform: translateY(0);
276
- }
277
- }
278
-
279
- .message-bubble--user {
280
- flex-direction: row-reverse;
281
- }
282
-
283
- .message-bubble--last {
284
- margin-bottom: var(--fd-space-xl);
285
- }
286
-
287
- /* ============================================================
288
- Avatar — smaller, aligned to bubble bottom
289
- ============================================================ */
290
- .message-bubble__avatar {
291
- flex-shrink: 0;
292
- width: 1.875rem;
293
- height: 1.875rem;
294
- display: flex;
295
- align-items: center;
296
- justify-content: center;
297
- border-radius: var(--fd-radius-full);
298
- font-size: 1rem;
299
- }
300
-
301
- .message-bubble--user .message-bubble__avatar {
302
- background-color: var(--fd-primary);
303
- color: var(--fd-primary-foreground);
304
- }
305
-
306
- .message-bubble--assistant .message-bubble__avatar {
307
- background-color: var(--fd-secondary);
308
- color: var(--fd-secondary-foreground);
309
- border: 1px solid var(--fd-border);
310
- }
311
-
312
- .message-bubble--system .message-bubble__avatar {
313
- background-color: var(--fd-muted);
314
- color: var(--fd-muted-foreground);
315
- }
316
-
317
- /* ============================================================
318
- Content — the actual visible bubble
319
- ============================================================ */
320
- .message-bubble__content {
321
- min-width: 0;
322
- max-width: 78%;
323
- padding: var(--fd-space-sm) var(--fd-space-md);
324
- border-radius: var(--fd-radius-2xl);
325
- }
326
-
327
- .message-bubble--user .message-bubble__content {
328
- background-color: var(--fd-primary);
329
- color: var(--fd-primary-foreground);
330
- border-bottom-right-radius: var(--fd-radius-sm);
331
- }
332
-
333
- .message-bubble--assistant .message-bubble__content {
334
- background-color: var(--fd-card);
335
- border: 1px solid var(--fd-border);
336
- color: var(--fd-card-foreground);
337
- box-shadow: 0 1px 3px 0 oklch(0% 0 0 / 0.06), 0 1px 2px -1px oklch(0% 0 0 / 0.04);
338
- border-bottom-left-radius: var(--fd-radius-sm);
339
- }
340
-
341
- .message-bubble--system .message-bubble__content {
342
- background-color: var(--fd-muted);
343
- border: 1px solid var(--fd-border);
344
- color: var(--fd-muted-foreground);
345
- font-size: var(--fd-text-sm);
346
- max-width: 88%;
347
- }
348
-
349
- /* ============================================================
350
- Header — role label + timestamp
351
- ============================================================ */
352
- .message-bubble__header {
353
- display: flex;
354
- align-items: center;
355
- gap: var(--fd-space-xs);
356
- margin-bottom: var(--fd-space-3xs);
357
- }
358
-
359
- .message-bubble--user .message-bubble__header {
360
- flex-direction: row-reverse;
361
- }
362
-
363
- .message-bubble__role {
364
- font-weight: 600;
365
- font-size: var(--fd-text-xs);
366
- text-transform: uppercase;
367
- letter-spacing: 0.05em;
368
- }
369
-
370
- .message-bubble--user .message-bubble__role {
371
- color: var(--fd-primary-foreground);
372
- opacity: 0.75;
373
- }
374
-
375
- .message-bubble--assistant .message-bubble__role {
376
- color: var(--fd-muted-foreground);
377
- }
378
-
379
- .message-bubble--system .message-bubble__role {
380
- color: var(--fd-muted-foreground);
381
- }
382
-
383
- .message-bubble__timestamp {
384
- font-size: 0.6875rem;
385
- font-family: var(--fd-font-mono);
386
- opacity: 0.55;
387
- }
388
-
389
- .message-bubble--user .message-bubble__timestamp {
390
- color: var(--fd-primary-foreground);
391
- }
392
-
393
- .message-bubble--assistant .message-bubble__timestamp {
394
- color: var(--fd-muted-foreground);
395
- }
396
-
397
- /* ============================================================
398
- Message text
399
- ============================================================ */
400
- .message-bubble__text {
401
- line-height: var(--fd-leading-relaxed);
402
- word-break: break-word;
403
- }
404
-
405
- /* Markdown — shared */
406
- .message-bubble__text :global(p) {
407
- margin: 0 0 var(--fd-space-md) 0;
408
- }
409
-
410
- .message-bubble__text :global(p:last-child) {
411
- margin-bottom: 0;
412
- }
413
-
414
- .message-bubble__text :global(h1),
415
- .message-bubble__text :global(h2),
416
- .message-bubble__text :global(h3),
417
- .message-bubble__text :global(h4),
418
- .message-bubble__text :global(h5),
419
- .message-bubble__text :global(h6) {
420
- margin: var(--fd-space-xl) 0 var(--fd-space-xs) 0;
421
- font-weight: 600;
422
- line-height: 1.3;
423
- }
424
-
425
- .message-bubble__text :global(h1:first-child),
426
- .message-bubble__text :global(h2:first-child),
427
- .message-bubble__text :global(h3:first-child),
428
- .message-bubble__text :global(h4:first-child),
429
- .message-bubble__text :global(h5:first-child),
430
- .message-bubble__text :global(h6:first-child) {
431
- margin-top: 0;
432
- }
433
-
434
- .message-bubble__text :global(h1) { font-size: var(--fd-text-xl); }
435
- .message-bubble__text :global(h2) { font-size: var(--fd-text-lg); }
436
- .message-bubble__text :global(h3) { font-size: var(--fd-text-base); }
437
-
438
- .message-bubble__text :global(ul),
439
- .message-bubble__text :global(ol) {
440
- margin: var(--fd-space-xs) 0;
441
- padding-left: var(--fd-space-3xl);
442
- }
443
-
444
- .message-bubble__text :global(li) {
445
- margin: var(--fd-space-3xs) 0;
446
- }
447
-
448
- .message-bubble__text :global(code) {
449
- background-color: var(--fd-secondary);
450
- padding: 0.125rem var(--fd-space-3xs);
451
- border-radius: var(--fd-radius-sm);
452
- font-family: var(--fd-font-mono);
453
- font-size: 0.875em;
454
- }
455
-
456
- .message-bubble__text :global(pre) {
457
- background-color: var(--fd-foreground);
458
- color: var(--fd-background);
459
- padding: var(--fd-space-md) var(--fd-space-xl);
460
- border-radius: var(--fd-radius-lg);
461
- overflow-x: auto;
462
- margin: var(--fd-space-md) 0;
463
- font-size: var(--fd-text-sm);
464
- line-height: var(--fd-leading-normal);
465
- }
466
-
467
- .message-bubble__text :global(pre code) {
468
- background-color: transparent;
469
- padding: 0;
470
- border-radius: 0;
471
- color: inherit;
472
- font-size: inherit;
473
- }
474
-
475
- .message-bubble__text :global(blockquote) {
476
- border-left: 3px solid var(--fd-border-strong);
477
- padding-left: var(--fd-space-xl);
478
- margin: var(--fd-space-md) 0;
479
- color: var(--fd-muted-foreground);
480
- font-style: italic;
481
- }
482
-
483
- .message-bubble__text :global(a) {
484
- color: var(--fd-primary);
485
- text-decoration: none;
486
- }
487
-
488
- .message-bubble__text :global(a:hover) {
489
- text-decoration: underline;
490
- }
491
-
492
- .message-bubble__text :global(hr) {
493
- border: none;
494
- border-top: 1px solid var(--fd-border);
495
- margin: var(--fd-space-xl) 0;
496
- }
497
-
498
- .message-bubble__text :global(table) {
499
- border-collapse: collapse;
500
- width: 100%;
501
- margin: var(--fd-space-md) 0;
502
- font-size: var(--fd-text-sm);
503
- }
504
-
505
- .message-bubble__text :global(th),
506
- .message-bubble__text :global(td) {
507
- border: 1px solid var(--fd-border);
508
- padding: var(--fd-space-xs) var(--fd-space-md);
509
- text-align: left;
510
- }
511
-
512
- .message-bubble__text :global(th) {
513
- background-color: var(--fd-muted);
514
- font-weight: 600;
515
- }
516
-
517
- .message-bubble__text :global(strong) { font-weight: 600; }
518
- .message-bubble__text :global(em) { font-style: italic; }
519
-
520
- /* Markdown overrides for primary-bg (user) bubbles */
521
- .message-bubble--user .message-bubble__text :global(code) {
522
- background-color: color-mix(in srgb, var(--fd-primary-foreground) 18%, transparent);
523
- color: var(--fd-primary-foreground);
524
- }
525
-
526
- .message-bubble--user .message-bubble__text :global(pre) {
527
- background-color: rgb(0 0 0 / 0.25);
528
- color: var(--fd-primary-foreground);
529
- }
530
-
531
- .message-bubble--user .message-bubble__text :global(a) {
532
- color: var(--fd-primary-foreground);
533
- text-decoration: underline;
534
- opacity: 0.85;
535
- }
536
-
537
- .message-bubble--user .message-bubble__text :global(blockquote) {
538
- border-left-color: color-mix(in srgb, var(--fd-primary-foreground) 40%, transparent);
539
- color: var(--fd-primary-foreground);
540
- opacity: 0.8;
541
- }
542
-
543
- /* ============================================================
544
- Footer — node / duration metadata
545
- ============================================================ */
546
- .message-bubble__footer {
547
- display: flex;
548
- align-items: center;
549
- gap: var(--fd-space-md);
550
- margin-top: var(--fd-space-xs);
551
- padding-top: var(--fd-space-3xs);
552
- border-top: 1px solid var(--fd-border);
553
- font-size: var(--fd-text-xs);
554
- color: var(--fd-muted-foreground);
555
- }
556
-
557
- .message-bubble--user .message-bubble__footer {
558
- justify-content: flex-end;
559
- border-top-color: color-mix(in srgb, var(--fd-primary-foreground) 20%, transparent);
560
- color: var(--fd-primary-foreground);
561
- opacity: 0.75;
562
- }
563
-
564
- .message-bubble__node,
565
- .message-bubble__duration {
566
- display: flex;
567
- align-items: center;
568
- gap: var(--fd-space-3xs);
569
- }
570
-
571
- /* ============================================================
572
- Responsive
573
- ============================================================ */
574
- @media (max-width: 640px) {
575
- .message-bubble__content {
576
- max-width: 88%;
577
- }
578
-
579
- .message-bubble__avatar {
580
- width: 1.625rem;
581
- height: 1.625rem;
582
- font-size: var(--fd-text-sm);
583
- }
584
- }
585
-
586
- /* ========================================
587
- Log Row Styles
588
- Compact terminal-style entry, distinct from chat bubbles
589
- ======================================== */
590
-
591
- .log-row {
592
- display: flex;
593
- align-items: center;
594
- gap: var(--fd-space-sm);
595
- padding: 0.1875rem var(--fd-space-xl);
596
- border-left: 2px solid var(--fd-info);
597
- margin: 1px 0;
598
- font-family: var(--fd-font-mono);
599
- font-size: var(--fd-text-xs);
600
- color: var(--fd-muted-foreground);
601
- line-height: var(--fd-leading-normal);
602
- background-color: transparent;
603
- }
604
-
605
- .log-row:hover {
606
- background-color: var(--fd-muted);
607
- }
608
-
609
- .log-row--error {
610
- border-left-color: var(--fd-error);
611
- color: var(--fd-error);
612
- }
613
-
614
- .log-row--warning {
615
- border-left-color: var(--fd-warning);
616
- color: var(--fd-warning);
617
- }
618
-
619
- .log-row--debug {
620
- border-left-color: var(--fd-border-strong);
621
- color: var(--fd-border-strong);
622
- }
623
-
624
- .log-row__level {
625
- flex-shrink: 0;
626
- display: flex;
627
- align-items: center;
628
- font-size: var(--fd-text-sm);
629
- opacity: 0.7;
630
- }
631
-
632
- .log-row--error .log-row__level {
633
- color: var(--fd-error);
634
- opacity: 1;
635
- }
636
-
637
- .log-row--warning .log-row__level {
638
- color: var(--fd-warning);
639
- opacity: 1;
640
- }
641
-
642
- .log-row__body {
643
- flex: 1;
644
- min-width: 0;
645
- display: flex;
646
- align-items: baseline;
647
- gap: var(--fd-space-sm);
648
- overflow: hidden;
649
- }
650
-
651
- .log-row__source {
652
- flex-shrink: 0;
653
- font-size: 0.6rem;
654
- text-transform: uppercase;
655
- letter-spacing: 0.06em;
656
- color: var(--fd-muted-foreground);
657
- opacity: 0.6;
658
- background-color: var(--fd-muted);
659
- border: 1px solid var(--fd-border);
660
- border-radius: var(--fd-radius-sm);
661
- padding: 0 0.25rem;
662
- line-height: 1.4;
663
- }
664
-
665
- .log-row__node {
666
- flex-shrink: 0;
667
- font-weight: 600;
668
- color: var(--fd-foreground);
669
- opacity: 0.5;
670
- font-size: 0.65rem;
671
- text-transform: uppercase;
672
- letter-spacing: 0.04em;
673
- }
674
-
675
- .log-row__text {
676
- flex: 1;
677
- min-width: 0;
678
- white-space: pre-wrap;
679
- word-break: break-word;
680
- }
681
-
682
- .log-row__timestamp {
683
- flex-shrink: 0;
684
- font-size: 0.625rem;
685
- color: var(--fd-border-strong);
686
- opacity: 0.8;
687
- }
688
-
689
- /* ========================================
690
- Compact System Notice Styles
691
- Minimal inline display for system messages
692
- ======================================== */
693
-
694
- .system-notice {
695
- display: flex;
696
- align-items: center;
697
- justify-content: center;
698
- gap: var(--fd-space-3xs);
699
- padding: var(--fd-space-3xs) var(--fd-space-md);
700
- margin: var(--fd-space-3xs) 0;
701
- font-size: var(--fd-text-xs);
702
- color: var(--fd-muted-foreground);
703
- text-align: center;
704
- }
705
-
706
- .system-notice--last {
707
- margin-bottom: var(--fd-space-md);
708
- }
709
-
710
- /* Icon styling - using :global for Iconify component */
711
- .system-notice :global(.system-notice__icon) {
712
- flex-shrink: 0;
713
- font-size: var(--fd-text-sm);
714
- color: var(--fd-border-strong);
715
- }
716
-
717
- .system-notice__source {
718
- flex-shrink: 0;
719
- font-size: 0.6rem;
720
- text-transform: uppercase;
721
- letter-spacing: 0.06em;
722
- color: var(--fd-muted-foreground);
723
- background-color: var(--fd-muted);
724
- border: 1px solid var(--fd-border);
725
- border-radius: var(--fd-radius-sm);
726
- padding: 0 0.25rem;
727
- line-height: 1.4;
728
- }
729
-
730
- .system-notice__text {
731
- line-height: var(--fd-leading-tight);
732
- }
733
-
734
- .system-notice--warning {
735
- color: var(--fd-warning);
736
- }
737
- .system-notice--warning :global(.system-notice__icon) {
738
- color: var(--fd-warning);
739
- }
740
-
741
- .system-notice--error {
742
- color: var(--fd-error);
743
- }
744
- .system-notice--error :global(.system-notice__icon) {
745
- color: var(--fd-error);
746
- }
747
-
748
- .system-notice--debug {
749
- color: var(--fd-border-strong);
750
- opacity: 0.6;
751
- }
752
-
753
- .system-notice__timestamp {
754
- flex-shrink: 0;
755
- font-size: 0.625rem;
756
- color: var(--fd-border-strong);
757
- font-family: var(--fd-font-mono);
758
- }
759
-
760
- /* Responsive: hide timestamp on small screens for compactness */
761
- @media (max-width: 640px) {
762
- .system-notice__timestamp {
763
- display: none;
764
- }
765
- }
766
- </style>