mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-10-26 10:45:22 +00:00
codegraph 有一等公民 CLI 且上游保证其输出与 codegraph_explore MCP 工具一致,走共享 MCP adapter 只是多余的传输层。改为原生 Pi 工具后 每次调用以短命 codegraph explore 进程完成,去掉常驻 server/daemon; 未初始化项目经 ctx.ui.confirm 确认后 init 并自动重试,拒绝或失败时 打回并引导模型回退 find/grep/read/LSP;结果按 codegraph.db mtime 做有界缓存,索引一变即失效。共享 MCP adapter 只保留 Exa;工具名 不变,权限策略、Tool Search 常驻表、路由规则与分组不受影响。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
230 lines
8.3 KiB
TypeScript
230 lines
8.3 KiB
TypeScript
import type {
|
||
AgentToolResult,
|
||
ExecOptions,
|
||
ExecResult,
|
||
ExtensionAPI,
|
||
ExtensionContext,
|
||
} from "@earendil-works/pi-coding-agent";
|
||
import { stat } from "node:fs/promises";
|
||
import { dirname, join, resolve } from "node:path";
|
||
|
||
const NOT_INDEXED_MARKER = "no .codegraph/ index exists";
|
||
const EXPLORE_TIMEOUT_MS = 120_000;
|
||
const INIT_TIMEOUT_MS = 600_000;
|
||
const CACHE_MAX_ENTRIES = 32;
|
||
|
||
export interface ExploreParams {
|
||
query: string;
|
||
maxFiles?: number;
|
||
projectPath?: string;
|
||
}
|
||
|
||
export type CodegraphExec = (
|
||
command: string,
|
||
args: string[],
|
||
options?: ExecOptions,
|
||
) => Promise<ExecResult>;
|
||
|
||
/** Walk up from startDir looking for a .codegraph/codegraph.db index file. */
|
||
export async function findIndexedRoot(startDir: string): Promise<string | undefined> {
|
||
let dir = resolve(startDir);
|
||
for (;;) {
|
||
try {
|
||
if ((await stat(join(dir, ".codegraph", "codegraph.db"))).isFile()) return dir;
|
||
} catch {
|
||
// Missing or unreadable index — keep walking up.
|
||
}
|
||
const parent = dirname(dir);
|
||
if (parent === dir) return undefined;
|
||
dir = parent;
|
||
}
|
||
}
|
||
|
||
export function buildExploreArgs(params: ExploreParams, root: string): string[] {
|
||
const args = ["explore", "-p", root];
|
||
if (params.maxFiles !== undefined) args.push("--max-files", String(params.maxFiles));
|
||
args.push(params.query);
|
||
return args;
|
||
}
|
||
|
||
export function isNotIndexedOutput(text: string): boolean {
|
||
return text.includes(NOT_INDEXED_MARKER);
|
||
}
|
||
|
||
async function databaseMtime(root: string): Promise<number | undefined> {
|
||
try {
|
||
return (await stat(join(root, ".codegraph", "codegraph.db"))).mtimeMs;
|
||
} catch {
|
||
return undefined;
|
||
}
|
||
}
|
||
|
||
function cacheKey(root: string, params: ExploreParams): string {
|
||
return `${root} |