mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-10-26 10:45:22 +00:00
feat(codegraph): codegraph_explore 改为自有 stdio JSON-RPC 客户端直连 codegraph serve
一次性 `codegraph explore` CLI 不会同步索引,新增符号在手动 sync 前 无法被搜到。改为按索引根惰性启动常驻 `codegraph serve --mcp` 子进程, 由组合包自有的逐行 JSON-RPC 客户端(extensions/codegraph-client.ts, 不依赖 MCP adapter/SDK)收发,serve 内置文件监听自动同步索引,删除 mtime 结果缓存。子进程闲置 10 分钟或会话结束关闭,子进程死亡时透明 重试一次;用户拒绝初始化在会话内记住;用户中止调用不关闭子进程; 所有失败以文本打回引导改用 find/grep/read/LSP。新增模拟服务与真实 CLI 集成测试。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
parent
da9908fb6e
commit
dc4fe92e27
+120
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Fake `codegraph serve --mcp`: newline-delimited JSON-RPC 2.0 on stdio, for
|
||||
* tests of extensions/codegraph-client.ts.
|
||||
*
|
||||
* Env:
|
||||
* FAKE_CG_MODE "ok" (default) | "no-tool" | "crash-first" | "crash" | "hang"
|
||||
* no-tool: tools/list returns no codegraph_explore
|
||||
* crash-first: on the first tools/call, write FAKE_CG_MARKER
|
||||
* and exit(1) — a second spawned process sees
|
||||
* the marker and serves normally
|
||||
* crash: exit(1) on every tools/call
|
||||
* hang: never reply to tools/call
|
||||
* FAKE_CG_SCHEMA JSON array of inputSchema property names
|
||||
* (default ["query","maxFiles","projectPath"])
|
||||
* FAKE_CG_MARKER marker file path for crash-first
|
||||
* FAKE_CG_LOG file to append every inbound message as a JSON line
|
||||
*/
|
||||
|
||||
import fs from "node:fs";
|
||||
import readline from "node:readline";
|
||||
|
||||
const mode = process.env.FAKE_CG_MODE || "ok";
|
||||
const marker = process.env.FAKE_CG_MARKER;
|
||||
const logFile = process.env.FAKE_CG_LOG;
|
||||
const schemaProps = (() => {
|
||||
try {
|
||||
return JSON.parse(process.env.FAKE_CG_SCHEMA || "");
|
||||
} catch {
|
||||
return ["query", "maxFiles", "projectPath"];
|
||||
}
|
||||
})();
|
||||
|
||||
function log(entry) {
|
||||
if (logFile) fs.appendFileSync(logFile, JSON.stringify(entry) + "\n");
|
||||
}
|
||||
|
||||
function send(msg) {
|
||||
process.stdout.write(JSON.stringify(msg) + "\n");
|
||||
}
|
||||
|
||||
const rl = readline.createInterface({ input: process.stdin });
|
||||
rl.on("line", (line) => {
|
||||
const text = line.trim();
|
||||
if (!text) return;
|
||||
let msg;
|
||||
try {
|
||||
msg = JSON.parse(text);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
if (!msg || typeof msg !== "object") return;
|
||||
log(msg);
|
||||
if (typeof msg.method !== "string") return;
|
||||
|
||||
switch (msg.method) {
|
||||
case "initialize":
|
||||
send({
|
||||
jsonrpc: "2.0",
|
||||
id: msg.id,
|
||||
result: {
|
||||
protocolVersion: "2025-06-18",
|
||||
capabilities: {},
|
||||
serverInfo: { name: "fake-codegraph", version: "0.0.0" },
|
||||
},
|
||||
});
|
||||
return;
|
||||
case "tools/list": {
|
||||
const tools =
|
||||
mode === "no-tool"
|
||||
? []
|
||||
: [
|
||||
{
|
||||
name: "codegraph_explore",
|
||||
description: "fake explore",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: Object.fromEntries(
|
||||
schemaProps.map((name) => [name, { type: "string" }]),
|
||||
),
|
||||
required: ["query"],
|
||||
},
|
||||
},
|
||||
];
|
||||
send({ jsonrpc: "2.0", id: msg.id, result: { tools } });
|
||||
return;
|
||||
}
|
||||
case "tools/call": {
|
||||
const shouldCrash =
|
||||
mode === "crash" ||
|
||||
(mode === "crash-first" && marker && !fs.existsSync(marker));
|
||||
if (shouldCrash) {
|
||||
if (mode === "crash-first") fs.writeFileSync(marker, "crashed");
|
||||
// Synchronous write — process.exit() can truncate pending pipe output.
|
||||
fs.writeSync(2, "fatal: codegraph index corrupted\n");
|
||||
process.exit(1);
|
||||
}
|
||||
if (mode === "hang") return; // Never reply — timeout/abort test.
|
||||
const args = (msg.params && msg.params.arguments) || {};
|
||||
send({
|
||||
jsonrpc: "2.0",
|
||||
id: msg.id,
|
||||
result: {
|
||||
content: [{ type: "text", text: `explore:${JSON.stringify(args)}` }],
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
default:
|
||||
// Notifications (initialized, cancelled) need no reply; unknown
|
||||
// requests get -32601.
|
||||
if (msg.id !== undefined) {
|
||||
send({
|
||||
jsonrpc: "2.0",
|
||||
id: msg.id,
|
||||
error: { code: -32601, message: "Method not found" },
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user