@memtensor/memos-local-openclaw-plugin 1.0.2-beta.4 → 1.0.2-beta.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/viewer/html.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,w1yQAkxIf,CAAC"}
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/viewer/html.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAk4IzD"}
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.viewerHTML = void 0;
4
- exports.viewerHTML = `<!DOCTYPE html>
3
+ exports.viewerHTML = viewerHTML;
4
+ function viewerHTML(pluginVersion) {
5
+ const vBadge = pluginVersion ? `<span class="version-badge">v${pluginVersion}</span>` : '';
6
+ return `<!DOCTYPE html>
5
7
  <html lang="zh-CN">
6
8
  <head>
7
9
  <meta charset="UTF-8">
@@ -113,13 +115,15 @@ input,textarea,select{font-family:inherit;font-size:inherit}
113
115
  .topbar .brand{display:flex;align-items:center;gap:10px;font-weight:700;font-size:15px;color:var(--text);letter-spacing:-.02em;flex-shrink:0}
114
116
  .topbar .brand .icon{width:32px;height:32px;display:flex;align-items:center;justify-content:center;font-size:22px;background:none;border-radius:0}
115
117
  .topbar .brand .sub{font-weight:400;color:var(--text-muted);font-size:11px}
118
+ .version-badge{font-size:10px;font-weight:600;color:var(--text-muted);background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.1);padding:1px 7px;border-radius:6px;margin-left:6px;letter-spacing:.02em;user-select:all}
119
+ [data-theme="light"] .version-badge{background:rgba(0,0,0,.05);border-color:rgba(0,0,0,.08);color:var(--text-sec)}
116
120
  .topbar-center{flex:1;display:flex;justify-content:center}
117
121
  .topbar .actions{display:flex;align-items:center;gap:6px;flex-shrink:0}
118
122
 
119
123
  .main-content{display:flex;flex:1;max-width:1400px;margin:0 auto;width:100%;padding:28px 32px;gap:28px}
120
124
 
121
125
  /* ─── Sidebar ─── */
122
- .sidebar{width:260px;flex-shrink:0}
126
+ .sidebar{width:260px;min-width:260px;flex-shrink:0}
123
127
  .sidebar .stats-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:24px}
124
128
  .stat-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:18px;transition:all .2s}
125
129
  .stat-card:hover{border-color:var(--border-glow);background:var(--bg-card-hover)}
@@ -244,6 +248,16 @@ input,textarea,select{font-family:inherit;font-size:inherit}
244
248
  .modal-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:28px}
245
249
 
246
250
  /* ─── Toast ─── */
251
+ .emb-banner{display:flex;align-items:center;gap:10px;padding:12px 20px;font-size:13px;font-weight:500;border-radius:10px;margin:0 32px 0;animation:slideIn .3s ease}
252
+ .emb-banner.warning{background:rgba(245,158,11,.1);color:#d97706;border:1px solid rgba(245,158,11,.25)}
253
+ .emb-banner.error{background:rgba(239,68,68,.1);color:#ef4444;border:1px solid rgba(239,68,68,.25)}
254
+ [data-theme="light"] .emb-banner.warning{background:rgba(245,158,11,.08);color:#b45309}
255
+ [data-theme="light"] .emb-banner.error{background:rgba(239,68,68,.08);color:#dc2626}
256
+ .emb-banner span{flex:1}
257
+ .emb-banner-btn{background:none;border:1px solid currentColor;border-radius:6px;padding:4px 12px;font-size:12px;font-weight:600;color:inherit;cursor:pointer;white-space:nowrap;opacity:.85;transition:opacity .15s}
258
+ .emb-banner-btn:hover{opacity:1}
259
+ .emb-banner-close{background:none;border:none;font-size:18px;color:inherit;cursor:pointer;opacity:.5;padding:0 4px;line-height:1}
260
+ .emb-banner-close:hover{opacity:1}
247
261
  .toast-container{position:fixed;top:80px;right:24px;z-index:1000;display:flex;flex-direction:column;gap:8px}
248
262
  .toast{padding:14px 20px;border-radius:10px;font-size:13px;font-weight:500;box-shadow:var(--shadow-lg);animation:slideIn .3s ease;display:flex;align-items:center;gap:10px;max-width:360px;border:1px solid}
249
263
  .toast.success{background:var(--green-bg);color:var(--green);border-color:rgba(16,185,129,.3)}
@@ -333,8 +347,12 @@ input,textarea,select{font-family:inherit;font-size:inherit}
333
347
  .task-chunk-role.user{color:var(--pri)}
334
348
  .task-chunk-role.assistant{color:var(--green)}
335
349
  .task-chunk-role.tool{color:var(--amber)}
336
- .task-chunk-bubble{padding:12px 16px;border-radius:16px;white-space:pre-wrap;word-break:break-word;max-height:200px;overflow:hidden;position:relative;transition:all .2s}
337
- .task-chunk-bubble.expanded{max-height:none}
350
+ .task-chunk-bubble{padding:12px 16px;border-radius:16px;white-space:pre-wrap;word-break:break-word;max-height:none;overflow:hidden;position:relative;transition:all .2s}
351
+ .task-chunk-bubble.collapsed{max-height:200px}
352
+ .task-chunk-expand{display:none;align-items:center;justify-content:center;gap:4px;margin-top:4px;padding:4px 12px;font-size:12px;font-weight:600;color:var(--text-sec);cursor:pointer;user-select:none;border-radius:8px;transition:all .15s}
353
+ .task-chunk-expand:hover{color:var(--pri);background:rgba(99,102,241,.08)}
354
+ .task-chunk-expand .expand-arrow{display:inline-block;font-size:10px;transition:transform .2s}
355
+ .task-chunk-expand.is-expanded .expand-arrow{transform:rotate(180deg)}
338
356
  .role-user .task-chunk-bubble{background:var(--pri);color:#000;border-bottom-right-radius:4px}
339
357
  .role-assistant .task-chunk-bubble{background:var(--bg-card);border:1px solid var(--border);color:var(--text-sec);border-bottom-left-radius:4px}
340
358
  .role-tool .task-chunk-bubble{background:rgba(245,158,11,.08);border:1px solid rgba(245,158,11,.2);color:var(--text-sec);border-bottom-left-radius:4px;font-family:'SF Mono',Monaco,Consolas,monospace;font-size:12px}
@@ -424,6 +442,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
424
442
  [data-theme="light"] .nav-tabs .tab.active{background:#fff;border-color:rgba(0,0,0,.1);box-shadow:0 1px 3px rgba(0,0,0,.08);color:var(--text)}
425
443
  .analytics-view,.settings-view,.logs-view,.migrate-view{display:none;flex:1;min-width:0;flex-direction:column;gap:20px}
426
444
  .analytics-view.show,.settings-view.show,.logs-view.show,.migrate-view.show{display:flex}
445
+ .feed-wrap,.tasks-view,.skills-view,.analytics-view,.settings-view,.logs-view,.migrate-view{max-width:960px}
427
446
 
428
447
  /* ─── Logs ─── */
429
448
  .logs-toolbar{display:flex;align-items:center;justify-content:space-between;padding:8px 0}
@@ -571,18 +590,19 @@ input,textarea,select{font-family:inherit;font-size:inherit}
571
590
  @keyframes migrateFadeIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
572
591
  .feed-wrap{flex:1;min-width:0;display:flex;flex-direction:column}
573
592
  .feed-wrap.hide{display:none}
593
+ .analytics-view{flex-direction:column;gap:20px}
574
594
  .analytics-cards{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
575
- .analytics-card{position:relative;overflow:hidden;border-radius:var(--radius-lg);padding:22px 20px;transition:all .2s ease;border:1px solid var(--border);background:var(--bg-card)}
595
+ .analytics-card{position:relative;overflow:hidden;border-radius:var(--radius-lg);padding:18px 16px;transition:all .2s ease;border:1px solid var(--border);background:var(--bg-card)}
576
596
  .analytics-card::before{content:'';position:absolute;top:0;left:0;right:0;height:2px;background:var(--pri);opacity:.5}
577
597
  .analytics-card::after{display:none}
578
598
  .analytics-card:hover{transform:translateY(-2px);box-shadow:var(--shadow);border-color:var(--border-glow)}
579
599
  .analytics-card.green::before{background:var(--green)}
580
600
  .analytics-card.amber::before{background:var(--amber)}
581
- .analytics-card .ac-value{font-size:28px;font-weight:700;letter-spacing:-.03em;color:var(--text);line-height:1;-webkit-text-fill-color:unset;background:none}
601
+ .analytics-card .ac-value{font-size:24px;font-weight:700;letter-spacing:-.03em;color:var(--text);line-height:1;-webkit-text-fill-color:unset;background:none}
582
602
  .analytics-card.green .ac-value{color:var(--green);background:none}
583
603
  .analytics-card.amber .ac-value{color:var(--amber);background:none}
584
604
  .analytics-card .ac-label{font-size:11px;color:var(--text-muted);margin-top:6px;font-weight:500;text-transform:uppercase;letter-spacing:.06em}
585
- .analytics-section{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:22px 24px;position:relative;overflow:hidden}
605
+ .analytics-section{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:18px 20px;position:relative;overflow:hidden}
586
606
  .analytics-section::before{display:none}
587
607
  .analytics-section h3{font-size:11px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.08em;margin-bottom:16px;display:flex;align-items:center;gap:8px}
588
608
  .analytics-section h3 .icon{font-size:14px;opacity:.6}
@@ -742,7 +762,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
742
762
  <div class="topbar">
743
763
  <div class="brand">
744
764
  <div class="icon"><svg width="24" height="24" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg" style="filter:drop-shadow(0 0 8px rgba(255,77,77,.3))"><defs><linearGradient id="tLG" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#ff4d4d"/><stop offset="100%" stop-color="#991b1b"/></linearGradient></defs><path d="M60 10C30 10 15 35 15 55C15 75 30 95 45 100L45 110L55 110L55 100C55 100 60 102 65 100L65 110L75 110L75 100C90 95 105 75 105 55C105 35 90 10 60 10Z" fill="url(#tLG)"/><path d="M20 45C5 40 0 50 5 60C10 70 20 65 25 55C28 48 25 45 20 45Z" fill="url(#tLG)"/><path d="M100 45C115 40 120 50 115 60C110 70 100 65 95 55C92 48 95 45 100 45Z" fill="url(#tLG)"/><path d="M45 15Q35 5 30 8" stroke="#ff4d4d" stroke-width="2" stroke-linecap="round"/><path d="M75 15Q85 5 90 8" stroke="#ff4d4d" stroke-width="2" stroke-linecap="round"/><circle cx="45" cy="35" r="6" fill="#050810"/><circle cx="75" cy="35" r="6" fill="#050810"/><circle cx="46" cy="34" r="2" fill="#00e5cc"/><circle cx="76" cy="34" r="2" fill="#00e5cc"/></svg></div>
745
- <span data-i18n="title">OpenClaw Memory</span>
765
+ <span data-i18n="title">OpenClaw Memory</span>${vBadge}
746
766
  </div>
747
767
  <div class="topbar-center">
748
768
  <nav class="nav-tabs">
@@ -771,10 +791,12 @@ input,textarea,select{font-family:inherit;font-size:inherit}
771
791
  <div class="stat-card amber"><div class="stat-value" id="statEmbeddings">-</div><div class="stat-label" data-i18n="stat.embeddings">Embeddings</div></div>
772
792
  <div class="stat-card rose"><div class="stat-value" id="statTimeSpan">-</div><div class="stat-label" data-i18n="stat.days">Days</div></div>
773
793
  </div>
774
- <div id="embeddingStatus"></div>
775
- <div class="section-title" data-i18n="sidebar.sessions">Sessions</div>
776
- <div class="session-list" id="sessionList"></div>
777
- <button class="btn btn-sm btn-ghost" style="width:100%;margin-top:20px;justify-content:center;color:var(--text-muted);font-size:11px" onclick="clearAll()" data-i18n="sidebar.clear">\u{1F5D1} Clear All Data</button>
794
+ <div id="sidebarSessionSection">
795
+ <div id="embeddingStatus"></div>
796
+ <div class="section-title" data-i18n="sidebar.sessions">Sessions</div>
797
+ <div class="session-list" id="sessionList"></div>
798
+ <button class="btn btn-sm btn-ghost" style="width:100%;margin-top:20px;justify-content:center;color:var(--text-muted);font-size:11px" onclick="clearAll()" data-i18n="sidebar.clear">\u{1F5D1} Clear All Data</button>
799
+ </div>
778
800
  </div>
779
801
 
780
802
  <div class="feed-wrap" id="feedWrap">
@@ -900,7 +922,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
900
922
  </div>
901
923
  </div>
902
924
  <div class="analytics-view" id="analyticsView">
903
- <div class="metrics-toolbar">
925
+ <div class="metrics-toolbar" style="margin-bottom:0">
904
926
  <span style="font-size:12px;color:var(--text-sec);font-weight:600" data-i18n="range">Range</span>
905
927
  <button class="range-btn" data-days="7" onclick="setMetricsDays(7)">7 <span data-i18n="range.days">days</span></button>
906
928
  <button class="range-btn active" data-days="30" onclick="setMetricsDays(30)">30 <span data-i18n="range.days">days</span></button>
@@ -932,7 +954,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
932
954
  <div id="toolAggTable" style="margin-top:20px"></div>
933
955
  </div>
934
956
 
935
- <div class="breakdown-grid" style="display:grid;grid-template-columns:1fr 1fr;gap:24px">
957
+ <div class="breakdown-grid" style="display:grid;grid-template-columns:1fr 1fr;gap:16px">
936
958
  <div class="analytics-section">
937
959
  <h3><span class="icon">\u{1F464}</span> <span data-i18n="breakdown.role">By Role</span></h3>
938
960
  <div id="breakdownRole"></div>
@@ -965,8 +987,11 @@ input,textarea,select{font-family:inherit;font-size:inherit}
965
987
  <div class="settings-view" id="settingsView">
966
988
  <div class="settings-group" id="settingsModelConfig">
967
989
  <h2 class="settings-group-title"><span data-i18n="settings.modelconfig">Model Configuration</span></h2>
968
- <div class="model-health-bar" id="modelHealthBar">
969
- <div style="font-size:12px;color:var(--text-muted);width:100%">Loading model status...</div>
990
+ <div class="settings-section">
991
+ <h3><span class="icon">\u{1F4CA}</span> <span data-i18n="settings.modelhealth">Model Health</span></h3>
992
+ <div class="model-health-bar" id="modelHealthBar">
993
+ <div style="font-size:12px;color:var(--text-muted);width:100%">Loading model status...</div>
994
+ </div>
970
995
  </div>
971
996
  <div class="settings-section">
972
997
  <h3><span class="icon">\u{1F4E1}</span> <span data-i18n="settings.embedding">Embedding Model</span></h3>
@@ -1336,6 +1361,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
1336
1361
 
1337
1362
  <script>
1338
1363
  let activeSession=null,activeRole='',editingId=null,searchTimer=null,memoryCache={},currentPage=1,totalPages=1,totalCount=0,PAGE_SIZE=40,metricsDays=30;
1364
+ let _embeddingWarningShown=false;
1339
1365
 
1340
1366
  /* ─── i18n ─── */
1341
1367
  const I18N={
@@ -1395,6 +1421,8 @@ const I18N={
1395
1421
  'tasks.untitled':'Untitled Task',
1396
1422
  'tasks.chunks':'Related Memories',
1397
1423
  'tasks.nochunks':'No memories in this task yet.',
1424
+ 'tasks.expand':'Show more',
1425
+ 'tasks.collapse':'Show less',
1398
1426
  'tasks.skipped.default':'This conversation was too brief to generate a summary. It will not appear in search results.',
1399
1427
  'refresh':'\\u21BB Refresh',
1400
1428
  'logout':'Logout',
@@ -1487,6 +1515,9 @@ const I18N={
1487
1515
  'confirm.clearall2':'Are you absolutely sure?',
1488
1516
  'embed.on':'Embedding: ',
1489
1517
  'embed.off':'No embedding model',
1518
+ 'embed.warn.local':'Using built-in mini model (384d). Search quality is limited — configure an embedding model in Settings for best results.',
1519
+ 'embed.err.fail':'Embedding model error detected. Check Settings → Model Health.',
1520
+ 'embed.banner.goto':'Go to Settings',
1490
1521
  'lang.switch':'中',
1491
1522
  'tab.logs':'\u{1F4DD} Logs',
1492
1523
  'logs.allTools':'All Tools',
@@ -1499,6 +1530,7 @@ const I18N={
1499
1530
  'tab.import':'\u{1F4E5} Import',
1500
1531
  'tab.settings':'\u2699 Settings',
1501
1532
  'settings.modelconfig':'Model Configuration',
1533
+ 'settings.modelhealth':'Model Health',
1502
1534
  'settings.embedding':'Embedding Model',
1503
1535
  'settings.summarizer':'Summarizer Model',
1504
1536
  'settings.skill':'Skill Evolution',
@@ -1704,6 +1736,8 @@ const I18N={
1704
1736
  'tasks.untitled':'未命名任务',
1705
1737
  'tasks.chunks':'关联记忆',
1706
1738
  'tasks.nochunks':'此任务暂无关联记忆。',
1739
+ 'tasks.expand':'展开全文',
1740
+ 'tasks.collapse':'收起',
1707
1741
  'tasks.skipped.default':'对话内容过少,未生成摘要。该任务不会出现在检索结果中。',
1708
1742
  'refresh':'\\u21BB 刷新',
1709
1743
  'logout':'退出',
@@ -1796,6 +1830,9 @@ const I18N={
1796
1830
  'confirm.clearall2':'你真的确定吗?',
1797
1831
  'embed.on':'嵌入模型:',
1798
1832
  'embed.off':'无嵌入模型',
1833
+ 'embed.warn.local':'当前使用内置迷你模型(384维),搜索效果有限。强烈建议在「设置」中配置专用 Embedding 模型以获得最佳效果。',
1834
+ 'embed.err.fail':'Embedding 模型调用异常,请前往「设置 → 模型健康」检查。',
1835
+ 'embed.banner.goto':'前往设置',
1799
1836
  'lang.switch':'EN',
1800
1837
  'tab.logs':'\u{1F4DD} 日志',
1801
1838
  'logs.allTools':'全部工具',
@@ -1808,6 +1845,7 @@ const I18N={
1808
1845
  'tab.import':'\u{1F4E5} 导入',
1809
1846
  'tab.settings':'\u2699 设置',
1810
1847
  'settings.modelconfig':'模型配置',
1848
+ 'settings.modelhealth':'模型健康',
1811
1849
  'settings.embedding':'嵌入模型',
1812
1850
  'settings.summarizer':'摘要模型',
1813
1851
  'settings.skill':'技能进化',
@@ -2071,6 +2109,7 @@ function switchView(view){
2071
2109
  const logsView=document.getElementById('logsView');
2072
2110
  const settingsView=document.getElementById('settingsView');
2073
2111
  const migrateView=document.getElementById('migrateView');
2112
+ const sidebar=document.getElementById('sidebar');
2074
2113
  feedWrap.classList.add('hide');
2075
2114
  analyticsView.classList.remove('show');
2076
2115
  tasksView.classList.remove('show');
@@ -2078,27 +2117,33 @@ function switchView(view){
2078
2117
  logsView.classList.remove('show');
2079
2118
  settingsView.classList.remove('show');
2080
2119
  migrateView.classList.remove('show');
2081
- if(view==='analytics'){
2082
- analyticsView.classList.add('show');
2083
- loadMetrics();
2084
- } else if(view==='tasks'){
2085
- tasksView.classList.add('show');
2086
- loadTasks();
2087
- } else if(view==='skills'){
2088
- skillsView.classList.add('show');
2089
- loadSkills();
2090
- } else if(view==='logs'){
2091
- logsView.classList.add('show');
2092
- loadLogs();
2093
- } else if(view==='settings'){
2094
- settingsView.classList.add('show');
2095
- loadConfig();
2096
- loadModelHealth();
2097
- } else if(view==='import'){
2098
- migrateView.classList.add('show');
2099
- if(!window._migrateRunning) migrateScan();
2100
- } else {
2120
+ const sessionSection=document.getElementById('sidebarSessionSection');
2121
+ if(view==='memories'){
2101
2122
  feedWrap.classList.remove('hide');
2123
+ sessionSection.style.visibility='';
2124
+ sessionSection.style.pointerEvents='';
2125
+ } else if(view==='tasks'||view==='skills'){
2126
+ sessionSection.style.visibility='hidden';
2127
+ sessionSection.style.pointerEvents='none';
2128
+ if(view==='tasks'){tasksView.classList.add('show');loadTasks();}
2129
+ else{skillsView.classList.add('show');loadSkills();}
2130
+ } else {
2131
+ sessionSection.style.visibility='hidden';
2132
+ sessionSection.style.pointerEvents='none';
2133
+ if(view==='analytics'){
2134
+ analyticsView.classList.add('show');
2135
+ loadMetrics();
2136
+ } else if(view==='logs'){
2137
+ logsView.classList.add('show');
2138
+ loadLogs();
2139
+ } else if(view==='settings'){
2140
+ settingsView.classList.add('show');
2141
+ loadConfig();
2142
+ loadModelHealth();
2143
+ } else if(view==='import'){
2144
+ migrateView.classList.add('show');
2145
+ if(!window._migrateRunning) migrateScan();
2146
+ }
2102
2147
  }
2103
2148
  }
2104
2149
 
@@ -2451,14 +2496,16 @@ async function openTaskDetail(taskId){
2451
2496
  if(task.chunks.length===0){
2452
2497
  document.getElementById('taskDetailChunks').innerHTML='<div style="color:var(--text-muted);padding:12px;font-size:13px">'+t('tasks.nochunks')+'</div>';
2453
2498
  }else{
2454
- document.getElementById('taskDetailChunks').innerHTML=task.chunks.map(c=>{
2499
+ document.getElementById('taskDetailChunks').innerHTML=task.chunks.map(function(c,i){
2455
2500
  var roleLabel=c.role==='user'?t('tasks.role.user'):c.role==='assistant'?t('tasks.role.assistant'):c.role.toUpperCase();
2456
2501
  return '<div class="task-chunk-item role-'+c.role+'">'+
2457
2502
  '<div class="task-chunk-role '+c.role+'">'+roleLabel+'</div>'+
2458
- '<div class="task-chunk-bubble" onclick="this.classList.toggle(\\\'expanded\\\')">'+esc(c.content)+'</div>'+
2503
+ '<div class="task-chunk-bubble collapsed" id="chunk_b_'+i+'">'+esc(c.content)+'</div>'+
2504
+ '<div class="task-chunk-expand" id="chunk_e_'+i+'" onclick="toggleChunkExpand('+i+')"><span class="expand-arrow">▼</span> <span class="expand-label">'+t('tasks.expand')+'</span></div>'+
2459
2505
  '<div class="task-chunk-time">'+formatTime(c.createdAt)+'</div>'+
2460
2506
  '</div>';
2461
2507
  }).join('');
2508
+ setTimeout(function(){initChunkExpanders(task.chunks.length)},50);
2462
2509
  }
2463
2510
  }catch(e){
2464
2511
  document.getElementById('taskDetailTitle').textContent=t('tasks.error');
@@ -2522,6 +2569,33 @@ function renderTaskSkillSection(task){
2522
2569
  }
2523
2570
  }
2524
2571
 
2572
+ function initChunkExpanders(count){
2573
+ for(var i=0;i<count;i++){
2574
+ var b=document.getElementById('chunk_b_'+i);
2575
+ var e=document.getElementById('chunk_e_'+i);
2576
+ if(b && b.scrollHeight > b.clientHeight + 4){
2577
+ e.style.display='flex';
2578
+ } else if(b) {
2579
+ b.classList.remove('collapsed');
2580
+ }
2581
+ }
2582
+ }
2583
+ function toggleChunkExpand(i){
2584
+ var b=document.getElementById('chunk_b_'+i);
2585
+ var e=document.getElementById('chunk_e_'+i);
2586
+ if(!b||!e)return;
2587
+ var expanding=b.classList.contains('collapsed');
2588
+ if(expanding){
2589
+ b.classList.remove('collapsed');
2590
+ e.classList.add('is-expanded');
2591
+ e.querySelector('.expand-label').textContent=t('tasks.collapse');
2592
+ }else{
2593
+ b.classList.add('collapsed');
2594
+ e.classList.remove('is-expanded');
2595
+ e.querySelector('.expand-label').textContent=t('tasks.expand');
2596
+ }
2597
+ }
2598
+
2525
2599
  function closeTaskDetail(event){
2526
2600
  if(event && event.target!==document.getElementById('taskDetailOverlay')) return;
2527
2601
  document.getElementById('taskDetailOverlay').classList.remove('show');
@@ -3063,15 +3137,16 @@ async function testModel(type){
3063
3137
  var d=await r.json();
3064
3138
  if(d.ok){
3065
3139
  resultEl.className='test-result ok';
3066
- resultEl.innerHTML='\\u2705 '+t('settings.test.ok')+'<div style="margin-top:4px;font-size:11px;color:var(--text-muted)">'+esc(d.detail||'')+'</div>';
3140
+ resultEl.innerHTML='\\u2705 '+t('settings.test.ok')+(d.detail?'<div style="margin-top:4px;font-size:11px;color:var(--text-muted)">'+esc(d.detail)+'</div>':'');
3067
3141
  }else{
3068
- var errMsg=d.error||'Unknown error';
3142
+ var errMsg=(d.error||'Unknown error').replace(/:\s*$/,'').trim();
3069
3143
  resultEl.className='test-result fail';
3070
- resultEl.innerHTML='\\u274C '+t('settings.test.fail')+'<div style="margin-top:6px;font-size:11px;padding:8px 10px;background:rgba(239,68,68,.06);border:1px solid rgba(239,68,68,.15);border-radius:6px;white-space:pre-wrap;word-break:break-all;max-height:120px;overflow-y:auto;font-family:SF Mono,Monaco,Consolas,monospace">'+esc(errMsg)+'</div>';
3144
+ resultEl.innerHTML='\\u274C '+t('settings.test.fail')+(errMsg?'<div style="margin-top:6px;font-size:11px;padding:8px 10px;background:rgba(239,68,68,.06);border:1px solid rgba(239,68,68,.15);border-radius:6px;white-space:pre-wrap;word-break:break-all;max-height:120px;overflow-y:auto;font-family:SF Mono,Monaco,Consolas,monospace">'+esc(errMsg)+'</div>':'');
3071
3145
  }
3072
3146
  }catch(e){
3147
+ var catchMsg=(e.message||'Network error').replace(/:\s*$/,'').trim();
3073
3148
  resultEl.className='test-result fail';
3074
- resultEl.innerHTML='\\u274C '+t('settings.test.fail')+'<div style="margin-top:6px;font-size:11px;padding:8px 10px;background:rgba(239,68,68,.06);border:1px solid rgba(239,68,68,.15);border-radius:6px;white-space:pre-wrap;word-break:break-all">'+esc(e.message)+'</div>';
3149
+ resultEl.innerHTML='\\u274C '+t('settings.test.fail')+(catchMsg?'<div style="margin-top:6px;font-size:11px;padding:8px 10px;background:rgba(239,68,68,.06);border:1px solid rgba(239,68,68,.15);border-radius:6px;white-space:pre-wrap;word-break:break-all">'+esc(catchMsg)+'</div>':'');
3075
3150
  }finally{btn.disabled=false;}
3076
3151
  }
3077
3152
 
@@ -3439,6 +3514,20 @@ async function loadStats(){
3439
3514
  provEl.innerHTML='<div class="provider-badge offline"><span>\\u26A0</span> '+t('embed.off')+'</div>';
3440
3515
  }
3441
3516
 
3517
+ if(!_embeddingWarningShown){
3518
+ _embeddingWarningShown=true;
3519
+ if(!d.embeddingProvider||d.embeddingProvider==='local'||d.embeddingProvider==='none'){
3520
+ showEmbeddingBanner(t('embed.warn.local'),'warning');
3521
+ }
3522
+ fetch('/api/model-health').then(r=>r.json()).then(mh=>{
3523
+ var models=mh.models||[];
3524
+ var embModel=models.find(m=>m.role==='embedding');
3525
+ if(embModel&&embModel.status==='error'){
3526
+ showEmbeddingBanner(t('embed.err.fail'),'error');
3527
+ }
3528
+ }).catch(()=>{});
3529
+ }
3530
+
3442
3531
  const sl=document.getElementById('sessionList');
3443
3532
  sl.innerHTML='<div class="session-item'+(activeSession===null?' active':'')+'" onclick="filterSession(null)"><span>'+t('sidebar.allsessions')+'</span><span class="count">'+tm+'</span></div>';
3444
3533
  (d.sessions||[]).forEach(s=>{
@@ -3502,17 +3591,24 @@ async function doSearch(q){
3502
3591
  if(!q.trim()){currentPage=1;loadMemories();return}
3503
3592
  const list=document.getElementById('memoryList');
3504
3593
  list.innerHTML='<div class="spinner"></div>';
3505
- const p=getFilterParams();
3506
- p.set('q',q);
3507
- const r=await fetch('/api/search?'+p.toString());
3508
- const d=await r.json();
3509
- const meta=[];
3510
- if(d.vectorCount>0) meta.push(d.vectorCount+t('search.meta.semantic'));
3511
- if(d.ftsCount>0) meta.push(d.ftsCount+t('search.meta.text'));
3512
- meta.push(d.total+t('search.meta.results'));
3513
- document.getElementById('searchMeta').textContent=meta.join(' \\u00B7 ');
3514
- renderMemories(d.results||[]);
3515
- document.getElementById('pagination').innerHTML='';
3594
+ try{
3595
+ const p=getFilterParams();
3596
+ p.set('q',q);
3597
+ const r=await fetch('/api/search?'+p.toString());
3598
+ const d=await r.json();
3599
+ const total=d.total||0;
3600
+ const meta=[];
3601
+ if(d.vectorCount>0) meta.push(d.vectorCount+t('search.meta.semantic'));
3602
+ if(d.ftsCount>0) meta.push(d.ftsCount+t('search.meta.text'));
3603
+ meta.push(total+t('search.meta.results'));
3604
+ document.getElementById('searchMeta').textContent=meta.join(' \\u00B7 ');
3605
+ renderMemories(d.results||[]);
3606
+ document.getElementById('pagination').innerHTML='';
3607
+ }catch(e){
3608
+ document.getElementById('searchMeta').textContent='0'+t('search.meta.results');
3609
+ renderMemories([]);
3610
+ document.getElementById('pagination').innerHTML='';
3611
+ }
3516
3612
  }
3517
3613
 
3518
3614
  function debounceSearch(){
@@ -4319,6 +4415,21 @@ function ppDone(wasStopped,wasFailed,skipReload){
4319
4415
  if(!skipReload) loadAll();
4320
4416
  }
4321
4417
 
4418
+ /* ─── Embedding Banner ─── */
4419
+ function showEmbeddingBanner(msg,type){
4420
+ if(document.getElementById('embBanner')) return;
4421
+ var cls=type==='error'?'emb-banner error':'emb-banner warning';
4422
+ var icon=type==='error'?'\\u274C':'\\u26A0\\uFE0F';
4423
+ var btn='<button class="emb-banner-btn" onclick="switchView(\\'settings\\');this.parentElement.remove()">'+t('embed.banner.goto')+'</button>';
4424
+ var close='<button class="emb-banner-close" onclick="this.parentElement.remove()">&times;</button>';
4425
+ var el=document.createElement('div');
4426
+ el.id='embBanner';
4427
+ el.className=cls;
4428
+ el.innerHTML=icon+' <span>'+esc(msg)+'</span>'+btn+close;
4429
+ var mc=document.querySelector('.main-content');
4430
+ if(mc) mc.parentElement.insertBefore(el,mc);
4431
+ }
4432
+
4322
4433
  /* ─── Toast ─── */
4323
4434
  function toast(msg,type='info'){
4324
4435
  const c=document.getElementById('toasts');
@@ -4372,4 +4483,5 @@ checkAuth();
4372
4483
 
4373
4484
  </body>
4374
4485
  </html>`;
4486
+ }
4375
4487
  //# sourceMappingURL=html.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/viewer/html.ts"],"names":[],"mappings":";;;AAAa,QAAA,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAkxIlB,CAAC"}
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/viewer/html.ts"],"names":[],"mappings":";;AAAA,gCAk4IC;AAl4ID,SAAgB,UAAU,CAAC,aAAsB;IACjD,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,gCAAgC,aAAa,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3F,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sDAuvB+C,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAwoHpD,CAAC;AACT,CAAC"}
@@ -20,6 +20,7 @@ export declare class ViewerServer {
20
20
  private readonly auth;
21
21
  private readonly ctx?;
22
22
  private static readonly SESSION_TTL;
23
+ private static readonly PLUGIN_VERSION;
23
24
  private resetToken;
24
25
  private migrationRunning;
25
26
  private migrationAbort;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/viewer/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/viewer/server.ts"],"names":[],"mappings":"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"}
@@ -35,6 +35,15 @@ class ViewerServer {
35
35
  auth;
36
36
  ctx;
37
37
  static SESSION_TTL = 24 * 60 * 60 * 1000;
38
+ static PLUGIN_VERSION = (() => {
39
+ try {
40
+ const pkgPath = node_path_1.default.resolve(__dirname, "../../package.json");
41
+ return JSON.parse(node_fs_1.default.readFileSync(pkgPath, "utf-8")).version ?? "unknown";
42
+ }
43
+ catch {
44
+ return "unknown";
45
+ }
46
+ })();
38
47
  resetToken;
39
48
  migrationRunning = false;
40
49
  migrationAbort = false;
@@ -372,7 +381,7 @@ class ViewerServer {
372
381
  // ─── Pages ───
373
382
  serveViewer(res) {
374
383
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-store, no-cache, must-revalidate, max-age=0", "Pragma": "no-cache", "Expires": "0" });
375
- res.end(html_1.viewerHTML);
384
+ res.end((0, html_1.viewerHTML)(ViewerServer.PLUGIN_VERSION));
376
385
  }
377
386
  // ─── Data APIs ───
378
387
  serveMemories(res, url) {
@@ -576,6 +585,8 @@ class ViewerServer {
576
585
  }
577
586
  const role = url.searchParams.get("role") ?? undefined;
578
587
  const kind = url.searchParams.get("kind") ?? undefined;
588
+ const session = url.searchParams.get("session") ?? undefined;
589
+ const owner = url.searchParams.get("owner") ?? undefined;
579
590
  const dateFrom = url.searchParams.get("dateFrom") ?? undefined;
580
591
  const dateTo = url.searchParams.get("dateTo") ?? undefined;
581
592
  const passesFilter = (r) => {
@@ -583,35 +594,71 @@ class ViewerServer {
583
594
  return false;
584
595
  if (kind && r.kind !== kind)
585
596
  return false;
597
+ if (session && r.session_key !== session)
598
+ return false;
599
+ if (owner && r.owner !== owner)
600
+ return false;
586
601
  if (dateFrom && r.created_at < new Date(dateFrom).getTime())
587
602
  return false;
588
603
  if (dateTo && r.created_at > new Date(dateTo).getTime())
589
604
  return false;
590
605
  return true;
591
606
  };
607
+ const ftsFilters = [];
608
+ const likeFilters = [];
609
+ const sqlParams = [];
610
+ if (session) {
611
+ ftsFilters.push("c.session_key = ?");
612
+ likeFilters.push("session_key = ?");
613
+ sqlParams.push(session);
614
+ }
615
+ if (owner) {
616
+ ftsFilters.push("c.owner = ?");
617
+ likeFilters.push("owner = ?");
618
+ sqlParams.push(owner);
619
+ }
620
+ const ftsWhere = ftsFilters.length > 0 ? " AND " + ftsFilters.join(" AND ") : "";
621
+ const likeWhere = likeFilters.length > 0 ? " AND " + likeFilters.join(" AND ") : "";
592
622
  const db = this.store.db;
593
623
  let ftsResults = [];
594
624
  try {
595
- ftsResults = db.prepare("SELECT c.* FROM chunks_fts f JOIN chunks c ON f.rowid = c.rowid WHERE chunks_fts MATCH ? ORDER BY rank LIMIT 100").all(q).filter(passesFilter);
625
+ ftsResults = db.prepare(`SELECT c.* FROM chunks_fts f JOIN chunks c ON f.rowid = c.rowid WHERE chunks_fts MATCH ?${ftsWhere} ORDER BY rank LIMIT 100`).all(q, ...sqlParams).filter(passesFilter);
596
626
  }
597
627
  catch { /* FTS syntax error, fall through */ }
598
628
  if (ftsResults.length === 0) {
599
- ftsResults = db.prepare("SELECT * FROM chunks WHERE content LIKE ? OR summary LIKE ? ORDER BY created_at DESC LIMIT 100").all(`%${q}%`, `%${q}%`).filter(passesFilter);
629
+ try {
630
+ ftsResults = db.prepare(`SELECT * FROM chunks WHERE (content LIKE ? OR summary LIKE ?)${likeWhere} ORDER BY created_at DESC LIMIT 100`).all(`%${q}%`, `%${q}%`, ...sqlParams).filter(passesFilter);
631
+ }
632
+ catch (err) {
633
+ this.log.warn(`LIKE search failed: ${err}`);
634
+ }
600
635
  }
601
636
  const SEMANTIC_THRESHOLD = 0.64;
637
+ const VECTOR_TIMEOUT_MS = 8000;
602
638
  let vectorResults = [];
603
639
  let scoreMap = new Map();
604
640
  try {
605
- const queryVec = await this.embedder.embedQuery(q);
606
- const hits = (0, vector_1.vectorSearch)(this.store, queryVec, 40);
607
- scoreMap = new Map(hits.map(h => [h.chunkId, h.score]));
608
- const hitIds = new Set(hits.filter(h => h.score >= SEMANTIC_THRESHOLD).map(h => h.chunkId));
609
- if (hitIds.size > 0) {
610
- const placeholders = [...hitIds].map(() => "?").join(",");
611
- const rows = db.prepare(`SELECT * FROM chunks WHERE id IN (${placeholders})`).all(...hitIds).filter(passesFilter);
612
- rows.forEach((r) => { r._vscore = scoreMap.get(r.id) ?? 0; });
613
- rows.sort((a, b) => (b._vscore ?? 0) - (a._vscore ?? 0));
614
- vectorResults = rows;
641
+ const vecPromise = (async () => {
642
+ const queryVec = await this.embedder.embedQuery(q);
643
+ return (0, vector_1.vectorSearch)(this.store, queryVec, 40);
644
+ })();
645
+ const hits = await Promise.race([
646
+ vecPromise,
647
+ new Promise((resolve) => setTimeout(() => resolve(null), VECTOR_TIMEOUT_MS)),
648
+ ]);
649
+ if (hits) {
650
+ scoreMap = new Map(hits.map(h => [h.chunkId, h.score]));
651
+ const hitIds = new Set(hits.filter(h => h.score >= SEMANTIC_THRESHOLD).map(h => h.chunkId));
652
+ if (hitIds.size > 0) {
653
+ const placeholders = [...hitIds].map(() => "?").join(",");
654
+ const rows = db.prepare(`SELECT * FROM chunks WHERE id IN (${placeholders})${likeWhere}`).all(...hitIds, ...sqlParams).filter(passesFilter);
655
+ rows.forEach((r) => { r._vscore = scoreMap.get(r.id) ?? 0; });
656
+ rows.sort((a, b) => (b._vscore ?? 0) - (a._vscore ?? 0));
657
+ vectorResults = rows;
658
+ }
659
+ }
660
+ else {
661
+ this.log.warn("Vector search timed out, returning FTS results only");
615
662
  }
616
663
  }
617
664
  catch (err) {