@henryqw/pi-codegraph 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -16
- package/extensions/codegraph.ts +23 -11
- package/package.json +6 -9
- package/mcp.json +0 -11
package/README.md
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
# `@henryqw/pi-codegraph`
|
|
2
2
|
|
|
3
|
-
Get a separate [CodeGraph](https://github.com/colbymchenry/codegraph) index when you start Pi in a new Git worktree
|
|
3
|
+
Get a separate [CodeGraph](https://github.com/colbymchenry/codegraph) index when you start Pi in a new Git worktree, and let agents explore the indexed code with the `codegraph_explore` tool.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install -g @colbymchenry/codegraph
|
|
9
|
-
pi install npm:pi-mcp-adapter
|
|
10
9
|
pi install npm:@henryqw/pi-codegraph
|
|
11
10
|
```
|
|
12
11
|
|
|
13
|
-
Requires the `codegraph`
|
|
12
|
+
Requires only the `codegraph` executable on Pi's `PATH`. No MCP server or MCP configuration is needed.
|
|
14
13
|
|
|
15
14
|
## Works with
|
|
16
15
|
|
|
17
16
|
| Package | Relationship | Purpose |
|
|
18
17
|
| --- | --- | --- |
|
|
19
|
-
| [`@colbymchenry/codegraph`](https://github.com/colbymchenry/codegraph) | Required | Builds the indexes and
|
|
20
|
-
| [
|
|
18
|
+
| [`@colbymchenry/codegraph`](https://github.com/colbymchenry/codegraph) | Required | Builds the indexes and answers `codegraph explore` queries. |
|
|
19
|
+
| [`@henryqw/pi-footer`](https://pi.henry.wang/extensions/pi-footer) | Improves | Shows a compact CodeGraph index badge and tool activity when loaded. |
|
|
21
20
|
|
|
22
21
|
## Use
|
|
23
22
|
|
|
@@ -27,15 +26,14 @@ From the primary checkout, initialize CodeGraph once:
|
|
|
27
26
|
codegraph init --yes
|
|
28
27
|
```
|
|
29
28
|
|
|
30
|
-
Then launch `pi` in a linked worktree. When the primary checkout has an index, pi-codegraph initializes a separate worktree index
|
|
29
|
+
Then launch `pi` in a linked worktree. When the primary checkout has an index, pi-codegraph initializes a separate worktree index.
|
|
31
30
|
|
|
32
31
|
| Surface | Type | Purpose |
|
|
33
32
|
| --- | --- | --- |
|
|
34
|
-
| `codegraph_explore` | tool | Lets agents explore the indexed code
|
|
35
|
-
| `mcp` | tool | Lets agents call other CodeGraph tools through the `henryqw_pi-codegraph__codegraph` adapter server. |
|
|
33
|
+
| `codegraph_explore` | tool | Lets agents explore the indexed code. It returns the source of the relevant symbols grouped by file, plus the call path between them. |
|
|
36
34
|
| CodeGraph setup status | ui | Shows users setup progress and errors, and confirms a new worktree index is ready. |
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
`codegraph_explore` takes a `query`, an optional `maxFiles` (default 12), and an optional `projectPath` (defaults to Pi's working directory). It runs `codegraph explore --path <projectPath> --max-files <maxFiles> <query>` and returns the output as-is. If the command exits with an error or runs longer than 120 seconds, the tool call fails and shows the end of CodeGraph's error output.
|
|
39
37
|
|
|
40
38
|
## Flow
|
|
41
39
|
|
|
@@ -43,22 +41,25 @@ The adapter discovers tools lazily.
|
|
|
43
41
|
- Initialization happens when Pi launches, not when Git creates the worktree.
|
|
44
42
|
- Each linked worktree keeps its own `.codegraph`; databases are never copied or shared between branches.
|
|
45
43
|
- Non-Git directories and repositories without a primary index are not initialized.
|
|
46
|
-
-
|
|
44
|
+
- The extension reports `checking index…` and `indexing…` during setup, `indexed` when a database file exists, `missing` when no index was built, `prerequisites missing` when setup was skipped, and `setup failed` on an error. `indexed` does not guarantee database health.
|
|
45
|
+
- If `pi-footer` is also loaded, it places a compact `CG` badge first on its third line: `✓ CG` indexed, `○ CG` missing, `◐ CG` checking or indexing, `! CG` setup problem, or `? CG` unknown state. It temporarily shows `● CG` only during `codegraph_explore` calls.
|
|
47
46
|
|
|
48
47
|
## State and storage
|
|
49
48
|
|
|
50
|
-
The extension relies on CodeGraph's own state — each worktree maintains its own `.codegraph/codegraph.db`. The extension never copies
|
|
49
|
+
The extension relies on CodeGraph's own state — each worktree maintains its own `.codegraph/codegraph.db`. The extension never copies or shares the database and does not write it directly: it delegates creation to `codegraph init --yes <worktree-root>`. Existing indexes are left alone.
|
|
51
50
|
|
|
52
51
|
## Limits and recovery
|
|
53
52
|
|
|
54
|
-
At startup, the extension
|
|
53
|
+
At startup, the extension runs `codegraph --version`. If that fails, Pi warns, reports `prerequisites missing`, and skips setup. Restart Pi or run `/reload` after fixing prerequisites.
|
|
55
54
|
|
|
56
|
-
Initialization uses an exclusive `pi-codegraph-init.lock` in the worktree's Git metadata. Failed or interrupted initialization keeps the lock so a partial database is not accepted. To recover
|
|
55
|
+
Initialization uses an exclusive `pi-codegraph-init.lock` in the worktree's Git metadata. Failed or interrupted initialization keeps the lock so a partial database is not accepted. To recover, first confirm no initializer is running, then run `codegraph index` **from the affected worktree root** (not the primary checkout or a nested directory). Only after it succeeds, remove the lock directory with `rmdir` using the path in the error message, then run `/reload`:
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
```bash
|
|
58
|
+
cd /path/to/affected-worktree-root && codegraph index && rmdir /path/to/pi-codegraph-init.lock
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The package never installs prerequisites automatically. Only Git worktree-root indexes using the default `.codegraph` directory are supported; nested monorepo indexes are not initialized automatically. The primary checkout must remain indexed for automatic opt-in detection.
|
|
59
62
|
|
|
60
63
|
Do not remove an active lock. Existing indexes without an extension-owned lock are not health-checked. The lock coordinates this extension's sessions, not manual `codegraph init` commands; avoid running those during initialization.
|
|
61
64
|
|
|
62
65
|
The extension does not add ignore rules, delete indexes, or prune worktrees — add `.codegraph/` to your own ignore rules if needed. Pi Subagent conservatively treats ignored files as retained work: an indexed worker worktree may require manual cleanup.
|
|
63
|
-
|
|
64
|
-
If you already configured a `codegraph` server manually, remove that entry after confirming the package server works. Keeping both can expose duplicate servers/tools. The extension does not change your MCP configuration.
|
package/extensions/codegraph.ts
CHANGED
|
@@ -2,9 +2,11 @@ import { mkdir, rmdir, stat } from "node:fs/promises";
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { setTimeout as delay } from "node:timers/promises";
|
|
4
4
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
5
|
+
import { Type } from "typebox";
|
|
5
6
|
|
|
6
7
|
const LOCK_WAIT_MS = 5 * 60_000;
|
|
7
8
|
const INIT_TIMEOUT_MS = 10 * 60_000;
|
|
9
|
+
const EXPLORE_TIMEOUT_MS = 120_000;
|
|
8
10
|
const WIDGET_KEY = "pi-codegraph";
|
|
9
11
|
const SUCCESS_TTL_MS = 5000;
|
|
10
12
|
|
|
@@ -26,17 +28,10 @@ async function git(pi: ExtensionAPI, cwd: string, args: string[]): Promise<strin
|
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
async function initialize(pi: ExtensionAPI, ctx: ExtensionContext): Promise<void> {
|
|
29
|
-
const prerequisites: string[] = [];
|
|
30
|
-
if (!pi.getAllTools().some((tool) => tool.name === "mcp")) {
|
|
31
|
-
prerequisites.push("Install and enable pi-mcp-adapter >=2.36.0: pi install npm:pi-mcp-adapter");
|
|
32
|
-
}
|
|
33
31
|
const version = await pi.exec("codegraph", ["--version"], { cwd: ctx.cwd, timeout: 10_000 });
|
|
34
32
|
if (version.code !== 0 || version.killed) {
|
|
35
33
|
const detail = version.killed ? "timed out or killed" : version.stderr.trim().slice(-1000) || `exit ${version.code}`;
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
if (prerequisites.length) {
|
|
39
|
-
const message = `pi-codegraph: setup skipped.\n${prerequisites.join("\n")}\nThen restart Pi or /reload.`;
|
|
34
|
+
const message = `pi-codegraph: setup skipped.\ncodegraph --version failed (${detail}). Install CodeGraph: npm install -g @colbymchenry/codegraph. If already installed, check that codegraph runs on Pi's PATH.\nThen restart Pi or /reload.`;
|
|
40
35
|
ctx.ui.setStatus("pi-codegraph", "pi-codegraph: prerequisites missing");
|
|
41
36
|
if (ctx.hasUI) ctx.ui.notify(message, "warning");
|
|
42
37
|
else console.warn(message);
|
|
@@ -74,7 +69,6 @@ async function initialize(pi: ExtensionAPI, ctx: ExtensionContext): Promise<void
|
|
|
74
69
|
}
|
|
75
70
|
}
|
|
76
71
|
let attempted = false;
|
|
77
|
-
let succeeded = false;
|
|
78
72
|
try {
|
|
79
73
|
if (await hasIndex(root)) {
|
|
80
74
|
indexed = true;
|
|
@@ -91,7 +85,6 @@ async function initialize(pi: ExtensionAPI, ctx: ExtensionContext): Promise<void
|
|
|
91
85
|
if (result.code !== 0 || result.killed || !(await hasIndex(root))) {
|
|
92
86
|
throw new Error(`CodeGraph init failed (${result.killed ? "timed out or killed" : `exit ${result.code}`}): ${(result.stderr || result.stdout).trim().slice(-2000)}`);
|
|
93
87
|
}
|
|
94
|
-
succeeded = true;
|
|
95
88
|
indexed = true;
|
|
96
89
|
if (ctx.hasUI) {
|
|
97
90
|
ctx.ui.setWidget(WIDGET_KEY, ["pi-codegraph: index ready"]);
|
|
@@ -104,7 +97,7 @@ async function initialize(pi: ExtensionAPI, ctx: ExtensionContext): Promise<void
|
|
|
104
97
|
throw error;
|
|
105
98
|
} finally {
|
|
106
99
|
// A failed or interrupted init stays locked; never accept its partial DB on reload.
|
|
107
|
-
if (!attempted ||
|
|
100
|
+
if (!attempted || indexed) await rmdir(lock);
|
|
108
101
|
}
|
|
109
102
|
} finally {
|
|
110
103
|
ctx.ui.setStatus("pi-codegraph", indexed ? "pi-codegraph: indexed" : "pi-codegraph: missing");
|
|
@@ -112,6 +105,25 @@ async function initialize(pi: ExtensionAPI, ctx: ExtensionContext): Promise<void
|
|
|
112
105
|
}
|
|
113
106
|
|
|
114
107
|
export default function codegraphExtension(pi: ExtensionAPI): void {
|
|
108
|
+
pi.registerTool({
|
|
109
|
+
name: "codegraph_explore",
|
|
110
|
+
label: "CodeGraph explore",
|
|
111
|
+
description: "Primary code exploration tool. Call it first for how-does-X-work, architecture, bug, or where-is-X questions, and before editing. Returns the verbatim source of the relevant symbols grouped by file, plus the call path among them, in one capped call. Treat the shown source as already read.",
|
|
112
|
+
parameters: Type.Object({
|
|
113
|
+
query: Type.String({ description: "Symbol names, file names, short code terms, or a natural-language question." }),
|
|
114
|
+
maxFiles: Type.Optional(Type.Number({ description: "Maximum files to include (default 12)." })),
|
|
115
|
+
projectPath: Type.Optional(Type.String({ description: "Absolute path to the project or any directory inside it. Defaults to the session cwd." })),
|
|
116
|
+
}),
|
|
117
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
118
|
+
async execute(_toolCallId, { query, maxFiles, projectPath }, signal, _onUpdate, ctx) {
|
|
119
|
+
const path = projectPath ?? ctx.cwd;
|
|
120
|
+
const result = await pi.exec("codegraph", ["explore", "--path", path, "--max-files", String(maxFiles ?? 12), query], { cwd: path, signal, timeout: EXPLORE_TIMEOUT_MS });
|
|
121
|
+
if (result.code !== 0 || result.killed) {
|
|
122
|
+
throw new Error(`codegraph explore failed (${result.killed ? "timed out or killed" : `exit ${result.code}`}): ${result.stderr.trim().slice(-2000)}`);
|
|
123
|
+
}
|
|
124
|
+
return { content: [{ type: "text", text: result.stdout }], details: undefined };
|
|
125
|
+
},
|
|
126
|
+
});
|
|
115
127
|
pi.on("session_start", async (_event, ctx) => {
|
|
116
128
|
try {
|
|
117
129
|
await initialize(pi, ctx);
|
package/package.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@henryqw/pi-codegraph",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Initialize CodeGraph indexes in opted-in Git worktrees and expose
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Initialize CodeGraph indexes in opted-in Git worktrees and expose codegraph_explore as a Pi tool.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
7
7
|
"pi",
|
|
8
8
|
"codegraph",
|
|
9
|
-
"mcp",
|
|
10
9
|
"worktree"
|
|
11
10
|
],
|
|
12
11
|
"type": "module",
|
|
@@ -17,7 +16,6 @@
|
|
|
17
16
|
"files": [
|
|
18
17
|
"LICENSE",
|
|
19
18
|
"extensions",
|
|
20
|
-
"mcp.json",
|
|
21
19
|
"README.md"
|
|
22
20
|
],
|
|
23
21
|
"scripts": {
|
|
@@ -26,11 +24,11 @@
|
|
|
26
24
|
"pack:check": "npm pack --dry-run"
|
|
27
25
|
},
|
|
28
26
|
"peerDependencies": {
|
|
29
|
-
"@earendil-works/pi-coding-agent": ">=0.87.0 <0.
|
|
30
|
-
"
|
|
27
|
+
"@earendil-works/pi-coding-agent": ">=0.87.0 <0.100.0",
|
|
28
|
+
"typebox": "^1.3.15"
|
|
31
29
|
},
|
|
32
30
|
"devDependencies": {
|
|
33
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
31
|
+
"@earendil-works/pi-coding-agent": "0.99.1"
|
|
34
32
|
},
|
|
35
33
|
"repository": {
|
|
36
34
|
"type": "git",
|
|
@@ -46,7 +44,6 @@
|
|
|
46
44
|
"pi": {
|
|
47
45
|
"extensions": [
|
|
48
46
|
"./extensions/codegraph.ts"
|
|
49
|
-
]
|
|
50
|
-
"mcp": "./mcp.json"
|
|
47
|
+
]
|
|
51
48
|
}
|
|
52
49
|
}
|