@wrongstack/tools 1.0.10 → 1.0.12

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 (80) hide show
  1. package/dist/builtin.js +17 -17
  2. package/dist/{chunk-6I6RXQFG.js → chunk-2BCRQAIW.js} +9 -9
  3. package/dist/{chunk-XRNN44QY.js → chunk-2IRHFHZY.js} +235 -71
  4. package/dist/{chunk-5RBUYFRV.js → chunk-4IMNVQRB.js} +8 -2
  5. package/dist/{chunk-NEYUPZL6.js → chunk-6D3UIQMF.js} +651 -303
  6. package/dist/chunk-BJ5LXLKE.js +351 -0
  7. package/dist/{chunk-C6ZOXNXV.js → chunk-CSS42GRP.js} +2 -2
  8. package/dist/{chunk-SKRMUHTU.js → chunk-HSLDY55L.js} +41 -8
  9. package/dist/{chunk-ENE22I5W.js → chunk-K37AKCTN.js} +884 -362
  10. package/dist/{chunk-V25Q6TQ7.js → chunk-K3VX6V5P.js} +3 -3
  11. package/dist/chunk-OIFY4XNP.js +855 -0
  12. package/dist/{chunk-OUERRFEM.js → chunk-OMQDKZOT.js} +17 -8
  13. package/dist/{chunk-7GOE2ZTZ.js → chunk-OMWC2OGT.js} +2 -2
  14. package/dist/{chunk-IE4KDAOB.js → chunk-OYQE2UNT.js} +3 -3
  15. package/dist/chunk-R3HR3QI3.js +97 -0
  16. package/dist/{chunk-XPVYZ2S6.js → chunk-RYLMSGR5.js} +2 -2
  17. package/dist/{chunk-HYHE4VNA.js → chunk-UMOP3VGK.js} +79 -45
  18. package/dist/{chunk-FVSMTEO3.js → chunk-VMNWQI4V.js} +2 -2
  19. package/dist/{chunk-2UVAIS5O.js → chunk-YPSVPCIE.js} +2 -2
  20. package/dist/{chunk-PWZUHZP7.js → chunk-Z77XMU3U.js} +2 -2
  21. package/dist/codebase-index/ast-invariant-engine.d.ts +19 -2
  22. package/dist/codebase-index/atlas-projection.d.ts +19 -0
  23. package/dist/codebase-index/background-indexer.d.ts +14 -0
  24. package/dist/codebase-index/circuit-breaker.d.ts +7 -0
  25. package/dist/codebase-index/codebase-ast-replace-tool.d.ts +1 -1
  26. package/dist/codebase-index/codebase-impact-analysis-tool.d.ts +6 -0
  27. package/dist/codebase-index/codebase-invariant-check-tool.d.ts +2 -0
  28. package/dist/codebase-index/codebase-targeted-test-tool.d.ts +26 -0
  29. package/dist/codebase-index/dead-code-scan.d.ts +4 -0
  30. package/dist/codebase-index/go-parser.d.ts +23 -3
  31. package/dist/codebase-index/graph-rank-pass.d.ts +10 -0
  32. package/dist/codebase-index/graph-rank.d.ts +8 -0
  33. package/dist/codebase-index/index.d.ts +1 -1
  34. package/dist/codebase-index/index.js +9 -9
  35. package/dist/codebase-index/lsp-kind.d.ts +3 -1
  36. package/dist/codebase-index/module-resolver.d.ts +21 -1
  37. package/dist/codebase-index/parser-batch.d.ts +6 -8
  38. package/dist/codebase-index/parser-output.d.ts +5 -1
  39. package/dist/codebase-index/parser-worker-script.js +4 -4
  40. package/dist/codebase-index/project-server-framing.d.ts +1 -17
  41. package/dist/codebase-index/project-server-watcher.d.ts +6 -0
  42. package/dist/codebase-index/project-server.js +72 -26
  43. package/dist/codebase-index/py-parser.d.ts +4 -4
  44. package/dist/codebase-index/rs-parser.d.ts +7 -0
  45. package/dist/codebase-index/toolchain-scripts.d.ts +64 -0
  46. package/dist/codebase-index/tree-sitter/queries.d.ts +14 -0
  47. package/dist/codebase-index/tree-sitter/util.d.ts +6 -1
  48. package/dist/codebase-index/tree-sitter-parser.d.ts +7 -0
  49. package/dist/codebase-index/worker.js +23 -16
  50. package/dist/codebase-index/writer-refs.d.ts +17 -2
  51. package/dist/codebase-index/writer-search-helpers.d.ts +9 -0
  52. package/dist/codebase-index/writer.d.ts +20 -1
  53. package/dist/edit.js +8 -8
  54. package/dist/{generic-parser-N2PLGBC2.js → generic-parser-IVWLFKMR.js} +2 -2
  55. package/dist/go-parser-LWV3L5V7.js +197 -0
  56. package/dist/index.js +19 -19
  57. package/dist/json-parser-PERV2JHX.js +204 -0
  58. package/dist/pack.js +18 -18
  59. package/dist/parser-dispatch-ZSWCQB6M.js +14 -0
  60. package/dist/patch.js +8 -8
  61. package/dist/{py-parser-4PFZYAJ7.js → py-parser-B6D6RGH7.js} +4 -4
  62. package/dist/read.js +8 -8
  63. package/dist/replace.js +8 -8
  64. package/dist/rs-parser-L7SP4GWJ.js +182 -0
  65. package/dist/test.d.ts +1 -0
  66. package/dist/test.js +1 -1
  67. package/dist/tool-tier.js +19 -19
  68. package/dist/{tree-sitter-parser-GILYQLS4.js → tree-sitter-parser-KU6JF3ZC.js} +6 -4
  69. package/dist/{ts-parser-7W26YB26.js → ts-parser-PML6QIH7.js} +55 -23
  70. package/dist/typecheck.js +1 -1
  71. package/dist/write.js +8 -8
  72. package/dist/{yaml-parser-DFBC5FWH.js → yaml-parser-7BJN544B.js} +41 -6
  73. package/package.json +5 -5
  74. package/dist/chunk-4CE3RKEP.js +0 -390
  75. package/dist/chunk-KHUCKLOR.js +0 -899
  76. package/dist/chunk-ZKC5UNGD.js +0 -167
  77. package/dist/go-parser-Z4H6SR3R.js +0 -474
  78. package/dist/json-parser-IJD77VL4.js +0 -256
  79. package/dist/parser-dispatch-WG4DNBHH.js +0 -14
  80. package/dist/rs-parser-GIWPUA3T.js +0 -81
@@ -69,6 +69,10 @@ export interface DeadCodeScanOutput {
69
69
  };
70
70
  }
71
71
  export declare const deadCodeScanTool: Tool<DeadCodeScanInput, DeadCodeScanOutput>;
72
+ /**
73
+ * Walk the workspace and discover entry-point files from package.json(s).
74
+ */
75
+ export declare function discoverEntryPoints(projectRoot: string, userEntryPoints: string[] | undefined): string[];
72
76
  export declare function runDeadCodeScan(projectRoot: string, opts?: {
73
77
  indexDir?: string | undefined;
74
78
  userEntryPoints?: string[] | undefined;
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * Go source symbol extraction using `go/parser`.
3
3
  *
4
- * Spawns a `go run -` child process that parses the file with go/ast and
5
- * emits JSON. Falls back to empty results on any error.
4
+ * Runs the extraction program from `toolchain-scripts.ts` under `go run`, with
5
+ * the source on stdin, and decodes its JSON. When the toolchain is missing or
6
+ * the run yields nothing, a line-based extractor keeps the file indexed.
6
7
  *
7
- * Extracts: package, func, type, const, var
8
+ * Extracts: func, method, type, const, var
8
9
  */
9
10
  import type { FileSymbols, SymbolLang } from './schema.js';
10
11
  export declare function parseSymbols(opts: {
@@ -13,4 +14,23 @@ export declare function parseSymbols(opts: {
13
14
  lang: SymbolLang;
14
15
  }): Promise<FileSymbols>;
15
16
  export { detectLang } from './languages.js';
17
+ /**
18
+ * Blank comment and string/rune literal contents, keeping offsets and newlines.
19
+ * Quote characters survive so the line structure stays readable.
20
+ */
21
+ export declare function maskGoNonCode(src: string): string;
22
+ /**
23
+ * Line-based extraction for when `go run` is unavailable or failed.
24
+ *
25
+ * Runs over {@link maskGoNonCode} output and only reads declarations at the top
26
+ * level. Previously it scanned every trimmed line of the raw source, so:
27
+ * - a `(` or `}` inside a string or comment tripped the delimiter check and
28
+ * the whole file indexed empty (`strings.Split(s, "(")` is enough);
29
+ * - every `var x` / `type t` local inside a function body became a
30
+ * package-level symbol;
31
+ * - generic functions (`func Map[T any](`) were missing, grouped
32
+ * `const ( … )` / `var ( … )` members were missing, and methods were
33
+ * scoped `pkg.Name` instead of the native parser's `pkg.Recv.Name`.
34
+ */
35
+ export declare function parseGoWithoutToolchain(filePath: string, content: string, lang?: SymbolLang): FileSymbols;
16
36
  //# sourceMappingURL=go-parser.d.ts.map
@@ -11,6 +11,16 @@
11
11
  * watcher run, which is what {@link shouldRefreshRanks} arbitrates.
12
12
  */
13
13
  import type { IndexStore } from './writer.js';
14
+ /**
15
+ * Build the `implicitlyVisible` predicate for one rank pass.
16
+ *
17
+ * Without it every same-package Go/Java/C# reference — code that needs no
18
+ * import by the language's own rules — was scored as a contradicted
19
+ * misresolution (weight 0.02), as was every call into a Go package other than
20
+ * the one file the resolver picked to represent it. Centrality for those
21
+ * languages was computed on a graph with its package-internal wiring erased.
22
+ */
23
+ export declare function createImplicitVisibility(): (sourceFile: string, targetFile: string, imports: ReadonlySet<string> | undefined) => boolean;
14
24
  /**
15
25
  * Data-version marker for the rank layer, in the same spirit as
16
26
  * `relation_graph_version`: bumping it forces every index to recompute ranks
@@ -156,6 +156,14 @@ export interface WiringGraphOptions {
156
156
  fileOf?: ReadonlyMap<number, string> | undefined;
157
157
  /** Files each source file imports, as resolved by the module resolver. */
158
158
  importsOf?: ReadonlyMap<string, ReadonlySet<string>> | undefined;
159
+ /**
160
+ * True when the target is visible to the source without a file-level import
161
+ * — the same Go package, Java package or C# namespace directory, or a file
162
+ * of a Go package the source imports (the resolver records ONE
163
+ * representative file per imported package). Those edges are ordinary
164
+ * code, not misresolutions, and must not take the contradicted weight.
165
+ */
166
+ implicitlyVisible?: ((sourceFile: string, targetFile: string, imports: ReadonlySet<string> | undefined) => boolean) | undefined;
159
167
  }
160
168
  export declare function buildWiringGraph(refs: readonly ResolvedRefEdge[], options?: WiringGraphOptions): WiringGraph;
161
169
  /**
@@ -17,7 +17,6 @@ export { type InvariantEvaluationResult, type InvariantRuleId, type InvariantVio
17
17
  export { type MutateSymbolOptions, type MutateSymbolResult, replaceSymbolInFile, } from './ast-symbol-mutator.js';
18
18
  export { cancelPendingReindexes, checkCodebaseIndexServerHealth, codebaseIndexStats, enqueueReindex, ensureCodebaseIndexServer, fileGraphService, getIndexState, incomingCallsService, isIndexableFile, isIndexing, isIndexReady, onIndexStateChange, outgoingCallsService, packageGraphService, runStartupIndex, searchCodebaseIndex, shutdownCodebaseIndexHost, shutdownCodebaseIndexServer, symbolGraphService, } from './background-indexer.js';
19
19
  export { buildBm25Index, buildIndexableText, tokenise, } from './bm25.js';
20
- export { getCodebaseIndexPerfSnapshot, resetCodebaseIndexPerfMetrics, type CodebaseIndexPerfSnapshot, } from './perf-metrics.js';
21
20
  export type { CircuitSnapshot, CircuitState } from './circuit-breaker.js';
22
21
  export { CircuitOpenError, IndexCircuitBreaker, IndexTimeoutError, indexCircuitBreaker, resetIndexCircuitBreaker, } from './circuit-breaker.js';
23
22
  export { type CodebaseAstReplaceInput, type CodebaseAstReplaceOutput, codebaseAstReplaceTool, } from './codebase-ast-replace-tool.js';
@@ -37,6 +36,7 @@ export { compileGitignore, type IgnoreMatcher, loadGitignoreMatcher, } from './g
37
36
  export { runIndexer } from './indexer.js';
38
37
  export { detectLang, INDEXABLE_EXTENSIONS, isIndexablePath } from './languages.js';
39
38
  export { internalKindToLspKind, lspKindToInternalKind, } from './lsp-kind.js';
39
+ export { type CodebaseIndexPerfSnapshot, getCodebaseIndexPerfSnapshot, resetCodebaseIndexPerfMetrics, } from './perf-metrics.js';
40
40
  export type { ProjectIndexServerClientHealth, ProjectIndexServerConnectionState, ProjectIndexServerConnectionStatus, } from './project-server-client.js';
41
41
  export { type ProjectIndexDaemonAvailability, resolveProjectIndexDaemonAvailability, } from './project-server-client.js';
42
42
  export { projectIndexServerEndpoint, projectIndexServerMetadataPath, } from './project-server-endpoint.js';
@@ -51,8 +51,8 @@ import {
51
51
  setContextQueryEmbedder,
52
52
  writeAtlas,
53
53
  writeProjectAtlas
54
- } from "../chunk-ENE22I5W.js";
55
- import "../chunk-XRNN44QY.js";
54
+ } from "../chunk-K37AKCTN.js";
55
+ import "../chunk-2IRHFHZY.js";
56
56
  import "../chunk-UVYRQKPZ.js";
57
57
  import "../chunk-SCMRM6NL.js";
58
58
  import "../chunk-HDYUBRMF.js";
@@ -78,11 +78,11 @@ import {
78
78
  shutdownCodebaseIndexHost,
79
79
  shutdownCodebaseIndexServer,
80
80
  symbolGraphService
81
- } from "../chunk-HYHE4VNA.js";
81
+ } from "../chunk-UMOP3VGK.js";
82
82
  import {
83
83
  projectIndexServerEndpoint,
84
84
  projectIndexServerMetadataPath
85
- } from "../chunk-XPVYZ2S6.js";
85
+ } from "../chunk-RYLMSGR5.js";
86
86
  import {
87
87
  CONCEPT_RELATIONS,
88
88
  CONTRADICTED_VISIBILITY_WEIGHT,
@@ -122,14 +122,14 @@ import {
122
122
  shouldRefreshRanks,
123
123
  toSymbolRankRows,
124
124
  tokenise
125
- } from "../chunk-NEYUPZL6.js";
126
- import "../chunk-KHUCKLOR.js";
127
- import "../chunk-4CE3RKEP.js";
128
- import "../chunk-SKRMUHTU.js";
125
+ } from "../chunk-6D3UIQMF.js";
126
+ import "../chunk-BJ5LXLKE.js";
127
+ import "../chunk-R3HR3QI3.js";
128
+ import "../chunk-HSLDY55L.js";
129
129
  import {
130
130
  getCodebaseIndexPerfSnapshot,
131
131
  resetCodebaseIndexPerfMetrics
132
- } from "../chunk-ZKC5UNGD.js";
132
+ } from "../chunk-OIFY4XNP.js";
133
133
  import {
134
134
  INDEXABLE_EXTENSIONS,
135
135
  detectLang,
@@ -36,8 +36,10 @@ export declare enum LSPSymbolKind {
36
36
  Operator = 25,
37
37
  TypeParameter = 26
38
38
  }
39
+ /** All internal kinds an LSP kind number covers; empty when it has no equivalent. */
40
+ export declare function lspKindToInternalKinds(k: number): readonly SymbolKind[];
39
41
  /**
40
- * Maps an LSP kind number to the corresponding internal SymbolKind.
42
+ * Maps an LSP kind number to its primary internal SymbolKind.
41
43
  * Returns null if the LSP kind has no equivalent in the internal taxonomy.
42
44
  */
43
45
  export declare function lspKindToInternalKind(k: number): SymbolKind | null;
@@ -66,8 +66,28 @@ export declare class ModuleResolver {
66
66
  * leading dots the extractor preserves (`.sibling`, `..parent.mod`).
67
67
  */
68
68
  private resolvePython;
69
- /** `use crate::a::b`, `use super::x`, `use self::y`, `use other_crate::z`. */
69
+ /**
70
+ * `use crate::a::b`, `use super::x`, `use self::y`, `use other_crate::z`,
71
+ * and `mod x;` declarations.
72
+ *
73
+ * Paths are resolved from the declaring file's MODULE directory, which is
74
+ * only its filesystem directory for `mod.rs`/`lib.rs`/`main.rs`. A plain
75
+ * `src/net.rs` owns `src/net/`: its `mod http;` is `src/net/http.rs`, its
76
+ * `super` is the crate root. Using the file's directory put every
77
+ * `self::`/`super::`/`mod` path from such a file one level too high, so
78
+ * those edges silently resolved to nothing (or to an unrelated file).
79
+ */
70
80
  private resolveRust;
81
+ /**
82
+ * Longest module prefix of `segments` under `base` that is an indexed file.
83
+ * The trailing segments of a `use` are usually items (`net::http::Client::new`),
84
+ * so each is dropped in turn until a module file matches.
85
+ */
86
+ private lookupRustPath;
87
+ /** The file defining the module whose children live in `dir`. */
88
+ private lookupRustModuleFile;
89
+ /** A crate's root file: the library root, else the binary root. */
90
+ private lookupRustCrateRoot;
71
91
  /** `com.example.Thing` and `com.example.*` against JVM source roots. */
72
92
  private resolveJvm;
73
93
  /** `#include "foo/bar.h"` — quoted form only; `<…>` is a system header. */
@@ -4,16 +4,15 @@
4
4
  * The single-file parsers spawn one `go run` / `python` child process per
5
5
  * file. For a 400-file Go project that is 400 process spawns, each paying
6
6
  * toolchain startup; the spawn gate serializes them, so parse time scales
7
- * linearly with spawn cost. This module runs the SAME extraction logic over
8
- * a batch: one child process per chunk of files, sources in over stdin as a
9
- * JSON array, one JSON envelope out per file.
7
+ * linearly with spawn cost. This module runs the SAME extraction core (see
8
+ * `toolchain-scripts.ts`) over a batch: one child process per chunk of files,
9
+ * sources in over stdin as a JSON array, one JSON envelope out per file.
10
10
  *
11
11
  * Fallback contract: a file the batch could not parse (per-file error in the
12
12
  * envelope, or the chunk itself failing) is simply ABSENT from the returned
13
13
  * map — the caller re-parses those files through the single-file parser,
14
14
  * which owns the per-language fallback semantics (Go: regex extractor;
15
- * Python: generic regex only when the runtime is missing). Parity with the
16
- * per-file path is therefore by construction, not by reimplementation.
15
+ * Python: generic regex only when the runtime is missing).
17
16
  */
18
17
  import type { FileSymbols, SymbolLang } from './schema.js';
19
18
  export interface BatchFile {
@@ -25,9 +24,8 @@ export interface BatchFile {
25
24
  * Generic so callers' extra per-file fields (e.g. source index) survive. */
26
25
  export declare function chunkBatchFiles<T extends BatchFile>(files: readonly T[]): T[][];
27
26
  /**
28
- * Test-only: the cached batch-script paths. The security regression test
29
- * observes WHERE the scripts were written without needing a toolchain
30
- * a missing binary still leaves the (already-created) path cached.
27
+ * Test-only: the cached batch-script paths, so a test can observe WHERE the
28
+ * scripts were written without needing a toolchain.
31
29
  */
32
30
  export declare function __batchScriptPathsForTest(): {
33
31
  go: string | null;
@@ -11,7 +11,7 @@
11
11
  * it, and a stale script must degrade to "symbols but no edges", never to a
12
12
  * hard parse failure that drops the file from the index entirely.
13
13
  */
14
- import type { Ref, SymbolLang } from './schema.js';
14
+ import type { Symbol as IndexSymbol, Ref, SymbolLang } from './schema.js';
15
15
  interface RawParsedSymbol {
16
16
  name: string;
17
17
  kind: string;
@@ -19,7 +19,11 @@ interface RawParsedSymbol {
19
19
  col: number;
20
20
  signature: string;
21
21
  scope: string;
22
+ /** First line of the declaration's doc comment / docstring. */
23
+ doc: string;
22
24
  }
25
+ /** Map decoded parser symbols onto index rows for `file`. */
26
+ export declare function toIndexSymbols(raw: readonly RawParsedSymbol[], file: string, lang: SymbolLang): IndexSymbol[];
23
27
  interface ParsedParserOutput {
24
28
  symbols: RawParsedSymbol[];
25
29
  refs: Ref[];
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  parseFilesContent
3
- } from "../chunk-KHUCKLOR.js";
4
- import "../chunk-4CE3RKEP.js";
5
- import "../chunk-SKRMUHTU.js";
6
- import "../chunk-ZKC5UNGD.js";
3
+ } from "../chunk-BJ5LXLKE.js";
4
+ import "../chunk-R3HR3QI3.js";
5
+ import "../chunk-HSLDY55L.js";
6
+ import "../chunk-OIFY4XNP.js";
7
7
  import "../chunk-YOHO4DVT.js";
8
8
  import "../chunk-XZLVJD56.js";
9
9
 
@@ -9,21 +9,5 @@ import type { ClientState } from './project-server-types.js';
9
9
  */
10
10
  export declare const MAX_CLIENT_WRITE_BUFFER_BYTES: number;
11
11
  export declare function sendServerMessage(state: ClientState, message: ProjectServerMessage): void;
12
- /**
13
- * Frame reader for one client connection. Each frame is sniffed per first
14
- * byte: `0x57` ('W') → length-prefixed MessagePack, anything else →
15
- * newline-delimited JSON text. Bytes stay raw until a complete frame is
16
- * assembled, so a multibyte UTF-8 sequence split across chunks is only ever
17
- * decoded as part of a finished line (raw `0x0a` only occurs as the JSON
18
- * delimiter — inside JSON strings `\n` is escaped — so a complete line is
19
- * always complete UTF-8).
20
- *
21
- * The buffer is consumed with a scan offset rather than re-slicing after
22
- * every frame: each parsed frame advances `scan` within the same Buffer,
23
- * and the leftover tail is compacted once at the end of the call. A burst
24
- * of small frames therefore costs one allocation per chunk, not one
25
- * per frame (the previous slice-per-frame loop reallocated on every frame
26
- * while pinning the whole parent buffer).
27
- */
28
- export declare function consumeClientChunk(state: ClientState, chunk: Buffer, onMessage: (state: ClientState, message: ProjectServerClientMessage) => void): void;
12
+ export declare function consumeClientChunk(state: ClientState, chunk: Buffer, onMessage: (state: ClientState, message: ProjectServerClientMessage) => void | Promise<void>): void;
29
13
  //# sourceMappingURL=project-server-framing.d.ts.map
@@ -2,6 +2,12 @@ import type { ClientState } from './project-server-types.js';
2
2
  export declare const DEFAULT_EXTERNAL_DEBOUNCE_MS = 400;
3
3
  export declare const DEFAULT_EXTERNAL_COALESCE_WINDOW_MS = 50;
4
4
  export declare function isIgnoredRelativePath(relativePath: string): boolean;
5
+ /**
6
+ * Whether a non-indexable `rename` path may be a directory whose files the
7
+ * index holds: an existing directory, or a vanished path without an
8
+ * extension (a deleted `.png` must not trigger an index write run).
9
+ */
10
+ export declare function isDirectoryWatchCandidate(absolute: string): Promise<boolean>;
5
11
  export interface ProjectServerWatcherOptions {
6
12
  projectRoot: string;
7
13
  onFilesChanged: (files: string[]) => void;
@@ -10,7 +10,7 @@ import {
10
10
  projectIndexServerBuildId,
11
11
  projectIndexServerEndpoint,
12
12
  projectIndexServerMetadataPath
13
- } from "../chunk-XPVYZ2S6.js";
13
+ } from "../chunk-RYLMSGR5.js";
14
14
  import {
15
15
  contextService,
16
16
  fileGraphService,
@@ -24,13 +24,13 @@ import {
24
24
  statsService,
25
25
  symbolGraphService,
26
26
  vectorSearchService
27
- } from "../chunk-NEYUPZL6.js";
28
- import "../chunk-KHUCKLOR.js";
29
- import "../chunk-4CE3RKEP.js";
30
- import "../chunk-SKRMUHTU.js";
27
+ } from "../chunk-6D3UIQMF.js";
28
+ import "../chunk-BJ5LXLKE.js";
29
+ import "../chunk-R3HR3QI3.js";
30
+ import "../chunk-HSLDY55L.js";
31
31
  import {
32
32
  recordWriteQueueWait
33
- } from "../chunk-ZKC5UNGD.js";
33
+ } from "../chunk-OIFY4XNP.js";
34
34
  import {
35
35
  isIndexablePath
36
36
  } from "../chunk-YOHO4DVT.js";
@@ -39,7 +39,7 @@ import "../chunk-XZLVJD56.js";
39
39
 
40
40
  // src/codebase-index/project-server.ts
41
41
  import { randomBytes } from "node:crypto";
42
- import * as fs2 from "node:fs";
42
+ import * as fs3 from "node:fs";
43
43
  import * as net from "node:net";
44
44
  import * as path3 from "node:path";
45
45
  import { startSharedHeapWatchdog, useDaemonPerfDefaults } from "@wrongstack/core/utils";
@@ -58,6 +58,29 @@ function sendServerMessage(state, message) {
58
58
  state.binary ? encodeBinaryFrame(message) : encodeProjectServerMessage(message)
59
59
  );
60
60
  }
61
+ function isClientMessage(value) {
62
+ return typeof value === "object" && value !== null && !Array.isArray(value) && typeof value.type === "string";
63
+ }
64
+ function rejectConnection(state, reason) {
65
+ state.buffer = Buffer.alloc(0);
66
+ if (!state.socket.destroyed) state.socket.destroy(new Error(reason));
67
+ }
68
+ function dispatchClientMessage(state, message, onMessage) {
69
+ const fail = (error) => {
70
+ const detail = error instanceof Error ? error.message : String(error);
71
+ process.stderr.write(`codebase-index server: client message handler failed: ${detail}
72
+ `);
73
+ rejectConnection(state, "codebase-index client message handler failed");
74
+ };
75
+ try {
76
+ const pending = onMessage(state, message);
77
+ if (pending && typeof pending.then === "function") pending.then(void 0, fail);
78
+ return true;
79
+ } catch (error) {
80
+ fail(error);
81
+ return false;
82
+ }
83
+ }
61
84
  function consumeClientChunk(state, chunk, onMessage) {
62
85
  const buffer = state.buffer.length === 0 ? chunk : Buffer.concat([state.buffer, chunk]);
63
86
  let scan = 0;
@@ -73,18 +96,21 @@ function consumeClientChunk(state, chunk, onMessage) {
73
96
  }
74
97
  if (buffer.length - scan < 5 + frameLen) break;
75
98
  const payload = buffer.subarray(scan + 5, scan + 5 + frameLen);
76
- let message2;
99
+ let decoded;
77
100
  try {
78
- message2 = decodeBinaryFrame(payload);
101
+ decoded = decodeBinaryFrame(payload);
79
102
  } catch {
80
- state.buffer = Buffer.alloc(0);
81
- state.socket.destroy(new Error("invalid codebase-index client binary frame"));
103
+ rejectConnection(state, "invalid codebase-index client binary frame");
104
+ return;
105
+ }
106
+ if (!isClientMessage(decoded)) {
107
+ rejectConnection(state, "invalid codebase-index client binary frame");
82
108
  return;
83
109
  }
84
110
  scan += 5 + frameLen;
85
111
  state.binary = true;
86
112
  state.lastSeenAt = Date.now();
87
- onMessage(state, message2);
113
+ if (!dispatchClientMessage(state, decoded, onMessage)) return;
88
114
  continue;
89
115
  }
90
116
  const newline = buffer.indexOf(10, scan);
@@ -104,16 +130,19 @@ function consumeClientChunk(state, chunk, onMessage) {
104
130
  const line = buffer.subarray(scan, newline).toString("utf8");
105
131
  scan = newline + 1;
106
132
  if (!line) continue;
107
- let message;
133
+ let parsed2;
108
134
  try {
109
- message = JSON.parse(line);
135
+ parsed2 = JSON.parse(line);
110
136
  } catch {
111
- state.buffer = Buffer.alloc(0);
112
- state.socket.destroy(new Error("invalid codebase-index client message"));
137
+ rejectConnection(state, "invalid codebase-index client message");
138
+ return;
139
+ }
140
+ if (!isClientMessage(parsed2)) {
141
+ rejectConnection(state, "invalid codebase-index client message");
113
142
  return;
114
143
  }
115
144
  state.lastSeenAt = Date.now();
116
- onMessage(state, message);
145
+ if (!dispatchClientMessage(state, parsed2, onMessage)) return;
117
146
  }
118
147
  state.buffer = scan === 0 ? buffer : Buffer.from(buffer.subarray(scan));
119
148
  }
@@ -475,6 +504,7 @@ async function dispatchOperation(ctx, state, message) {
475
504
  }
476
505
 
477
506
  // src/codebase-index/project-server-watcher.ts
507
+ import * as fs2 from "node:fs/promises";
478
508
  import * as path2 from "node:path";
479
509
  import {
480
510
  DEFAULT_WALK_IGNORE_SET,
@@ -485,6 +515,14 @@ var DEFAULT_EXTERNAL_COALESCE_WINDOW_MS = 50;
485
515
  function isIgnoredRelativePath(relativePath) {
486
516
  return relativePath.split(/[/\\]/u).some((segment) => DEFAULT_WALK_IGNORE_SET.has(segment));
487
517
  }
518
+ async function isDirectoryWatchCandidate(absolute) {
519
+ try {
520
+ return (await fs2.stat(absolute)).isDirectory();
521
+ } catch (err) {
522
+ const code = err?.code;
523
+ return (code === "ENOENT" || code === "ENOTDIR") && path2.extname(absolute) === "";
524
+ }
525
+ }
488
526
  var ProjectServerWatcherManager = class {
489
527
  constructor(options) {
490
528
  this.options = options;
@@ -525,14 +563,21 @@ var ProjectServerWatcherManager = class {
525
563
  const projectRoot2 = this.options.projectRoot;
526
564
  this.externalWatcher = watchProjectTree(
527
565
  projectRoot2,
528
- ({ filename }) => {
566
+ ({ eventType, filename }) => {
529
567
  if (!filename || isIgnoredRelativePath(filename)) return;
530
568
  const absolute = path2.resolve(projectRoot2, filename);
531
569
  const relative2 = path2.relative(projectRoot2, absolute);
532
- if (relative2 === ".." || relative2.startsWith(`..${path2.sep}`) || path2.isAbsolute(relative2) || !isIndexablePath(absolute)) {
570
+ if (relative2 === ".." || relative2.startsWith(`..${path2.sep}`) || path2.isAbsolute(relative2)) {
571
+ return;
572
+ }
573
+ if (isIndexablePath(absolute)) {
574
+ this.enqueueExternalFile(absolute);
533
575
  return;
534
576
  }
535
- this.enqueueExternalFile(absolute);
577
+ if (eventType !== "rename") return;
578
+ void isDirectoryWatchCandidate(absolute).then((candidate) => {
579
+ if (candidate && this.externalWatcher) this.enqueueExternalFile(absolute);
580
+ });
536
581
  },
537
582
  {
538
583
  onError: () => {
@@ -910,11 +955,12 @@ async function handleMessage(state, message) {
910
955
  const previousDebounceMs = state.debounceMs;
911
956
  const previousCoalesceWindowMs = state.coalesceWindowMs;
912
957
  try {
913
- state.watchExternal = message.watchExternal;
914
- state.debounceMs = Math.max(0, message.debounceMs);
915
- state.coalesceWindowMs = Math.max(
916
- 0,
917
- message.coalesceWindowMs ?? DEFAULT_EXTERNAL_COALESCE_WINDOW_MS
958
+ const nonNegative = (value, fallback) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : fallback;
959
+ state.watchExternal = message.watchExternal === true;
960
+ state.debounceMs = nonNegative(message.debounceMs, DEFAULT_EXTERNAL_DEBOUNCE_MS);
961
+ state.coalesceWindowMs = nonNegative(
962
+ message.coalesceWindowMs,
963
+ DEFAULT_EXTERNAL_COALESCE_WINDOW_MS
918
964
  );
919
965
  watcherManager.reconcile(clients);
920
966
  send(state, {
@@ -1054,7 +1100,7 @@ async function stop(_reason) {
1054
1100
  });
1055
1101
  if (process.platform !== "win32") {
1056
1102
  try {
1057
- fs2.rmSync(endpoint, { force: true });
1103
+ fs3.rmSync(endpoint, { force: true });
1058
1104
  } catch {
1059
1105
  }
1060
1106
  }
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Python source symbol extraction using the `ast` module.
3
3
  *
4
- * Spawns a `python -c` child process that parses the file with Python's `ast`
5
- * module and emits JSON. Falls back to empty results on any error.
4
+ * Runs the extraction program from `toolchain-scripts.ts` under the resolved
5
+ * interpreter, with the source on stdin, and decodes its JSON.
6
6
  *
7
- * Extracts: class, function, async function, const, var, import, import_from
7
+ * Extracts: class, function, method, property, const, var, type
8
8
  */
9
9
  import type { FileSymbols, SymbolLang } from './schema.js';
10
10
  /**
@@ -23,7 +23,7 @@ export declare function parseSymbols(opts: {
23
23
  export { detectLang } from './languages.js';
24
24
  /**
25
25
  * The resolved Python binary (or null when no runtime is available).
26
- * Shared with the P3.8 batch parser so both paths run the same interpreter.
26
+ * Shared with the batch parser so both paths run the same interpreter.
27
27
  */
28
28
  export declare function resolvePythonBinary(): Promise<string | null>;
29
29
  //# sourceMappingURL=py-parser.d.ts.map
@@ -27,4 +27,11 @@ export declare function parseSymbols(opts: {
27
27
  lang: SymbolLang;
28
28
  }): Promise<FileSymbols>;
29
29
  export { detectLang } from './languages.js';
30
+ /**
31
+ * Replace comments and string/char literal contents with spaces, keeping every
32
+ * offset and newline intact so match positions map straight back to the
33
+ * original source. Quote characters survive, so the lifetime guard
34
+ * (`'static`) still sees its apostrophe.
35
+ */
36
+ export declare function maskRustNonCode(src: string): string;
30
37
  //# sourceMappingURL=rs-parser.d.ts.map