orchid-ai 2.0.2 → 2.1.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/orchid-ai.css CHANGED
@@ -382,6 +382,323 @@
382
382
  border-bottom-left-radius: 4px;
383
383
  }
384
384
 
385
+ /* ── Tool / preamble trace (Claude-style timeline, light theme) ── */
386
+
387
+ .ai-chat-process-trace {
388
+ --ai-process-bg: #f4f6f8;
389
+ --ai-process-border: #e4e8ed;
390
+ --ai-process-rail: #d8dde4;
391
+ --ai-process-text: #5c6570;
392
+ --ai-process-text-strong: #2d3748;
393
+ --ai-process-dot: #9aa5b1;
394
+ --ai-process-dot-tool: #059669;
395
+ --ai-process-dot-compile: #4f46e5;
396
+ --ai-process-dot-mind: #94a3b8;
397
+ --ai-process-interim-fg: #475569;
398
+
399
+ margin: 0 0 12px;
400
+ border-radius: 12px;
401
+ border: 1px solid transparent;
402
+ background: transparent;
403
+ box-shadow: none;
404
+ font-size: 12.5px;
405
+ line-height: 1.45;
406
+ color: var(--ai-process-text);
407
+ overflow: visible;
408
+ transition:
409
+ background 0.22s ease,
410
+ border-color 0.22s ease,
411
+ box-shadow 0.22s ease;
412
+ }
413
+
414
+ /* Collapsed: no chrome — summary reads as muted underlined text on the bubble background */
415
+ .ai-chat-process-trace:not([open]) {
416
+ overflow: visible;
417
+ }
418
+
419
+ .ai-chat-process-trace[open] {
420
+ overflow: hidden;
421
+ border-color: var(--ai-process-border);
422
+ background: linear-gradient(165deg, var(--ai-process-bg) 0%, #eef1f4 100%);
423
+ box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
424
+ }
425
+
426
+ .ai-chat-process-trace__summary {
427
+ cursor: pointer;
428
+ list-style: none;
429
+ display: flex;
430
+ align-items: center;
431
+ gap: 8px;
432
+ padding: 4px 0 10px;
433
+ margin: 0;
434
+ font-weight: 500;
435
+ font-size: 13px;
436
+ letter-spacing: 0.01em;
437
+ text-transform: none;
438
+ color: #6b7280;
439
+ text-decoration: none;
440
+ user-select: none;
441
+ background: transparent;
442
+ border-bottom: none;
443
+ transition:
444
+ color 0.18s ease,
445
+ padding 0.2s ease,
446
+ font-size 0.2s ease,
447
+ font-weight 0.2s ease,
448
+ letter-spacing 0.2s ease,
449
+ background 0.22s ease,
450
+ border-color 0.22s ease;
451
+ }
452
+
453
+ /* Collapsed: underline only the label — chevron / dots sit beside it, not underlined */
454
+ .ai-chat-process-trace:not([open]) > .ai-chat-process-trace__summary {
455
+ gap: 5px;
456
+ width: fit-content;
457
+ max-width: 100%;
458
+ }
459
+
460
+ .ai-chat-process-trace:not([open]) > .ai-chat-process-trace__summary:hover {
461
+ color: #4b5563;
462
+ }
463
+
464
+ .ai-chat-process-trace:not([open]) > .ai-chat-process-trace__summary:hover .ai-chat-process-trace__summary-text {
465
+ text-decoration-color: #4b5563;
466
+ }
467
+
468
+ .ai-chat-process-trace:not([open]) > .ai-chat-process-trace__summary:focus-visible {
469
+ outline: 2px solid #93c5fd;
470
+ outline-offset: 2px;
471
+ border-radius: 4px;
472
+ }
473
+
474
+ /* Expanded: restore panel header strip inside the tinted card */
475
+ .ai-chat-process-trace[open] > .ai-chat-process-trace__summary {
476
+ padding: 10px 14px;
477
+ font-weight: 600;
478
+ font-size: 12px;
479
+ letter-spacing: 0.02em;
480
+ text-transform: uppercase;
481
+ color: var(--ai-process-text-strong);
482
+ text-decoration: none;
483
+ background: rgba(255, 255, 255, 0.45);
484
+ border-bottom: 1px solid var(--ai-process-border);
485
+ }
486
+
487
+ .ai-chat-process-trace__summary::-webkit-details-marker {
488
+ display: none;
489
+ }
490
+
491
+ .ai-chat-process-trace__summary-text {
492
+ flex: 1;
493
+ text-decoration: none;
494
+ }
495
+
496
+ .ai-chat-process-trace:not([open]) .ai-chat-process-trace__summary-text {
497
+ flex: 0 1 auto;
498
+ text-decoration: underline;
499
+ text-underline-offset: 3px;
500
+ text-decoration-thickness: 1px;
501
+ transition: text-decoration-color 0.18s ease;
502
+ }
503
+
504
+ .ai-chat-process-trace[open] .ai-chat-process-trace__summary-text {
505
+ flex: 1;
506
+ text-decoration: none;
507
+ }
508
+
509
+ /* Single expand chevron (right); hidden while streaming — dots replace it. */
510
+ .ai-chat-process-trace__summary-chevron {
511
+ display: inline-flex;
512
+ align-items: center;
513
+ justify-content: center;
514
+ flex-shrink: 0;
515
+ min-width: 1.25em;
516
+ font-size: 15px;
517
+ font-weight: 700;
518
+ line-height: 1;
519
+ opacity: 0.55;
520
+ text-decoration: none;
521
+ transition: transform 0.18s ease, opacity 0.15s ease;
522
+ }
523
+
524
+ .ai-chat-process-trace:not([open]) .ai-chat-process-trace__summary-chevron {
525
+ opacity: 0.45;
526
+ min-width: auto;
527
+ }
528
+
529
+ .ai-chat-process-trace:not([open]) .ai-chat-process-trace__mini-typing span {
530
+ opacity: 0.72;
531
+ }
532
+
533
+ .ai-chat-process-trace[open] > .ai-chat-process-trace__summary .ai-chat-process-trace__summary-chevron {
534
+ transform: rotate(90deg);
535
+ opacity: 0.78;
536
+ }
537
+
538
+ .ai-chat-process-trace__mini-typing {
539
+ display: inline-flex;
540
+ align-items: center;
541
+ flex-shrink: 0;
542
+ gap: 3px;
543
+ }
544
+
545
+ .ai-chat-process-trace__mini-typing span {
546
+ width: 4px;
547
+ height: 4px;
548
+ border-radius: 50%;
549
+ background: var(--ai-process-dot-tool);
550
+ opacity: 0.85;
551
+ animation: ai-chat-process-mini-dot 1.05s ease-in-out infinite;
552
+ }
553
+
554
+ .ai-chat-process-trace__mini-typing span:nth-child(2) {
555
+ animation-delay: 0.12s;
556
+ }
557
+
558
+ .ai-chat-process-trace__mini-typing span:nth-child(3) {
559
+ animation-delay: 0.24s;
560
+ }
561
+
562
+ @keyframes ai-chat-process-mini-dot {
563
+ 0%,
564
+ 80%,
565
+ 100% {
566
+ transform: translateY(0);
567
+ opacity: 0.35;
568
+ }
569
+ 40% {
570
+ transform: translateY(-2px);
571
+ opacity: 1;
572
+ }
573
+ }
574
+
575
+ @keyframes ai-chat-process-pulse {
576
+ 0% {
577
+ box-shadow: 0 0 0 0 rgba(5, 150, 105, 0.35);
578
+ }
579
+ 70% {
580
+ box-shadow: 0 0 0 6px rgba(5, 150, 105, 0);
581
+ }
582
+ 100% {
583
+ box-shadow: 0 0 0 0 rgba(5, 150, 105, 0);
584
+ }
585
+ }
586
+
587
+ .ai-chat-process-trace__panel {
588
+ padding: 10px 12px 12px 8px;
589
+ }
590
+
591
+ .ai-chat-process-trace__timeline {
592
+ list-style: none;
593
+ margin: 0;
594
+ padding: 0;
595
+ }
596
+
597
+ .ai-chat-process-trace__step {
598
+ display: flex;
599
+ align-items: stretch;
600
+ gap: 10px;
601
+ margin: 0;
602
+ padding: 0 0 14px;
603
+ }
604
+
605
+ .ai-chat-process-trace__step:last-child {
606
+ padding-bottom: 0;
607
+ }
608
+
609
+ .ai-chat-process-trace__rail {
610
+ position: relative;
611
+ width: 18px;
612
+ flex-shrink: 0;
613
+ display: flex;
614
+ justify-content: center;
615
+ padding-top: 4px;
616
+ }
617
+
618
+ .ai-chat-process-trace__rail::after {
619
+ content: "";
620
+ position: absolute;
621
+ top: 13px;
622
+ bottom: -14px;
623
+ left: 50%;
624
+ width: 1px;
625
+ transform: translateX(-50%);
626
+ background: var(--ai-process-rail);
627
+ }
628
+
629
+ .ai-chat-process-trace__step:last-child .ai-chat-process-trace__rail::after {
630
+ display: none;
631
+ }
632
+
633
+ .ai-chat-process-trace__dot {
634
+ position: relative;
635
+ z-index: 1;
636
+ width: 7px;
637
+ height: 7px;
638
+ border-radius: 50%;
639
+ background: var(--ai-process-dot);
640
+ box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.85);
641
+ }
642
+
643
+ .ai-chat-process-trace__step--tool .ai-chat-process-trace__dot {
644
+ background: var(--ai-process-dot-tool);
645
+ }
646
+
647
+ .ai-chat-process-trace__step--compile .ai-chat-process-trace__dot {
648
+ background: var(--ai-process-dot-compile);
649
+ }
650
+
651
+ .ai-chat-process-trace__step--mind .ai-chat-process-trace__dot {
652
+ background: var(--ai-process-dot-mind);
653
+ }
654
+
655
+ .ai-chat-process-trace__step--text .ai-chat-process-trace__dot {
656
+ background: var(--ai-process-dot);
657
+ }
658
+
659
+ .ai-chat-process-trace__step--interim .ai-chat-process-trace__dot {
660
+ background: var(--ai-process-dot);
661
+ animation: ai-chat-process-pulse 1.4s ease-out infinite;
662
+ }
663
+
664
+ .ai-chat-process-trace__step--live .ai-chat-process-trace__dot {
665
+ animation: ai-chat-process-pulse 1.2s ease-out infinite;
666
+ }
667
+
668
+ .ai-chat-process-trace__body {
669
+ flex: 1;
670
+ min-width: 0;
671
+ padding-top: 1px;
672
+ }
673
+
674
+ .ai-chat-process-trace__line {
675
+ display: block;
676
+ color: var(--ai-process-text-strong);
677
+ font-weight: 500;
678
+ }
679
+
680
+ .ai-chat-process-trace__step--tool .ai-chat-process-trace__line {
681
+ color: #047857;
682
+ }
683
+
684
+ .ai-chat-process-trace__step--compile .ai-chat-process-trace__line {
685
+ color: #4338ca;
686
+ }
687
+
688
+ .ai-chat-process-trace__prose {
689
+ margin: 0;
690
+ white-space: pre-wrap;
691
+ word-break: break-word;
692
+ color: var(--ai-process-interim-fg);
693
+ font-weight: 400;
694
+ }
695
+
696
+ .ai-chat-process-trace__step--interim .ai-chat-process-trace__prose {
697
+ border-left: 2px solid var(--ai-process-rail);
698
+ padding-left: 10px;
699
+ margin-left: 2px;
700
+ }
701
+
385
702
  /* ── Markdown Typography (assistant bubbles) ── */
386
703
 
387
704
  .ai-chat-bubble.assistant p {
@@ -1731,6 +2048,141 @@
1731
2048
  color: #b45309;
1732
2049
  }
1733
2050
 
2051
+ /* ── Query Summary ── */
2052
+
2053
+ .ai-chat-query-summary {
2054
+ margin-top: 10px;
2055
+ border-radius: 7px;
2056
+ border: 1px solid #e5e7eb;
2057
+ background: #f9fafb;
2058
+ font-size: 12px;
2059
+ }
2060
+
2061
+ .ai-chat-query-summary__summary {
2062
+ display: flex;
2063
+ align-items: center;
2064
+ justify-content: space-between;
2065
+ padding: 6px 10px;
2066
+ cursor: pointer;
2067
+ -webkit-user-select: none;
2068
+ user-select: none;
2069
+ list-style: none;
2070
+ color: #6b7280;
2071
+ gap: 8px;
2072
+ }
2073
+
2074
+ .ai-chat-query-summary__summary::-webkit-details-marker {
2075
+ display: none;
2076
+ }
2077
+
2078
+ .ai-chat-query-summary__summary:hover {
2079
+ color: #374151;
2080
+ }
2081
+
2082
+ .ai-chat-query-summary__label {
2083
+ font-size: 11px;
2084
+ font-weight: 500;
2085
+ letter-spacing: 0.02em;
2086
+ text-transform: uppercase;
2087
+ }
2088
+
2089
+ .ai-chat-query-summary__chevron {
2090
+ font-size: 10px;
2091
+ transition: transform 0.15s;
2092
+ flex-shrink: 0;
2093
+ }
2094
+
2095
+ .ai-chat-query-summary[open] .ai-chat-query-summary__chevron {
2096
+ transform: rotate(90deg);
2097
+ }
2098
+
2099
+ .ai-chat-query-summary__list {
2100
+ list-style: none;
2101
+ margin: 0;
2102
+ padding: 4px 10px 8px;
2103
+ display: flex;
2104
+ flex-direction: column;
2105
+ gap: 3px;
2106
+ border-top: 1px solid #e5e7eb;
2107
+ }
2108
+
2109
+ .ai-chat-query-summary__item {
2110
+ display: flex;
2111
+ gap: 6px;
2112
+ align-items: baseline;
2113
+ line-height: 1.5;
2114
+ }
2115
+
2116
+ .ai-chat-query-summary__key {
2117
+ color: #6b7280;
2118
+ white-space: nowrap;
2119
+ flex-shrink: 0;
2120
+ }
2121
+
2122
+ .ai-chat-query-summary__key::after {
2123
+ content: ':';
2124
+ }
2125
+
2126
+ .ai-chat-query-summary__value {
2127
+ color: #374151;
2128
+ word-break: break-word;
2129
+ }
2130
+
2131
+ /* ── Query sub-step (nested under a tool status row) ── */
2132
+
2133
+ .ai-chat-process-trace__step--query {
2134
+ padding-left: 16px;
2135
+ }
2136
+
2137
+ .ai-chat-process-trace__step--query .ai-chat-process-trace__rail {
2138
+ opacity: 0.4;
2139
+ }
2140
+
2141
+ .ai-chat-process-trace__step--query .ai-chat-process-trace__dot {
2142
+ width: 6px;
2143
+ height: 6px;
2144
+ background: var(--ai-process-dot, #9aa5b1);
2145
+ }
2146
+
2147
+ .ai-chat-process-trace__query-collection {
2148
+ display: block;
2149
+ font-size: 11px;
2150
+ font-weight: 600;
2151
+ letter-spacing: 0.04em;
2152
+ text-transform: uppercase;
2153
+ color: var(--ai-process-text, #5c6570);
2154
+ margin-bottom: 4px;
2155
+ }
2156
+
2157
+ .ai-chat-process-trace__query-params {
2158
+ display: grid;
2159
+ grid-template-columns: auto 1fr;
2160
+ gap: 1px 10px;
2161
+ margin: 0;
2162
+ }
2163
+
2164
+ .ai-chat-process-trace__query-param {
2165
+ display: contents;
2166
+ font-size: 11.5px;
2167
+ line-height: 1.5;
2168
+ }
2169
+
2170
+ .ai-chat-process-trace__query-param dt {
2171
+ color: var(--ai-process-text, #5c6570);
2172
+ font-weight: 500;
2173
+ white-space: nowrap;
2174
+ }
2175
+
2176
+ .ai-chat-process-trace__query-param dt::after {
2177
+ content: ":";
2178
+ }
2179
+
2180
+ .ai-chat-process-trace__query-param dd {
2181
+ color: var(--ai-process-text-strong, #2d3748);
2182
+ margin: 0;
2183
+ word-break: break-word;
2184
+ }
2185
+
1734
2186
  /* ── Message Actions ── */
1735
2187
 
1736
2188
  .ai-chat-message-actions {
@@ -1816,6 +2268,29 @@
1816
2268
  animation-delay: 0.4s;
1817
2269
  }
1818
2270
 
2271
+ /* Smaller dots for inline status (next to “Compiling…”) */
2272
+ .ai-chat-typing--inline {
2273
+ gap: 4px;
2274
+ padding: 0;
2275
+ }
2276
+
2277
+ .ai-chat-typing--inline span {
2278
+ width: 5px;
2279
+ height: 5px;
2280
+ }
2281
+
2282
+ .ai-chat-streaming-status {
2283
+ display: flex;
2284
+ align-items: center;
2285
+ gap: 8px;
2286
+ flex-wrap: wrap;
2287
+ margin-bottom: 8px;
2288
+ }
2289
+
2290
+ .ai-chat-streaming-status .ai-chat-status-text {
2291
+ margin: 0;
2292
+ }
2293
+
1819
2294
  @keyframes typing {
1820
2295
  0%,
1821
2296
  60%,
@@ -1829,6 +2304,48 @@
1829
2304
  }
1830
2305
  }
1831
2306
 
2307
+ /* ── Building Block (streaming code-block placeholder) ── */
2308
+
2309
+ .ai-building-block {
2310
+ display: flex;
2311
+ align-items: center;
2312
+ gap: 10px;
2313
+ flex-wrap: wrap;
2314
+ padding: 8px 12px;
2315
+ border-radius: 8px;
2316
+ margin: 6px 0 0;
2317
+ background: #f3f4f6;
2318
+ border: 1px solid #e5e7eb;
2319
+ }
2320
+
2321
+ .ai-building-block__label {
2322
+ font-size: 13px;
2323
+ font-weight: 600;
2324
+ color: #4b5563;
2325
+ }
2326
+
2327
+ .ai-building-block__dots {
2328
+ display: flex;
2329
+ align-items: center;
2330
+ gap: 4px;
2331
+ }
2332
+
2333
+ .ai-building-block__dot {
2334
+ width: 5px;
2335
+ height: 5px;
2336
+ border-radius: 50%;
2337
+ background: #9ca3af;
2338
+ animation: typing 1.4s infinite;
2339
+ }
2340
+
2341
+ .ai-building-block__dots .ai-building-block__dot:nth-child(2) {
2342
+ animation-delay: 0.2s;
2343
+ }
2344
+
2345
+ .ai-building-block__dots .ai-building-block__dot:nth-child(3) {
2346
+ animation-delay: 0.4s;
2347
+ }
2348
+
1832
2349
  /* ── Input Area ── */
1833
2350
 
1834
2351
  .ai-chat-input-form {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orchid-ai",
3
- "version": "2.0.2",
3
+ "version": "2.1.0",
4
4
  "description": "Shared Orchid AI chat UI and visualization components",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -22,13 +22,15 @@ export default function ChatWindow({
22
22
  emptyDescription,
23
23
  suggestions = DEFAULT_SUGGESTIONS,
24
24
  suggestionsDisabled = false,
25
+ showProcessTracePanel = true,
26
+ showQuerySummary = false,
25
27
  }) {
26
28
  const exportPrefix = appName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
27
29
  const bottomRef = useRef(null);
28
30
 
29
31
  useEffect(() => {
30
32
  bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
31
- }, [messages, loading]);
33
+ }, [messages, loading, statusText]);
32
34
 
33
35
  const renderEmptyState = () => {
34
36
  if (!aiEnabled) {
@@ -100,13 +102,34 @@ export default function ChatWindow({
100
102
  );
101
103
  };
102
104
 
105
+ const lastMsg = messages?.[messages.length - 1];
106
+ const hasStreamingMessage = lastMsg?.isStreaming === true;
107
+
103
108
  return (
104
109
  <div className="ai-chat-window">
105
110
  {messages?.length === 0 && !loading && renderEmptyState()}
106
- {(messages ?? []).map((msg, i) => (
107
- <Message key={i} role={msg.role} content={msg.content} truncated={msg.truncated} exportPrefix={exportPrefix} />
108
- ))}
109
- {loading && (
111
+ {(messages ?? []).map((msg, i) => {
112
+ const isLast = i === (messages?.length ?? 0) - 1;
113
+ const streamingStatusText =
114
+ loading && isLast && msg.role === 'assistant' && msg.isStreaming ? statusText : undefined;
115
+ return (
116
+ <Message
117
+ key={i}
118
+ role={msg.role}
119
+ content={msg.content}
120
+ truncated={msg.truncated}
121
+ exportPrefix={exportPrefix}
122
+ isStreaming={msg.isStreaming}
123
+ streamingStatusText={streamingStatusText}
124
+ processTrace={msg.processTrace}
125
+ processInterimLive={msg.processInterimLive}
126
+ showProcessTracePanel={showProcessTracePanel}
127
+ queryContext={msg.queryContext}
128
+ showQuerySummary={showQuerySummary}
129
+ />
130
+ );
131
+ })}
132
+ {loading && !hasStreamingMessage && (
110
133
  <div className="ai-chat-message assistant">
111
134
  <div className="ai-chat-avatar assistant">AI</div>
112
135
  <div className="ai-chat-bubble assistant">