Add search_project tool to the AI assistant (#31879)

GitOrigin-RevId: 257b59bea43bd8ee3ff81b2f5439455c4a6ea403
This commit is contained in:
Alf Eaton
2026-09-17 11:34:23 +00:00
committed by Copybot
parent 5c8a4f3210
commit b4d2d11c7b
3 changed files with 61 additions and 31 deletions
@@ -1,42 +1,13 @@
import React, { FC, useMemo } from 'react'
import { Hit } from '../util/search-snapshot'
import { getMatchedHitSnippet } from '../util/matched-hit-snippet'
export const MatchedHitHighlight: FC<{ text: string; hit: Hit }> = ({
text,
hit,
}) => {
const parts = useMemo(() => {
let before = text.substring(0, hit.matchIndex).trimStart()
const match = text.substring(hit.matchIndex, hit.matchIndex + hit.length)
let after = text.substring(hit.matchIndex + hit.length).trimEnd()
// reduce the prefix to a sensible size before trimming
if (before.length > 250) {
before = before.substring(before.length - 250)
}
while (before.length > 10) {
const replacement = before.replace(/^\S+\s+/, '')
if (before.length === replacement.length) {
break
}
before = replacement
}
// reduce the suffix to a sensible size before trimming
if (after.length > 250) {
after = after.substring(0, 250)
}
while (after.length > 100) {
const replacement = after.replace(/\s+\S+$/, '')
if (after.length === replacement.length) {
break
}
after = replacement
}
return { before, match, after }
return getMatchedHitSnippet(text, hit.matchIndex, hit.length)
}, [hit, text])
return (
@@ -0,0 +1,35 @@
export const getMatchedHitSnippet = (
text: string,
matchIndex: number,
length: number
) => {
let before = text.substring(0, matchIndex).trimStart()
const match = text.substring(matchIndex, matchIndex + length)
let after = text.substring(matchIndex + length).trimEnd()
if (before.length > 250) {
before = before.substring(before.length - 250)
}
while (before.length > 10) {
const replacement = before.replace(/^\S+\s+/, '')
if (before.length === replacement.length) {
break
}
before = replacement
}
if (after.length > 250) {
after = after.substring(0, 250)
}
while (after.length > 100) {
const replacement = after.replace(/\s+\S+$/, '')
if (after.length === replacement.length) {
break
}
after = replacement
}
return { before, match, after }
}
@@ -0,0 +1,24 @@
import { expect } from 'chai'
import { getMatchedHitSnippet } from '../../../frontend/js/util/matched-hit-snippet'
describe('getMatchedHitSnippet', function () {
it('builds before/match/after for a simple match', function () {
const text = 'alpha beta gamma delta'
const snippet = getMatchedHitSnippet(text, 6, 4)
expect(snippet).to.deep.equal({
before: 'alpha ',
match: 'beta',
after: ' gamma delta',
})
})
it('caps raw prefix/suffix size when surrounding text is very long', function () {
const text = `${'a'.repeat(300)}needle${'b'.repeat(300)}`
const snippet = getMatchedHitSnippet(text, 300, 6)
expect(snippet.match).to.equal('needle')
expect(snippet.before.length).to.equal(250)
expect(snippet.after.length).to.equal(250)
})
})