@danypops/lector 0.1.7 → 0.1.9

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.
Files changed (37) hide show
  1. package/README.md +11 -7
  2. package/package.json +5 -1
  3. package/src/adapters/fallback-code-intelligence-index.ts +73 -0
  4. package/src/adapters/find-source-files.ts +1 -1
  5. package/src/adapters/git-repo-fetcher.ts +154 -37
  6. package/src/adapters/lsp/discover-seed-file.ts +17 -9
  7. package/src/adapters/lsp/json-rpc-stream.ts +52 -2
  8. package/src/adapters/lsp/language-server-process.ts +54 -10
  9. package/src/adapters/lsp/lsp-symbol-index.ts +167 -41
  10. package/src/adapters/normalize-npm-repository.ts +77 -0
  11. package/src/adapters/npm-lockfile-version-resolver.ts +519 -0
  12. package/src/adapters/npm-package-source-resolver.ts +322 -0
  13. package/src/adapters/npm-registry-client.ts +304 -0
  14. package/src/adapters/polyglot-code-intelligence-index.ts +135 -0
  15. package/src/adapters/sqlite-symbol-graph.ts +68 -3
  16. package/src/adapters/tree-sitter/typescript-tree-sitter-symbol-index.ts +61 -11
  17. package/src/adapters/typescript-compiler-symbol-index.ts +129 -0
  18. package/src/cli.ts +97 -23
  19. package/src/daemon.ts +4 -0
  20. package/src/domain/find-workspace-symbols.ts +4 -3
  21. package/src/domain/installed-package-version.ts +66 -0
  22. package/src/domain/intelligence-provenance.ts +27 -0
  23. package/src/domain/language-server-descriptor.ts +22 -0
  24. package/src/domain/npm-package-metadata.ts +26 -0
  25. package/src/domain/package-source.ts +143 -0
  26. package/src/domain/repo-fetch-result.ts +33 -1
  27. package/src/domain/resolve-package-source.ts +204 -0
  28. package/src/domain/symbol-graph-generation.ts +5 -0
  29. package/src/domain/symbol-query.ts +16 -0
  30. package/src/domain/workspace-symbol.ts +13 -0
  31. package/src/index.ts +68 -4
  32. package/src/ports/installed-package-version-resolver-port.ts +5 -0
  33. package/src/ports/npm-registry-port.ts +5 -0
  34. package/src/ports/package-source-resolver-port.ts +5 -0
  35. package/src/ports/repo-fetcher-port.ts +2 -2
  36. package/src/ports/symbol-index-port.ts +4 -2
  37. package/src/service.ts +152 -43
@@ -5,9 +5,41 @@ export interface RepoFetchResult {
5
5
  /** The ref actually checked out -- may differ from the requested ref if it didn't exist and cloning fell back to the default branch. */
6
6
  readonly resolvedRef: string;
7
7
  readonly refFallbackOccurred: boolean;
8
+ readonly commit: string;
8
9
  }
9
10
 
10
- /** Raised when neither the requested ref nor a default-branch fallback could be cloned. */
11
+ export interface RepoFetchPolicy {
12
+ readonly exactRef?: boolean;
13
+ readonly maxCloneBytes?: number;
14
+ readonly maxCacheBytes?: number;
15
+ readonly timeoutMs?: number;
16
+ }
17
+
18
+ export class RepoFetchCapacityExceeded extends Error {
19
+ readonly maxQueued: number;
20
+
21
+ constructor(maxQueued: number) {
22
+ super(`repository fetch queue is full (${maxQueued} queued)`);
23
+ this.name = "RepoFetchCapacityExceeded";
24
+ this.maxQueued = maxQueued;
25
+ }
26
+ }
27
+
28
+ export class RepoFetchLimitExceeded extends Error {
29
+ readonly resource: "clone-bytes" | "cache-bytes";
30
+ readonly limit: number;
31
+ readonly observed: number;
32
+
33
+ constructor(resource: RepoFetchLimitExceeded["resource"], limit: number, observed: number) {
34
+ super(`repository ${resource} ${observed} exceeded limit ${limit}`);
35
+ this.name = "RepoFetchLimitExceeded";
36
+ this.resource = resource;
37
+ this.limit = limit;
38
+ this.observed = observed;
39
+ }
40
+ }
41
+
42
+ /** Raised when the requested ref cannot be cloned under the caller's fallback policy. */
11
43
  export class RepoFetchFailed extends Error {
12
44
  constructor(host: string, owner: string, repo: string, ref: string | null, cause: unknown) {
13
45
  const target = `${host}/${owner}/${repo}${ref ? `@${ref}` : ""}`;
@@ -0,0 +1,204 @@
1
+ import type { PackageSourceResolverPort } from "../ports/package-source-resolver-port.ts";
2
+ import type {
3
+ AmbiguousPackageSource,
4
+ MismatchedPackageSource,
5
+ OversizedPackageSource,
6
+ PackageSourceBounds,
7
+ PackageSourceOutcome,
8
+ PackageSourceRequest,
9
+ UnauthenticatedPackageSource,
10
+ VerifiedPackageSource,
11
+ } from "./package-source.ts";
12
+
13
+ const COMMIT_HASH = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/i;
14
+ const CREDENTIAL_NAME = /^[A-Z][A-Z0-9_]{0,127}$/;
15
+ const ECOSYSTEMS = ["npm", "pypi", "cargo", "go", "maven", "conan", "vcpkg", "nuget", "swiftpm"] as const;
16
+ const VERIFICATION_METHODS = ["lockfile-vcs-pin", "registry-metadata-and-commit", "source-artifact-checksum", "local-content-digest"] as const;
17
+ const UNAVAILABLE_CODES = [
18
+ "package-not-found",
19
+ "version-not-found",
20
+ "source-metadata-missing",
21
+ "unsupported-ecosystem",
22
+ "unsupported-manifest",
23
+ "unverifiable-source",
24
+ ] as const;
25
+ const AMBIGUOUS_CODES = ["multiple-installed-versions", "multiple-source-candidates"] as const;
26
+ const UNAUTHENTICATED_CODES = ["registry-authentication-required", "repository-authentication-required"] as const;
27
+ const OVERSIZED_CODES = ["manifest-limit-exceeded", "registry-response-limit-exceeded", "clone-limit-exceeded", "cache-limit-exceeded"] as const;
28
+ const OVERSIZED_RESOURCES = [
29
+ "manifest-bytes",
30
+ "manifest-entries",
31
+ "manifest-nesting",
32
+ "workspaces",
33
+ "diagnostics",
34
+ "registry-response-bytes",
35
+ "clone-bytes",
36
+ "cache-bytes",
37
+ ] as const;
38
+ const MISMATCHED_CODES = ["coordinate-mismatch", "repository-ref-mismatch", "repository-commit-mismatch", "integrity-mismatch"] as const;
39
+
40
+ export class InvalidPackageSourceContract extends Error {
41
+ constructor(reason: string) {
42
+ super(`invalid package-source contract: ${reason}`);
43
+ this.name = "InvalidPackageSourceContract";
44
+ }
45
+ }
46
+
47
+ function containsControlCharacter(value: string): boolean {
48
+ for (let index = 0; index < value.length; index++) {
49
+ const code = value.charCodeAt(index);
50
+ if (code <= 31 || code === 127) return true;
51
+ }
52
+ return false;
53
+ }
54
+
55
+ function assertText(value: string, name: string, maxLength: number): void {
56
+ if (value.length === 0 || value.length > maxLength || containsControlCharacter(value)) throw new InvalidPackageSourceContract(name);
57
+ }
58
+
59
+ function assertOptionalText(value: string | null, name: string, maxLength: number): void {
60
+ if (value !== null) assertText(value, name, maxLength);
61
+ }
62
+
63
+ function assertAllowed(value: string, allowed: readonly string[], name: string): void {
64
+ if (!allowed.includes(value)) throw new InvalidPackageSourceContract(name);
65
+ }
66
+
67
+ function assertPositiveSafeInteger(value: number, name: string): void {
68
+ if (!Number.isSafeInteger(value) || value < 1) throw new InvalidPackageSourceContract(name);
69
+ }
70
+
71
+ function assertNonNegativeSafeInteger(value: number, name: string): void {
72
+ if (!Number.isSafeInteger(value) || value < 0) throw new InvalidPackageSourceContract(name);
73
+ }
74
+
75
+ function validateRequest(request: PackageSourceRequest): void {
76
+ assertText(request.projectRoot, "projectRoot", 4096);
77
+ assertAllowed(request.coordinate.ecosystem, ECOSYSTEMS, "coordinate.ecosystem");
78
+ assertText(request.coordinate.name, "coordinate.name", 512);
79
+ assertOptionalText(request.coordinate.registry, "coordinate.registry", 2048);
80
+ assertOptionalText(request.coordinate.requestedVersion, "coordinate.requestedVersion", 256);
81
+ }
82
+
83
+ function validateBounds(bounds: PackageSourceBounds): void {
84
+ assertPositiveSafeInteger(bounds.maxManifestBytes, "maxManifestBytes");
85
+ assertPositiveSafeInteger(bounds.maxManifestEntries, "maxManifestEntries");
86
+ assertPositiveSafeInteger(bounds.maxManifestNesting, "maxManifestNesting");
87
+ assertPositiveSafeInteger(bounds.maxWorkspaces, "maxWorkspaces");
88
+ assertPositiveSafeInteger(bounds.maxDiagnostics, "maxDiagnostics");
89
+ assertPositiveSafeInteger(bounds.maxRegistryResponseBytes, "maxRegistryResponseBytes");
90
+ assertNonNegativeSafeInteger(bounds.maxRedirects, "maxRedirects");
91
+ assertNonNegativeSafeInteger(bounds.maxRetries, "maxRetries");
92
+ assertPositiveSafeInteger(bounds.maxCloneBytes, "maxCloneBytes");
93
+ assertPositiveSafeInteger(bounds.maxCacheBytes, "maxCacheBytes");
94
+ assertPositiveSafeInteger(bounds.maxCandidates, "maxCandidates");
95
+ assertPositiveSafeInteger(bounds.timeoutMs, "timeoutMs");
96
+ }
97
+
98
+ function validateVerified(outcome: VerifiedPackageSource, request: PackageSourceRequest): void {
99
+ if (outcome.coordinate.ecosystem !== request.coordinate.ecosystem || outcome.coordinate.name !== request.coordinate.name) {
100
+ throw new InvalidPackageSourceContract("resolved coordinate differs from request");
101
+ }
102
+ if (outcome.coordinate.requestedVersion !== request.coordinate.requestedVersion || outcome.coordinate.registry !== request.coordinate.registry) {
103
+ throw new InvalidPackageSourceContract("resolved request identity differs from request");
104
+ }
105
+ assertText(outcome.coordinate.resolvedVersion, "coordinate.resolvedVersion", 256);
106
+ assertOptionalText(outcome.coordinate.registry, "coordinate.registry", 2048);
107
+ assertOptionalText(outcome.repository.url, "repository.url", 4096);
108
+ assertOptionalText(outcome.repository.requestedRef, "repository.requestedRef", 512);
109
+ assertOptionalText(outcome.repository.resolvedRef, "repository.resolvedRef", 512);
110
+ if (outcome.repository.requestedRef !== null && outcome.repository.resolvedRef !== outcome.repository.requestedRef) {
111
+ throw new InvalidPackageSourceContract("verified source cannot fall back from requestedRef");
112
+ }
113
+ assertAllowed(outcome.workspace.origin, ["local", "fetched"], "workspace.origin");
114
+ if (outcome.workspace.origin === "fetched") {
115
+ if (outcome.repository.commit === null || !COMMIT_HASH.test(outcome.repository.commit)) {
116
+ throw new InvalidPackageSourceContract("fetched source requires an exact commit");
117
+ }
118
+ if (outcome.repository.url === null || outcome.repository.resolvedRef === null) {
119
+ throw new InvalidPackageSourceContract("fetched source requires repository identity");
120
+ }
121
+ } else if (outcome.repository.commit !== null && !COMMIT_HASH.test(outcome.repository.commit)) {
122
+ throw new InvalidPackageSourceContract("repository.commit");
123
+ }
124
+ if (outcome.workspace.readOnly !== true) throw new InvalidPackageSourceContract("workspace must be read-only");
125
+ assertText(outcome.workspace.cachePath, "workspace.cachePath", 4096);
126
+ if (outcome.verification.status !== "verified") throw new InvalidPackageSourceContract("verification.status");
127
+ assertAllowed(outcome.verification.method, VERIFICATION_METHODS, "verification.method");
128
+ assertText(outcome.verification.integrity, "verification.integrity", 1024);
129
+ }
130
+
131
+ function validateAmbiguous(outcome: AmbiguousPackageSource, bounds: PackageSourceBounds): void {
132
+ assertAllowed(outcome.code, AMBIGUOUS_CODES, "ambiguous.code");
133
+ if (outcome.candidates.length === 0 || outcome.candidates.length > bounds.maxCandidates) {
134
+ throw new InvalidPackageSourceContract("ambiguous candidates exceed bounds");
135
+ }
136
+ for (const candidate of outcome.candidates) {
137
+ assertText(candidate.version, "candidate.version", 256);
138
+ assertText(candidate.source, "candidate.source", 4096);
139
+ }
140
+ }
141
+
142
+ function validateUnauthenticated(outcome: UnauthenticatedPackageSource, bounds: PackageSourceBounds): void {
143
+ assertAllowed(outcome.code, UNAUTHENTICATED_CODES, "unauthenticated.code");
144
+ if (outcome.requiredCredentialNames.length === 0 || outcome.requiredCredentialNames.length > bounds.maxCandidates) {
145
+ throw new InvalidPackageSourceContract("requiredCredentialNames exceed bounds");
146
+ }
147
+ for (const name of outcome.requiredCredentialNames) {
148
+ if (!CREDENTIAL_NAME.test(name)) throw new InvalidPackageSourceContract("credential names must be environment-variable names");
149
+ }
150
+ }
151
+
152
+ function validateOversized(outcome: OversizedPackageSource): void {
153
+ assertAllowed(outcome.code, OVERSIZED_CODES, "oversized.code");
154
+ assertAllowed(outcome.resource, OVERSIZED_RESOURCES, "oversized.resource");
155
+ assertPositiveSafeInteger(outcome.limit, "oversized.limit");
156
+ if (outcome.observed !== null) {
157
+ assertPositiveSafeInteger(outcome.observed, "oversized.observed");
158
+ if (outcome.observed <= outcome.limit) throw new InvalidPackageSourceContract("oversized observation does not exceed limit");
159
+ }
160
+ }
161
+
162
+ function validateMismatched(outcome: MismatchedPackageSource): void {
163
+ assertAllowed(outcome.code, MISMATCHED_CODES, "mismatched.code");
164
+ assertText(outcome.expected, "mismatch.expected", 4096);
165
+ assertText(outcome.actual, "mismatch.actual", 4096);
166
+ if (outcome.expected === outcome.actual) throw new InvalidPackageSourceContract("mismatch values are equal");
167
+ }
168
+
169
+ function validateOutcome(outcome: PackageSourceOutcome, request: PackageSourceRequest, bounds: PackageSourceBounds): void {
170
+ switch (outcome.status) {
171
+ case "verified":
172
+ validateVerified(outcome, request);
173
+ return;
174
+ case "unavailable":
175
+ assertAllowed(outcome.code, UNAVAILABLE_CODES, "unavailable.code");
176
+ return;
177
+ case "ambiguous":
178
+ validateAmbiguous(outcome, bounds);
179
+ return;
180
+ case "unauthenticated":
181
+ validateUnauthenticated(outcome, bounds);
182
+ return;
183
+ case "oversized":
184
+ validateOversized(outcome);
185
+ return;
186
+ case "mismatched":
187
+ validateMismatched(outcome);
188
+ return;
189
+ default:
190
+ throw new InvalidPackageSourceContract("outcome.status");
191
+ }
192
+ }
193
+
194
+ export async function resolvePackageSource(
195
+ resolver: PackageSourceResolverPort,
196
+ request: PackageSourceRequest,
197
+ bounds: PackageSourceBounds,
198
+ ): Promise<PackageSourceOutcome> {
199
+ validateRequest(request);
200
+ validateBounds(bounds);
201
+ const outcome = await resolver.resolve(request, bounds);
202
+ validateOutcome(outcome, request, bounds);
203
+ return outcome;
204
+ }
@@ -1,3 +1,4 @@
1
+ import type { IntelligenceProvenance } from "./intelligence-provenance.ts";
1
2
  import type { PopulateSymbolGraphResult } from "./populate-symbol-graph.ts";
2
3
 
3
4
  export interface SymbolGraphGeneration {
@@ -5,6 +6,10 @@ export interface SymbolGraphGeneration {
5
6
  readonly maxFiles: number;
6
7
  readonly maxSymbolsPerFile: number;
7
8
  readonly completedAt: number;
9
+ /** Absent only for generations persisted before provenance was recorded. */
10
+ readonly provenance?: IntelligenceProvenance;
11
+ /** Per-language authorities included when provenance is polyglot. */
12
+ readonly sources?: readonly IntelligenceProvenance[];
8
13
  readonly result: PopulateSymbolGraphResult;
9
14
  }
10
15
 
@@ -0,0 +1,16 @@
1
+ export const MAX_SYMBOL_QUERY_BYTES = 4_096;
2
+
3
+ export class InvalidSymbolQuery extends Error {
4
+ constructor(
5
+ readonly maxBytes: number,
6
+ readonly observedBytes: number,
7
+ ) {
8
+ super(`symbol query exceeds ${maxBytes} UTF-8 bytes (observed ${observedBytes})`);
9
+ this.name = "InvalidSymbolQuery";
10
+ }
11
+ }
12
+
13
+ export function assertBoundedSymbolQuery(query: string): void {
14
+ const observedBytes = Buffer.byteLength(query, "utf-8");
15
+ if (observedBytes > MAX_SYMBOL_QUERY_BYTES) throw new InvalidSymbolQuery(MAX_SYMBOL_QUERY_BYTES, observedBytes);
16
+ }
@@ -1,3 +1,5 @@
1
+ import type { IntelligenceProvenance, IntelligenceSourceOutcome } from "./intelligence-provenance.ts";
2
+
1
3
  /** A location within a workspace file: 1-indexed line and character, matching how humans and CLIs present positions. */
2
4
  export interface WorkspaceLocation {
3
5
  readonly path: string;
@@ -11,4 +13,15 @@ export interface WorkspaceSymbol {
11
13
  readonly kind: string;
12
14
  readonly location: WorkspaceLocation;
13
15
  readonly containerName?: string;
16
+ /** Present when a workspace-wide composite query needs to preserve which backend produced this symbol. */
17
+ readonly provenance?: IntelligenceProvenance;
18
+ }
19
+
20
+ export interface SymbolSearchResult {
21
+ readonly symbols: readonly WorkspaceSymbol[];
22
+ readonly truncated: boolean;
23
+ readonly provenance: IntelligenceProvenance;
24
+ /** Present for composite workspace queries; omitted for one-language adapters. */
25
+ readonly completeness?: "complete" | "partial";
26
+ readonly sources?: readonly IntelligenceSourceOutcome[];
14
27
  }
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,26 @@ 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, LanguageFileOutsideWorkspace, 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";
29
+ export { PolyglotCodeIntelligenceIndex, type PolyglotIndexEntry } from "./adapters/polyglot-code-intelligence-index.ts";
14
30
  export { ReadOnlyWorkspace, WorkspaceIsReadOnly } from "./adapters/read-only-workspace.ts";
15
31
  export { RipgrepTextSearch } from "./adapters/ripgrep-text-search.ts";
16
32
  export { deriveSourceManifest, type SourceManifest, SourceManifestLimitExceeded } from "./adapters/source-manifest.ts";
@@ -18,7 +34,8 @@ export { SqliteContentCache } from "./adapters/sqlite-content-cache.ts";
18
34
  export { SqliteSearchCache, type SqliteSearchCacheOptions } from "./adapters/sqlite-search-cache.ts";
19
35
  export { SqliteSymbolGraph } from "./adapters/sqlite-symbol-graph.ts";
20
36
  export { TieredSearchCache } from "./adapters/tiered-search-cache.ts";
21
- export { TreeSitterSymbolIndex } from "./adapters/tree-sitter/typescript-tree-sitter-symbol-index.ts";
37
+ export { TreeSitterSymbolIndex, type TreeSitterSymbolIndexOptions } from "./adapters/tree-sitter/typescript-tree-sitter-symbol-index.ts";
38
+ export { TypeScriptCompilerSymbolIndex, type TypeScriptCompilerSymbolIndexOptions } from "./adapters/typescript-compiler-symbol-index.ts";
22
39
  export {
23
40
  type ConnectLectorClientOptions,
24
41
  connectLectorClient,
@@ -64,6 +81,25 @@ export { goToImplementation } from "./domain/go-to-implementation.ts";
64
81
  export type { Hover } from "./domain/hover.ts";
65
82
  export { hoverAt } from "./domain/hover-at.ts";
66
83
  export { incomingCalls } from "./domain/incoming-calls.ts";
84
+ export type {
85
+ AmbiguousInstalledPackageVersion,
86
+ InstalledPackageEvidence,
87
+ InstalledPackageVersionBounds,
88
+ InstalledPackageVersionCandidate,
89
+ InstalledPackageVersionOutcome,
90
+ InstalledPackageVersionRequest,
91
+ JavaScriptPackageManager,
92
+ OversizedInstalledPackageVersion,
93
+ ResolvedInstalledPackageVersion,
94
+ UnavailableInstalledPackageVersion,
95
+ } from "./domain/installed-package-version.ts";
96
+ export type {
97
+ IntelligenceFidelity,
98
+ IntelligenceProvenance,
99
+ IntelligenceSourceOutcome,
100
+ ProvenancedResult,
101
+ SymbolSearchBounds,
102
+ } from "./domain/intelligence-provenance.ts";
67
103
  export {
68
104
  descriptorForExtension,
69
105
  LANGUAGE_SERVER_DESCRIPTORS,
@@ -71,26 +107,53 @@ export {
71
107
  PYTHON_DESCRIPTOR,
72
108
  TYPESCRIPT_DESCRIPTOR,
73
109
  } from "./domain/language-server-descriptor.ts";
110
+ export type { NpmPackageVersionMetadata, NpmRegistryBounds, NpmRegistryVersionRequest, NpmRepositoryMetadata } from "./domain/npm-package-metadata.ts";
74
111
  export { outgoingCalls } from "./domain/outgoing-calls.ts";
112
+ export type {
113
+ AmbiguousPackageSource,
114
+ MismatchedPackageSource,
115
+ OversizedPackageSource,
116
+ PackageCoordinateRequest,
117
+ PackageEcosystem,
118
+ PackageRepositoryIdentity,
119
+ PackageSourceBounds,
120
+ PackageSourceCandidate,
121
+ PackageSourceOperationResult,
122
+ PackageSourceOutcome,
123
+ PackageSourceRequest,
124
+ PackageSourceVerification,
125
+ PackageSourceVerificationMethod,
126
+ PackageSourceWorkspace,
127
+ ResolvedPackageCoordinate,
128
+ UnauthenticatedPackageSource,
129
+ UnavailablePackageSource,
130
+ VerifiedPackageSource,
131
+ } from "./domain/package-source.ts";
132
+ export { DEFAULT_PACKAGE_SOURCE_BOUNDS } from "./domain/package-source.ts";
75
133
  export { type PopulateSymbolGraphResult, populateSymbolGraph } from "./domain/populate-symbol-graph.ts";
76
134
  export { prepareCallHierarchy } from "./domain/prepare-call-hierarchy.ts";
77
135
  export { raceWorkspaceQuery } from "./domain/race-workspace-query.ts";
78
136
  export { type RawRead, rawRead, WorkspaceEntryNotFound } from "./domain/raw-read.ts";
79
137
  export { reachableSymbolsFrom } from "./domain/reachable-symbols-from.ts";
80
- export { RepoFetchFailed, type RepoFetchResult } from "./domain/repo-fetch-result.ts";
138
+ export { RepoFetchCapacityExceeded, RepoFetchFailed, RepoFetchLimitExceeded, type RepoFetchPolicy, type RepoFetchResult } from "./domain/repo-fetch-result.ts";
81
139
  export type { RepoReference } from "./domain/repo-reference.ts";
140
+ export { InvalidPackageSourceContract, resolvePackageSource } from "./domain/resolve-package-source.ts";
82
141
  export { deriveSearchCacheKey, type SearchCacheKey } from "./domain/search-cache-key.ts";
83
142
  export { searchText } from "./domain/search-text.ts";
84
143
  export { symbolEdgesFrom } from "./domain/symbol-edges-from.ts";
85
144
  export { symbolEdgesTo } from "./domain/symbol-edges-to.ts";
86
145
  export type { SymbolGraphGeneration, WorkspaceCacheStatus } from "./domain/symbol-graph-generation.ts";
87
146
  export { deriveSymbolNodeId, type SymbolNodeId } from "./domain/symbol-node-id.ts";
147
+ export { assertBoundedSymbolQuery, InvalidSymbolQuery, MAX_SYMBOL_QUERY_BYTES } from "./domain/symbol-query.ts";
88
148
  export type { TextSearchMatch, TextSearchResult } from "./domain/text-search-result.ts";
89
149
  export type { WorkspaceQueryOutcome, WorkspaceQueryStatus } from "./domain/workspace-query-outcome.ts";
90
- export type { WorkspaceLocation, WorkspaceSymbol } from "./domain/workspace-symbol.ts";
150
+ export type { SymbolSearchResult, WorkspaceLocation, WorkspaceSymbol } from "./domain/workspace-symbol.ts";
91
151
  export type { CodeIntelligencePort } from "./ports/code-intelligence-port.ts";
92
152
  export type { ContentCacheEntry, ContentCachePort, ContentSymbol } from "./ports/content-cache-port.ts";
93
153
  export type { GitPort } from "./ports/git-port.ts";
154
+ export type { InstalledPackageVersionResolverPort } from "./ports/installed-package-version-resolver-port.ts";
155
+ export type { NpmRegistryPort } from "./ports/npm-registry-port.ts";
156
+ export type { PackageSourceResolverPort } from "./ports/package-source-resolver-port.ts";
94
157
  export type { RepoFetcherPort } from "./ports/repo-fetcher-port.ts";
95
158
  export type { SearchCachePort } from "./ports/search-cache-port.ts";
96
159
  export type { SymbolEdgeKind, SymbolGraphPort, SymbolNode } from "./ports/symbol-graph-port.ts";
@@ -111,6 +174,7 @@ export {
111
174
  type OperationInputs,
112
175
  type OperationName,
113
176
  type OperationOutputs,
177
+ PackageSourceResolverNotConfigured,
114
178
  RepoFetcherNotConfigured,
115
179
  SymbolQueryUnavailable,
116
180
  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
+ }
@@ -0,0 +1,5 @@
1
+ import type { PackageSourceBounds, PackageSourceOutcome, PackageSourceRequest } from "../domain/package-source.ts";
2
+
3
+ export interface PackageSourceResolverPort {
4
+ resolve(request: PackageSourceRequest, bounds: PackageSourceBounds): Promise<PackageSourceOutcome>;
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 { WorkspaceSymbol } from "../domain/workspace-symbol.ts";
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
- findSymbols(query: string): Promise<WorkspaceSymbol[]>;
11
+ readonly provenance: IntelligenceProvenance;
12
+ findSymbols(query: string, bounds?: SymbolSearchBounds): Promise<SymbolSearchResult>;
11
13
  }