@danypops/lector 0.1.6 → 0.1.8
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 +9 -7
- package/package.json +5 -1
- package/src/adapters/fallback-code-intelligence-index.ts +73 -0
- package/src/adapters/find-source-files.ts +1 -1
- package/src/adapters/git-repo-fetcher.ts +154 -37
- package/src/adapters/lsp/json-rpc-stream.ts +52 -2
- package/src/adapters/lsp/language-server-process.ts +54 -10
- package/src/adapters/lsp/lsp-symbol-index.ts +133 -32
- package/src/adapters/normalize-npm-repository.ts +77 -0
- package/src/adapters/npm-lockfile-version-resolver.ts +519 -0
- package/src/adapters/npm-package-source-resolver.ts +322 -0
- package/src/adapters/npm-registry-client.ts +304 -0
- package/src/adapters/sqlite-symbol-graph.ts +47 -3
- package/src/adapters/tree-sitter/typescript-tree-sitter-symbol-index.ts +61 -11
- package/src/adapters/typescript-compiler-symbol-index.ts +129 -0
- package/src/cli.ts +87 -23
- package/src/daemon.ts +4 -0
- package/src/domain/find-workspace-symbols.ts +4 -3
- package/src/domain/installed-package-version.ts +66 -0
- package/src/domain/intelligence-provenance.ts +19 -0
- package/src/domain/language-server-descriptor.ts +18 -0
- package/src/domain/npm-package-metadata.ts +26 -0
- package/src/domain/package-source.ts +143 -0
- package/src/domain/repo-fetch-result.ts +33 -1
- package/src/domain/resolve-package-source.ts +204 -0
- package/src/domain/symbol-graph-generation.ts +3 -0
- package/src/domain/symbol-query.ts +16 -0
- package/src/domain/workspace-symbol.ts +8 -0
- package/src/index.ts +61 -4
- package/src/ports/installed-package-version-resolver-port.ts +5 -0
- package/src/ports/npm-registry-port.ts +5 -0
- package/src/ports/package-source-resolver-port.ts +5 -0
- package/src/ports/repo-fetcher-port.ts +2 -2
- package/src/ports/symbol-index-port.ts +4 -2
- package/src/service.ts +89 -25
package/src/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { type ClosableIntelligenceIndex, FallbackCodeIntelligenceIndex } from "./adapters/fallback-code-intelligence-index.ts";
|
|
1
2
|
export { GitRepoFetcher, type GitRepoFetcherOptions } from "./adapters/git-repo-fetcher.ts";
|
|
2
3
|
export { InMemoryContentCache } from "./adapters/in-memory-content-cache.ts";
|
|
3
4
|
export { InMemorySearchCache, type InMemorySearchCacheOptions } from "./adapters/in-memory-search-cache.ts";
|
|
@@ -6,11 +7,25 @@ export { InMemoryWorkspace } from "./adapters/in-memory-workspace.ts";
|
|
|
6
7
|
export { LocalFilesystemWorkspace, PathEscapesWorkspaceRoot } from "./adapters/local-filesystem-workspace.ts";
|
|
7
8
|
export { LocalGit } from "./adapters/local-git.ts";
|
|
8
9
|
export {
|
|
10
|
+
LanguageServerCapacityExceeded,
|
|
9
11
|
LanguageServerProcess,
|
|
10
12
|
LanguageServerProcessExited,
|
|
11
13
|
LanguageServerRequestTimedOut,
|
|
12
14
|
} from "./adapters/lsp/language-server-process.ts";
|
|
13
|
-
export { LspSymbolIndex } from "./adapters/lsp/lsp-symbol-index.ts";
|
|
15
|
+
export { LanguageFileLimitExceeded, LspSymbolIndex, type LspSymbolIndexOptions } from "./adapters/lsp/lsp-symbol-index.ts";
|
|
16
|
+
export { InvalidInstalledPackageVersionRequest, NpmLockfileVersionResolver } from "./adapters/npm-lockfile-version-resolver.ts";
|
|
17
|
+
export { NpmPackageSourceResolver, type NpmPackageSourceResolverOptions } from "./adapters/npm-package-source-resolver.ts";
|
|
18
|
+
export {
|
|
19
|
+
DEFAULT_NPM_REGISTRY,
|
|
20
|
+
InvalidNpmRegistryRequest,
|
|
21
|
+
NpmPackageNotFound,
|
|
22
|
+
NpmRegistryAuthenticationRequired,
|
|
23
|
+
NpmRegistryClient,
|
|
24
|
+
type NpmRegistryClientOptions,
|
|
25
|
+
NpmRegistryRequestFailed,
|
|
26
|
+
NpmRegistryResponseLimitExceeded,
|
|
27
|
+
NpmVersionNotFound,
|
|
28
|
+
} from "./adapters/npm-registry-client.ts";
|
|
14
29
|
export { ReadOnlyWorkspace, WorkspaceIsReadOnly } from "./adapters/read-only-workspace.ts";
|
|
15
30
|
export { RipgrepTextSearch } from "./adapters/ripgrep-text-search.ts";
|
|
16
31
|
export { deriveSourceManifest, type SourceManifest, SourceManifestLimitExceeded } from "./adapters/source-manifest.ts";
|
|
@@ -18,7 +33,8 @@ export { SqliteContentCache } from "./adapters/sqlite-content-cache.ts";
|
|
|
18
33
|
export { SqliteSearchCache, type SqliteSearchCacheOptions } from "./adapters/sqlite-search-cache.ts";
|
|
19
34
|
export { SqliteSymbolGraph } from "./adapters/sqlite-symbol-graph.ts";
|
|
20
35
|
export { TieredSearchCache } from "./adapters/tiered-search-cache.ts";
|
|
21
|
-
export { TreeSitterSymbolIndex } from "./adapters/tree-sitter/typescript-tree-sitter-symbol-index.ts";
|
|
36
|
+
export { TreeSitterSymbolIndex, type TreeSitterSymbolIndexOptions } from "./adapters/tree-sitter/typescript-tree-sitter-symbol-index.ts";
|
|
37
|
+
export { TypeScriptCompilerSymbolIndex, type TypeScriptCompilerSymbolIndexOptions } from "./adapters/typescript-compiler-symbol-index.ts";
|
|
22
38
|
export {
|
|
23
39
|
type ConnectLectorClientOptions,
|
|
24
40
|
connectLectorClient,
|
|
@@ -64,6 +80,19 @@ export { goToImplementation } from "./domain/go-to-implementation.ts";
|
|
|
64
80
|
export type { Hover } from "./domain/hover.ts";
|
|
65
81
|
export { hoverAt } from "./domain/hover-at.ts";
|
|
66
82
|
export { incomingCalls } from "./domain/incoming-calls.ts";
|
|
83
|
+
export type {
|
|
84
|
+
AmbiguousInstalledPackageVersion,
|
|
85
|
+
InstalledPackageEvidence,
|
|
86
|
+
InstalledPackageVersionBounds,
|
|
87
|
+
InstalledPackageVersionCandidate,
|
|
88
|
+
InstalledPackageVersionOutcome,
|
|
89
|
+
InstalledPackageVersionRequest,
|
|
90
|
+
JavaScriptPackageManager,
|
|
91
|
+
OversizedInstalledPackageVersion,
|
|
92
|
+
ResolvedInstalledPackageVersion,
|
|
93
|
+
UnavailableInstalledPackageVersion,
|
|
94
|
+
} from "./domain/installed-package-version.ts";
|
|
95
|
+
export type { IntelligenceFidelity, IntelligenceProvenance, ProvenancedResult, SymbolSearchBounds } from "./domain/intelligence-provenance.ts";
|
|
67
96
|
export {
|
|
68
97
|
descriptorForExtension,
|
|
69
98
|
LANGUAGE_SERVER_DESCRIPTORS,
|
|
@@ -71,26 +100,53 @@ export {
|
|
|
71
100
|
PYTHON_DESCRIPTOR,
|
|
72
101
|
TYPESCRIPT_DESCRIPTOR,
|
|
73
102
|
} from "./domain/language-server-descriptor.ts";
|
|
103
|
+
export type { NpmPackageVersionMetadata, NpmRegistryBounds, NpmRegistryVersionRequest, NpmRepositoryMetadata } from "./domain/npm-package-metadata.ts";
|
|
74
104
|
export { outgoingCalls } from "./domain/outgoing-calls.ts";
|
|
105
|
+
export type {
|
|
106
|
+
AmbiguousPackageSource,
|
|
107
|
+
MismatchedPackageSource,
|
|
108
|
+
OversizedPackageSource,
|
|
109
|
+
PackageCoordinateRequest,
|
|
110
|
+
PackageEcosystem,
|
|
111
|
+
PackageRepositoryIdentity,
|
|
112
|
+
PackageSourceBounds,
|
|
113
|
+
PackageSourceCandidate,
|
|
114
|
+
PackageSourceOperationResult,
|
|
115
|
+
PackageSourceOutcome,
|
|
116
|
+
PackageSourceRequest,
|
|
117
|
+
PackageSourceVerification,
|
|
118
|
+
PackageSourceVerificationMethod,
|
|
119
|
+
PackageSourceWorkspace,
|
|
120
|
+
ResolvedPackageCoordinate,
|
|
121
|
+
UnauthenticatedPackageSource,
|
|
122
|
+
UnavailablePackageSource,
|
|
123
|
+
VerifiedPackageSource,
|
|
124
|
+
} from "./domain/package-source.ts";
|
|
125
|
+
export { DEFAULT_PACKAGE_SOURCE_BOUNDS } from "./domain/package-source.ts";
|
|
75
126
|
export { type PopulateSymbolGraphResult, populateSymbolGraph } from "./domain/populate-symbol-graph.ts";
|
|
76
127
|
export { prepareCallHierarchy } from "./domain/prepare-call-hierarchy.ts";
|
|
77
128
|
export { raceWorkspaceQuery } from "./domain/race-workspace-query.ts";
|
|
78
129
|
export { type RawRead, rawRead, WorkspaceEntryNotFound } from "./domain/raw-read.ts";
|
|
79
130
|
export { reachableSymbolsFrom } from "./domain/reachable-symbols-from.ts";
|
|
80
|
-
export { RepoFetchFailed, type RepoFetchResult } from "./domain/repo-fetch-result.ts";
|
|
131
|
+
export { RepoFetchCapacityExceeded, RepoFetchFailed, RepoFetchLimitExceeded, type RepoFetchPolicy, type RepoFetchResult } from "./domain/repo-fetch-result.ts";
|
|
81
132
|
export type { RepoReference } from "./domain/repo-reference.ts";
|
|
133
|
+
export { InvalidPackageSourceContract, resolvePackageSource } from "./domain/resolve-package-source.ts";
|
|
82
134
|
export { deriveSearchCacheKey, type SearchCacheKey } from "./domain/search-cache-key.ts";
|
|
83
135
|
export { searchText } from "./domain/search-text.ts";
|
|
84
136
|
export { symbolEdgesFrom } from "./domain/symbol-edges-from.ts";
|
|
85
137
|
export { symbolEdgesTo } from "./domain/symbol-edges-to.ts";
|
|
86
138
|
export type { SymbolGraphGeneration, WorkspaceCacheStatus } from "./domain/symbol-graph-generation.ts";
|
|
87
139
|
export { deriveSymbolNodeId, type SymbolNodeId } from "./domain/symbol-node-id.ts";
|
|
140
|
+
export { assertBoundedSymbolQuery, InvalidSymbolQuery, MAX_SYMBOL_QUERY_BYTES } from "./domain/symbol-query.ts";
|
|
88
141
|
export type { TextSearchMatch, TextSearchResult } from "./domain/text-search-result.ts";
|
|
89
142
|
export type { WorkspaceQueryOutcome, WorkspaceQueryStatus } from "./domain/workspace-query-outcome.ts";
|
|
90
|
-
export type { WorkspaceLocation, WorkspaceSymbol } from "./domain/workspace-symbol.ts";
|
|
143
|
+
export type { SymbolSearchResult, WorkspaceLocation, WorkspaceSymbol } from "./domain/workspace-symbol.ts";
|
|
91
144
|
export type { CodeIntelligencePort } from "./ports/code-intelligence-port.ts";
|
|
92
145
|
export type { ContentCacheEntry, ContentCachePort, ContentSymbol } from "./ports/content-cache-port.ts";
|
|
93
146
|
export type { GitPort } from "./ports/git-port.ts";
|
|
147
|
+
export type { InstalledPackageVersionResolverPort } from "./ports/installed-package-version-resolver-port.ts";
|
|
148
|
+
export type { NpmRegistryPort } from "./ports/npm-registry-port.ts";
|
|
149
|
+
export type { PackageSourceResolverPort } from "./ports/package-source-resolver-port.ts";
|
|
94
150
|
export type { RepoFetcherPort } from "./ports/repo-fetcher-port.ts";
|
|
95
151
|
export type { SearchCachePort } from "./ports/search-cache-port.ts";
|
|
96
152
|
export type { SymbolEdgeKind, SymbolGraphPort, SymbolNode } from "./ports/symbol-graph-port.ts";
|
|
@@ -111,6 +167,7 @@ export {
|
|
|
111
167
|
type OperationInputs,
|
|
112
168
|
type OperationName,
|
|
113
169
|
type OperationOutputs,
|
|
170
|
+
PackageSourceResolverNotConfigured,
|
|
114
171
|
RepoFetcherNotConfigured,
|
|
115
172
|
SymbolQueryUnavailable,
|
|
116
173
|
UnknownWorkspace,
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { InstalledPackageVersionBounds, InstalledPackageVersionOutcome, InstalledPackageVersionRequest } from "../domain/installed-package-version.ts";
|
|
2
|
+
|
|
3
|
+
export interface InstalledPackageVersionResolverPort {
|
|
4
|
+
resolve(request: InstalledPackageVersionRequest, bounds: InstalledPackageVersionBounds): Promise<InstalledPackageVersionOutcome>;
|
|
5
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { NpmPackageVersionMetadata, NpmRegistryBounds, NpmRegistryVersionRequest } from "../domain/npm-package-metadata.ts";
|
|
2
|
+
|
|
3
|
+
export interface NpmRegistryPort {
|
|
4
|
+
fetchVersion(request: NpmRegistryVersionRequest, bounds: NpmRegistryBounds): Promise<NpmPackageVersionMetadata>;
|
|
5
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RepoFetchResult } from "../domain/repo-fetch-result.ts";
|
|
1
|
+
import type { RepoFetchPolicy, RepoFetchResult } from "../domain/repo-fetch-result.ts";
|
|
2
2
|
import type { RepoReference } from "../domain/repo-reference.ts";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -7,5 +7,5 @@ import type { RepoReference } from "../domain/repo-reference.ts";
|
|
|
7
7
|
* directory to read and analyze, not one the caller owns.
|
|
8
8
|
*/
|
|
9
9
|
export interface RepoFetcherPort {
|
|
10
|
-
fetch(reference: RepoReference): Promise<RepoFetchResult>;
|
|
10
|
+
fetch(reference: RepoReference, policy?: RepoFetchPolicy): Promise<RepoFetchResult>;
|
|
11
11
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { IntelligenceProvenance, SymbolSearchBounds } from "../domain/intelligence-provenance.ts";
|
|
2
|
+
import type { SymbolSearchResult } from "../domain/workspace-symbol.ts";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* SymbolIndexPort -- the role a driven adapter plays for symbol queries:
|
|
@@ -7,5 +8,6 @@ import type { WorkspaceSymbol } from "../domain/workspace-symbol.ts";
|
|
|
7
8
|
* this same interface.
|
|
8
9
|
*/
|
|
9
10
|
export interface SymbolIndexPort {
|
|
10
|
-
|
|
11
|
+
readonly provenance: IntelligenceProvenance;
|
|
12
|
+
findSymbols(query: string, bounds?: SymbolSearchBounds): Promise<SymbolSearchResult>;
|
|
11
13
|
}
|
package/src/service.ts
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { stat } from "node:fs/promises";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
|
+
import { FallbackCodeIntelligenceIndex } from "./adapters/fallback-code-intelligence-index.ts";
|
|
4
5
|
import { InMemorySearchCache } from "./adapters/in-memory-search-cache.ts";
|
|
5
6
|
import { InMemorySymbolGraph } from "./adapters/in-memory-symbol-graph.ts";
|
|
6
7
|
import { LocalFilesystemWorkspace } from "./adapters/local-filesystem-workspace.ts";
|
|
7
8
|
import { LocalGit } from "./adapters/local-git.ts";
|
|
8
9
|
import { discoverWorkspaceDescriptor } from "./adapters/lsp/discover-seed-file.ts";
|
|
9
10
|
import { LspSymbolIndex } from "./adapters/lsp/lsp-symbol-index.ts";
|
|
11
|
+
import { NpmLockfileVersionResolver } from "./adapters/npm-lockfile-version-resolver.ts";
|
|
12
|
+
import { NpmPackageSourceResolver } from "./adapters/npm-package-source-resolver.ts";
|
|
13
|
+
import { NpmRegistryClient } from "./adapters/npm-registry-client.ts";
|
|
10
14
|
import { ReadOnlyWorkspace } from "./adapters/read-only-workspace.ts";
|
|
11
15
|
import { RipgrepTextSearch } from "./adapters/ripgrep-text-search.ts";
|
|
12
16
|
import { deriveSourceManifest } from "./adapters/source-manifest.ts";
|
|
17
|
+
import { TreeSitterSymbolIndex } from "./adapters/tree-sitter/typescript-tree-sitter-symbol-index.ts";
|
|
18
|
+
import { TypeScriptCompilerSymbolIndex } from "./adapters/typescript-compiler-symbol-index.ts";
|
|
13
19
|
import { BoundedJobExecutor, type JobSnapshot } from "./domain/bounded-job-executor.ts";
|
|
14
20
|
import type { CallHierarchyEntry, IncomingCall, OutgoingCall } from "./domain/call-hierarchy.ts";
|
|
15
21
|
import type { Diagnostic } from "./domain/diagnostic.ts";
|
|
@@ -27,8 +33,10 @@ import { goToImplementation as goToImplementationQuery } from "./domain/go-to-im
|
|
|
27
33
|
import type { Hover } from "./domain/hover.ts";
|
|
28
34
|
import { hoverAt } from "./domain/hover-at.ts";
|
|
29
35
|
import { incomingCalls as incomingCallsQuery } from "./domain/incoming-calls.ts";
|
|
36
|
+
import type { IntelligenceProvenance } from "./domain/intelligence-provenance.ts";
|
|
30
37
|
import { descriptorForPath, LANGUAGE_SERVER_DESCRIPTORS, type LanguageServerDescriptor } from "./domain/language-server-descriptor.ts";
|
|
31
38
|
import { outgoingCalls as outgoingCallsQuery } from "./domain/outgoing-calls.ts";
|
|
39
|
+
import type { PackageSourceBounds, PackageSourceOperationResult, PackageSourceRequest } from "./domain/package-source.ts";
|
|
32
40
|
import { type PopulateSymbolGraphResult, populateSymbolGraph as populateSymbolGraphQuery } from "./domain/populate-symbol-graph.ts";
|
|
33
41
|
import { prepareCallHierarchy as prepareCallHierarchyQuery } from "./domain/prepare-call-hierarchy.ts";
|
|
34
42
|
import { raceWorkspaceQuery } from "./domain/race-workspace-query.ts";
|
|
@@ -36,16 +44,19 @@ import { type RawRead, rawRead, WorkspaceEntryNotFound } from "./domain/raw-read
|
|
|
36
44
|
import { reachableSymbolsFrom } from "./domain/reachable-symbols-from.ts";
|
|
37
45
|
import type { RepoFetchResult } from "./domain/repo-fetch-result.ts";
|
|
38
46
|
import type { RepoReference } from "./domain/repo-reference.ts";
|
|
47
|
+
import { resolvePackageSource } from "./domain/resolve-package-source.ts";
|
|
39
48
|
import { searchText as searchTextQuery } from "./domain/search-text.ts";
|
|
40
49
|
import { symbolEdgesFrom } from "./domain/symbol-edges-from.ts";
|
|
41
50
|
import { symbolEdgesTo } from "./domain/symbol-edges-to.ts";
|
|
42
51
|
import type { WorkspaceCacheStatus } from "./domain/symbol-graph-generation.ts";
|
|
43
52
|
import { deriveSymbolNodeId } from "./domain/symbol-node-id.ts";
|
|
53
|
+
import { assertBoundedSymbolQuery } from "./domain/symbol-query.ts";
|
|
44
54
|
import type { TextSearchResult } from "./domain/text-search-result.ts";
|
|
45
55
|
import type { WorkspaceQueryOutcome } from "./domain/workspace-query-outcome.ts";
|
|
46
|
-
import type {
|
|
56
|
+
import type { SymbolSearchResult, WorkspaceLocation } from "./domain/workspace-symbol.ts";
|
|
47
57
|
import type { CodeIntelligencePort } from "./ports/code-intelligence-port.ts";
|
|
48
58
|
import type { GitPort } from "./ports/git-port.ts";
|
|
59
|
+
import type { PackageSourceResolverPort } from "./ports/package-source-resolver-port.ts";
|
|
49
60
|
import type { RepoFetcherPort } from "./ports/repo-fetcher-port.ts";
|
|
50
61
|
import type { SearchCachePort } from "./ports/search-cache-port.ts";
|
|
51
62
|
import type { SymbolEdgeKind, SymbolGraphPort, SymbolNode } from "./ports/symbol-graph-port.ts";
|
|
@@ -128,6 +139,13 @@ export class RepoFetcherNotConfigured extends Error {
|
|
|
128
139
|
}
|
|
129
140
|
}
|
|
130
141
|
|
|
142
|
+
export class PackageSourceResolverNotConfigured extends Error {
|
|
143
|
+
constructor() {
|
|
144
|
+
super("package.resolveSource requires a service constructed with repository fetching");
|
|
145
|
+
this.name = "PackageSourceResolverNotConfigured";
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
131
149
|
export class UnsupportedJobOperation extends Error {
|
|
132
150
|
constructor(readonly operation: string) {
|
|
133
151
|
super(`operation "${operation}" cannot run as a background job; supported operations: workspace.populateSymbolGraph`);
|
|
@@ -185,6 +203,7 @@ export type OperationName =
|
|
|
185
203
|
| "workspace.gitLog"
|
|
186
204
|
| "workspace.gitDiff"
|
|
187
205
|
| "repo.fetch"
|
|
206
|
+
| "package.resolveSource"
|
|
188
207
|
| "workspace.searchText"
|
|
189
208
|
| "search.symbols"
|
|
190
209
|
| "search.text"
|
|
@@ -215,6 +234,7 @@ export const OPERATION_NAMES: readonly OperationName[] = [
|
|
|
215
234
|
"workspace.gitLog",
|
|
216
235
|
"workspace.gitDiff",
|
|
217
236
|
"repo.fetch",
|
|
237
|
+
"package.resolveSource",
|
|
218
238
|
"workspace.searchText",
|
|
219
239
|
"search.symbols",
|
|
220
240
|
"search.text",
|
|
@@ -234,7 +254,7 @@ export interface OperationInputs {
|
|
|
234
254
|
"workspace.rawRead": { workspaceId: WorkspaceId; path: string };
|
|
235
255
|
"workspace.exactEdit": { workspaceId: WorkspaceId } & ExpectedHashEdit;
|
|
236
256
|
"workspace.registerPath": { path: string };
|
|
237
|
-
"workspace.findSymbols": { workspaceId: WorkspaceId; query: string; seedFile?: string };
|
|
257
|
+
"workspace.findSymbols": { workspaceId: WorkspaceId; query: string; seedFile?: string; maxResults?: number };
|
|
238
258
|
"workspace.goToDefinition": WorkspacePosition;
|
|
239
259
|
"workspace.goToImplementation": WorkspacePosition;
|
|
240
260
|
"workspace.findReferences": WorkspacePosition & { includeDeclaration: boolean };
|
|
@@ -254,6 +274,7 @@ export interface OperationInputs {
|
|
|
254
274
|
"workspace.gitLog": { workspaceId: WorkspaceId; maxCount: number };
|
|
255
275
|
"workspace.gitDiff": { workspaceId: WorkspaceId; ref?: string; maxBytes: number };
|
|
256
276
|
"repo.fetch": RepoReference;
|
|
277
|
+
"package.resolveSource": { request: PackageSourceRequest; bounds: PackageSourceBounds };
|
|
257
278
|
"workspace.searchText": { workspaceId: WorkspaceId; query: string; maxMatches: number; maxBytes: number };
|
|
258
279
|
/**
|
|
259
280
|
* No single workspaceId -- fans out across several at once, unlike every other findSymbols-
|
|
@@ -275,20 +296,22 @@ export interface OperationInputs {
|
|
|
275
296
|
"job.status": { jobId: string };
|
|
276
297
|
}
|
|
277
298
|
|
|
299
|
+
type Provenanced<T> = T & { readonly provenance: IntelligenceProvenance };
|
|
300
|
+
|
|
278
301
|
export interface OperationOutputs {
|
|
279
302
|
"workspace.rawRead": RawRead;
|
|
280
303
|
"workspace.exactEdit": EditOutcome;
|
|
281
304
|
"workspace.registerPath": { workspaceId: WorkspaceId; created: boolean };
|
|
282
|
-
"workspace.findSymbols":
|
|
283
|
-
"workspace.goToDefinition": { locations: readonly WorkspaceLocation[] }
|
|
284
|
-
"workspace.goToImplementation": { locations: readonly WorkspaceLocation[] }
|
|
285
|
-
"workspace.findReferences": { locations: readonly WorkspaceLocation[] }
|
|
286
|
-
"workspace.hover": { hover: Hover | undefined }
|
|
287
|
-
"workspace.documentSymbols": { symbols: readonly DocumentSymbolEntry[] }
|
|
288
|
-
"workspace.diagnostics": { diagnostics: readonly Diagnostic[] }
|
|
289
|
-
"workspace.prepareCallHierarchy": { items: readonly CallHierarchyEntry[] }
|
|
290
|
-
"workspace.incomingCalls": { calls: readonly IncomingCall[] }
|
|
291
|
-
"workspace.outgoingCalls": { calls: readonly OutgoingCall[] }
|
|
305
|
+
"workspace.findSymbols": SymbolSearchResult;
|
|
306
|
+
"workspace.goToDefinition": Provenanced<{ locations: readonly WorkspaceLocation[] }>;
|
|
307
|
+
"workspace.goToImplementation": Provenanced<{ locations: readonly WorkspaceLocation[] }>;
|
|
308
|
+
"workspace.findReferences": Provenanced<{ locations: readonly WorkspaceLocation[] }>;
|
|
309
|
+
"workspace.hover": Provenanced<{ hover: Hover | undefined }>;
|
|
310
|
+
"workspace.documentSymbols": Provenanced<{ symbols: readonly DocumentSymbolEntry[] }>;
|
|
311
|
+
"workspace.diagnostics": Provenanced<{ diagnostics: readonly Diagnostic[] }>;
|
|
312
|
+
"workspace.prepareCallHierarchy": Provenanced<{ items: readonly CallHierarchyEntry[] }>;
|
|
313
|
+
"workspace.incomingCalls": Provenanced<{ calls: readonly IncomingCall[] }>;
|
|
314
|
+
"workspace.outgoingCalls": Provenanced<{ calls: readonly OutgoingCall[] }>;
|
|
292
315
|
"workspace.populateSymbolGraph": { filesProcessed: number; symbolsProcessed: number; nodesAdded: number; edgesAdded: number };
|
|
293
316
|
"workspace.reachableFrom": { symbols: readonly SymbolNode[] };
|
|
294
317
|
"workspace.symbolEdgesFrom": { symbols: readonly SymbolNode[] };
|
|
@@ -299,8 +322,9 @@ export interface OperationOutputs {
|
|
|
299
322
|
"workspace.gitLog": { entries: readonly GitLogEntry[] };
|
|
300
323
|
"workspace.gitDiff": GitDiffResult;
|
|
301
324
|
"repo.fetch": RepoFetchResult & { workspaceId: WorkspaceId };
|
|
325
|
+
"package.resolveSource": PackageSourceOperationResult;
|
|
302
326
|
"workspace.searchText": TextSearchResult;
|
|
303
|
-
"search.symbols": { results: readonly WorkspaceQueryOutcome<
|
|
327
|
+
"search.symbols": { results: readonly WorkspaceQueryOutcome<SymbolSearchResult>[] };
|
|
304
328
|
"search.text": { results: readonly WorkspaceQueryOutcome<TextSearchResult>[] };
|
|
305
329
|
"job.submit": { job: JobSnapshot<PopulateSymbolGraphResult> };
|
|
306
330
|
"job.status": { job: JobSnapshot<PopulateSymbolGraphResult> };
|
|
@@ -366,6 +390,8 @@ export interface LectorServiceOptions {
|
|
|
366
390
|
createGitPort?: (rootPath: string) => GitPort;
|
|
367
391
|
/** Factory for the port backing repo.fetch. No default -- unlike createSymbolGraph's safe in-memory fallback, fetching a real external repo always needs a real disk location only a host (daemon.ts) can supply. Called once at construction and reused, not per-call. */
|
|
368
392
|
createRepoFetcher?: () => RepoFetcherPort;
|
|
393
|
+
/** Override package-source resolution. With a repo fetcher configured, the default composes npm lockfiles, registry metadata, and exact Git fetching. */
|
|
394
|
+
createPackageSourceResolver?: () => PackageSourceResolverPort;
|
|
369
395
|
/** Factory for the port backing workspace.searchText. Defaults to RipgrepTextSearch -- cheap to construct, no disk dependency, safe like createGitPort's default. Called once at construction and reused. */
|
|
370
396
|
createTextSearch?: () => TextSearchPort;
|
|
371
397
|
/** Factory for workspace.searchText's result cache. Defaults to an in-memory-only InMemorySearchCache -- safe, no disk dependency. A host wanting the disk-backed tier too (surviving a restart) supplies a TieredSearchCache here. Called once at construction and reused. */
|
|
@@ -418,6 +444,7 @@ async function registerPath(registry: MutableRegistry, input: OperationInputs["w
|
|
|
418
444
|
*/
|
|
419
445
|
const DEFAULT_CROSS_WORKSPACE_TIMEOUT_MS = 3000;
|
|
420
446
|
const MAX_INITIAL_JOB_WAIT_MS = 30_000;
|
|
447
|
+
const MAX_SYMBOL_RESULTS = 5_000;
|
|
421
448
|
const MAX_SOURCE_MANIFEST_BYTES = 50 * 1024 * 1024;
|
|
422
449
|
|
|
423
450
|
/**
|
|
@@ -455,7 +482,11 @@ export function createLectorService(workspaces: ReadonlyMap<WorkspaceId, Workspa
|
|
|
455
482
|
const symbolIndexes = new Map<string, { index: ClosableSymbolIndex; workspaceId: WorkspaceId; lastUsedAt: number }>();
|
|
456
483
|
const createSymbolIndex =
|
|
457
484
|
options.createSymbolIndex ??
|
|
458
|
-
((rootPath: string, descriptor: LanguageServerDescriptor, seedFile?: string) =>
|
|
485
|
+
((rootPath: string, descriptor: LanguageServerDescriptor, seedFile?: string) => {
|
|
486
|
+
const semantic = new LspSymbolIndex(rootPath, descriptor, seedFile);
|
|
487
|
+
if (descriptor.languageId !== "typescript") return semantic;
|
|
488
|
+
return new FallbackCodeIntelligenceIndex(semantic, [new TypeScriptCompilerSymbolIndex(rootPath), new TreeSitterSymbolIndex(rootPath)]);
|
|
489
|
+
});
|
|
459
490
|
function symbolIndexKey(workspaceId: WorkspaceId, languageId: string): string {
|
|
460
491
|
return `${workspaceId}:${languageId}`;
|
|
461
492
|
}
|
|
@@ -481,6 +512,11 @@ export function createLectorService(workspaces: ReadonlyMap<WorkspaceId, Workspa
|
|
|
481
512
|
// every time, wastefully, and would risk losing the in-memory LRU's recency ordering
|
|
482
513
|
// between calls for no benefit (the index itself is what makes rehydration correct at all).
|
|
483
514
|
const repoFetcher = options.createRepoFetcher?.();
|
|
515
|
+
const packageSourceResolver =
|
|
516
|
+
options.createPackageSourceResolver?.() ??
|
|
517
|
+
(repoFetcher
|
|
518
|
+
? new NpmPackageSourceResolver({ versions: new NpmLockfileVersionResolver(), registry: new NpmRegistryClient(), repositories: repoFetcher })
|
|
519
|
+
: undefined);
|
|
484
520
|
const textSearch = options.createTextSearch?.() ?? new RipgrepTextSearch();
|
|
485
521
|
const searchCache = options.createSearchCache?.() ?? new InMemorySearchCache();
|
|
486
522
|
|
|
@@ -521,6 +557,28 @@ export function createLectorService(workspaces: ReadonlyMap<WorkspaceId, Workspa
|
|
|
521
557
|
return { workspaceId, ...result };
|
|
522
558
|
}
|
|
523
559
|
|
|
560
|
+
async function packageSourceHandler(
|
|
561
|
+
registry: MutableRegistry,
|
|
562
|
+
input: OperationInputs["package.resolveSource"],
|
|
563
|
+
): Promise<OperationOutputs["package.resolveSource"]> {
|
|
564
|
+
if (!packageSourceResolver) throw new PackageSourceResolverNotConfigured();
|
|
565
|
+
const outcome = await resolvePackageSource(packageSourceResolver, input.request, input.bounds);
|
|
566
|
+
if (outcome.status !== "verified") return { outcome, workspaceId: null };
|
|
567
|
+
const absolutePath = resolve(outcome.workspace.cachePath);
|
|
568
|
+
let sourceStats: Awaited<ReturnType<typeof stat>>;
|
|
569
|
+
try {
|
|
570
|
+
sourceStats = await stat(absolutePath);
|
|
571
|
+
} catch {
|
|
572
|
+
throw new InvalidWorkspaceRoot(absolutePath, "verified package source does not exist or is not accessible");
|
|
573
|
+
}
|
|
574
|
+
if (!sourceStats.isDirectory()) throw new InvalidWorkspaceRoot(absolutePath, "verified package source is not a directory");
|
|
575
|
+
const workspaceId = deriveWorkspaceId(absolutePath);
|
|
576
|
+
if (!registry.has(workspaceId)) {
|
|
577
|
+
registry.set(workspaceId, { port: new ReadOnlyWorkspace(new LocalFilesystemWorkspace(absolutePath)), rootPath: absolutePath, origin: "remote" });
|
|
578
|
+
}
|
|
579
|
+
return { outcome, workspaceId };
|
|
580
|
+
}
|
|
581
|
+
|
|
524
582
|
async function searchTextHandler(
|
|
525
583
|
registry: MutableRegistry,
|
|
526
584
|
input: OperationInputs["workspace.searchText"],
|
|
@@ -660,9 +718,13 @@ export function createLectorService(workspaces: ReadonlyMap<WorkspaceId, Workspa
|
|
|
660
718
|
}
|
|
661
719
|
|
|
662
720
|
async function findSymbols(_registry: MutableRegistry, input: OperationInputs["workspace.findSymbols"]): Promise<OperationOutputs["workspace.findSymbols"]> {
|
|
721
|
+
assertBoundedSymbolQuery(input.query);
|
|
722
|
+
const maxResults = input.maxResults ?? 1_000;
|
|
723
|
+
if (!Number.isSafeInteger(maxResults) || maxResults < 1 || maxResults > MAX_SYMBOL_RESULTS) {
|
|
724
|
+
throw new TypeError(`maxResults must be a positive safe integer no greater than ${MAX_SYMBOL_RESULTS}`);
|
|
725
|
+
}
|
|
663
726
|
const { index } = await ensureWarmIndex(input);
|
|
664
|
-
|
|
665
|
-
return { symbols };
|
|
727
|
+
return findWorkspaceSymbols(index, input.query, { maxResults });
|
|
666
728
|
}
|
|
667
729
|
|
|
668
730
|
async function requireCodeIntelligence(input: {
|
|
@@ -681,7 +743,7 @@ export function createLectorService(workspaces: ReadonlyMap<WorkspaceId, Workspa
|
|
|
681
743
|
): Promise<OperationOutputs["workspace.goToDefinition"]> {
|
|
682
744
|
const { index } = await requireCodeIntelligence(input);
|
|
683
745
|
const locations = await goToDefinitionQuery(index, { path: input.path, line: input.line, character: input.character });
|
|
684
|
-
return { locations };
|
|
746
|
+
return { locations, provenance: index.provenance };
|
|
685
747
|
}
|
|
686
748
|
|
|
687
749
|
async function goToImplementation(
|
|
@@ -690,7 +752,7 @@ export function createLectorService(workspaces: ReadonlyMap<WorkspaceId, Workspa
|
|
|
690
752
|
): Promise<OperationOutputs["workspace.goToImplementation"]> {
|
|
691
753
|
const { index } = await requireCodeIntelligence(input);
|
|
692
754
|
const locations = await goToImplementationQuery(index, { path: input.path, line: input.line, character: input.character });
|
|
693
|
-
return { locations };
|
|
755
|
+
return { locations, provenance: index.provenance };
|
|
694
756
|
}
|
|
695
757
|
|
|
696
758
|
async function findReferences(
|
|
@@ -699,13 +761,13 @@ export function createLectorService(workspaces: ReadonlyMap<WorkspaceId, Workspa
|
|
|
699
761
|
): Promise<OperationOutputs["workspace.findReferences"]> {
|
|
700
762
|
const { index } = await requireCodeIntelligence(input);
|
|
701
763
|
const locations = await findReferencesQuery(index, { path: input.path, line: input.line, character: input.character }, input.includeDeclaration);
|
|
702
|
-
return { locations };
|
|
764
|
+
return { locations, provenance: index.provenance };
|
|
703
765
|
}
|
|
704
766
|
|
|
705
767
|
async function hover(_registry: MutableRegistry, input: OperationInputs["workspace.hover"]): Promise<OperationOutputs["workspace.hover"]> {
|
|
706
768
|
const { index } = await requireCodeIntelligence(input);
|
|
707
769
|
const hover = await hoverAt(index, { path: input.path, line: input.line, character: input.character });
|
|
708
|
-
return { hover };
|
|
770
|
+
return { hover, provenance: index.provenance };
|
|
709
771
|
}
|
|
710
772
|
|
|
711
773
|
async function documentSymbolsHandler(
|
|
@@ -714,7 +776,7 @@ export function createLectorService(workspaces: ReadonlyMap<WorkspaceId, Workspa
|
|
|
714
776
|
): Promise<OperationOutputs["workspace.documentSymbols"]> {
|
|
715
777
|
const { index } = await requireCodeIntelligence(input);
|
|
716
778
|
const symbols = await documentSymbolsQuery(index, input.path);
|
|
717
|
-
return { symbols };
|
|
779
|
+
return { symbols, provenance: index.provenance };
|
|
718
780
|
}
|
|
719
781
|
|
|
720
782
|
async function diagnosticsHandler(
|
|
@@ -723,7 +785,7 @@ export function createLectorService(workspaces: ReadonlyMap<WorkspaceId, Workspa
|
|
|
723
785
|
): Promise<OperationOutputs["workspace.diagnostics"]> {
|
|
724
786
|
const { index } = await requireCodeIntelligence(input);
|
|
725
787
|
const diagnostics = await diagnosticsQuery(index, input.path);
|
|
726
|
-
return { diagnostics };
|
|
788
|
+
return { diagnostics, provenance: index.provenance };
|
|
727
789
|
}
|
|
728
790
|
|
|
729
791
|
async function prepareCallHierarchyHandler(
|
|
@@ -732,7 +794,7 @@ export function createLectorService(workspaces: ReadonlyMap<WorkspaceId, Workspa
|
|
|
732
794
|
): Promise<OperationOutputs["workspace.prepareCallHierarchy"]> {
|
|
733
795
|
const { index } = await requireCodeIntelligence(input);
|
|
734
796
|
const items = await prepareCallHierarchyQuery(index, { path: input.path, line: input.line, character: input.character });
|
|
735
|
-
return { items };
|
|
797
|
+
return { items, provenance: index.provenance };
|
|
736
798
|
}
|
|
737
799
|
|
|
738
800
|
async function incomingCallsHandler(
|
|
@@ -741,7 +803,7 @@ export function createLectorService(workspaces: ReadonlyMap<WorkspaceId, Workspa
|
|
|
741
803
|
): Promise<OperationOutputs["workspace.incomingCalls"]> {
|
|
742
804
|
const { index } = await requireCodeIntelligence(input);
|
|
743
805
|
const calls = await incomingCallsQuery(index, { path: input.path, line: input.line, character: input.character });
|
|
744
|
-
return { calls };
|
|
806
|
+
return { calls, provenance: index.provenance };
|
|
745
807
|
}
|
|
746
808
|
|
|
747
809
|
async function outgoingCallsHandler(
|
|
@@ -750,7 +812,7 @@ export function createLectorService(workspaces: ReadonlyMap<WorkspaceId, Workspa
|
|
|
750
812
|
): Promise<OperationOutputs["workspace.outgoingCalls"]> {
|
|
751
813
|
const { index } = await requireCodeIntelligence(input);
|
|
752
814
|
const calls = await outgoingCallsQuery(index, { path: input.path, line: input.line, character: input.character });
|
|
753
|
-
return { calls };
|
|
815
|
+
return { calls, provenance: index.provenance };
|
|
754
816
|
}
|
|
755
817
|
|
|
756
818
|
async function populateSymbolGraphHandler(
|
|
@@ -771,6 +833,7 @@ export function createLectorService(workspaces: ReadonlyMap<WorkspaceId, Workspa
|
|
|
771
833
|
maxFiles: input.maxFiles,
|
|
772
834
|
maxSymbolsPerFile: input.maxSymbolsPerFile,
|
|
773
835
|
completedAt: Date.now(),
|
|
836
|
+
provenance: index.provenance,
|
|
774
837
|
result,
|
|
775
838
|
});
|
|
776
839
|
return result;
|
|
@@ -920,6 +983,7 @@ export function createLectorService(workspaces: ReadonlyMap<WorkspaceId, Workspa
|
|
|
920
983
|
"workspace.gitLog": gitLogHandler,
|
|
921
984
|
"workspace.gitDiff": gitDiffHandler,
|
|
922
985
|
"repo.fetch": repoFetchHandler,
|
|
986
|
+
"package.resolveSource": packageSourceHandler,
|
|
923
987
|
"workspace.searchText": searchTextHandler,
|
|
924
988
|
"search.symbols": crossFindSymbols,
|
|
925
989
|
"search.text": crossSearchText,
|