mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-10-04 02:52:55 +08:00
126 lines
4.2 KiB
JavaScript
126 lines
4.2 KiB
JavaScript
// Persistent-process adapter for measuring CodeGraph library search without CLI startup noise.
|
|
|
|
'use strict'
|
|
|
|
const fs = require('node:fs')
|
|
const path = require('node:path')
|
|
|
|
async function main() {
|
|
const [libraryRoot, projectRoot, repetitionsText, limitText] = process.argv.slice(2)
|
|
const repetitions = Number(repetitionsText)
|
|
const limit = Number(limitText)
|
|
const input = JSON.parse(fs.readFileSync(0, 'utf8'))
|
|
const loadStarted = process.hrtime.bigint()
|
|
const codegraphModule = require(path.join(libraryRoot, 'dist/index.js'))
|
|
const generatedModule = require(path.join(
|
|
libraryRoot,
|
|
'dist/extraction/generated-detection.js',
|
|
))
|
|
const { ToolHandler } = require(path.join(libraryRoot, 'dist/mcp/tools.js'))
|
|
const CodeGraph = codegraphModule.CodeGraph || codegraphModule.default
|
|
const graph = await CodeGraph.open(projectRoot, { sync: false, readOnly: true })
|
|
const loadMs = millisecondsSince(loadStarted)
|
|
const stats = graph.getStats()
|
|
const handler = new ToolHandler(graph)
|
|
const tracks = []
|
|
for (const track of input.tracks) {
|
|
const queries = []
|
|
for (const query of track.queries) {
|
|
queries.push(
|
|
track.name !== 'symbol'
|
|
? await runExplore(handler, query, repetitions, limit)
|
|
: runSearch(graph, generatedModule, query, repetitions, limit),
|
|
)
|
|
}
|
|
tracks.push({ name: track.name, queries })
|
|
}
|
|
graph.close()
|
|
process.stdout.write(JSON.stringify({ loadMs, stats, tracks }))
|
|
}
|
|
|
|
async function runExplore(handler, query, repetitions, limit) {
|
|
const first = await explore(handler, query.query, limit)
|
|
const durationsMs = []
|
|
for (let index = 0; index < repetitions; index += 1) {
|
|
const started = process.hrtime.bigint()
|
|
await explore(handler, query.query, limit)
|
|
durationsMs.push(millisecondsSince(started))
|
|
}
|
|
return { id: query.id, query: query.query, durationsMs, results: first }
|
|
}
|
|
|
|
async function explore(handler, query, limit) {
|
|
const response = await handler.execute('codegraph_explore', { query, maxFiles: limit })
|
|
if (response.isError) throw new Error(response.content?.[0]?.text || 'CodeGraph explore failed')
|
|
return parseExplore(response.content?.[0]?.text || '')
|
|
}
|
|
|
|
function parseExplore(text) {
|
|
const results = []
|
|
let current = null
|
|
let inCode = false
|
|
for (const line of text.split('\n')) {
|
|
const heading = line.match(/^####\s+(.+?)(?:\s+—|$)/)
|
|
if (heading) {
|
|
current = { path: heading[1].trim(), startLine: 0, endLine: 0, score: 0, lines: [] }
|
|
results.push(current)
|
|
inCode = false
|
|
continue
|
|
}
|
|
if (line.startsWith('```')) {
|
|
inCode = !inCode
|
|
continue
|
|
}
|
|
if (!inCode || !current) continue
|
|
const numbered = line.match(/^(\d+)\t/)
|
|
if (!numbered) continue
|
|
const number = Number(numbered[1])
|
|
current.lines.push(number)
|
|
if (current.startLine === 0) current.startLine = number
|
|
current.endLine = number
|
|
}
|
|
return results
|
|
.filter((result) => result.lines.length > 0)
|
|
.map((result, index) => ({ ...result, score: 1 / (index + 1) }))
|
|
}
|
|
|
|
function runSearch(graph, generatedModule, query, repetitions, limit) {
|
|
const durationsMs = []
|
|
const first = sortedResults(graph, generatedModule, query.query, limit)
|
|
for (let index = 0; index < repetitions; index += 1) {
|
|
const started = process.hrtime.bigint()
|
|
sortedResults(graph, generatedModule, query.query, limit)
|
|
durationsMs.push(millisecondsSince(started))
|
|
}
|
|
return {
|
|
id: query.id,
|
|
query: query.query,
|
|
durationsMs,
|
|
results: first.map(({ node, score }) => ({
|
|
path: node.filePath,
|
|
startLine: node.startLine,
|
|
endLine: node.endLine,
|
|
score,
|
|
lines: null,
|
|
})),
|
|
}
|
|
}
|
|
|
|
function sortedResults(graph, generatedModule, query, limit) {
|
|
const raw = graph.searchNodes(query, { limit })
|
|
return [...raw].sort((left, right) => {
|
|
const leftGenerated = generatedModule.isGeneratedFile(left.node.filePath) ? 1 : 0
|
|
const rightGenerated = generatedModule.isGeneratedFile(right.node.filePath) ? 1 : 0
|
|
return leftGenerated - rightGenerated
|
|
})
|
|
}
|
|
|
|
function millisecondsSince(started) {
|
|
return Number(process.hrtime.bigint() - started) / 1_000_000
|
|
}
|
|
|
|
main().catch((error) => {
|
|
process.stderr.write(`${error.stack || error}\n`)
|
|
process.exitCode = 1
|
|
})
|