|
73 | 73 | if (!Array.isArray(raw) || !raw.length) { |
74 | 74 | return []; |
75 | 75 | } |
76 | | - return raw |
| 76 | + const seen = new Set(); |
| 77 | + const result = []; |
| 78 | + raw |
77 | 79 | .filter((item) => item && typeof item === 'object') |
78 | | - .filter((item) => (item.selected === undefined) || Boolean(item.selected)); |
| 80 | + .filter((item) => (item.selected === undefined) || Boolean(item.selected)) |
| 81 | + .forEach((reference) => { |
| 82 | + const key = this.getReferenceKey(reference); |
| 83 | + if (key) { |
| 84 | + if (!seen.has(key)) { |
| 85 | + seen.add(key); |
| 86 | + result.push(reference); |
| 87 | + } |
| 88 | + } else { |
| 89 | + result.push(reference); |
| 90 | + } |
| 91 | + }); |
| 92 | + return result; |
79 | 93 | } |
80 | 94 |
|
81 | 95 | renderReferenceSection(references, metadata) { |
|
129 | 143 | return null; |
130 | 144 | } |
131 | 145 |
|
| 146 | + const seen = new Set(); |
132 | 147 | const matches = rawMatches.map((match, index) => { |
133 | 148 | if (!match || typeof match !== 'object') { |
134 | 149 | return null; |
135 | 150 | } |
136 | 151 | const summaryText = typeof match.summary_text === 'string' |
137 | 152 | ? match.summary_text |
138 | 153 | : (match.summary_preview || ''); |
| 154 | + const key = this.getSummaryMatchKey(match, index); |
| 155 | + if (key && seen.has(key)) { |
| 156 | + return null; |
| 157 | + } |
| 158 | + if (key) { |
| 159 | + seen.add(key); |
| 160 | + } |
139 | 161 | return { |
140 | 162 | name: (match.filename || '').trim() || `文档-${match.rank || index + 1}`, |
141 | 163 | summary: summaryText, |
|
217 | 239 | return card; |
218 | 240 | } |
219 | 241 |
|
| 242 | + getReferenceKey(reference) { |
| 243 | + if (!reference || typeof reference !== 'object') { |
| 244 | + return ''; |
| 245 | + } |
| 246 | + const absolute = ChatUtils.normalizePath(reference.absolute_path); |
| 247 | + if (absolute) { |
| 248 | + return `abs:${absolute}`; |
| 249 | + } |
| 250 | + const projectPath = ChatUtils.normalizePath(reference.project_relative_path); |
| 251 | + if (projectPath) { |
| 252 | + return `proj:${projectPath}`; |
| 253 | + } |
| 254 | + const filePath = ChatUtils.normalizePath(reference.file_path); |
| 255 | + if (filePath) { |
| 256 | + return `file:${filePath}`; |
| 257 | + } |
| 258 | + if (reference.reference_id) { |
| 259 | + return `id:${reference.reference_id}`; |
| 260 | + } |
| 261 | + const displayName = (reference.display_name || reference.filename || '').trim(); |
| 262 | + if (displayName) { |
| 263 | + return `name:${displayName}`; |
| 264 | + } |
| 265 | + if (reference.snippet) { |
| 266 | + return `snippet:${String(reference.snippet).slice(0, 64)}`; |
| 267 | + } |
| 268 | + return ''; |
| 269 | + } |
| 270 | + |
| 271 | + getSummaryMatchKey(match, index) { |
| 272 | + if (!match || typeof match !== 'object') { |
| 273 | + return `idx:${index}`; |
| 274 | + } |
| 275 | + const filename = (match.filename || '').trim(); |
| 276 | + const summary = typeof match.summary_text === 'string' |
| 277 | + ? match.summary_text.trim() |
| 278 | + : (typeof match.summary_preview === 'string' ? match.summary_preview.trim() : ''); |
| 279 | + const scorePart = Number.isFinite(match.score) ? match.score.toFixed(3) : 'na'; |
| 280 | + if (filename || summary) { |
| 281 | + return `summary:${filename || summary}:${scorePart}`; |
| 282 | + } |
| 283 | + return `idx:${index}`; |
| 284 | + } |
| 285 | + |
220 | 286 | createReferenceItem(reference, metadata) { |
221 | 287 | if (!reference || typeof reference !== 'object') { |
222 | 288 | return null; |
|
0 commit comments