@danypops/pi-lector 0.2.0 → 0.2.2
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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { JobSnapshot, OperationInputs, OperationOutputs, PopulateSymbolGraphResult, SymbolEdgeKind, SymbolNode } from "@danypops/lector";
|
|
2
|
-
import { lectorClient, withWorkspace, workspaceForCodeIntelligencePath } from "./lector-client.ts";
|
|
2
|
+
import { lectorClient, withWorkspace, workspaceForCodeIntelligencePath, workspaceForPathOrDirectory } from "./lector-client.ts";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Thin wrappers over Lector's code-intelligence operations: goToDefinition,
|
|
@@ -13,6 +13,13 @@ import { lectorClient, withWorkspace, workspaceForCodeIntelligencePath } from ".
|
|
|
13
13
|
* falling back to the file's own containing directory, never the filesystem
|
|
14
14
|
* root -- every one of these operations spawns a real language server,
|
|
15
15
|
* unlike read/write/edit) -- never a value captured once at session start.
|
|
16
|
+
*
|
|
17
|
+
* Exception: populateSymbolGraph, workspaceMap, and hasWarmIndex are not file-anchored --
|
|
18
|
+
* their `path` genuinely means "the project itself", so they resolve via
|
|
19
|
+
* workspaceForPathOrDirectory instead, which does not blindly take dirname() first. A real,
|
|
20
|
+
* confirmed live bug: passing a project's own root directory through workspaceForCodeIntelligencePath
|
|
21
|
+
* silently resolved to that directory's *parent* (dirname strips the final segment even when the
|
|
22
|
+
* given path was already a directory with its own .git), mixing in every sibling project's graph.
|
|
16
23
|
*/
|
|
17
24
|
export interface CodeIntelligenceOperations {
|
|
18
25
|
goToDefinition(path: string, line: number, character: number): Promise<OperationOutputs["workspace.goToDefinition"]>;
|
|
@@ -123,7 +130,7 @@ export function createLectorCodeIntelligenceOperations(): CodeIntelligenceOperat
|
|
|
123
130
|
},
|
|
124
131
|
async populateSymbolGraph(path, maxFiles, maxSymbolsPerFile, waitMs = 500) {
|
|
125
132
|
return withWorkspace(
|
|
126
|
-
() =>
|
|
133
|
+
() => workspaceForPathOrDirectory(path),
|
|
127
134
|
async ({ workspaceId }) => {
|
|
128
135
|
const client = await lectorClient();
|
|
129
136
|
const { job } = await client.call("job.submit", {
|
|
@@ -152,7 +159,7 @@ export function createLectorCodeIntelligenceOperations(): CodeIntelligenceOperat
|
|
|
152
159
|
},
|
|
153
160
|
async hasWarmIndex(path) {
|
|
154
161
|
return withWorkspace(
|
|
155
|
-
() =>
|
|
162
|
+
() => workspaceForPathOrDirectory(path),
|
|
156
163
|
async ({ workspaceId }) => {
|
|
157
164
|
const client = await lectorClient();
|
|
158
165
|
const { warm } = await client.call("workspace.hasWarmIndex", { workspaceId });
|
|
@@ -162,7 +169,7 @@ export function createLectorCodeIntelligenceOperations(): CodeIntelligenceOperat
|
|
|
162
169
|
},
|
|
163
170
|
async workspaceMap(path, maxNodes, maxEdges, maxEntries, maxBytes) {
|
|
164
171
|
return withWorkspace(
|
|
165
|
-
() =>
|
|
172
|
+
() => workspaceForPathOrDirectory(path),
|
|
166
173
|
async ({ workspaceId }) => {
|
|
167
174
|
const client = await lectorClient();
|
|
168
175
|
return client.call("workspace.map", { workspaceId, maxNodes, maxEdges, maxEntries, maxBytes });
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { existsSync, statSync } from "node:fs";
|
|
1
2
|
import { dirname, parse } from "node:path";
|
|
2
3
|
import { createRetryingClient, type RetryingClient } from "@danypops/daemon-kit/pi-client";
|
|
3
4
|
import {
|
|
@@ -111,6 +112,24 @@ export function workspaceForCodeIntelligencePath(absolutePath: string): Promise<
|
|
|
111
112
|
return workspaceForDirectory(dirname(absolutePath));
|
|
112
113
|
}
|
|
113
114
|
|
|
115
|
+
/**
|
|
116
|
+
* For an operation whose `path` genuinely means "the project/workspace itself"
|
|
117
|
+
* (populateSymbolGraph, workspaceMap, hasWarmIndex) rather than one specific file
|
|
118
|
+
* to act on -- unlike workspaceForCodeIntelligencePath, does NOT blindly take
|
|
119
|
+
* dirname() first. A real, confirmed live bug: passing a project's own root
|
|
120
|
+
* directory (e.g. "/repo", which has its own .git right there) through
|
|
121
|
+
* dirname() strips its final segment, silently resolving to the *parent*
|
|
122
|
+
* directory's own nearest git root instead -- for a project nested one level
|
|
123
|
+
* under a broader already-registered workspace, this mixes in every sibling
|
|
124
|
+
* project's own graph, with no error at all. Checks whether the path is
|
|
125
|
+
* itself a real, existing directory first; only takes dirname() when it is
|
|
126
|
+
* not (a file, or a not-yet-existing path).
|
|
127
|
+
*/
|
|
128
|
+
export function workspaceForPathOrDirectory(path: string): Promise<ResolvedWorkspace> {
|
|
129
|
+
const isRealDirectory = existsSync(path) && statSync(path).isDirectory();
|
|
130
|
+
return workspaceForDirectory(isRealDirectory ? path : dirname(path));
|
|
131
|
+
}
|
|
132
|
+
|
|
114
133
|
/**
|
|
115
134
|
* Resolves a workspace via `resolve`, then calls `perform` with it. A daemon
|
|
116
135
|
* restart wipes its in-memory workspace registry (workspace ids are not
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danypops/pi-lector",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Pi host adapter for Lector: overrides read/write/edit with a daemon-backed, hash-guarded filesystem",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@danypops/daemon-kit": "^0.4.0",
|
|
22
|
-
"@danypops/lector": "^0.
|
|
22
|
+
"@danypops/lector": "^0.2.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@earendil-works/pi-ai": "^0.81.1",
|