R-Kentaren commited on
Commit
1e1a8bc
Β·
verified Β·
1 Parent(s): 75a6442

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +175 -2
index.html CHANGED
@@ -305,7 +305,8 @@ a:hover { text-decoration: underline; text-shadow: var(--glow-cyan); }
305
  .msg-prefix { font-weight: 600; margin-right: 4px; }
306
  .msg-user .msg-prefix { color: var(--green); text-shadow: var(--glow-green); }
307
  .msg-user .msg-content { color: var(--green); text-shadow: var(--glow-green); }
308
- .msg-assistant .msg-prefix { color: var(--cyan); text-shadow: var(--glow-cyan); }
 
309
  .msg-assistant .msg-content { color: var(--gray-light); }
310
  .msg-system .msg-prefix { color: var(--amber); text-shadow: var(--glow-amber); }
311
  .msg-system .msg-content { color: var(--amber); opacity: 0.85; }
@@ -379,6 +380,112 @@ a:hover { text-decoration: underline; text-shadow: var(--glow-cyan); }
379
  /* Hide thinking blocks entirely when toggle is off */
380
  body.hide-thinking .think-block { display: none; }
381
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  /* Streaming cursor */
383
  .streaming-cursor::after {
384
  content: '\u2588'; animation: blink 0.8s step-end infinite;
@@ -1156,6 +1263,8 @@ const state = {
1156
  modelReady: false,
1157
  searchEnabled: false,
1158
  lastSearchResults: [],
 
 
1159
  showThinking: true,
1160
  currentModelKey: 'minicpm5-1b',
1161
  currentModelType: 'text',
@@ -1397,9 +1506,11 @@ function addAssistantMessage() {
1397
  const div = document.createElement('div');
1398
  div.className = 'msg msg-assistant';
1399
  div.id = 'current-assistant-msg';
1400
- div.innerHTML = `<span class="msg-prefix">ai&gt;</span><span class="msg-content streaming-cursor"></span>`;
1401
  container.appendChild(div);
1402
  state.reasoningExpanded = false;
 
 
1403
  scrollToBottom();
1404
  return div;
1405
  }
@@ -1917,6 +2028,15 @@ async function sendMessage(prompt) {
1917
  function handlePayload(payload, isStreaming) {
1918
  if (payload.status_text) renderStatus(payload.status_text, payload.status_state || 'working');
1919
 
 
 
 
 
 
 
 
 
 
1920
  if (payload.history) {
1921
  state.history = payload.history;
1922
  const lastMsg = payload.history[payload.history.length - 1];
@@ -2229,6 +2349,59 @@ function renderSearchResults(results) {
2229
  container.innerHTML = html;
2230
  }
2231
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2232
  // ═══════════════════════════════════════════════════════
2233
  // HUGGINGFACE PUSH
2234
  // ═══════════════════════════════════════════════════════
 
305
  .msg-prefix { font-weight: 600; margin-right: 4px; }
306
  .msg-user .msg-prefix { color: var(--green); text-shadow: var(--glow-green); }
307
  .msg-user .msg-content { color: var(--green); text-shadow: var(--glow-green); }
308
+ .msg-assistant .msg-prefix { color: var(--cyan); text-shadow: var(--glow-cyan); float: left; }
309
+ .msg-assistant .msg-body { overflow: hidden; }
310
  .msg-assistant .msg-content { color: var(--gray-light); }
311
  .msg-system .msg-prefix { color: var(--amber); text-shadow: var(--glow-amber); }
312
  .msg-system .msg-content { color: var(--amber); opacity: 0.85; }
 
380
  /* Hide thinking blocks entirely when toggle is off */
381
  body.hide-thinking .think-block { display: none; }
382
 
383
+ /* ─── Search Source Badge (Grok-style) ────────────────────── */
384
+ .search-source-badge {
385
+ display: inline-flex;
386
+ align-items: center;
387
+ gap: 5px;
388
+ margin: 4px 0 2px;
389
+ padding: 4px 10px;
390
+ border-radius: 20px;
391
+ background: rgba(168, 85, 247, 0.08);
392
+ border: 1px solid rgba(168, 85, 247, 0.2);
393
+ cursor: pointer;
394
+ transition: all 0.2s ease;
395
+ font-size: 11px;
396
+ color: var(--purple);
397
+ user-select: none;
398
+ white-space: nowrap;
399
+ }
400
+ .search-source-badge:hover {
401
+ background: rgba(168, 85, 247, 0.15);
402
+ border-color: rgba(168, 85, 247, 0.4);
403
+ box-shadow: 0 0 8px rgba(168, 85, 247, 0.15);
404
+ }
405
+ .search-source-badge .badge-icon {
406
+ font-size: 13px;
407
+ line-height: 1;
408
+ }
409
+ .search-source-badge .badge-count {
410
+ font-weight: 600;
411
+ }
412
+ .search-source-badge .badge-arrow {
413
+ font-size: 9px;
414
+ transition: transform 0.2s ease;
415
+ opacity: 0.6;
416
+ }
417
+ .search-source-badge.open .badge-arrow {
418
+ transform: rotate(180deg);
419
+ }
420
+
421
+ .search-source-panel {
422
+ margin: 0 0 6px;
423
+ border-radius: 8px;
424
+ border: 1px solid rgba(168, 85, 247, 0.15);
425
+ background: rgba(168, 85, 247, 0.03);
426
+ max-height: 0;
427
+ overflow: hidden;
428
+ transition: max-height 0.3s ease, padding 0.3s ease, opacity 0.3s ease;
429
+ opacity: 0;
430
+ }
431
+ .search-source-panel.open {
432
+ max-height: 600px;
433
+ overflow-y: auto;
434
+ opacity: 1;
435
+ padding: 8px 10px;
436
+ }
437
+ .search-source-panel::-webkit-scrollbar { width: 4px; }
438
+ .search-source-panel::-webkit-scrollbar-track { background: transparent; }
439
+ .search-source-panel::-webkit-scrollbar-thumb { background: var(--gray-dim); border-radius: 2px; }
440
+
441
+ .source-item {
442
+ display: flex;
443
+ gap: 8px;
444
+ padding: 6px 4px;
445
+ border-bottom: 1px solid rgba(168, 85, 247, 0.07);
446
+ align-items: flex-start;
447
+ }
448
+ .source-item:last-child { border-bottom: none; }
449
+ .source-favicon {
450
+ width: 16px; height: 16px;
451
+ border-radius: 3px;
452
+ flex-shrink: 0;
453
+ margin-top: 2px;
454
+ background: var(--bg-code);
455
+ border: 1px solid var(--border);
456
+ object-fit: contain;
457
+ }
458
+ .source-favicon-placeholder {
459
+ width: 16px; height: 16px;
460
+ border-radius: 3px;
461
+ flex-shrink: 0;
462
+ margin-top: 2px;
463
+ background: var(--bg-code);
464
+ border: 1px solid var(--border);
465
+ display: flex; align-items: center; justify-content: center;
466
+ font-size: 8px; color: var(--gray-dim);
467
+ }
468
+ .source-info { flex: 1; min-width: 0; }
469
+ .source-title {
470
+ font-size: 11px; font-weight: 600; color: var(--cyan);
471
+ text-decoration: none; display: block;
472
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
473
+ }
474
+ .source-title:hover { text-decoration: underline; }
475
+ .source-domain {
476
+ font-size: 9px; color: var(--green-dim);
477
+ display: block; margin-top: 1px;
478
+ }
479
+ .source-snippet {
480
+ font-size: 10px; color: var(--gray-mid);
481
+ line-height: 1.35;
482
+ margin-top: 2px;
483
+ display: -webkit-box;
484
+ -webkit-line-clamp: 2;
485
+ -webkit-box-orient: vertical;
486
+ overflow: hidden;
487
+ }
488
+
489
  /* Streaming cursor */
490
  .streaming-cursor::after {
491
  content: '\u2588'; animation: blink 0.8s step-end infinite;
 
1263
  modelReady: false,
1264
  searchEnabled: false,
1265
  lastSearchResults: [],
1266
+ currentSearchResults: [],
1267
+ searchPanelExpanded: false,
1268
  showThinking: true,
1269
  currentModelKey: 'minicpm5-1b',
1270
  currentModelType: 'text',
 
1506
  const div = document.createElement('div');
1507
  div.className = 'msg msg-assistant';
1508
  div.id = 'current-assistant-msg';
1509
+ div.innerHTML = `<span class="msg-prefix">ai&gt;</span><div class="msg-body"><div class="search-source-container"></div><span class="msg-content streaming-cursor"></span></div>`;
1510
  container.appendChild(div);
1511
  state.reasoningExpanded = false;
1512
+ state.currentSearchResults = [];
1513
+ state.searchPanelExpanded = false;
1514
  scrollToBottom();
1515
  return div;
1516
  }
 
2028
  function handlePayload(payload, isStreaming) {
2029
  if (payload.status_text) renderStatus(payload.status_text, payload.status_state || 'working');
2030
 
2031
+ // Handle search results (show inline source badge)
2032
+ if (payload.type === 'search_results' && payload.search_results) {
2033
+ state.currentSearchResults = payload.search_results;
2034
+ state.lastSearchResults = payload.search_results;
2035
+ renderSearchSourceBadge(payload.search_results, false);
2036
+ // Also render in the Search tab
2037
+ renderSearchResults(payload.search_results);
2038
+ }
2039
+
2040
  if (payload.history) {
2041
  state.history = payload.history;
2042
  const lastMsg = payload.history[payload.history.length - 1];
 
2349
  container.innerHTML = html;
2350
  }
2351
 
2352
+ // ═══════════════════════════════════════════════════════
2353
+ // SEARCH SOURCE BADGE (Grok-style inline in chat)
2354
+ // ═══════════════════════════════════════════════════════
2355
+ function renderSearchSourceBadge(results, expanded) {
2356
+ const div = document.getElementById('current-assistant-msg');
2357
+ if (!div) return;
2358
+ const container = div.querySelector('.search-source-container');
2359
+ if (!container || !results || results.length === 0) return;
2360
+
2361
+ const count = results.length;
2362
+ const openClass = expanded ? ' open' : '';
2363
+
2364
+ // Build source items HTML
2365
+ let sourceItems = '';
2366
+ results.forEach((r) => {
2367
+ let domain = '';
2368
+ try { domain = new URL(r.url).hostname.replace('www.', ''); } catch(e) { domain = r.host_name || r.url; }
2369
+ const faviconUrl = r.favicon || `https://www.google.com/s2/favicons?domain=${domain}&sz=16`;
2370
+ sourceItems += `<div class="source-item">
2371
+ <img class="source-favicon" src="${escapeHtml(faviconUrl)}" alt="" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
2372
+ <div class="source-favicon-placeholder" style="display:none;">${escapeHtml(domain.charAt(0).toUpperCase())}</div>
2373
+ <div class="source-info">
2374
+ <a class="source-title" href="${escapeHtml(r.url)}" target="_blank" rel="noopener" onclick="event.stopPropagation();">${escapeHtml(r.title)}</a>
2375
+ <span class="source-domain">${escapeHtml(domain)}</span>
2376
+ <div class="source-snippet">${escapeHtml(r.snippet)}</div>
2377
+ </div>
2378
+ </div>`;
2379
+ });
2380
+
2381
+ container.innerHTML = `
2382
+ <div class="search-source-badge${openClass}" onclick="toggleSearchPanel(this)">
2383
+ <span class="badge-icon">&#128269;</span>
2384
+ <span>Searched</span>
2385
+ <span class="badge-count">${count} source${count !== 1 ? 's' : ''}</span>
2386
+ <span class="badge-arrow">&#9660;</span>
2387
+ </div>
2388
+ <div class="search-source-panel${openClass}">
2389
+ ${sourceItems}
2390
+ </div>
2391
+ `;
2392
+
2393
+ scrollToBottom();
2394
+ }
2395
+
2396
+ function toggleSearchPanel(badge) {
2397
+ const panel = badge.nextElementSibling;
2398
+ const isOpen = badge.classList.contains('open');
2399
+ badge.classList.toggle('open', !isOpen);
2400
+ panel.classList.toggle('open', !isOpen);
2401
+ state.searchPanelExpanded = !isOpen;
2402
+ scrollToBottom();
2403
+ }
2404
+
2405
  // ═══════════════════════════════════════════════════════
2406
  // HUGGINGFACE PUSH
2407
  // ═══════════════════════════════════════════════════════