@unerr-ai/unerr 0.2.1 → 0.2.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 +36 -45
- package/dist/cli.js +37443 -36022
- package/package.json +2 -1
- package/dist/behaviors/agent-llm-bridge.js +0 -166
- package/dist/behaviors/architecture-guard.js +0 -256
- package/dist/behaviors/auto-doc.js +0 -247
- package/dist/behaviors/cascade-guard.js +0 -289
- package/dist/behaviors/change-narrative.js +0 -270
- package/dist/behaviors/convention-drift.js +0 -290
- package/dist/behaviors/framework.js +0 -235
- package/dist/behaviors/guard-formatter.js +0 -44
- package/dist/behaviors/incomplete-work.js +0 -270
- package/dist/behaviors/loop-breaker.js +0 -300
- package/dist/behaviors/session-continuity.js +0 -208
- package/dist/commands/branches.js +0 -97
- package/dist/commands/check-commit.js +0 -225
- package/dist/commands/compress-output.js +0 -64
- package/dist/commands/config-verify.js +0 -243
- package/dist/commands/daemon.js +0 -905
- package/dist/commands/dashboard.js +0 -52
- package/dist/commands/debug.js +0 -200
- package/dist/commands/enrich.js +0 -184
- package/dist/commands/exec.js +0 -233
- package/dist/commands/gain.js +0 -156
- package/dist/commands/hook.js +0 -88
- package/dist/commands/index.js +0 -88
- package/dist/commands/init.js +0 -74
- package/dist/commands/install.js +0 -505
- package/dist/commands/learn.js +0 -116
- package/dist/commands/manifest.js +0 -193
- package/dist/commands/rewind.js +0 -103
- package/dist/commands/serve.js +0 -19
- package/dist/commands/setup-wizard.js +0 -414
- package/dist/commands/skills.js +0 -64
- package/dist/commands/stats.js +0 -20
- package/dist/commands/status.js +0 -654
- package/dist/commands/timeline.js +0 -139
- package/dist/commands/uninstall.js +0 -230
- package/dist/components/App.js +0 -109
- package/dist/components/Banner.js +0 -12
- package/dist/components/ConfirmPrompt.js +0 -25
- package/dist/components/DriftSummary.js +0 -23
- package/dist/components/GradeBadge.js +0 -15
- package/dist/components/HealthCard.js +0 -18
- package/dist/components/InkSpinner.js +0 -22
- package/dist/components/InputBox.js +0 -17
- package/dist/components/KeyValue.js +0 -13
- package/dist/components/MessageList.js +0 -14
- package/dist/components/ProgressBar.js +0 -26
- package/dist/components/Section.js +0 -16
- package/dist/components/SessionSummaryCard.js +0 -73
- package/dist/components/StartupDisplay.js +0 -24
- package/dist/components/StatusDashboard.js +0 -57
- package/dist/components/StatusLine.js +0 -8
- package/dist/components/StepLine.js +0 -22
- package/dist/components/Theme.js +0 -20
- package/dist/components/ToolProgress.js +0 -8
- package/dist/components/ViolationList.js +0 -21
- package/dist/components/render.js +0 -13
- package/dist/config/agent-registry.js +0 -237
- package/dist/config/claude-settings-hooks.js +0 -304
- package/dist/config/hook-installer.js +0 -65
- package/dist/config/instruction-writer.js +0 -388
- package/dist/config/mcp-config-writer.js +0 -266
- package/dist/config/settings.js +0 -174
- package/dist/config/tool-detector.js +0 -42
- package/dist/config/value-surfacing.js +0 -119
- package/dist/core/context-assembly.js +0 -108
- package/dist/core/conversation.js +0 -33
- package/dist/core/local-chat-provider.js +0 -475
- package/dist/core/provider-factory.js +0 -55
- package/dist/core/providers.js +0 -90
- package/dist/core/query-engine.js +0 -174
- package/dist/daemon/api.js +0 -312
- package/dist/daemon/autostart.js +0 -119
- package/dist/daemon/bootstrap.js +0 -39
- package/dist/daemon/client.js +0 -164
- package/dist/daemon/detect-ci.js +0 -81
- package/dist/daemon/platform-linux.js +0 -146
- package/dist/daemon/platform-macos.js +0 -134
- package/dist/daemon/platform-windows.js +0 -116
- package/dist/daemon/process-manager.js +0 -299
- package/dist/daemon/protocol.js +0 -23
- package/dist/daemon/registry.js +0 -270
- package/dist/daemon/settings-schema.js +0 -72
- package/dist/daemon/system-health.js +0 -134
- package/dist/daemon/version-checker.js +0 -262
- package/dist/daemon/warm-start.js +0 -223
- package/dist/entrypoints/cli.js +0 -1043
- package/dist/entrypoints/daemon.js +0 -380
- package/dist/entrypoints/repl.js +0 -147
- package/dist/hooks/adapters/claude-code.js +0 -90
- package/dist/hooks/adapters/cline.js +0 -100
- package/dist/hooks/adapters/cursor.js +0 -98
- package/dist/hooks/hook-dedup.js +0 -79
- package/dist/hooks/hook-runner.js +0 -113
- package/dist/hooks/navigation-hooks.js +0 -175
- package/dist/hooks/prompt-hooks.js +0 -63
- package/dist/hooks/shell-hooks.js +0 -47
- package/dist/ignore.js +0 -111
- package/dist/intelligence/approach-suggester.js +0 -61
- package/dist/intelligence/ast-extractor.js +0 -2615
- package/dist/intelligence/ast-worker.js +0 -34
- package/dist/intelligence/background-indexer.js +0 -121
- package/dist/intelligence/blast-radius.js +0 -200
- package/dist/intelligence/community-detection.js +0 -691
- package/dist/intelligence/community-detector.js +0 -184
- package/dist/intelligence/computation-scheduler.js +0 -75
- package/dist/intelligence/confidence-propagation.js +0 -47
- package/dist/intelligence/convention-detector.js +0 -242
- package/dist/intelligence/convention-learner.js +0 -205
- package/dist/intelligence/convention-matcher.js +0 -205
- package/dist/intelligence/cozo-schema.js +0 -376
- package/dist/intelligence/decision-point-detector.js +0 -90
- package/dist/intelligence/deep-dive-tools.js +0 -586
- package/dist/intelligence/durability-scorer.js +0 -84
- package/dist/intelligence/exploration-cost.js +0 -204
- package/dist/intelligence/exploration-pattern-tracker.js +0 -61
- package/dist/intelligence/fact-generator.js +0 -322
- package/dist/intelligence/facts-schema.js +0 -90
- package/dist/intelligence/file-intelligence.js +0 -59
- package/dist/intelligence/graph-holder.js +0 -220
- package/dist/intelligence/graph-temporal-joiner.js +0 -238
- package/dist/intelligence/health-grade.js +0 -423
- package/dist/intelligence/health-grader.js +0 -200
- package/dist/intelligence/health-map-data.js +0 -259
- package/dist/intelligence/import-symbols.js +0 -136
- package/dist/intelligence/incremental-indexer.js +0 -658
- package/dist/intelligence/indexer/centrality.js +0 -62
- package/dist/intelligence/indexer/cfg-context.js +0 -95
- package/dist/intelligence/indexer/confidence.js +0 -34
- package/dist/intelligence/indexer/cross-file-resolver.js +0 -104
- package/dist/intelligence/indexer/edge-repair.js +0 -89
- package/dist/intelligence/indexer/entity-key.js +0 -17
- package/dist/intelligence/indexer/export-map.js +0 -132
- package/dist/intelligence/indexer/git-cochange.js +0 -128
- package/dist/intelligence/indexer/graph-patch.js +0 -147
- package/dist/intelligence/indexer/incremental.js +0 -78
- package/dist/intelligence/indexer/ingest.js +0 -160
- package/dist/intelligence/indexer/language-detect.js +0 -226
- package/dist/intelligence/indexer/metadata.js +0 -63
- package/dist/intelligence/indexer/mutation-tracker.js +0 -79
- package/dist/intelligence/indexer/orchestrator.js +0 -155
- package/dist/intelligence/indexer/plugin-interface.js +0 -31
- package/dist/intelligence/indexer/plugins/csharp.js +0 -440
- package/dist/intelligence/indexer/plugins/go.js +0 -335
- package/dist/intelligence/indexer/plugins/java.js +0 -370
- package/dist/intelligence/indexer/plugins/python.js +0 -358
- package/dist/intelligence/indexer/plugins/regex-fallback.js +0 -82
- package/dist/intelligence/indexer/plugins/ruby.js +0 -290
- package/dist/intelligence/indexer/plugins/rust.js +0 -484
- package/dist/intelligence/indexer/plugins/tier2-generic.js +0 -310
- package/dist/intelligence/indexer/plugins/typescript.js +0 -456
- package/dist/intelligence/indexer/resource-monitor.js +0 -93
- package/dist/intelligence/indexer/scip/decoder.js +0 -253
- package/dist/intelligence/indexer/scip/detector.js +0 -232
- package/dist/intelligence/indexer/scip/downloader.js +0 -427
- package/dist/intelligence/indexer/scip/fallback.js +0 -34
- package/dist/intelligence/indexer/scip/merger.js +0 -109
- package/dist/intelligence/indexer/scip/orchestrator.js +0 -433
- package/dist/intelligence/indexer/scip/runner.js +0 -98
- package/dist/intelligence/indexer/snapshot.js +0 -66
- package/dist/intelligence/indexer/test-detector.js +0 -196
- package/dist/intelligence/indexer/watch-integration.js +0 -61
- package/dist/intelligence/indexer/worker.js +0 -85
- package/dist/intelligence/local-convention-detector.js +0 -437
- package/dist/intelligence/local-embeddings.js +0 -190
- package/dist/intelligence/local-graph.js +0 -1946
- package/dist/intelligence/local-indexer.js +0 -1575
- package/dist/intelligence/local-llm.js +0 -163
- package/dist/intelligence/local-rule-generator.js +0 -154
- package/dist/intelligence/local-snapshot.js +0 -213
- package/dist/intelligence/negative-knowledge.js +0 -103
- package/dist/intelligence/persistent-db.js +0 -85
- package/dist/intelligence/query-router.js +0 -2556
- package/dist/intelligence/risk-classifier.js +0 -116
- package/dist/intelligence/rule-evaluator.js +0 -380
- package/dist/intelligence/rule-generator.js +0 -49
- package/dist/intelligence/search-index.js +0 -173
- package/dist/intelligence/semantic/docstring-extractor.js +0 -67
- package/dist/intelligence/semantic/embedding-store.js +0 -52
- package/dist/intelligence/semantic/enrichment-orchestrator.js +0 -48
- package/dist/intelligence/semantic/git-message-miner.js +0 -114
- package/dist/intelligence/semantic/identifier-tokenizer.js +0 -51
- package/dist/intelligence/semantic/node2vec-embeddings.js +0 -71
- package/dist/intelligence/semantic/node2vec-walks.js +0 -103
- package/dist/intelligence/semantic/path-domain-inference.js +0 -112
- package/dist/intelligence/semantic/similarity-engine.js +0 -60
- package/dist/intelligence/semantic/tfidf-vectors.js +0 -88
- package/dist/intelligence/session-brief-builder.js +0 -159
- package/dist/intelligence/session-context.js +0 -221
- package/dist/intelligence/session-health-monitor.js +0 -211
- package/dist/intelligence/session-narrative.js +0 -197
- package/dist/intelligence/session-pattern-analyzer.js +0 -218
- package/dist/intelligence/signal-scorer.js +0 -390
- package/dist/intelligence/signal-show-store.js +0 -182
- package/dist/intelligence/smart-truncate.js +0 -158
- package/dist/intelligence/subgraph-cache.js +0 -88
- package/dist/intelligence/temporal-facts.js +0 -494
- package/dist/intelligence/token-estimator.js +0 -100
- package/dist/intelligence/tool-injector.js +0 -87
- package/dist/intelligence/tree-sitter-loader.js +0 -71
- package/dist/intelligence/worker-pool.js +0 -116
- package/dist/proxy/arg-validator.js +0 -79
- package/dist/proxy/auto-bootstrap.js +0 -167
- package/dist/proxy/bridge.js +0 -147
- package/dist/proxy/budget-enforcer.js +0 -70
- package/dist/proxy/compression-quality-monitor.js +0 -160
- package/dist/proxy/compression-stats.js +0 -51
- package/dist/proxy/context-rot-detector.js +0 -137
- package/dist/proxy/drift-detector.js +0 -139
- package/dist/proxy/efficiency-tracker.js +0 -79
- package/dist/proxy/fact-ranking.js +0 -154
- package/dist/proxy/format-encoder.js +0 -266
- package/dist/proxy/http-transport.js +0 -90
- package/dist/proxy/lifecycle-actor.js +0 -55
- package/dist/proxy/lifecycle-machine.js +0 -187
- package/dist/proxy/log-tailer.js +0 -265
- package/dist/proxy/model-pricing.js +0 -98
- package/dist/proxy/network-firewall.js +0 -141
- package/dist/proxy/nudge-state.js +0 -93
- package/dist/proxy/output-compressor.js +0 -185
- package/dist/proxy/pid-lock.js +0 -291
- package/dist/proxy/proxy-context.js +0 -11
- package/dist/proxy/proxy.js +0 -2633
- package/dist/proxy/response-enrichment.js +0 -32
- package/dist/proxy/response-envelope.js +0 -313
- package/dist/proxy/session-dedup.js +0 -82
- package/dist/proxy/session-legend.js +0 -30
- package/dist/proxy/session-persistence.js +0 -210
- package/dist/proxy/session-resume.js +0 -94
- package/dist/proxy/session-stats.js +0 -513
- package/dist/proxy/shell-classifier.js +0 -1346
- package/dist/proxy/shell-compression-log.js +0 -93
- package/dist/proxy/shell-compressor.js +0 -390
- package/dist/proxy/shell-graph-boost.js +0 -202
- package/dist/proxy/shell-monitor-map.js +0 -18
- package/dist/proxy/shell-stats.js +0 -54
- package/dist/proxy/shell-strategies/cloud.js +0 -215
- package/dist/proxy/shell-strategies/diff.js +0 -159
- package/dist/proxy/shell-strategies/error-diagnostic.js +0 -796
- package/dist/proxy/shell-strategies/filter-dsl.js +0 -358
- package/dist/proxy/shell-strategies/git-status.js +0 -177
- package/dist/proxy/shell-strategies/key-value.js +0 -193
- package/dist/proxy/shell-strategies/log-text.js +0 -154
- package/dist/proxy/shell-strategies/omni.js +0 -188
- package/dist/proxy/shell-strategies/progress.js +0 -55
- package/dist/proxy/shell-strategies/redact.js +0 -76
- package/dist/proxy/shell-strategies/structured.js +0 -241
- package/dist/proxy/shell-strategies/tabular.js +0 -243
- package/dist/proxy/shell-strategies/test-results-types.js +0 -13
- package/dist/proxy/shell-strategies/test-results.js +0 -784
- package/dist/proxy/shell-strategies/tree-paths.js +0 -144
- package/dist/proxy/shell-strategies/yaml.js +0 -182
- package/dist/proxy/shell-tee.js +0 -111
- package/dist/proxy/signal-dedup.js +0 -171
- package/dist/proxy/startup-renderer.js +0 -158
- package/dist/proxy/task-token-display.js +0 -38
- package/dist/proxy/token-counter.js +0 -61
- package/dist/proxy/tool-clusters.js +0 -273
- package/dist/proxy/tool-definitions.js +0 -525
- package/dist/proxy/transport-mux.js +0 -229
- package/dist/proxy/wire-cap.js +0 -268
- package/dist/rules/developer.mozilla.org.json +0 -9
- package/dist/rules/github.com.json +0 -21
- package/dist/schemas/api/skills.js +0 -19
- package/dist/schemas/common/errors.js +0 -7
- package/dist/schemas/common/headers.js +0 -5
- package/dist/schemas/entities/edge.js +0 -25
- package/dist/schemas/entities/entity.js +0 -22
- package/dist/schemas/entities/rule.js +0 -18
- package/dist/schemas/index.js +0 -14
- package/dist/server/event-bus.js +0 -59
- package/dist/server/http.js +0 -156
- package/dist/server/middleware.js +0 -70
- package/dist/server/routes/drift.js +0 -97
- package/dist/server/routes/intelligence.js +0 -1217
- package/dist/server/routes/reasoning-quality.js +0 -444
- package/dist/server/routes/session.js +0 -86
- package/dist/server/routes/stream.js +0 -120
- package/dist/server/routes/system.js +0 -73
- package/dist/server/routes/temporal.js +0 -170
- package/dist/server/routes/timeline.js +0 -232
- package/dist/server/routes/token-flow.js +0 -403
- package/dist/skills/effectiveness-tracker.js +0 -93
- package/dist/skills/local-pack.js +0 -380
- package/dist/skills/resolver.js +0 -495
- package/dist/state-detector.js +0 -83
- package/dist/timeline/intent-detector.js +0 -263
- package/dist/timeline/loop-miner.js +0 -140
- package/dist/timeline/open-threads.js +0 -49
- package/dist/timeline/signal-reinforcer.js +0 -62
- package/dist/timeline/timeline-bootstrap.js +0 -151
- package/dist/timeline/timeline-store.js +0 -618
- package/dist/tools/coding/bash.js +0 -49
- package/dist/tools/coding/file-edit.js +0 -72
- package/dist/tools/coding/file-outline.js +0 -227
- package/dist/tools/coding/file-read-protocol.js +0 -425
- package/dist/tools/coding/file-read.js +0 -35
- package/dist/tools/coding/file-write.js +0 -43
- package/dist/tools/coding/glob-tool.js +0 -109
- package/dist/tools/coding/grep.js +0 -162
- package/dist/tools/coding/index.js +0 -27
- package/dist/tools/intelligence/index.js +0 -269
- package/dist/tools/intelligence/record-fact.js +0 -48
- package/dist/tools/intelligence/timeline-markers.js +0 -130
- package/dist/tools/registry.js +0 -47
- package/dist/tools/types.js +0 -8
- package/dist/tracking/auto-snapshot-triggers.js +0 -246
- package/dist/tracking/branch-context.js +0 -115
- package/dist/tracking/branch-snapshot.js +0 -217
- package/dist/tracking/causal-bridge.js +0 -317
- package/dist/tracking/circuit-breaker.js +0 -147
- package/dist/tracking/commit-watcher.js +0 -114
- package/dist/tracking/context-ledger.js +0 -119
- package/dist/tracking/correction-detector.js +0 -324
- package/dist/tracking/drift-tracker.js +0 -874
- package/dist/tracking/durability-tracker.js +0 -94
- package/dist/tracking/entity-rewind.js +0 -200
- package/dist/tracking/file-hash-state.js +0 -114
- package/dist/tracking/git-attribution.js +0 -132
- package/dist/tracking/git-trailers.js +0 -171
- package/dist/tracking/intelligence-counter.js +0 -46
- package/dist/tracking/intent-correlator.js +0 -202
- package/dist/tracking/intent-encoder.js +0 -52
- package/dist/tracking/intent-token-tracker.js +0 -159
- package/dist/tracking/ledger-archiver.js +0 -94
- package/dist/tracking/ledger-chains.js +0 -245
- package/dist/tracking/metrics-store.js +0 -361
- package/dist/tracking/native-watcher.js +0 -131
- package/dist/tracking/offline-rewind.js +0 -295
- package/dist/tracking/pending-violations.js +0 -74
- package/dist/tracking/persistence-effectiveness.js +0 -167
- package/dist/tracking/prompt-durability.js +0 -202
- package/dist/tracking/quality-signals.js +0 -213
- package/dist/tracking/redactor.js +0 -73
- package/dist/tracking/rewind-engine.js +0 -161
- package/dist/tracking/session-history.js +0 -128
- package/dist/tracking/session-receipt.js +0 -88
- package/dist/tracking/session-summary-writer.js +0 -157
- package/dist/tracking/shadow-ledger.js +0 -321
- package/dist/tracking/stash-manager.js +0 -258
- package/dist/tracking/timeline-fork.js +0 -213
- package/dist/tracking/timeline.js +0 -69
- package/dist/tracking/token-flow.js +0 -276
- package/dist/tracking/turn-segmenter.js +0 -122
- package/dist/tracking/weekly-accumulator.js +0 -179
- package/dist/tracking/working-snapshots.js +0 -188
- package/dist/tracking/workspace-manifest.js +0 -176
- package/dist/transport/http.js +0 -102
- package/dist/utils/counterfactual.js +0 -65
- package/dist/utils/deep-link.js +0 -34
- package/dist/utils/detect.js +0 -193
- package/dist/utils/exec.js +0 -73
- package/dist/utils/file-logger.js +0 -87
- package/dist/utils/format-error.js +0 -29
- package/dist/utils/git.js +0 -181
- package/dist/utils/log.js +0 -57
- package/dist/utils/logger.js +0 -35
- package/dist/utils/mcp-content-json.js +0 -8
- package/dist/utils/session-logger.js +0 -154
- package/dist/utils/startup-log.js +0 -512
- package/dist/utils/ui.js +0 -56
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Graph Patch Operations — surgical updates to the CozoDB graph.
|
|
3
|
-
*
|
|
4
|
-
* Instead of full re-ingestion, patches apply targeted:
|
|
5
|
-
* - Delete entity + all edges to/from it
|
|
6
|
-
* - Update entity in place (body_hash changed)
|
|
7
|
-
* - Insert new entities + edges
|
|
8
|
-
*
|
|
9
|
-
* This is the write-side of incremental indexing.
|
|
10
|
-
*/
|
|
11
|
-
import { createModuleLogger } from "../../utils/logger.js";
|
|
12
|
-
const log = createModuleLogger("graph-patch");
|
|
13
|
-
/**
|
|
14
|
-
* Delete an entity and all its edges from the graph.
|
|
15
|
-
*/
|
|
16
|
-
async function deleteEntity(db, entityKey) {
|
|
17
|
-
try {
|
|
18
|
-
await db.run("?[key] <- [[$key]] :rm entities { key }", { key: entityKey });
|
|
19
|
-
}
|
|
20
|
-
catch {
|
|
21
|
-
/* entity may not exist — safe to ignore */
|
|
22
|
-
}
|
|
23
|
-
try {
|
|
24
|
-
await db.run(`?[from_key, to_key, type] := *edges{ from_key, to_key, type }, from_key = $key
|
|
25
|
-
:rm edges { from_key, to_key, type }`, { key: entityKey });
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
/* no outgoing edges — safe */
|
|
29
|
-
}
|
|
30
|
-
try {
|
|
31
|
-
await db.run(`?[from_key, to_key, type] := *edges{ from_key, to_key, type }, to_key = $key
|
|
32
|
-
:rm edges { from_key, to_key, type }`, { key: entityKey });
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
/* no incoming edges — safe */
|
|
36
|
-
}
|
|
37
|
-
try {
|
|
38
|
-
await db.run(`?[file_path, entity_key] := *file_index{ file_path, entity_key }, entity_key = $key
|
|
39
|
-
:rm file_index { file_path, entity_key }`, { key: entityKey });
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
/* not in file_index — safe */
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Upsert an entity into the graph.
|
|
47
|
-
*/
|
|
48
|
-
async function upsertEntity(db, entity) {
|
|
49
|
-
try {
|
|
50
|
-
await db.run(`?[key, kind, name, file_path, start_line, end_line, signature, body, fan_in, fan_out, risk_level, community] <-
|
|
51
|
-
[[$key, $kind, $name, $fp, $sl, $el, $sig, $body, 0, 0, "normal", -1]]
|
|
52
|
-
:put entities { key => kind, name, file_path, start_line, end_line, signature, body, fan_in, fan_out, risk_level, community }`, {
|
|
53
|
-
key: entity.key,
|
|
54
|
-
kind: entity.kind,
|
|
55
|
-
name: entity.name,
|
|
56
|
-
fp: entity.file_path,
|
|
57
|
-
sl: entity.start_line,
|
|
58
|
-
sig: entity.signature,
|
|
59
|
-
el: entity.end_line,
|
|
60
|
-
body: entity.body_hash,
|
|
61
|
-
});
|
|
62
|
-
await db.run(`?[file_path, entity_key] <- [[$fp, $ek]]
|
|
63
|
-
:put file_index { file_path, entity_key }`, { fp: entity.file_path, ek: entity.key });
|
|
64
|
-
}
|
|
65
|
-
catch (err) {
|
|
66
|
-
log.debug(`Upsert entity failed for ${entity.key}: ${err instanceof Error ? err.message : String(err)}`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Insert edges into the graph (skipping unresolved).
|
|
71
|
-
*/
|
|
72
|
-
async function insertEdges(db, edges) {
|
|
73
|
-
const valid = edges.filter((e) => !e.to_key.startsWith("unresolved:"));
|
|
74
|
-
if (valid.length === 0)
|
|
75
|
-
return 0;
|
|
76
|
-
let count = 0;
|
|
77
|
-
for (const edge of valid) {
|
|
78
|
-
try {
|
|
79
|
-
await db.run(`?[from_key, to_key, type] <- [[$fk, $tk, $type]]
|
|
80
|
-
:put edges { from_key, to_key, type }`, { fk: edge.from_key, tk: edge.to_key, type: edge.type });
|
|
81
|
-
count++;
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
/* edge may conflict — safe to skip */
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return count;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Apply an entity diff as graph patches.
|
|
91
|
-
*/
|
|
92
|
-
export async function applyGraphPatch(db, diff, newEdges, oldEdgeKeys) {
|
|
93
|
-
const start = performance.now();
|
|
94
|
-
for (const entity of diff.deleted) {
|
|
95
|
-
await deleteEntity(db, entity.key);
|
|
96
|
-
}
|
|
97
|
-
for (const entity of diff.updated) {
|
|
98
|
-
await deleteEntity(db, entity.key);
|
|
99
|
-
await upsertEntity(db, entity);
|
|
100
|
-
}
|
|
101
|
-
for (const entity of diff.added) {
|
|
102
|
-
await upsertEntity(db, entity);
|
|
103
|
-
}
|
|
104
|
-
if (oldEdgeKeys) {
|
|
105
|
-
for (const edgeKey of oldEdgeKeys) {
|
|
106
|
-
const [fromKey, toKey, type] = edgeKey.split("::");
|
|
107
|
-
if (fromKey && toKey && type) {
|
|
108
|
-
try {
|
|
109
|
-
await db.run(`?[from_key, to_key, type] <- [[$fk, $tk, $type]]
|
|
110
|
-
:rm edges { from_key, to_key, type }`, { fk: fromKey, tk: toKey, type });
|
|
111
|
-
}
|
|
112
|
-
catch {
|
|
113
|
-
/* safe */
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
const edgesAdded = await insertEdges(db, newEdges);
|
|
119
|
-
const durationMs = performance.now() - start;
|
|
120
|
-
log.debug(`Patch: +${diff.added.length} ~${diff.updated.length} -${diff.deleted.length} entities, +${edgesAdded} edges (${Math.round(durationMs)}ms)`);
|
|
121
|
-
return {
|
|
122
|
-
entitiesDeleted: diff.deleted.length,
|
|
123
|
-
entitiesUpdated: diff.updated.length,
|
|
124
|
-
entitiesAdded: diff.added.length,
|
|
125
|
-
edgesDeleted: oldEdgeKeys?.size ?? 0,
|
|
126
|
-
edgesAdded,
|
|
127
|
-
durationMs,
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Delete all entities and edges for a specific file.
|
|
132
|
-
*/
|
|
133
|
-
export async function deleteFileFromGraph(db, filePath) {
|
|
134
|
-
let deleted = 0;
|
|
135
|
-
try {
|
|
136
|
-
const result = await db.run("?[entity_key] := *file_index{ file_path: $fp, entity_key }", { fp: filePath });
|
|
137
|
-
const keys = result.rows.map((r) => r[0]);
|
|
138
|
-
for (const key of keys) {
|
|
139
|
-
await deleteEntity(db, key);
|
|
140
|
-
deleted++;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
catch {
|
|
144
|
-
/* file not in index — safe */
|
|
145
|
-
}
|
|
146
|
-
return deleted;
|
|
147
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Incremental Indexing — entity diff + cascade invalidation.
|
|
3
|
-
*
|
|
4
|
-
* K.1: Compares old vs new entities for a file. Produces added/updated/deleted sets.
|
|
5
|
-
* Uses body_hash for efficient change detection (no content comparison needed).
|
|
6
|
-
*
|
|
7
|
-
* K.2: When an entity changes, identifies all edges that reference it
|
|
8
|
-
* (both incoming and outgoing) for invalidation and re-resolution.
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* Diff old vs new entities for a single file.
|
|
12
|
-
* Matches by key (deterministic). Detects changes via body_hash.
|
|
13
|
-
*/
|
|
14
|
-
export function diffEntities(oldEntities, newEntities) {
|
|
15
|
-
const oldMap = new Map(oldEntities.map((e) => [e.key, e]));
|
|
16
|
-
const newMap = new Map(newEntities.map((e) => [e.key, e]));
|
|
17
|
-
const added = [];
|
|
18
|
-
const updated = [];
|
|
19
|
-
const unchanged = [];
|
|
20
|
-
const deleted = [];
|
|
21
|
-
for (const [key, newEntity] of newMap) {
|
|
22
|
-
const oldEntity = oldMap.get(key);
|
|
23
|
-
if (!oldEntity) {
|
|
24
|
-
added.push(newEntity);
|
|
25
|
-
}
|
|
26
|
-
else if (oldEntity.body_hash !== newEntity.body_hash) {
|
|
27
|
-
updated.push(newEntity);
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
unchanged.push(newEntity);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
for (const [key, oldEntity] of oldMap) {
|
|
34
|
-
if (!newMap.has(key)) {
|
|
35
|
-
deleted.push(oldEntity);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return { added, updated, deleted, unchanged };
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Determine which edges are invalidated by entity changes.
|
|
42
|
-
* An edge is invalidated if either its from_key or to_key was added, updated, or deleted.
|
|
43
|
-
*/
|
|
44
|
-
export function cascadeInvalidation(diff, allEdges) {
|
|
45
|
-
const changedKeys = new Set();
|
|
46
|
-
for (const e of diff.added)
|
|
47
|
-
changedKeys.add(e.key);
|
|
48
|
-
for (const e of diff.updated)
|
|
49
|
-
changedKeys.add(e.key);
|
|
50
|
-
for (const e of diff.deleted)
|
|
51
|
-
changedKeys.add(e.key);
|
|
52
|
-
const invalidatedEdges = [];
|
|
53
|
-
const affectedFiles = new Set();
|
|
54
|
-
const affectedEntityKeys = new Set();
|
|
55
|
-
for (const edge of allEdges) {
|
|
56
|
-
if (changedKeys.has(edge.from_key) || changedKeys.has(edge.to_key)) {
|
|
57
|
-
invalidatedEdges.push(edge);
|
|
58
|
-
affectedFiles.add(edge.file_path);
|
|
59
|
-
affectedEntityKeys.add(edge.from_key);
|
|
60
|
-
affectedEntityKeys.add(edge.to_key);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return { invalidatedEdges, affectedFiles, affectedEntityKeys };
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Check if a file needs re-indexing by comparing entity hashes.
|
|
67
|
-
* Returns true if any entity has changed (fast short-circuit).
|
|
68
|
-
*/
|
|
69
|
-
export function fileNeedsReindex(oldEntities, newEntities) {
|
|
70
|
-
if (oldEntities.length !== newEntities.length)
|
|
71
|
-
return true;
|
|
72
|
-
const oldHashes = new Set(oldEntities.map((e) => `${e.key}:${e.body_hash}`));
|
|
73
|
-
for (const e of newEntities) {
|
|
74
|
-
if (!oldHashes.has(`${e.key}:${e.body_hash}`))
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CozoDB Bulk Ingestion — batch inserts entities + edges into the graph store.
|
|
3
|
-
*
|
|
4
|
-
* Designed for initial indexing and full re-index scenarios.
|
|
5
|
-
* Uses CozoDB's `:put` (upsert) to handle re-indexing gracefully.
|
|
6
|
-
* Batch size is configurable to respect memory limits.
|
|
7
|
-
*
|
|
8
|
-
* File-as-L0: Every file gets a `file:<path>` entity (kind="module") and every
|
|
9
|
-
* entity gets a `contains` edge from its parent file entity. This guarantees
|
|
10
|
-
* zero orphans in the graph — every entity is reachable via its file node.
|
|
11
|
-
*/
|
|
12
|
-
import { basename } from "node:path";
|
|
13
|
-
import { createModuleLogger } from "../../utils/logger.js";
|
|
14
|
-
import { isTestFile } from "./test-detector.js";
|
|
15
|
-
const log = createModuleLogger("ingest");
|
|
16
|
-
const ENTITY_BATCH_SIZE = 500;
|
|
17
|
-
const EDGE_BATCH_SIZE = 1000;
|
|
18
|
-
/**
|
|
19
|
-
* Collect unique file paths and create file-level entities.
|
|
20
|
-
* Each file gets a `file:<path>` entity with kind="module".
|
|
21
|
-
*/
|
|
22
|
-
function ingestFileEntities(db, entities) {
|
|
23
|
-
const filePaths = new Set();
|
|
24
|
-
for (const e of entities) {
|
|
25
|
-
if (e.file_path)
|
|
26
|
-
filePaths.add(e.file_path);
|
|
27
|
-
}
|
|
28
|
-
if (filePaths.size === 0)
|
|
29
|
-
return 0;
|
|
30
|
-
const rows = Array.from(filePaths, (fp) => [
|
|
31
|
-
`file:${fp}`,
|
|
32
|
-
"module",
|
|
33
|
-
basename(fp),
|
|
34
|
-
fp,
|
|
35
|
-
0,
|
|
36
|
-
"",
|
|
37
|
-
"",
|
|
38
|
-
0,
|
|
39
|
-
0,
|
|
40
|
-
"normal",
|
|
41
|
-
-1,
|
|
42
|
-
]);
|
|
43
|
-
let ingested = 0;
|
|
44
|
-
for (let i = 0; i < rows.length; i += ENTITY_BATCH_SIZE) {
|
|
45
|
-
const batch = rows.slice(i, i + ENTITY_BATCH_SIZE);
|
|
46
|
-
try {
|
|
47
|
-
db.run(`?[key, kind, name, file_path, start_line, signature, body, fan_in, fan_out, risk_level, community] <- $rows
|
|
48
|
-
:put entities { key => kind, name, file_path, start_line, signature, body, fan_in, fan_out, risk_level, community }`, { rows: batch });
|
|
49
|
-
ingested += batch.length;
|
|
50
|
-
}
|
|
51
|
-
catch (err) {
|
|
52
|
-
log.warn(`File entity batch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return ingested;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Create `contains` edges from file entities to their child entities.
|
|
59
|
-
* This guarantees every entity is reachable via its parent file node.
|
|
60
|
-
*/
|
|
61
|
-
function ingestContainsEdges(db, entities) {
|
|
62
|
-
const rows = entities
|
|
63
|
-
.filter((e) => e.file_path)
|
|
64
|
-
.map((e) => [`file:${e.file_path}`, e.key, "contains"]);
|
|
65
|
-
let ingested = 0;
|
|
66
|
-
for (let i = 0; i < rows.length; i += EDGE_BATCH_SIZE) {
|
|
67
|
-
const batch = rows.slice(i, i + EDGE_BATCH_SIZE);
|
|
68
|
-
try {
|
|
69
|
-
db.run(`?[from_key, to_key, type] <- $rows
|
|
70
|
-
:put edges { from_key, to_key, type }`, { rows: batch });
|
|
71
|
-
ingested += batch.length;
|
|
72
|
-
}
|
|
73
|
-
catch (err) {
|
|
74
|
-
log.warn(`Contains edge batch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return ingested;
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Bulk ingest entities into CozoDB.
|
|
81
|
-
* Also populates file_index for fast file→entity lookups.
|
|
82
|
-
*/
|
|
83
|
-
function ingestEntities(db, entities) {
|
|
84
|
-
let ingested = 0;
|
|
85
|
-
for (let i = 0; i < entities.length; i += ENTITY_BATCH_SIZE) {
|
|
86
|
-
const batch = entities.slice(i, i + ENTITY_BATCH_SIZE);
|
|
87
|
-
const rows = batch.map((e) => [
|
|
88
|
-
e.key,
|
|
89
|
-
e.kind,
|
|
90
|
-
e.name,
|
|
91
|
-
e.file_path,
|
|
92
|
-
e.start_line,
|
|
93
|
-
e.signature,
|
|
94
|
-
e.body_hash,
|
|
95
|
-
0,
|
|
96
|
-
0,
|
|
97
|
-
"normal",
|
|
98
|
-
-1,
|
|
99
|
-
e.is_test ?? isTestFile(e.file_path),
|
|
100
|
-
]);
|
|
101
|
-
try {
|
|
102
|
-
db.run(`?[key, kind, name, file_path, start_line, signature, body, fan_in, fan_out, risk_level, community, is_test] <- $rows
|
|
103
|
-
:put entities { key => kind, name, file_path, start_line, signature, body, fan_in, fan_out, risk_level, community, is_test }`, { rows });
|
|
104
|
-
const fileIndexRows = batch.map((e) => [e.file_path, e.key]);
|
|
105
|
-
db.run(`?[file_path, entity_key] <- $rows
|
|
106
|
-
:put file_index { file_path, entity_key }`, { rows: fileIndexRows });
|
|
107
|
-
ingested += batch.length;
|
|
108
|
-
}
|
|
109
|
-
catch (err) {
|
|
110
|
-
log.warn(`Entity batch ingest failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return ingested;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Bulk ingest edges into CozoDB.
|
|
117
|
-
*/
|
|
118
|
-
function ingestEdges(db, edges) {
|
|
119
|
-
let ingested = 0;
|
|
120
|
-
const validEdges = edges.filter((e) => !e.to_key.startsWith("unresolved:"));
|
|
121
|
-
for (let i = 0; i < validEdges.length; i += EDGE_BATCH_SIZE) {
|
|
122
|
-
const batch = validEdges.slice(i, i + EDGE_BATCH_SIZE);
|
|
123
|
-
const rows = batch.map((e) => [e.from_key, e.to_key, e.type]);
|
|
124
|
-
try {
|
|
125
|
-
db.run(`?[from_key, to_key, type] <- $rows
|
|
126
|
-
:put edges { from_key, to_key, type }`, { rows });
|
|
127
|
-
ingested += batch.length;
|
|
128
|
-
}
|
|
129
|
-
catch (err) {
|
|
130
|
-
log.warn(`Edge batch ingest failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return ingested;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Ingest a full index result into CozoDB.
|
|
137
|
-
*
|
|
138
|
-
* Order: file entities → code entities → contains edges → code edges.
|
|
139
|
-
* File entities must exist before contains edges reference them.
|
|
140
|
-
*/
|
|
141
|
-
export function ingestIndexResult(db, entities, edges) {
|
|
142
|
-
const start = performance.now();
|
|
143
|
-
// R.1: Create file-level entities (file:<path> with kind="module")
|
|
144
|
-
const fileEntities = ingestFileEntities(db, entities);
|
|
145
|
-
// Ingest code-level entities
|
|
146
|
-
const entitiesIngested = ingestEntities(db, entities);
|
|
147
|
-
// R.2: Create contains edges (file → entity)
|
|
148
|
-
const containsEdges = ingestContainsEdges(db, entities);
|
|
149
|
-
// Ingest code-level edges (calls, imports, extends, etc.)
|
|
150
|
-
const edgesIngested = ingestEdges(db, edges);
|
|
151
|
-
const durationMs = performance.now() - start;
|
|
152
|
-
log.info(`Ingested ${fileEntities} files + ${entitiesIngested} entities + ${containsEdges + edgesIngested} edges in ${Math.round(durationMs)}ms`);
|
|
153
|
-
return {
|
|
154
|
-
entitiesIngested,
|
|
155
|
-
edgesIngested,
|
|
156
|
-
fileEntities,
|
|
157
|
-
containsEdges,
|
|
158
|
-
durationMs,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Language Detection & Tier Assignment — maps file extensions to languages,
|
|
3
|
-
* assigns extraction tiers, and dispatches to the correct plugin.
|
|
4
|
-
*
|
|
5
|
-
* Tiers:
|
|
6
|
-
* Tier 1: Full tree-sitter + SCIP enrichment path (8 languages)
|
|
7
|
-
* Tier 2: Tree-sitter extraction only (10+ languages)
|
|
8
|
-
* Tier 3: Regex fallback for unknown languages
|
|
9
|
-
*/
|
|
10
|
-
const LANGUAGE_MAP = {
|
|
11
|
-
".ts": {
|
|
12
|
-
id: "typescript",
|
|
13
|
-
name: "TypeScript",
|
|
14
|
-
tier: 1,
|
|
15
|
-
extensions: [".ts", ".tsx"],
|
|
16
|
-
grammarWasm: "tree-sitter-typescript.wasm",
|
|
17
|
-
},
|
|
18
|
-
".tsx": {
|
|
19
|
-
id: "typescript",
|
|
20
|
-
name: "TypeScript",
|
|
21
|
-
tier: 1,
|
|
22
|
-
extensions: [".ts", ".tsx"],
|
|
23
|
-
grammarWasm: "tree-sitter-typescript.wasm",
|
|
24
|
-
},
|
|
25
|
-
".js": {
|
|
26
|
-
id: "javascript",
|
|
27
|
-
name: "JavaScript",
|
|
28
|
-
tier: 1,
|
|
29
|
-
extensions: [".js", ".jsx", ".mjs", ".cjs"],
|
|
30
|
-
grammarWasm: "tree-sitter-javascript.wasm",
|
|
31
|
-
},
|
|
32
|
-
".jsx": {
|
|
33
|
-
id: "javascript",
|
|
34
|
-
name: "JavaScript",
|
|
35
|
-
tier: 1,
|
|
36
|
-
extensions: [".js", ".jsx", ".mjs", ".cjs"],
|
|
37
|
-
grammarWasm: "tree-sitter-javascript.wasm",
|
|
38
|
-
},
|
|
39
|
-
".mjs": {
|
|
40
|
-
id: "javascript",
|
|
41
|
-
name: "JavaScript",
|
|
42
|
-
tier: 1,
|
|
43
|
-
extensions: [".js", ".jsx", ".mjs", ".cjs"],
|
|
44
|
-
grammarWasm: "tree-sitter-javascript.wasm",
|
|
45
|
-
},
|
|
46
|
-
".cjs": {
|
|
47
|
-
id: "javascript",
|
|
48
|
-
name: "JavaScript",
|
|
49
|
-
tier: 1,
|
|
50
|
-
extensions: [".js", ".jsx", ".mjs", ".cjs"],
|
|
51
|
-
grammarWasm: "tree-sitter-javascript.wasm",
|
|
52
|
-
},
|
|
53
|
-
".py": {
|
|
54
|
-
id: "python",
|
|
55
|
-
name: "Python",
|
|
56
|
-
tier: 1,
|
|
57
|
-
extensions: [".py"],
|
|
58
|
-
grammarWasm: "tree-sitter-python.wasm",
|
|
59
|
-
},
|
|
60
|
-
".go": {
|
|
61
|
-
id: "go",
|
|
62
|
-
name: "Go",
|
|
63
|
-
tier: 1,
|
|
64
|
-
extensions: [".go"],
|
|
65
|
-
grammarWasm: "tree-sitter-go.wasm",
|
|
66
|
-
},
|
|
67
|
-
".java": {
|
|
68
|
-
id: "java",
|
|
69
|
-
name: "Java",
|
|
70
|
-
tier: 1,
|
|
71
|
-
extensions: [".java"],
|
|
72
|
-
grammarWasm: "tree-sitter-java.wasm",
|
|
73
|
-
},
|
|
74
|
-
".rs": {
|
|
75
|
-
id: "rust",
|
|
76
|
-
name: "Rust",
|
|
77
|
-
tier: 1,
|
|
78
|
-
extensions: [".rs"],
|
|
79
|
-
grammarWasm: "tree-sitter-rust.wasm",
|
|
80
|
-
},
|
|
81
|
-
".rb": {
|
|
82
|
-
id: "ruby",
|
|
83
|
-
name: "Ruby",
|
|
84
|
-
tier: 1,
|
|
85
|
-
extensions: [".rb"],
|
|
86
|
-
grammarWasm: "tree-sitter-ruby.wasm",
|
|
87
|
-
},
|
|
88
|
-
".cs": {
|
|
89
|
-
id: "csharp",
|
|
90
|
-
name: "C#",
|
|
91
|
-
tier: 1,
|
|
92
|
-
extensions: [".cs"],
|
|
93
|
-
grammarWasm: "tree-sitter-c_sharp.wasm",
|
|
94
|
-
},
|
|
95
|
-
".c": {
|
|
96
|
-
id: "c",
|
|
97
|
-
name: "C",
|
|
98
|
-
tier: 2,
|
|
99
|
-
extensions: [".c", ".h"],
|
|
100
|
-
grammarWasm: "tree-sitter-c.wasm",
|
|
101
|
-
},
|
|
102
|
-
".h": {
|
|
103
|
-
id: "c",
|
|
104
|
-
name: "C",
|
|
105
|
-
tier: 2,
|
|
106
|
-
extensions: [".c", ".h"],
|
|
107
|
-
grammarWasm: "tree-sitter-c.wasm",
|
|
108
|
-
},
|
|
109
|
-
".cpp": {
|
|
110
|
-
id: "cpp",
|
|
111
|
-
name: "C++",
|
|
112
|
-
tier: 2,
|
|
113
|
-
extensions: [".cpp", ".cc", ".cxx", ".hpp"],
|
|
114
|
-
grammarWasm: "tree-sitter-cpp.wasm",
|
|
115
|
-
},
|
|
116
|
-
".cc": {
|
|
117
|
-
id: "cpp",
|
|
118
|
-
name: "C++",
|
|
119
|
-
tier: 2,
|
|
120
|
-
extensions: [".cpp", ".cc", ".cxx", ".hpp"],
|
|
121
|
-
grammarWasm: "tree-sitter-cpp.wasm",
|
|
122
|
-
},
|
|
123
|
-
".cxx": {
|
|
124
|
-
id: "cpp",
|
|
125
|
-
name: "C++",
|
|
126
|
-
tier: 2,
|
|
127
|
-
extensions: [".cpp", ".cc", ".cxx", ".hpp"],
|
|
128
|
-
grammarWasm: "tree-sitter-cpp.wasm",
|
|
129
|
-
},
|
|
130
|
-
".hpp": {
|
|
131
|
-
id: "cpp",
|
|
132
|
-
name: "C++",
|
|
133
|
-
tier: 2,
|
|
134
|
-
extensions: [".cpp", ".cc", ".cxx", ".hpp"],
|
|
135
|
-
grammarWasm: "tree-sitter-cpp.wasm",
|
|
136
|
-
},
|
|
137
|
-
".php": {
|
|
138
|
-
id: "php",
|
|
139
|
-
name: "PHP",
|
|
140
|
-
tier: 2,
|
|
141
|
-
extensions: [".php"],
|
|
142
|
-
grammarWasm: "tree-sitter-php.wasm",
|
|
143
|
-
},
|
|
144
|
-
".swift": {
|
|
145
|
-
id: "swift",
|
|
146
|
-
name: "Swift",
|
|
147
|
-
tier: 2,
|
|
148
|
-
extensions: [".swift"],
|
|
149
|
-
grammarWasm: "tree-sitter-swift.wasm",
|
|
150
|
-
},
|
|
151
|
-
".kt": {
|
|
152
|
-
id: "kotlin",
|
|
153
|
-
name: "Kotlin",
|
|
154
|
-
tier: 2,
|
|
155
|
-
extensions: [".kt", ".kts"],
|
|
156
|
-
grammarWasm: "tree-sitter-kotlin.wasm",
|
|
157
|
-
},
|
|
158
|
-
".kts": {
|
|
159
|
-
id: "kotlin",
|
|
160
|
-
name: "Kotlin",
|
|
161
|
-
tier: 2,
|
|
162
|
-
extensions: [".kt", ".kts"],
|
|
163
|
-
grammarWasm: "tree-sitter-kotlin.wasm",
|
|
164
|
-
},
|
|
165
|
-
".scala": {
|
|
166
|
-
id: "scala",
|
|
167
|
-
name: "Scala",
|
|
168
|
-
tier: 2,
|
|
169
|
-
extensions: [".scala"],
|
|
170
|
-
grammarWasm: "tree-sitter-scala.wasm",
|
|
171
|
-
},
|
|
172
|
-
".lua": {
|
|
173
|
-
id: "lua",
|
|
174
|
-
name: "Lua",
|
|
175
|
-
tier: 2,
|
|
176
|
-
extensions: [".lua"],
|
|
177
|
-
grammarWasm: "tree-sitter-lua.wasm",
|
|
178
|
-
},
|
|
179
|
-
".dart": {
|
|
180
|
-
id: "dart",
|
|
181
|
-
name: "Dart",
|
|
182
|
-
tier: 2,
|
|
183
|
-
extensions: [".dart"],
|
|
184
|
-
grammarWasm: "tree-sitter-dart.wasm",
|
|
185
|
-
},
|
|
186
|
-
".ex": {
|
|
187
|
-
id: "elixir",
|
|
188
|
-
name: "Elixir",
|
|
189
|
-
tier: 2,
|
|
190
|
-
extensions: [".ex", ".exs"],
|
|
191
|
-
grammarWasm: "tree-sitter-elixir.wasm",
|
|
192
|
-
},
|
|
193
|
-
".exs": {
|
|
194
|
-
id: "elixir",
|
|
195
|
-
name: "Elixir",
|
|
196
|
-
tier: 2,
|
|
197
|
-
extensions: [".ex", ".exs"],
|
|
198
|
-
grammarWasm: "tree-sitter-elixir.wasm",
|
|
199
|
-
},
|
|
200
|
-
".zig": {
|
|
201
|
-
id: "zig",
|
|
202
|
-
name: "Zig",
|
|
203
|
-
tier: 2,
|
|
204
|
-
extensions: [".zig"],
|
|
205
|
-
grammarWasm: "tree-sitter-zig.wasm",
|
|
206
|
-
},
|
|
207
|
-
};
|
|
208
|
-
export function detectLanguage(filePath) {
|
|
209
|
-
const dot = filePath.lastIndexOf(".");
|
|
210
|
-
if (dot < 0)
|
|
211
|
-
return null;
|
|
212
|
-
const ext = filePath.slice(dot).toLowerCase();
|
|
213
|
-
return LANGUAGE_MAP[ext] ?? null;
|
|
214
|
-
}
|
|
215
|
-
export function getLanguageTier(filePath) {
|
|
216
|
-
const info = detectLanguage(filePath);
|
|
217
|
-
if (!info)
|
|
218
|
-
return 3;
|
|
219
|
-
return info.tier;
|
|
220
|
-
}
|
|
221
|
-
export function isSupportedExtension(ext) {
|
|
222
|
-
return ext in LANGUAGE_MAP;
|
|
223
|
-
}
|
|
224
|
-
export function getAllSupportedExtensions() {
|
|
225
|
-
return Object.keys(LANGUAGE_MAP);
|
|
226
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Index Metadata Persistence — tracks indexing state in .unerr/index/metadata.json.
|
|
3
|
-
*
|
|
4
|
-
* Stores: last index timestamp, file hashes, entity counts per file.
|
|
5
|
-
* Used by incremental indexing to determine which files need re-processing.
|
|
6
|
-
*/
|
|
7
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
8
|
-
import { join } from "node:path";
|
|
9
|
-
const METADATA_VERSION = 1;
|
|
10
|
-
function defaultMetadata() {
|
|
11
|
-
return {
|
|
12
|
-
version: METADATA_VERSION,
|
|
13
|
-
lastFullIndex: new Date().toISOString(),
|
|
14
|
-
files: {},
|
|
15
|
-
totalEntities: 0,
|
|
16
|
-
totalEdges: 0,
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
export function loadMetadata(unerrDir) {
|
|
20
|
-
const indexDir = join(unerrDir, "index");
|
|
21
|
-
const metaPath = join(indexDir, "metadata.json");
|
|
22
|
-
if (!existsSync(metaPath))
|
|
23
|
-
return defaultMetadata();
|
|
24
|
-
try {
|
|
25
|
-
const raw = readFileSync(metaPath, "utf-8");
|
|
26
|
-
const parsed = JSON.parse(raw);
|
|
27
|
-
if (parsed.version !== METADATA_VERSION)
|
|
28
|
-
return defaultMetadata();
|
|
29
|
-
return parsed;
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
return defaultMetadata();
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
export function saveMetadata(unerrDir, metadata) {
|
|
36
|
-
const indexDir = join(unerrDir, "index");
|
|
37
|
-
if (!existsSync(indexDir)) {
|
|
38
|
-
mkdirSync(indexDir, { recursive: true });
|
|
39
|
-
}
|
|
40
|
-
const metaPath = join(indexDir, "metadata.json");
|
|
41
|
-
try {
|
|
42
|
-
writeFileSync(metaPath, JSON.stringify(metadata, null, 2), "utf-8");
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
/* best effort */
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
export function updateFileMetadata(metadata, filePath, hash, entityCount) {
|
|
49
|
-
metadata.files[filePath] = {
|
|
50
|
-
hash,
|
|
51
|
-
entityCount,
|
|
52
|
-
lastIndexed: new Date().toISOString(),
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
export function removeFileMetadata(metadata, filePath) {
|
|
56
|
-
delete metadata.files[filePath];
|
|
57
|
-
}
|
|
58
|
-
export function fileNeedsReindex(metadata, filePath, currentHash) {
|
|
59
|
-
const existing = metadata.files[filePath];
|
|
60
|
-
if (!existing)
|
|
61
|
-
return true;
|
|
62
|
-
return existing.hash !== currentHash;
|
|
63
|
-
}
|