@aroman22/codegraph-vba 1.3.3
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 +855 -0
- package/dist/bin/codegraph.d.ts +26 -0
- package/dist/bin/command-supervision.d.ts +12 -0
- package/dist/bin/fatal-handler.d.ts +20 -0
- package/dist/bin/node-version-check.d.ts +37 -0
- package/dist/bin/uninstall.d.ts +14 -0
- package/dist/context/formatter.d.ts +30 -0
- package/dist/context/index.d.ts +119 -0
- package/dist/context/markers.d.ts +19 -0
- package/dist/db/index.d.ts +122 -0
- package/dist/db/migrations.d.ts +44 -0
- package/dist/db/queries.d.ts +402 -0
- package/dist/db/sqlite-adapter.d.ts +53 -0
- package/dist/directory.d.ts +179 -0
- package/dist/errors.d.ts +136 -0
- package/dist/extraction/astro-extractor.d.ts +79 -0
- package/dist/extraction/dfm-extractor.d.ts +31 -0
- package/dist/extraction/extraction-version.d.ts +25 -0
- package/dist/extraction/function-ref.d.ts +118 -0
- package/dist/extraction/generated-detection.d.ts +30 -0
- package/dist/extraction/grammars.d.ts +128 -0
- package/dist/extraction/index.d.ts +187 -0
- package/dist/extraction/languages/c-cpp.d.ts +12 -0
- package/dist/extraction/languages/csharp.d.ts +25 -0
- package/dist/extraction/languages/dart.d.ts +3 -0
- package/dist/extraction/languages/go.d.ts +3 -0
- package/dist/extraction/languages/index.d.ts +10 -0
- package/dist/extraction/languages/java.d.ts +3 -0
- package/dist/extraction/languages/javascript.d.ts +3 -0
- package/dist/extraction/languages/kotlin.d.ts +3 -0
- package/dist/extraction/languages/lua.d.ts +3 -0
- package/dist/extraction/languages/luau.d.ts +3 -0
- package/dist/extraction/languages/objc.d.ts +3 -0
- package/dist/extraction/languages/pascal.d.ts +3 -0
- package/dist/extraction/languages/php.d.ts +3 -0
- package/dist/extraction/languages/python.d.ts +3 -0
- package/dist/extraction/languages/r.d.ts +3 -0
- package/dist/extraction/languages/ruby.d.ts +3 -0
- package/dist/extraction/languages/rust.d.ts +3 -0
- package/dist/extraction/languages/scala.d.ts +3 -0
- package/dist/extraction/languages/swift.d.ts +3 -0
- package/dist/extraction/languages/typescript.d.ts +16 -0
- package/dist/extraction/liquid-extractor.d.ts +59 -0
- package/dist/extraction/mybatis-extractor.d.ts +48 -0
- package/dist/extraction/parse-pool.d.ts +126 -0
- package/dist/extraction/parse-worker.d.ts +8 -0
- package/dist/extraction/razor-extractor.d.ts +42 -0
- package/dist/extraction/sql-query-extractor.d.ts +25 -0
- package/dist/extraction/svelte-extractor.d.ts +56 -0
- package/dist/extraction/tree-sitter-helpers.d.ts +28 -0
- package/dist/extraction/tree-sitter-types.d.ts +239 -0
- package/dist/extraction/tree-sitter.d.ts +647 -0
- package/dist/extraction/vba-extractor.d.ts +394 -0
- package/dist/extraction/vba-form-extractor.d.ts +89 -0
- package/dist/extraction/vba-preprocess.d.ts +81 -0
- package/dist/extraction/vue-extractor.d.ts +51 -0
- package/dist/extraction/wasm-runtime-flags.d.ts +38 -0
- package/dist/graph/index.d.ts +8 -0
- package/dist/graph/queries.d.ts +106 -0
- package/dist/graph/traversal.d.ts +127 -0
- package/dist/index.d.ts +563 -0
- package/dist/installer/config-writer.d.ts +28 -0
- package/dist/installer/index.d.ts +100 -0
- package/dist/installer/instructions-template.d.ts +41 -0
- package/dist/installer/targets/antigravity.d.ts +57 -0
- package/dist/installer/targets/claude.d.ts +62 -0
- package/dist/installer/targets/codex.d.ts +18 -0
- package/dist/installer/targets/cursor.d.ts +35 -0
- package/dist/installer/targets/gemini.d.ts +26 -0
- package/dist/installer/targets/hermes.d.ts +18 -0
- package/dist/installer/targets/kiro.d.ts +27 -0
- package/dist/installer/targets/opencode.d.ts +38 -0
- package/dist/installer/targets/registry.d.ts +35 -0
- package/dist/installer/targets/shared.d.ts +101 -0
- package/dist/installer/targets/toml.d.ts +52 -0
- package/dist/installer/targets/types.d.ts +108 -0
- package/dist/mcp/daemon-manager.d.ts +42 -0
- package/dist/mcp/daemon-paths.d.ts +73 -0
- package/dist/mcp/daemon-registry.d.ts +47 -0
- package/dist/mcp/daemon.d.ts +258 -0
- package/dist/mcp/dynamic-boundaries.d.ts +41 -0
- package/dist/mcp/engine.d.ts +122 -0
- package/dist/mcp/index.d.ts +113 -0
- package/dist/mcp/liveness-watchdog.d.ts +18 -0
- package/dist/mcp/ppid-watchdog.d.ts +62 -0
- package/dist/mcp/proxy.d.ts +87 -0
- package/dist/mcp/query-pool.d.ts +94 -0
- package/dist/mcp/query-worker.d.ts +24 -0
- package/dist/mcp/server-instructions.d.ts +34 -0
- package/dist/mcp/session.d.ts +79 -0
- package/dist/mcp/stdin-teardown.d.ts +27 -0
- package/dist/mcp/tools.d.ts +591 -0
- package/dist/mcp/transport.d.ts +188 -0
- package/dist/mcp/version.d.ts +19 -0
- package/dist/project-config.d.ts +56 -0
- package/dist/reasoning/config.d.ts +45 -0
- package/dist/reasoning/credentials.d.ts +5 -0
- package/dist/reasoning/login.d.ts +21 -0
- package/dist/reasoning/reasoner.d.ts +43 -0
- package/dist/resolution/c-fnptr-synthesizer.d.ts +5 -0
- package/dist/resolution/callback-synthesizer.d.ts +15 -0
- package/dist/resolution/frameworks/astro.d.ts +9 -0
- package/dist/resolution/frameworks/cargo-workspace.d.ts +18 -0
- package/dist/resolution/frameworks/csharp.d.ts +8 -0
- package/dist/resolution/frameworks/drupal.d.ts +51 -0
- package/dist/resolution/frameworks/expo-modules.d.ts +3 -0
- package/dist/resolution/frameworks/express.d.ts +8 -0
- package/dist/resolution/frameworks/fabric.d.ts +3 -0
- package/dist/resolution/frameworks/go.d.ts +8 -0
- package/dist/resolution/frameworks/goframe.d.ts +41 -0
- package/dist/resolution/frameworks/index.d.ts +50 -0
- package/dist/resolution/frameworks/java.d.ts +8 -0
- package/dist/resolution/frameworks/laravel.d.ts +13 -0
- package/dist/resolution/frameworks/nestjs.d.ts +26 -0
- package/dist/resolution/frameworks/play.d.ts +19 -0
- package/dist/resolution/frameworks/python.d.ts +10 -0
- package/dist/resolution/frameworks/react-native.d.ts +3 -0
- package/dist/resolution/frameworks/react.d.ts +8 -0
- package/dist/resolution/frameworks/ruby.d.ts +8 -0
- package/dist/resolution/frameworks/rust.d.ts +8 -0
- package/dist/resolution/frameworks/svelte.d.ts +9 -0
- package/dist/resolution/frameworks/swift-objc.d.ts +37 -0
- package/dist/resolution/frameworks/swift.d.ts +10 -0
- package/dist/resolution/frameworks/vue.d.ts +9 -0
- package/dist/resolution/go-module.d.ts +26 -0
- package/dist/resolution/goframe-synthesizer.d.ts +28 -0
- package/dist/resolution/import-resolver.d.ts +78 -0
- package/dist/resolution/index.d.ts +196 -0
- package/dist/resolution/lru-cache.d.ts +24 -0
- package/dist/resolution/name-matcher.d.ts +93 -0
- package/dist/resolution/path-aliases.d.ts +68 -0
- package/dist/resolution/strip-comments.d.ts +27 -0
- package/dist/resolution/swift-objc-bridge.d.ts +134 -0
- package/dist/resolution/types.d.ts +233 -0
- package/dist/resolution/workspace-packages.d.ts +48 -0
- package/dist/search/query-parser.d.ts +57 -0
- package/dist/search/query-utils.d.ts +87 -0
- package/dist/sync/git-hooks.d.ts +45 -0
- package/dist/sync/index.d.ts +19 -0
- package/dist/sync/watch-policy.d.ts +48 -0
- package/dist/sync/watcher.d.ts +358 -0
- package/dist/sync/worktree.d.ts +54 -0
- package/dist/telemetry/index.d.ts +143 -0
- package/dist/types.d.ts +409 -0
- package/dist/ui/glyphs.d.ts +42 -0
- package/dist/ui/shimmer-progress.d.ts +11 -0
- package/dist/ui/shimmer-worker.d.ts +2 -0
- package/dist/ui/types.d.ts +17 -0
- package/dist/upgrade/index.d.ts +132 -0
- package/dist/utils.d.ts +224 -0
- package/npm-sdk.js +75 -0
- package/npm-shim.js +246 -0
- package/package.json +32 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Sync Hooks
|
|
3
|
+
*
|
|
4
|
+
* When the live file watcher is disabled (e.g. on WSL2 `/mnt/*` drives,
|
|
5
|
+
* see watch-policy.ts), the CodeGraph index would otherwise go stale until
|
|
6
|
+
* the user runs `codegraph sync` by hand. As an opt-in alternative, we can
|
|
7
|
+
* install git hooks that refresh the index after the operations that change
|
|
8
|
+
* files on disk: commit, merge (covers `git pull`), and checkout.
|
|
9
|
+
*
|
|
10
|
+
* The hooks run `codegraph sync` in the background so they never block git,
|
|
11
|
+
* and are guarded by `command -v codegraph` so they no-op cleanly when the
|
|
12
|
+
* CLI isn't on PATH. Our snippet is delimited by marker comments so install
|
|
13
|
+
* is idempotent and removal preserves any user-authored hook content.
|
|
14
|
+
*/
|
|
15
|
+
export type GitHookName = 'post-commit' | 'post-merge' | 'post-checkout';
|
|
16
|
+
/** Hooks installed by default: commit, merge (git pull), and checkout. */
|
|
17
|
+
export declare const DEFAULT_SYNC_HOOKS: GitHookName[];
|
|
18
|
+
export interface GitHookResult {
|
|
19
|
+
/** Hook names that were created or updated. */
|
|
20
|
+
installed: GitHookName[];
|
|
21
|
+
/** Resolved hooks directory, or null when not a git repo. */
|
|
22
|
+
hooksDir: string | null;
|
|
23
|
+
/** Reason nothing happened (e.g. not a git repository). */
|
|
24
|
+
skipped?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Whether `projectRoot` is inside a git working tree. Returns false if git
|
|
28
|
+
* isn't installed or the path isn't a repo.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isGitRepo(projectRoot: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Install (or update) the CodeGraph sync hooks in a git repository.
|
|
33
|
+
* Idempotent: re-running replaces our marker block rather than duplicating
|
|
34
|
+
* it, and any user-authored hook content is preserved.
|
|
35
|
+
*/
|
|
36
|
+
export declare function installGitSyncHook(projectRoot: string, hooks?: GitHookName[]): GitHookResult;
|
|
37
|
+
/**
|
|
38
|
+
* Remove the CodeGraph sync hooks. Strips only our marker block; deletes the
|
|
39
|
+
* hook file entirely when nothing but a shebang remains, otherwise rewrites
|
|
40
|
+
* the user's content untouched.
|
|
41
|
+
*/
|
|
42
|
+
export declare function removeGitSyncHook(projectRoot: string, hooks?: GitHookName[]): GitHookResult;
|
|
43
|
+
/** Whether any CodeGraph sync hook is currently installed. */
|
|
44
|
+
export declare function isSyncHookInstalled(projectRoot: string, hooks?: GitHookName[]): boolean;
|
|
45
|
+
//# sourceMappingURL=git-hooks.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync Module
|
|
3
|
+
*
|
|
4
|
+
* Provides synchronization functionality for keeping the code graph
|
|
5
|
+
* up-to-date with file system changes.
|
|
6
|
+
*
|
|
7
|
+
* Components:
|
|
8
|
+
* - FileWatcher: Debounced fs.watch that auto-triggers sync on file changes
|
|
9
|
+
* - Watch policy: decides when the watcher must be disabled (e.g. WSL2 /mnt)
|
|
10
|
+
* - Git sync hooks: opt-in commit/merge/checkout hooks when watching is off
|
|
11
|
+
* - Git worktree awareness: detect when a query borrows another tree's index
|
|
12
|
+
* - Content hashing for change detection (in extraction module)
|
|
13
|
+
* - Incremental reindexing (in extraction module)
|
|
14
|
+
*/
|
|
15
|
+
export { FileWatcher, WatchOptions, PendingFile, LockUnavailableError } from './watcher';
|
|
16
|
+
export { watchDisabledReason, detectWsl } from './watch-policy';
|
|
17
|
+
export { installGitSyncHook, removeGitSyncHook, isSyncHookInstalled, isGitRepo, DEFAULT_SYNC_HOOKS, type GitHookName, type GitHookResult, } from './git-hooks';
|
|
18
|
+
export { gitWorktreeRoot, detectWorktreeIndexMismatch, worktreeMismatchWarning, worktreeMismatchNotice, type WorktreeIndexMismatch, } from './worktree';
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Watch Policy
|
|
3
|
+
*
|
|
4
|
+
* Decides whether the live file watcher should run for a given project.
|
|
5
|
+
*
|
|
6
|
+
* Native recursive `fs.watch` is pathologically slow on WSL2 `/mnt/*`
|
|
7
|
+
* drives (NTFS exposed over the 9p/drvfs bridge): setting up the recursive
|
|
8
|
+
* watch walks the directory tree, and every readdir/stat crosses the
|
|
9
|
+
* Windows boundary. Inside an MCP server this stalls the event loop during
|
|
10
|
+
* startup long enough to blow past host handshake timeouts (opencode's 30s),
|
|
11
|
+
* so the tools never appear. See issue #199.
|
|
12
|
+
*
|
|
13
|
+
* This module centralizes the on/off decision so the watcher, the MCP
|
|
14
|
+
* server (for diagnostics), and the installer all agree.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Detect whether the current process is running under WSL (Windows
|
|
18
|
+
* Subsystem for Linux). Result is cached after the first call.
|
|
19
|
+
*
|
|
20
|
+
* Checks the WSL-specific env vars first (no I/O), then falls back to
|
|
21
|
+
* `/proc/version`, which contains "microsoft" on WSL kernels.
|
|
22
|
+
*/
|
|
23
|
+
export declare function detectWsl(): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Inputs that can be overridden in tests so the decision is deterministic
|
|
26
|
+
* without touching real env vars or `/proc/version`.
|
|
27
|
+
*/
|
|
28
|
+
export interface WatchProbe {
|
|
29
|
+
/** Defaults to `process.env`. */
|
|
30
|
+
env?: NodeJS.ProcessEnv;
|
|
31
|
+
/** Defaults to `detectWsl()`. */
|
|
32
|
+
isWsl?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Decide whether the file watcher should be disabled for a project, and why.
|
|
36
|
+
*
|
|
37
|
+
* Returns a short human-readable reason when watching should be skipped, or
|
|
38
|
+
* `null` when it should run normally.
|
|
39
|
+
*
|
|
40
|
+
* Precedence (first match wins):
|
|
41
|
+
* 1. `CODEGRAPH_NO_WATCH=1` → off (explicit opt-out always wins)
|
|
42
|
+
* 2. `CODEGRAPH_FORCE_WATCH=1` → on (overrides auto-detection)
|
|
43
|
+
* 3. WSL2 + `/mnt/*` drive → off (recursive fs.watch is too slow; #199)
|
|
44
|
+
*/
|
|
45
|
+
export declare function watchDisabledReason(projectRoot: string, probe?: WatchProbe): string | null;
|
|
46
|
+
/** Test-only: reset the cached WSL detection. */
|
|
47
|
+
export declare function __resetWslCacheForTests(): void;
|
|
48
|
+
//# sourceMappingURL=watch-policy.d.ts.map
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Watcher
|
|
3
|
+
*
|
|
4
|
+
* Watches the project directory for file changes and triggers debounced sync
|
|
5
|
+
* operations to keep the code graph up-to-date.
|
|
6
|
+
*
|
|
7
|
+
* Uses Node's built-in `fs.watch` directly (no third-party watcher, no native
|
|
8
|
+
* addon) with a per-platform strategy chosen to keep the open-descriptor /
|
|
9
|
+
* kernel-watch cost BOUNDED rather than growing with the number of files:
|
|
10
|
+
*
|
|
11
|
+
* - macOS / Windows: a SINGLE recursive `fs.watch(root, {recursive:true})`.
|
|
12
|
+
* libuv maps this to one FSEvents stream (macOS) / one
|
|
13
|
+
* ReadDirectoryChangesW handle (Windows), so it costs O(1) descriptors no
|
|
14
|
+
* matter how large the tree. This is the fix for the macOS file-table
|
|
15
|
+
* exhaustion (#644 / #496 / #555 / #628): the previous watcher held one
|
|
16
|
+
* open fd PER WATCHED FILE on macOS (tens of thousands of REG fds), which
|
|
17
|
+
* exhausted `kern.maxfiles` and crashed unrelated processes system-wide.
|
|
18
|
+
*
|
|
19
|
+
* - Linux: recursive `fs.watch` is unsupported, so we watch each (non-ignored)
|
|
20
|
+
* DIRECTORY with one inotify watch — O(directories), NOT O(files). New
|
|
21
|
+
* directories are picked up dynamically and an overall watch cap bounds
|
|
22
|
+
* inotify usage on pathological monorepos (#579). A single inotify watch on
|
|
23
|
+
* a directory already reports create/modify/delete for its children, so
|
|
24
|
+
* per-file watches are never needed.
|
|
25
|
+
*
|
|
26
|
+
* Excluded trees (node_modules/, dist/, .git/, …) are filtered via the
|
|
27
|
+
* indexer's `buildScopeIgnore` (built-in default-ignore dirs + the project's
|
|
28
|
+
* .gitignore) — on Linux they're never descended into (so they cost no watch),
|
|
29
|
+
* and on macOS/Windows the single recursive stream still covers them but their
|
|
30
|
+
* events are dropped before any sync is scheduled. Either way the watcher's
|
|
31
|
+
* scope matches the indexer's (#276 / #407).
|
|
32
|
+
*/
|
|
33
|
+
import * as fs from 'fs';
|
|
34
|
+
/**
|
|
35
|
+
* Indirection over `fs.watch` so tests can inject a fake that throws or emits
|
|
36
|
+
* `EMFILE`/`ENFILE` deterministically (real watch-resource exhaustion can't be
|
|
37
|
+
* provoked reliably, and `fs.watch` is a non-configurable property so it can't
|
|
38
|
+
* be spied). Production always uses the real `fs.watch`.
|
|
39
|
+
*/
|
|
40
|
+
type WatchFn = typeof fs.watch;
|
|
41
|
+
/** @internal Test-only seam to inject a fake fs.watch implementation. */
|
|
42
|
+
export declare function __setFsWatchForTests(fn: WatchFn | null): void;
|
|
43
|
+
/**
|
|
44
|
+
* Options for the file watcher
|
|
45
|
+
*/
|
|
46
|
+
export interface WatchOptions {
|
|
47
|
+
/**
|
|
48
|
+
* Debounce delay in milliseconds.
|
|
49
|
+
* After the last file change, wait this long before triggering sync.
|
|
50
|
+
* Default: 2000ms
|
|
51
|
+
*/
|
|
52
|
+
debounceMs?: number;
|
|
53
|
+
/**
|
|
54
|
+
* Callback when a sync completes (for logging/diagnostics).
|
|
55
|
+
*/
|
|
56
|
+
onSyncComplete?: (result: {
|
|
57
|
+
filesChanged: number;
|
|
58
|
+
durationMs: number;
|
|
59
|
+
}) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Callback when a sync errors (for logging/diagnostics).
|
|
62
|
+
*/
|
|
63
|
+
onSyncError?: (error: Error) => void;
|
|
64
|
+
/**
|
|
65
|
+
* Callback fired ONCE when live watching degrades permanently and auto-sync
|
|
66
|
+
* is disabled — OS watch-resource exhaustion (EMFILE/ENFILE), or a write lock
|
|
67
|
+
* held past the retry budget. The string is an actionable, human-readable
|
|
68
|
+
* reason. Lets a host (MCP server, daemon, CLI) tell the user that the index
|
|
69
|
+
* will no longer auto-update instead of silently serving stale results.
|
|
70
|
+
*/
|
|
71
|
+
onDegraded?: (reason: string) => void;
|
|
72
|
+
/**
|
|
73
|
+
* Test-only. When true, `start()` installs NO OS-level fs.watch — the
|
|
74
|
+
* watcher is "inert" and only the {@link __emitWatchEventForTests} /
|
|
75
|
+
* {@link FileWatcher.ingestEventForTests} seam drives its pipeline. This
|
|
76
|
+
* restores the deterministic, OS-free behavior the unit tests need (real
|
|
77
|
+
* FSEvents/inotify delivery races under parallel vitest). Production never
|
|
78
|
+
* sets it.
|
|
79
|
+
*/
|
|
80
|
+
inertForTests?: boolean;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Thrown by a `syncFn` to signal that the underlying sync couldn't acquire
|
|
84
|
+
* the cross-process write lock (#449). The watcher treats this as "no
|
|
85
|
+
* progress" — preserves `pendingFiles`, skips `onSyncComplete`, and the
|
|
86
|
+
* `finally` block reschedules. Quiet (debug-only) because a long-running
|
|
87
|
+
* external indexer can hit this every debounce cycle.
|
|
88
|
+
*/
|
|
89
|
+
export declare class LockUnavailableError extends Error {
|
|
90
|
+
constructor(message?: string);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Per-file pending entry — tracks a source file the watcher saw an event for
|
|
94
|
+
* but hasn't yet synced into the index. Exposed via {@link FileWatcher.getPendingFiles}
|
|
95
|
+
* so MCP tool responses can mark stale results without forcing a wait.
|
|
96
|
+
*/
|
|
97
|
+
export interface PendingFile {
|
|
98
|
+
/** Project-relative POSIX path (e.g. "src/foo.ts"). */
|
|
99
|
+
path: string;
|
|
100
|
+
/** Wall-clock ms at the first event we saw for this path since the last sync. */
|
|
101
|
+
firstSeenMs: number;
|
|
102
|
+
/** Wall-clock ms at the most recent event we saw for this path. */
|
|
103
|
+
lastSeenMs: number;
|
|
104
|
+
/**
|
|
105
|
+
* True when a sync is currently in flight that began AFTER this file's most
|
|
106
|
+
* recent event — i.e. the next successful sync will pick it up. False when
|
|
107
|
+
* the file is still in the debounce window (no sync running yet).
|
|
108
|
+
*/
|
|
109
|
+
indexing: boolean;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* FileWatcher monitors a project directory for changes and triggers
|
|
113
|
+
* debounced sync operations via a provided callback.
|
|
114
|
+
*
|
|
115
|
+
* Design goals:
|
|
116
|
+
* - Bounded resource usage: O(1) descriptors on macOS/Windows (one recursive
|
|
117
|
+
* watch), O(directories) inotify watches on Linux — never O(files), which
|
|
118
|
+
* was the system-crashing fd leak on macOS (#644/#496/#555/#628).
|
|
119
|
+
* - Debounced to avoid thrashing on rapid saves
|
|
120
|
+
* - Filters to supported source files by extension
|
|
121
|
+
* - Ignores .codegraph/ and .git/ regardless of .gitignore
|
|
122
|
+
* - Tracks per-file pending state so MCP tools can flag stale results
|
|
123
|
+
* without blocking on a sync (issue #403)
|
|
124
|
+
*/
|
|
125
|
+
export declare class FileWatcher {
|
|
126
|
+
/** macOS/Windows: the single recursive watcher. Null on Linux. */
|
|
127
|
+
private recursiveWatcher;
|
|
128
|
+
/** Linux: one watcher per watched directory (keyed by absolute path). */
|
|
129
|
+
private dirWatchers;
|
|
130
|
+
/** Set once the per-directory watch cap is hit, so we log only once. */
|
|
131
|
+
private dirCapWarned;
|
|
132
|
+
/**
|
|
133
|
+
* Set once the Linux inotify watch limit (ENOSPC) is hit. Double duty: we
|
|
134
|
+
* warn only once, AND we stop attempting new directory watches for the rest
|
|
135
|
+
* of the session — once the kernel budget is exhausted every further
|
|
136
|
+
* `inotify_add_watch` fails too, so trying the rest of the tree is pure
|
|
137
|
+
* waste. NON-fatal (does not degrade): installed watches keep working.
|
|
138
|
+
*/
|
|
139
|
+
private inotifyLimitWarned;
|
|
140
|
+
/**
|
|
141
|
+
* One-way latch: the reason live watching was permanently disabled at runtime
|
|
142
|
+
* (watch-resource exhaustion, or lock contention past the retry budget), or
|
|
143
|
+
* null while healthy. Set by {@link degrade}; cleared only by a fresh start().
|
|
144
|
+
*/
|
|
145
|
+
private degradedReason;
|
|
146
|
+
/** Consecutive lock-contention retries for watcher-triggered syncs. */
|
|
147
|
+
private lockRetryCount;
|
|
148
|
+
/** Test-only inert mode: started, but with no OS watcher installed. */
|
|
149
|
+
private inert;
|
|
150
|
+
private debounceTimer;
|
|
151
|
+
/**
|
|
152
|
+
* Files seen by the watcher since the last successful sync — populated on
|
|
153
|
+
* every change event, cleared at the start of a sync, and re-populated by
|
|
154
|
+
* events that arrive mid-sync (or restored on sync failure). Keyed by the
|
|
155
|
+
* same project-relative POSIX path the rest of the codebase uses, so a
|
|
156
|
+
* caller can intersect tool-response file paths against this map cheaply.
|
|
157
|
+
*/
|
|
158
|
+
private pendingFiles;
|
|
159
|
+
/**
|
|
160
|
+
* Wall-clock ms at which the in-flight sync began. Combined with
|
|
161
|
+
* {@link pendingFiles}'s `lastSeenMs`, this distinguishes "still in the
|
|
162
|
+
* debounce window" (lastSeen > syncStarted, sync hasn't started yet for
|
|
163
|
+
* this edit) from "currently being indexed" (lastSeen <= syncStarted).
|
|
164
|
+
*/
|
|
165
|
+
private syncStartedMs;
|
|
166
|
+
private syncing;
|
|
167
|
+
private stopped;
|
|
168
|
+
/**
|
|
169
|
+
* True once the initial watch set is established. Unlike the previous
|
|
170
|
+
* chokidar implementation there is no asynchronous initial "crawl" emitting
|
|
171
|
+
* an `add` per existing file — `fs.watch` only reports changes from the
|
|
172
|
+
* moment it's installed — so this flips to true synchronously at the end of
|
|
173
|
+
* `start()`. The startup reconcile against on-disk state is handled
|
|
174
|
+
* separately by the engine's catch-up sync, not by the watcher.
|
|
175
|
+
*/
|
|
176
|
+
private ready;
|
|
177
|
+
/**
|
|
178
|
+
* Callbacks that resolve when the watch set is established. Used by tests
|
|
179
|
+
* (and any production caller that cares about a clean baseline) to
|
|
180
|
+
* deterministically gate on watcher readiness.
|
|
181
|
+
*/
|
|
182
|
+
private readyWaiters;
|
|
183
|
+
private ignoreMatcher;
|
|
184
|
+
private readonly projectRoot;
|
|
185
|
+
private readonly debounceMs;
|
|
186
|
+
private readonly syncFn;
|
|
187
|
+
private readonly onSyncComplete?;
|
|
188
|
+
private readonly onSyncError?;
|
|
189
|
+
private readonly onDegraded?;
|
|
190
|
+
private readonly inertForTests;
|
|
191
|
+
constructor(projectRoot: string, syncFn: () => Promise<{
|
|
192
|
+
filesChanged: number;
|
|
193
|
+
durationMs: number;
|
|
194
|
+
}>, options?: WatchOptions);
|
|
195
|
+
/**
|
|
196
|
+
* Start watching for file changes.
|
|
197
|
+
* Returns true if watching started successfully, false otherwise.
|
|
198
|
+
*/
|
|
199
|
+
start(): boolean;
|
|
200
|
+
/**
|
|
201
|
+
* macOS/Windows: one recursive watcher for the whole tree. O(1) descriptors.
|
|
202
|
+
* `filename` arrives relative to the project root (with subdirectories), so
|
|
203
|
+
* it maps straight to a project-relative path.
|
|
204
|
+
*/
|
|
205
|
+
private startRecursive;
|
|
206
|
+
/**
|
|
207
|
+
* Linux: walk the (non-ignored) tree and watch each directory. One inotify
|
|
208
|
+
* watch per directory reports create/modify/delete for that directory's
|
|
209
|
+
* direct children, so we never watch individual files.
|
|
210
|
+
*/
|
|
211
|
+
private startPerDirectory;
|
|
212
|
+
/**
|
|
213
|
+
* Add an inotify watch for `dir` and recurse into its non-ignored
|
|
214
|
+
* subdirectories. When `markExisting` is true (a directory that appeared
|
|
215
|
+
* AFTER startup), the source files already inside it are recorded as pending
|
|
216
|
+
* — this closes the `mkdir + write` race where files created before the new
|
|
217
|
+
* directory's watch is installed would otherwise be missed until the next
|
|
218
|
+
* full sync. The initial startup walk passes false (the engine's catch-up
|
|
219
|
+
* sync owns the baseline).
|
|
220
|
+
*/
|
|
221
|
+
private watchTree;
|
|
222
|
+
/**
|
|
223
|
+
* Linux per-directory event handler. `filename` is relative to `dir`. A new
|
|
224
|
+
* sub-directory is picked up by extending the watch tree; everything else is
|
|
225
|
+
* routed through the shared change handler.
|
|
226
|
+
*/
|
|
227
|
+
private handleDirEvent;
|
|
228
|
+
/**
|
|
229
|
+
* True when `rel` is a Dysflow saved-query `.sql` file — i.e. a `.sql` whose
|
|
230
|
+
* directory also contains a `queries.json` manifest. This mirrors the
|
|
231
|
+
* directory-discovery gate so incremental edits to a query file are picked
|
|
232
|
+
* up, while ordinary `.sql` files (no sibling manifest) are ignored exactly
|
|
233
|
+
* as they are during a full index.
|
|
234
|
+
*/
|
|
235
|
+
private isDysflowQuerySql;
|
|
236
|
+
/**
|
|
237
|
+
* Shared change handler for both watch strategies. `rel` is a
|
|
238
|
+
* project-relative POSIX path. Applies the ignore + source-file filters and,
|
|
239
|
+
* for a real source change, records it as pending (#403) and schedules a
|
|
240
|
+
* debounced sync.
|
|
241
|
+
*
|
|
242
|
+
* The recursive (macOS/Windows) watcher reports events for ignored trees too
|
|
243
|
+
* (one stream covers the whole repo), so the ignore check here is load-bearing
|
|
244
|
+
* — it drops node_modules/dist/.git churn before any sync is scheduled.
|
|
245
|
+
*/
|
|
246
|
+
private handleChange;
|
|
247
|
+
/** Close and forget the watch for a directory that errored/was removed. */
|
|
248
|
+
private unwatchDir;
|
|
249
|
+
/** Our own dirs are always ignored, regardless of .gitignore. */
|
|
250
|
+
private isAlwaysIgnored;
|
|
251
|
+
/**
|
|
252
|
+
* True for any directory that should NOT be watched (used while building the
|
|
253
|
+
* Linux per-directory watch tree). Tests the directory form of the path so a
|
|
254
|
+
* dir-only ignore rule like `build/` matches.
|
|
255
|
+
*/
|
|
256
|
+
private shouldIgnoreDir;
|
|
257
|
+
/**
|
|
258
|
+
* Permanently disable live watching after a terminal runtime failure
|
|
259
|
+
* (watch-resource exhaustion, or lock contention past the retry budget).
|
|
260
|
+
* Idempotent: logs one actionable warning, fires {@link WatchOptions.onDegraded}
|
|
261
|
+
* once, and stops the watcher. A subsequent start() clears the latch.
|
|
262
|
+
*/
|
|
263
|
+
private degrade;
|
|
264
|
+
/**
|
|
265
|
+
* Warn ONCE that the Linux inotify watch budget is exhausted (ENOSPC), and
|
|
266
|
+
* stop adding new watches for the rest of this session — every further
|
|
267
|
+
* `inotify_add_watch` would fail too, so walking the rest of the tree is
|
|
268
|
+
* waste. Unlike {@link degrade} this is NON-fatal: the watches already
|
|
269
|
+
* installed keep firing, and `codegraph sync` covers the unwatched remainder.
|
|
270
|
+
* The message names the kernel knob to raise (`fs.inotify.max_user_watches`).
|
|
271
|
+
*/
|
|
272
|
+
private warnInotifyLimit;
|
|
273
|
+
/**
|
|
274
|
+
* Whether live watching has degraded permanently (until the next start()).
|
|
275
|
+
* Distinct from {@link isActive}: a degraded watcher is inactive, but an
|
|
276
|
+
* inactive watcher is not necessarily degraded (it may simply be stopped or
|
|
277
|
+
* never started). Hosts use this to tell the user auto-sync is off.
|
|
278
|
+
*/
|
|
279
|
+
isDegraded(): boolean;
|
|
280
|
+
/** The reason live watching degraded, or null if it is healthy. */
|
|
281
|
+
getDegradedReason(): string | null;
|
|
282
|
+
/**
|
|
283
|
+
* Stop watching for file changes.
|
|
284
|
+
*/
|
|
285
|
+
stop(): void;
|
|
286
|
+
/**
|
|
287
|
+
* @internal Test-only: feed a synthetic project-relative change through the
|
|
288
|
+
* same filter → pendingFiles → debounced-sync path a real fs.watch event
|
|
289
|
+
* takes. Lets the watcher / staleness-banner suites stay deterministic
|
|
290
|
+
* instead of racing on OS watch-delivery latency. See
|
|
291
|
+
* {@link __emitWatchEventForTests}.
|
|
292
|
+
*/
|
|
293
|
+
ingestEventForTests(relPath: string): void;
|
|
294
|
+
/**
|
|
295
|
+
* Whether the watcher is currently active.
|
|
296
|
+
*/
|
|
297
|
+
isActive(): boolean;
|
|
298
|
+
/**
|
|
299
|
+
* Resolves once the watch set has been installed (or immediately if it
|
|
300
|
+
* already has). Useful for tests that need a deterministic boundary before
|
|
301
|
+
* asserting on `pendingFiles`.
|
|
302
|
+
*
|
|
303
|
+
* Production callers don't need this: `pendingFiles` is read continuously,
|
|
304
|
+
* the staleness banner is always correct (empty or populated), and there is
|
|
305
|
+
* no asynchronous initial-scan window with `fs.watch`.
|
|
306
|
+
*/
|
|
307
|
+
waitUntilReady(timeoutMs?: number): Promise<void>;
|
|
308
|
+
/**
|
|
309
|
+
* Schedule a normal debounced sync after a source edit.
|
|
310
|
+
*/
|
|
311
|
+
private scheduleSync;
|
|
312
|
+
/**
|
|
313
|
+
* Schedule a retry after a recoverable sync failure (lock contention). Kept
|
|
314
|
+
* separate from {@link scheduleSync} so prolonged contention backs off
|
|
315
|
+
* exponentially instead of hammering the lock every debounce cycle.
|
|
316
|
+
*/
|
|
317
|
+
private scheduleRetrySync;
|
|
318
|
+
/**
|
|
319
|
+
* Flush pending changes by running sync.
|
|
320
|
+
*
|
|
321
|
+
* pendingFiles is NOT cleared at the start of sync — entries are removed
|
|
322
|
+
* only after sync commits successfully, and only for entries whose
|
|
323
|
+
* lastSeenMs <= syncStartedMs. That way, a query that arrives mid-sync
|
|
324
|
+
* still sees the affected files marked stale (the DB hasn't been updated
|
|
325
|
+
* yet), and an event that lands mid-sync persists into the follow-up.
|
|
326
|
+
*
|
|
327
|
+
* On sync failure pendingFiles is left untouched — every edit is still
|
|
328
|
+
* unindexed, and the rescheduled sync will absorb the same set next time.
|
|
329
|
+
*/
|
|
330
|
+
private flush;
|
|
331
|
+
/**
|
|
332
|
+
* Snapshot of files seen by the watcher since the last successful sync.
|
|
333
|
+
*
|
|
334
|
+
* Used by MCP tool responses to mark stale results without blocking on a
|
|
335
|
+
* sync: a tool that returns a hit in `src/foo.ts` while `src/foo.ts` is in
|
|
336
|
+
* this list tells the agent "Read this file directly, the index lags."
|
|
337
|
+
*
|
|
338
|
+
* `indexing` is true when a sync is currently in flight whose start time is
|
|
339
|
+
* AFTER this file's most recent event — i.e. that sync will absorb the
|
|
340
|
+
* edit. False means the file is still inside the debounce window and no
|
|
341
|
+
* sync has started yet (a follow-up call a few hundred ms later may show
|
|
342
|
+
* `indexing: true` or the file may have left the list entirely).
|
|
343
|
+
*
|
|
344
|
+
* Cheap: O(pendingFiles.size), no I/O, no locks.
|
|
345
|
+
*/
|
|
346
|
+
getPendingFiles(): PendingFile[];
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Test-only: synthesize a source-file change for the live watcher running at
|
|
350
|
+
* `projectRoot`, exercising the real filter → pendingFiles → debounced-sync
|
|
351
|
+
* logic without depending on fs.watch delivery timing (which races under
|
|
352
|
+
* parallel vitest). `relPath` is project-relative POSIX (e.g. "src/foo.ts").
|
|
353
|
+
* Returns false if no live watcher is registered for that root (e.g. outside a
|
|
354
|
+
* test runtime, where the registry is intentionally not populated).
|
|
355
|
+
*/
|
|
356
|
+
export declare function __emitWatchEventForTests(projectRoot: string, relPath: string): boolean;
|
|
357
|
+
export {};
|
|
358
|
+
//# sourceMappingURL=watcher.d.ts.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Worktree Awareness
|
|
3
|
+
*
|
|
4
|
+
* A CodeGraph index lives in a `.codegraph/` directory and is resolved by
|
|
5
|
+
* walking up parent directories to the nearest one (see
|
|
6
|
+
* `findNearestCodeGraphRoot`). That walk is unaware of git worktrees: when a
|
|
7
|
+
* worktree is created *inside* the main checkout (e.g. some tools place them
|
|
8
|
+
* under `.gitignore`d paths like `.claude/worktrees/<name>/`), a command run
|
|
9
|
+
* from the worktree walks up and silently resolves the MAIN checkout's index.
|
|
10
|
+
*
|
|
11
|
+
* Every query then returns results from the main tree's code — usually a
|
|
12
|
+
* different branch — rather than the worktree the user is actually editing.
|
|
13
|
+
* Symbols added or changed only in the worktree are invisible. This module
|
|
14
|
+
* detects that "borrowed index" situation so callers can warn about it.
|
|
15
|
+
*
|
|
16
|
+
* Detection is best-effort: when git is unavailable or the path isn't a repo,
|
|
17
|
+
* it reports "no mismatch" and callers carry on unchanged.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Absolute, symlink-resolved toplevel of the git working tree that `dir`
|
|
21
|
+
* belongs to, or null when `dir` isn't inside a git repo (or git is missing).
|
|
22
|
+
*
|
|
23
|
+
* `git rev-parse --show-toplevel` returns the per-worktree root: the main
|
|
24
|
+
* checkout and each linked worktree report their own distinct directory, which
|
|
25
|
+
* is exactly the distinction this module relies on.
|
|
26
|
+
*/
|
|
27
|
+
export declare function gitWorktreeRoot(dir: string): string | null;
|
|
28
|
+
export interface WorktreeIndexMismatch {
|
|
29
|
+
/** The git working tree the command was run from. */
|
|
30
|
+
worktreeRoot: string;
|
|
31
|
+
/** The (different) working tree whose `.codegraph` index is being used. */
|
|
32
|
+
indexRoot: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Detect when `startPath` lives in one git working tree but the resolved
|
|
36
|
+
* CodeGraph index (`indexRoot`) belongs to a *different* working tree.
|
|
37
|
+
*
|
|
38
|
+
* Returns null — meaning "nothing to warn about" — when:
|
|
39
|
+
* - `startPath` isn't in a git repo (or git is unavailable),
|
|
40
|
+
* - the index already lives in `startPath`'s own working tree, or
|
|
41
|
+
* - `indexRoot` isn't itself a working-tree root (an unrelated parent dir
|
|
42
|
+
* that merely happens to contain a `.codegraph/`), which keeps non-git
|
|
43
|
+
* and monorepo-subdir layouts from producing false warnings.
|
|
44
|
+
*/
|
|
45
|
+
export declare function detectWorktreeIndexMismatch(startPath: string, indexRoot: string): WorktreeIndexMismatch | null;
|
|
46
|
+
/** One-line-per-fact warning describing a detected mismatch. */
|
|
47
|
+
export declare function worktreeMismatchWarning(m: WorktreeIndexMismatch): string;
|
|
48
|
+
/**
|
|
49
|
+
* Compact, single-line variant for prefixing a tool's result. Read tools
|
|
50
|
+
* return their answer inline, so the heads-up has to ride on the same payload
|
|
51
|
+
* the agent is already reading — a multi-line block would bury the result.
|
|
52
|
+
*/
|
|
53
|
+
export declare function worktreeMismatchNotice(m: WorktreeIndexMismatch): string;
|
|
54
|
+
//# sourceMappingURL=worktree.d.ts.map
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anonymous usage telemetry — client side.
|
|
3
|
+
*
|
|
4
|
+
* The contract for what may be collected lives in docs/design/telemetry.md
|
|
5
|
+
* (and user-facing TELEMETRY.md); the ingest endpoint that enforces it is
|
|
6
|
+
* public at telemetry-worker/. This module honors four invariants:
|
|
7
|
+
*
|
|
8
|
+
* 1. Zero hot-path cost: recording is an in-memory increment. Disk writes are
|
|
9
|
+
* a tiny synchronous append at process exit (works under `process.exit()`,
|
|
10
|
+
* where `beforeExit` never fires); network sends happen opportunistically
|
|
11
|
+
* (startup of long-running commands, daemon interval, bounded await at the
|
|
12
|
+
* end of install/init) and are fire-and-forget everywhere else.
|
|
13
|
+
* 2. Zero stdout: stdio is the MCP protocol channel. Notices and debug output
|
|
14
|
+
* go to stderr only.
|
|
15
|
+
* 3. Off is off: when disabled, nothing is recorded, nothing is sent, and no
|
|
16
|
+
* socket is opened — there is no "opted out" ping. Turning telemetry off
|
|
17
|
+
* also deletes any buffered, unsent data.
|
|
18
|
+
* 4. Fail silent: offline, endpoint down, disk full — every failure mode is
|
|
19
|
+
* silence, never a retry loop, never an error surfaced to the user/agent.
|
|
20
|
+
*
|
|
21
|
+
* Usage counts aggregate locally into per-day rollups; only *completed* (UTC)
|
|
22
|
+
* days are sent, so volume scales with active machines, not with tool calls.
|
|
23
|
+
*/
|
|
24
|
+
export declare const TELEMETRY_ENDPOINT = "https://telemetry.getcodegraph.com/v1/events";
|
|
25
|
+
export declare const TELEMETRY_DOCS = "https://github.com/colbymchenry/codegraph/blob/main/TELEMETRY.md";
|
|
26
|
+
export type UsageKind = 'mcp_tool' | 'cli_command';
|
|
27
|
+
export type LifecycleEvent = 'install' | 'index' | 'uninstall';
|
|
28
|
+
/** Coarse buckets — exact counts are deliberately not collected. */
|
|
29
|
+
export declare function bucketFileCount(n: number): '<100' | '100-1k' | '1k-10k' | '10k+';
|
|
30
|
+
export declare function bucketDuration(ms: number): '<10s' | '10-60s' | '1-5m' | '5m+';
|
|
31
|
+
/**
|
|
32
|
+
* Shared "a full index completed" event (CLI init/index + installer local
|
|
33
|
+
* init): language names and coarse buckets only — never paths, file names,
|
|
34
|
+
* or exact counts. Structurally typed so callers don't need engine imports.
|
|
35
|
+
*/
|
|
36
|
+
export declare function recordIndexEvent(cg: {
|
|
37
|
+
getStats(): {
|
|
38
|
+
filesByLanguage: Record<string, number>;
|
|
39
|
+
};
|
|
40
|
+
}, result: {
|
|
41
|
+
filesIndexed: number;
|
|
42
|
+
durationMs: number;
|
|
43
|
+
}): void;
|
|
44
|
+
export interface ClientInfo {
|
|
45
|
+
name?: string;
|
|
46
|
+
version?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface TelemetryStatus {
|
|
49
|
+
enabled: boolean;
|
|
50
|
+
/** What decided the current state — mirrors the precedence order. */
|
|
51
|
+
decidedBy: 'DO_NOT_TRACK' | 'CODEGRAPH_TELEMETRY' | 'config' | 'default';
|
|
52
|
+
machineId: string | null;
|
|
53
|
+
configPath: string;
|
|
54
|
+
}
|
|
55
|
+
export interface TelemetryOptions {
|
|
56
|
+
/** Global state dir; defaults to ~/.codegraph. Tests inject a temp dir. */
|
|
57
|
+
dir?: string;
|
|
58
|
+
fetchImpl?: typeof globalThis.fetch;
|
|
59
|
+
now?: () => Date;
|
|
60
|
+
env?: NodeJS.ProcessEnv;
|
|
61
|
+
stderr?: (line: string) => void;
|
|
62
|
+
/** Tests opt out so short-lived instances don't pile onto process 'exit'. */
|
|
63
|
+
installExitHook?: boolean;
|
|
64
|
+
}
|
|
65
|
+
export declare class Telemetry {
|
|
66
|
+
private readonly dir;
|
|
67
|
+
private readonly fetchImpl;
|
|
68
|
+
private readonly now;
|
|
69
|
+
private readonly env;
|
|
70
|
+
private readonly writeStderr;
|
|
71
|
+
private counts;
|
|
72
|
+
private events;
|
|
73
|
+
private readonly installExitHook;
|
|
74
|
+
private exitHookInstalled;
|
|
75
|
+
private configCache;
|
|
76
|
+
private intervalHandle;
|
|
77
|
+
constructor(opts?: TelemetryOptions);
|
|
78
|
+
get configPath(): string;
|
|
79
|
+
get queuePath(): string;
|
|
80
|
+
/**
|
|
81
|
+
* Resolution order (first match wins) — keep in sync with TELEMETRY.md:
|
|
82
|
+
* DO_NOT_TRACK=1 > CODEGRAPH_TELEMETRY=0|1 > stored config > default on.
|
|
83
|
+
*/
|
|
84
|
+
getStatus(): TelemetryStatus;
|
|
85
|
+
isEnabled(): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Persist an explicit user choice (installer toggle or `codegraph
|
|
88
|
+
* telemetry on|off`). Turning telemetry off also deletes any buffered,
|
|
89
|
+
* unsent data — off means off.
|
|
90
|
+
*/
|
|
91
|
+
setEnabled(enabled: boolean, source: 'installer' | 'cli'): void;
|
|
92
|
+
/** True once any consent decision (or the first-run notice) is on disk. */
|
|
93
|
+
hasStoredChoice(): boolean;
|
|
94
|
+
/** In-memory increment — safe on the MCP tool-call hot path. */
|
|
95
|
+
recordUsage(kind: UsageKind, name: string, ok: boolean, client?: ClientInfo): void;
|
|
96
|
+
/** install / index / uninstall — buffered like everything else. */
|
|
97
|
+
recordLifecycle(event: LifecycleEvent, props: Record<string, unknown>): void;
|
|
98
|
+
/**
|
|
99
|
+
* Fire-and-forget send of everything sendable. Never throws, never logs
|
|
100
|
+
* above debug. Safe to call at startup of long-running commands.
|
|
101
|
+
*/
|
|
102
|
+
maybeFlush(): void;
|
|
103
|
+
/**
|
|
104
|
+
* Drain in-memory state to the buffer, then send completed-day rollups and
|
|
105
|
+
* lifecycle events. Bounded by `timeoutMs`; leftovers stay buffered for the
|
|
106
|
+
* next process. Awaited only where latency is invisible (install/init).
|
|
107
|
+
*/
|
|
108
|
+
flushNow(timeoutMs?: number): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* Periodic flush for long-lived processes (MCP daemon / serve). Unref'd so
|
|
111
|
+
* it never keeps the process alive.
|
|
112
|
+
*/
|
|
113
|
+
startInterval(everyMs?: number): void;
|
|
114
|
+
stopInterval(): void;
|
|
115
|
+
private utcDay;
|
|
116
|
+
private readConfig;
|
|
117
|
+
private writeConfig;
|
|
118
|
+
/**
|
|
119
|
+
* Default-on consent is gated by a one-time stderr notice (interactive
|
|
120
|
+
* installs record their choice explicitly and never reach this).
|
|
121
|
+
*/
|
|
122
|
+
private firstRunNotice;
|
|
123
|
+
/**
|
|
124
|
+
* Synchronous, tiny, exit-safe: drain in-memory deltas to the JSONL queue.
|
|
125
|
+
* Runs on `process.on('exit')`, so it must never be async or slow.
|
|
126
|
+
*/
|
|
127
|
+
persistSync(): void;
|
|
128
|
+
private appendLines;
|
|
129
|
+
/**
|
|
130
|
+
* Atomically claim the queue for sending (rename). Concurrent processes
|
|
131
|
+
* can't double-send; a crash mid-send leaves a claim file that
|
|
132
|
+
* `recoverStaleClaims` merges back after an hour.
|
|
133
|
+
*/
|
|
134
|
+
private claimQueue;
|
|
135
|
+
private recoverStaleClaims;
|
|
136
|
+
/** Returns the lines that did NOT make it out (to be re-queued). */
|
|
137
|
+
private send;
|
|
138
|
+
private packageVersion;
|
|
139
|
+
private ensureExitHook;
|
|
140
|
+
private debug;
|
|
141
|
+
}
|
|
142
|
+
export declare function getTelemetry(): Telemetry;
|
|
143
|
+
//# sourceMappingURL=index.d.ts.map
|