codegraphcontext 0.6.0__py3-none-any.whl → 0.6.1__py3-none-any.whl

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.
@@ -274,6 +274,7 @@ dist/
274
274
  build/
275
275
  target/
276
276
  out/
277
+ obj/
277
278
  .git/
278
279
  .idea/
279
280
  .vscode/
@@ -1200,8 +1200,11 @@ class EmbeddedSessionWrapper:
1200
1200
  return f"{prefix}NOT label({var_name}) = '{label_name}'"
1201
1201
  query = re.sub(r'(WHERE\s+|AND\s+|OR\s+)NOT\s+(\w+):([a-zA-Z0-9_`]+)', not_label_replacer, query, flags=re.IGNORECASE)
1202
1202
 
1203
- # 4. Polymorphic matches and label access
1204
- query = query.replace("labels(n)[0]", "label(n)")
1203
+ # 4. Polymorphic matches and label access. Kùzu has no labels();
1204
+ # rewrite labels(<var>)[0] for ANY variable name — the literal
1205
+ # "labels(n)[0]" form missed n1/n2 and the simulator's relationship
1206
+ # query reached the engine unsupported (#1512).
1207
+ query = re.sub(r'labels\((\w+)\)\s*\[\s*0\s*\]', r'label(\1)', query)
1205
1208
 
1206
1209
  query = query.replace("coalesce(", "COALESCE(")
1207
1210
  query = re.sub(r'\btype\(', 'label(', query)
@@ -40,6 +40,7 @@ class JobInfo:
40
40
  result: Optional[Dict[str, Any]] = None
41
41
  path: Optional[str] = None
42
42
  is_dependency: bool = False
43
+ last_update_time: Optional[datetime] = None
43
44
 
44
45
  def __post_init__(self):
45
46
  """Ensures the errors list is initialized after the object is created."""
@@ -93,6 +94,7 @@ class JobManager:
93
94
  for key, value in kwargs.items():
94
95
  if hasattr(job, key):
95
96
  setattr(job, key, value)
97
+ job.last_update_time = datetime.now()
96
98
 
97
99
  def get_job(self, job_id: str) -> Optional[JobInfo]:
98
100
  """Retrieves the information for a single job."""
@@ -132,15 +134,36 @@ class JobManager:
132
134
  def cleanup_old_jobs(self, max_age_hours: int = 24):
133
135
  """Removes old jobs from memory to prevent memory leaks.
134
136
 
135
- Finished jobs are aged by end_time; jobs that never finished (e.g.
136
- crashed while PENDING/RUNNING) are aged by start_time so they don't
137
- leak forever.
137
+ Terminal jobs (COMPLETED/FAILED/CANCELLED) are aged by end_time,
138
+ falling back to start_time.
139
+
140
+ Jobs still PENDING/RUNNING are never deleted outright (#1537): a
141
+ healthy long-running index updates its progress constantly, and
142
+ deleting its record makes update_job silently no-op and
143
+ check_job_status report not_found while the worker keeps writing.
144
+ Instead, an active job with *no progress update* for the whole window
145
+ is presumed crashed and flipped to FAILED — the record stays visible,
146
+ and the next sweep ages it out through the terminal path.
138
147
  """
139
148
  cutoff_time = datetime.now() - timedelta(hours=max_age_hours)
140
149
  with self.lock:
150
+ active = (JobStatus.PENDING, JobStatus.RUNNING)
141
151
  jobs_to_remove = [
142
152
  job_id for job_id, job in self.jobs.items()
143
- if (job.end_time or job.start_time) < cutoff_time
153
+ if job.status not in active
154
+ and (job.end_time or job.start_time) < cutoff_time
144
155
  ]
145
156
  for job_id in jobs_to_remove:
146
157
  del self.jobs[job_id]
158
+
159
+ for job in self.jobs.values():
160
+ if job.status in active:
161
+ last_progress = job.last_update_time or job.start_time
162
+ if last_progress < cutoff_time:
163
+ job.status = JobStatus.FAILED
164
+ job.end_time = datetime.now()
165
+ if job.errors is None:
166
+ job.errors = []
167
+ job.errors.append(
168
+ f"Presumed crashed: no progress update for {max_age_hours}h"
169
+ )
@@ -48,9 +48,11 @@ class CodeGraphTwin:
48
48
  """
49
49
 
50
50
  # 2. Fetch all relationships originating from nodes in the repository
51
+ # `*0..` includes the repository node itself (zero-length path), which
52
+ # replaces the old `WHERE n1 = r OR (r)-[:CONTAINS*]->(n1)` form — a
53
+ # bare pattern predicate the embedded backends cannot plan (#1512).
51
54
  rel_query = """
52
- MATCH (r:Repository {path: $path})
53
- MATCH (n1) WHERE n1 = r OR (r)-[:CONTAINS*]->(n1)
55
+ MATCH (r:Repository {path: $path})-[:CONTAINS*0..]->(n1)
54
56
  MATCH (n1)-[rel]->(n2)
55
57
  RETURN
56
58
  labels(n1)[0] as source_label,
@@ -458,6 +458,13 @@ class CodeWatcher:
458
458
  h.cancel_timers()
459
459
  self.handlers.clear()
460
460
 
461
+ # A stopped watchdog Observer cannot be restarted, so the watch state
462
+ # must not survive it: a stale entry makes watch_directory answer
463
+ # "Already watching" for a dead observer and the graph silently goes
464
+ # stale (#1519).
465
+ self.watched_paths.clear()
466
+ self.watches.clear()
467
+
461
468
  if self.observer.is_alive():
462
469
  self.observer.stop()
463
470
  self.observer.join()
@@ -39,7 +39,7 @@ class GraphBuilder:
39
39
  linking for Neo4j, FalkorDB, and Kùzu backends.
40
40
  """
41
41
 
42
- def __init__(self, db_manager: DatabaseManager, job_manager: JobManager, loop: asyncio.AbstractEventLoop):
42
+ def __init__(self, db_manager: DatabaseManager, job_manager: JobManager, loop: asyncio.AbstractEventLoop, graph_name: str = None):
43
43
  """Initialize GraphBuilder.
44
44
 
45
45
  Parameters
@@ -50,11 +50,16 @@ class GraphBuilder:
50
50
  Job manager for tracking indexing progress.
51
51
  loop : asyncio.AbstractEventLoop
52
52
  Event loop for async operations.
53
+ graph_name : str, optional
54
+ Named graph to write into, on backends that support multiple
55
+ graphs per instance (FalkorDB). None selects the default graph
56
+ (#1558).
53
57
  """
54
58
  self.db_manager = db_manager
55
59
  self.job_manager = job_manager
56
60
  self.loop = loop
57
- self._writer = GraphWriter(self.db_manager.get_driver(), db_manager=self.db_manager)
61
+ self.graph_name = graph_name
62
+ self._writer = GraphWriter(self.db_manager.get_driver(graph_name), db_manager=self.db_manager)
58
63
  self.last_call_resolution_diagnostics: list[Dict[str, Any]] = []
59
64
  self.last_index_summary: Dict[str, Any] = {}
60
65
  self.parsers = {
@@ -118,8 +123,9 @@ class GraphBuilder:
118
123
 
119
124
  @property
120
125
  def driver(self):
121
- """Default graph driver (backward compatible)."""
122
- return self.db_manager.get_driver()
126
+ """Driver for this builder's graph (default graph unless a
127
+ graph_name was given at construction)."""
128
+ return self.db_manager.get_driver(self.graph_name)
123
129
 
124
130
  def _driver_for(self, graph_name: str = None):
125
131
  """Get driver for a specific graph, or default."""
@@ -184,21 +190,6 @@ class GraphBuilder:
184
190
 
185
191
 
186
192
  # Language-agnostic method
187
- def add_repository_to_graph(self, repo_path: Path, is_dependency: bool = False):
188
- """Adds a repository node using its absolute path as the unique key."""
189
- repo_name = repo_path.name
190
- repo_path_str = repo_path.resolve().as_posix()
191
- with self.driver.session() as session:
192
- session.run(
193
- """
194
- MERGE (r:Repository {path: $path})
195
- SET r.name = $name, r.is_dependency = $is_dependency
196
- """,
197
- path=repo_path_str,
198
- name=repo_name,
199
- is_dependency=is_dependency,
200
- )
201
-
202
193
  def add_repository_to_graph(self, repo_path: Path, is_dependency: bool = False) -> None:
203
194
  """Add a repository node to the graph.
204
195
 
@@ -20,24 +20,29 @@ def add_code_to_graph(graph_builder, job_manager, loop, list_repos_func, **args)
20
20
  if not path:
21
21
  return {"error": "Path is a required argument (repo_path)."}
22
22
 
23
- # `graph_name` is advertised in this tool's schema but indexing cannot yet
24
- # honour it: GraphBuilder binds its GraphWriter to the default driver at
25
- # construction, so a named graph would need a per-job writer threaded
26
- # through the whole pipeline. Refuse explicitly rather than write to the
27
- # default graph and report success — an agent that believed the repository
28
- # landed in a named graph would find nothing there later, with no error to
29
- # explain it.
23
+ # Indexing into a named graph is supported on multi-graph backends
24
+ # (FalkorDB): a scoped GraphBuilder is constructed whose writer binds to
25
+ # get_driver(graph_name). Single-graph backends (KùzuDB/LadybugDB/Neo4j)
26
+ # would silently ignore the name and land the repo in the default graph —
27
+ # the exact lie #1558 is about — so those still refuse explicitly.
30
28
  graph_name = args.get("graph_name")
31
29
  if graph_name:
32
- return {
33
- "error": (
34
- f"Indexing into a named graph is not supported yet, so "
35
- f"graph_name={graph_name!r} cannot be honoured. Omit it to index "
36
- "into the default graph, or select the graph via the CLI context "
37
- "(`cgc context create` / `cgc index --context`)."
38
- ),
39
- "unsupported_argument": "graph_name",
40
- }
30
+ backend = graph_builder.db_manager.get_backend_type()
31
+ if backend in ("falkordb", "falkordb-remote"):
32
+ from ..graph_builder import GraphBuilder
33
+ graph_builder = GraphBuilder(
34
+ graph_builder.db_manager, job_manager, loop, graph_name=graph_name
35
+ )
36
+ else:
37
+ return {
38
+ "error": (
39
+ f"The active backend ({backend}) is single-graph, so "
40
+ f"graph_name={graph_name!r} cannot be honoured. Omit it to "
41
+ "index into the default graph, or select a graph via the CLI "
42
+ "context (`cgc context create` / `cgc index --context`)."
43
+ ),
44
+ "unsupported_argument": "graph_name",
45
+ }
41
46
 
42
47
  try:
43
48
  path_obj = Path(path).resolve()
@@ -61,8 +66,10 @@ def add_code_to_graph(graph_builder, job_manager, loop, list_repos_func, **args)
61
66
  "message": f"Path '{path}' does not exist.",
62
67
  }
63
68
 
64
- # Prevent re-indexing the same repository.
65
- indexed_repos = list_repos_func().get("repositories", [])
69
+ # Prevent re-indexing the same repository. list_repos_func reads the
70
+ # default graph, so the check only applies there — a named graph is a
71
+ # separate namespace and legitimately re-indexes the same path.
72
+ indexed_repos = [] if graph_name else list_repos_func().get("repositories", [])
66
73
  for repo in indexed_repos:
67
74
  if repo_record_matches_path(repo, path_obj):
68
75
  return {
@@ -85,7 +92,9 @@ def add_code_to_graph(graph_builder, job_manager, loop, list_repos_func, **args)
85
92
 
86
93
  return {
87
94
  "success": True, "job_id": job_id,
88
- "message": f"Background processing started for {str(path_obj)}",
95
+ **({"graph_name": graph_name} if graph_name else {}),
96
+ "message": f"Background processing started for {str(path_obj)}"
97
+ + (f" into graph '{graph_name}'" if graph_name else ""),
89
98
  "estimated_files": total_files,
90
99
  "estimated_duration_seconds": round(estimated_time, 2),
91
100
  "estimated_duration_human": f"{int(estimated_time // 60)}m {int(estimated_time % 60)}s" if estimated_time >= 60 else f"{int(estimated_time)}s",
@@ -15,6 +15,9 @@ DEFAULT_IGNORE_PATTERNS = [
15
15
  "build/",
16
16
  "target/",
17
17
  "out/",
18
+ # .NET intermediate output: contains *generated* source (AssemblyInfo.cs,
19
+ # GlobalUsings.g.cs) that pollutes the graph with phantom modules (#1585).
20
+ "obj/",
18
21
  ".git/",
19
22
  "__pycache__/",
20
23
  "*.png",
@@ -505,38 +505,49 @@ class JavascriptTreeSitterParser:
505
505
  if node.type == 'import_statement':
506
506
  source = self._get_node_text(node.child_by_field_name('source')).strip('\'"')
507
507
 
508
- # Look for different import structures
509
- import_clause = node.child_by_field_name('import')
508
+ # `import_clause` is an unnamed child of import_statement, not a
509
+ # field, so child_by_field_name('import') always returned None and
510
+ # every ES import collapsed into the bare-module fallback (#1526).
511
+ import_clause = next(
512
+ (c for c in node.children if c.type == 'import_clause'), None
513
+ )
510
514
  if not import_clause:
515
+ # Side-effect import: import 'polyfill';
511
516
  imports.append({'name': source, 'source': source, 'alias': None, 'line_number': line_number,
512
517
  'lang': self.language_name})
513
518
  continue
514
519
 
515
- # Default import: import defaultExport from '...'
516
- if import_clause.type == 'identifier':
517
- alias = self._get_node_text(import_clause)
518
- imports.append({'name': 'default', 'source': source, 'alias': alias, 'line_number': line_number,
519
- 'lang': self.language_name})
520
-
521
- # Namespace import: import * as name from '...'
522
- elif import_clause.type == 'namespace_import':
523
- alias_node = import_clause.child_by_field_name('alias')
524
- if alias_node:
525
- alias = self._get_node_text(alias_node)
526
- imports.append({'name': '*', 'source': source, 'alias': alias, 'line_number': line_number,
520
+ # One clause can carry several bindings at once
521
+ # (import Def, { a as b } from 'mod'), so walk its children.
522
+ for binding in import_clause.children:
523
+ # Default import: import defaultExport from '...'
524
+ if binding.type == 'identifier':
525
+ alias = self._get_node_text(binding)
526
+ imports.append({'name': 'default', 'source': source, 'alias': alias, 'line_number': line_number,
527
527
  'lang': self.language_name})
528
528
 
529
- # Named imports: import { name, name as alias } from '...'
530
- elif import_clause.type == 'named_imports':
531
- for specifier in import_clause.children:
532
- if specifier.type == 'import_specifier':
533
- name_node = specifier.child_by_field_name('name')
534
- alias_node = specifier.child_by_field_name('alias')
535
- original_name = self._get_node_text(name_node)
536
- alias = self._get_node_text(alias_node) if alias_node else None
537
- imports.append(
538
- {'name': original_name, 'source': source, 'alias': alias, 'line_number': line_number,
539
- 'lang': self.language_name})
529
+ # Namespace import: import * as name from '...' — the alias
530
+ # is the identifier child (there is no 'alias' field).
531
+ elif binding.type == 'namespace_import':
532
+ alias = next(
533
+ (self._get_node_text(c) for c in binding.children if c.type == 'identifier'),
534
+ None,
535
+ )
536
+ if alias:
537
+ imports.append({'name': '*', 'source': source, 'alias': alias, 'line_number': line_number,
538
+ 'lang': self.language_name})
539
+
540
+ # Named imports: import { name, name as alias } from '...'
541
+ elif binding.type == 'named_imports':
542
+ for specifier in binding.children:
543
+ if specifier.type == 'import_specifier':
544
+ name_node = specifier.child_by_field_name('name')
545
+ alias_node = specifier.child_by_field_name('alias')
546
+ original_name = self._get_node_text(name_node)
547
+ alias = self._get_node_text(alias_node) if alias_node else None
548
+ imports.append(
549
+ {'name': original_name, 'source': source, 'alias': alias, 'line_number': line_number,
550
+ 'lang': self.language_name})
540
551
 
541
552
  elif node.type == 'call_expression': # require('...')
542
553
  args = node.child_by_field_name('arguments')
@@ -419,31 +419,49 @@ class TypescriptTreeSitterParser:
419
419
  line_number = node.start_point[0] + 1
420
420
  if node.type == 'import_statement':
421
421
  source = self._get_node_text(node.child_by_field_name('source')).strip('\'"')
422
- import_clause = node.child_by_field_name('import')
422
+ # `import_clause` is an unnamed child of import_statement, not a
423
+ # field, so child_by_field_name('import') always returned None and
424
+ # every ES import collapsed into the bare-module fallback (#1526).
425
+ import_clause = next(
426
+ (c for c in node.children if c.type == 'import_clause'), None
427
+ )
423
428
  if not import_clause:
429
+ # Side-effect import: import 'polyfill';
424
430
  imports.append({'name': source, 'source': source, 'alias': None, 'line_number': line_number,
425
431
  'lang': self.language_name})
426
432
  continue
427
- if import_clause.type == 'identifier':
428
- alias = self._get_node_text(import_clause)
429
- imports.append({'name': 'default', 'source': source, 'alias': alias, 'line_number': line_number,
430
- 'lang': self.language_name})
431
- elif import_clause.type == 'namespace_import':
432
- alias_node = import_clause.child_by_field_name('alias')
433
- if alias_node:
434
- alias = self._get_node_text(alias_node)
435
- imports.append({'name': '*', 'source': source, 'alias': alias, 'line_number': line_number,
433
+
434
+ # One clause can carry several bindings at once
435
+ # (import Def, { a as b } from 'mod'), so walk its children.
436
+ for binding in import_clause.children:
437
+ # Default import: import defaultExport from '...'
438
+ if binding.type == 'identifier':
439
+ alias = self._get_node_text(binding)
440
+ imports.append({'name': 'default', 'source': source, 'alias': alias, 'line_number': line_number,
436
441
  'lang': self.language_name})
437
- elif import_clause.type == 'named_imports':
438
- for specifier in import_clause.children:
439
- if specifier.type == 'import_specifier':
440
- name_node = specifier.child_by_field_name('name')
441
- alias_node = specifier.child_by_field_name('alias')
442
- original_name = self._get_node_text(name_node)
443
- alias = self._get_node_text(alias_node) if alias_node else None
444
- imports.append(
445
- {'name': original_name, 'source': source, 'alias': alias, 'line_number': line_number,
446
- 'lang': self.language_name})
442
+
443
+ # Namespace import: import * as name from '...' — the alias
444
+ # is the identifier child (there is no 'alias' field).
445
+ elif binding.type == 'namespace_import':
446
+ alias = next(
447
+ (self._get_node_text(c) for c in binding.children if c.type == 'identifier'),
448
+ None,
449
+ )
450
+ if alias:
451
+ imports.append({'name': '*', 'source': source, 'alias': alias, 'line_number': line_number,
452
+ 'lang': self.language_name})
453
+
454
+ # Named imports: import { name, name as alias } from '...'
455
+ elif binding.type == 'named_imports':
456
+ for specifier in binding.children:
457
+ if specifier.type == 'import_specifier':
458
+ name_node = specifier.child_by_field_name('name')
459
+ alias_node = specifier.child_by_field_name('alias')
460
+ original_name = self._get_node_text(name_node)
461
+ alias = self._get_node_text(alias_node) if alias_node else None
462
+ imports.append(
463
+ {'name': original_name, 'source': source, 'alias': alias, 'line_number': line_number,
464
+ 'lang': self.language_name})
447
465
  elif node.type == 'call_expression':
448
466
  args = node.child_by_field_name('arguments')
449
467
  if not args or args.named_child_count == 0: continue
@@ -68,6 +68,31 @@ def _strip_literals_and_comments(query: str) -> str:
68
68
  return _LITERAL_OR_COMMENT_RE.sub(" ", query)
69
69
 
70
70
 
71
+ # A forbidden keyword only functions as a write *clause* in clause position.
72
+ # The same word is inert — and common in real codebases' graphs — when it is:
73
+ # n.load a property access (preceded by '.')
74
+ # (n:Insert) a label / rel-type (preceded by ':')
75
+ # $update a parameter name (preceded by '$')
76
+ # AS set a result-column alias (preceded by the token AS)
77
+ # Only those provably-safe positions are carved out (#1511); anything
78
+ # ambiguous stays rejected, because a false negative here is a write slipping
79
+ # through a read-only gate while a false positive is merely an inconvenience.
80
+ _TOKEN_RE = re.compile(r"\w+|[^\w\s]")
81
+
82
+
83
+ def _keyword_in_clause_position(stripped: str, keyword: str) -> bool:
84
+ tokens = _TOKEN_RE.findall(stripped)
85
+ kw = keyword.upper()
86
+ for i, tok in enumerate(tokens):
87
+ if tok.upper() != kw:
88
+ continue
89
+ prev = tokens[i - 1] if i > 0 else ""
90
+ if prev in (".", ":", "$") or prev.upper() == "AS":
91
+ continue
92
+ return True
93
+ return False
94
+
95
+
71
96
  def is_read_only_cypher(query: str) -> bool:
72
97
  """Return True when *query* has no write keywords outside string literals."""
73
98
  if not query or not query.strip():
@@ -76,7 +101,7 @@ def is_read_only_cypher(query: str) -> bool:
76
101
  if ";" in stripped:
77
102
  return False
78
103
  for keyword in _FORBIDDEN_KEYWORDS:
79
- if re.search(r"\b" + keyword + r"\b", stripped, re.IGNORECASE):
104
+ if _keyword_in_clause_position(stripped, keyword):
80
105
  return False
81
106
  for pattern in _FORBIDDEN_PATTERNS:
82
107
  if pattern.search(stripped):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codegraphcontext
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: An MCP server that indexes local code into a graph database to provide context to AI assistants.
5
5
  Author-email: Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
6
6
  License: MIT License
@@ -12,7 +12,7 @@ codegraphcontext/api/router.py,sha256=9XCm5FBZY4z-k8k9Z1OlE9vMdSK-bh6tC5_Qef1F1e
12
12
  codegraphcontext/api/schemas.py,sha256=pGLuKtdn55pf8mS8wv8MwehbT_3-4OZuSYjI5LJxzOc,1034
13
13
  codegraphcontext/cli/__init__.py,sha256=2vUlnf7H09M9JbS2gS_LmMUBJWAWcGGHkkl4I2YrdSg,39
14
14
  codegraphcontext/cli/cli_helpers.py,sha256=w7TCwcL5T6XyRPYKzLkBdt0V6O3YEkWlPl_WTBZHWEA,54179
15
- codegraphcontext/cli/config_manager.py,sha256=jUth6HSWjB4D2SwGaIOBpckfCsDSklnlUrFp1cPz1p4,55409
15
+ codegraphcontext/cli/config_manager.py,sha256=6Nuoyg47S9HeEk6zbUv_4AP4bJsnfuk3fKq3B8dyCYg,55414
16
16
  codegraphcontext/cli/hook_manager.py,sha256=nKr6SiuM6zA3eZv1rZSNPXUyqkha8Ja0VGQ3_145bLE,7615
17
17
  codegraphcontext/cli/main.py,sha256=eKrEM2obDqC_Cz4UL19---4p5mpZxT3xSBM1n-vu31g,152775
18
18
  codegraphcontext/cli/project_config.py,sha256=Slae6fIojlcqRbFzRkAMAsglamryLCPrjUFG16e165g,7492
@@ -26,7 +26,7 @@ codegraphcontext/core/bundle_registry.py,sha256=xlVBe-fmvEOLY9xDq7w0vXFlTPzeFVIw
26
26
  codegraphcontext/core/cgc_bundle.py,sha256=X2aOji754UyjvCEJc3hOQCP6KF_H4OJNQMfUunrYY5I,74714
27
27
  codegraphcontext/core/cgcignore.py,sha256=x50FOG04kmR12LqixTlfiHW4ka05jf6_jaRA-5yiqis,10847
28
28
  codegraphcontext/core/database.py,sha256=ZLOHXv46hVxWiPYQala0Co7_Z8vqj5juaenudwq6DTU,14893
29
- codegraphcontext/core/database_embedded_kuzu.py,sha256=jB6y3F10rLUQPSezd7jk3V87WX0UJdXBSrtJLqos_U4,81428
29
+ codegraphcontext/core/database_embedded_kuzu.py,sha256=xa3hpCJcV4mcigmJf0RkafZULOzOxhkZtZD4Y0h0CcQ,81677
30
30
  codegraphcontext/core/database_falkordb.py,sha256=8TSFfgKoaNdTzSx7P4qXMMs2kTNBzrcW5tZxR8JV4bY,35834
31
31
  codegraphcontext/core/database_falkordb_remote.py,sha256=HdkcmwgUxPy1bwiFqqcU8yMQYib7B3JarYQ1LlTwfJ8,7957
32
32
  codegraphcontext/core/database_kuzu.py,sha256=5I31dGm7wRo3YjIWeWGRVcX1eYRXYc7fPWnT7zHFjf0,1123
@@ -34,13 +34,13 @@ codegraphcontext/core/database_ladybug.py,sha256=n-cI8ihTn0NijF5lvj9xiX-xINMH8DK
34
34
  codegraphcontext/core/database_nornic.py,sha256=8cKufnAvc9bIklAsdIirD_UBON-K8KNigRrzU41f-_8,8491
35
35
  codegraphcontext/core/falkor_worker.py,sha256=JMF32LWS4EO48Kzc6ATzOKolakaQSaCcKtbmflmTf_A,6772
36
36
  codegraphcontext/core/graph_query.py,sha256=G8St1PAcBa44_2vw578h7ypEOt_ERNl-6u-dXVJ_CoI,1471
37
- codegraphcontext/core/jobs.py,sha256=4VRZvz6Eawng8q4S0RzNw5R0wd3yF_KbqJHRqsG-OlI,5329
38
- codegraphcontext/core/simulator.py,sha256=Sb3PpnoMGVDWvqPVSv5dcQqiL3nTvhmLzzLzJ41krkE,24140
39
- codegraphcontext/core/watcher.py,sha256=Rk89Tqgg6q8UizLfCg34fMZ8uMEFYL_yNKwAqvo5Jdg,19085
37
+ codegraphcontext/core/jobs.py,sha256=06kXZV2P3FVhOHG8yDDEsXQrDd_lkD56tyF3pFAhfHk,6549
38
+ codegraphcontext/core/simulator.py,sha256=qfjR5_EFd8elZWUZE92mi6F3mzjpBTfdnZMQr19bLqY,24338
39
+ codegraphcontext/core/watcher.py,sha256=2cJ3hT-nS7CSeKpIvdqg6Vgx4hb3axx4_dLukIXo2uw,19404
40
40
  codegraphcontext/tools/__init__.py,sha256=iqQPEkDlGXO7rAaLNQrS_ZAbLSklBSK-OowpARq0mig,41
41
41
  codegraphcontext/tools/advanced_language_query_tool.py,sha256=8pRVMg-Tbp3JrbN31McyTbum91gJPlrjHFCFVJ78coA,4169
42
42
  codegraphcontext/tools/code_finder.py,sha256=Mm3J0i_i2wAfUNM3B7zWLG81ZFckhihbvh7LkXfavQo,85331
43
- codegraphcontext/tools/graph_builder.py,sha256=86oL_2J0q9IxqTNcx9Lx9q579_Ha928RDk_YVw0aRi4,27217
43
+ codegraphcontext/tools/graph_builder.py,sha256=ky1cVDWyD8tX4DrvBEe9MWGO9kXMZarj6rJErInOphk,26950
44
44
  codegraphcontext/tools/package_resolver.py,sha256=j6s4H5VnourUdJ-CkA3kCOc-Vdewnjc-PNDshAPCiaU,7802
45
45
  codegraphcontext/tools/report_generator.py,sha256=3tH83_24nm-pWcY_oXUeLB2jYtGGZmkiBb_oyuhS4WM,16114
46
46
  codegraphcontext/tools/scip_indexer.py,sha256=8ZHaooZeQgTtO_wRI0VwiMgIQF1QNAg7o6Xx5VGj3BM,39112
@@ -53,12 +53,12 @@ codegraphcontext/tools/datasources/cassandra_ingester.py,sha256=sgbskSkvE98qtOpr
53
53
  codegraphcontext/tools/datasources/mysql_ingester.py,sha256=uWstOv7mOEws1pmT8uAsEBkoOGM1FXOWt_2VCE-tZeg,3991
54
54
  codegraphcontext/tools/datasources/redis_ingester.py,sha256=mVUKYmr_v6g7wYaavmQscEHGi_CPZrxYLjfkldc6cWE,3788
55
55
  codegraphcontext/tools/handlers/analysis_handlers.py,sha256=jPow6EEwUEQd3H7XfnU7no9GnZ80sY1E6KQyKv5sl_0,14186
56
- codegraphcontext/tools/handlers/indexing_handlers.py,sha256=sKtbP19EX694zs-6rsVkhwihGwSIWaKjm4N41jMXP2M,7437
56
+ codegraphcontext/tools/handlers/indexing_handlers.py,sha256=GNpIR_4vY1DawOGUnU0PY4m_9VSUkWV7eh-J9eY5RIg,8031
57
57
  codegraphcontext/tools/handlers/management_handlers.py,sha256=19-fCuMuY5oHXQ9O4F1qG4ZsKKsGpSGbxxA1gH4AE-g,17419
58
58
  codegraphcontext/tools/handlers/query_handlers.py,sha256=mqI7pfuSRc92ChAS5IGtrkPyhpPeh-dg-ewVnysx5nw,4643
59
59
  codegraphcontext/tools/handlers/watcher_handlers.py,sha256=po0NP3WnUqJAiDyZW9pz2g2V-itnazI10cXQJuc1UZ8,3809
60
60
  codegraphcontext/tools/indexing/__init__.py,sha256=exCNeB4UYhKhNSoEBNta_EZ51Kdze4iK4e3oWH8B4X8,126
61
- codegraphcontext/tools/indexing/constants.py,sha256=Le_oBo1jMOtRnhFjpNRtal_kg3Z8z34Qi7xufkL9zQA,573
61
+ codegraphcontext/tools/indexing/constants.py,sha256=-ZiD5tdX95efNo2gOFrTNlmDnY4TALMN4GT0jOGPbcQ,742
62
62
  codegraphcontext/tools/indexing/discovery.py,sha256=l0uoCCPRWClXPbHzbExrkC2RRjhN8u5KX6gOhQZliII,5326
63
63
  codegraphcontext/tools/indexing/embeddings.py,sha256=Iny1K1HZaHtgApWpw88RLy1T10Rk4yJ8G6LNt5OcKfg,11406
64
64
  codegraphcontext/tools/indexing/pipeline.py,sha256=oDx3l65OC5lwqtkJ5ImaquaCfnpyZ4DNNEAXQhvAvto,18602
@@ -87,7 +87,7 @@ codegraphcontext/tools/languages/gradle.py,sha256=P1NPMhHGsqgObGjqy17InFxzgE6IO4
87
87
  codegraphcontext/tools/languages/haskell.py,sha256=YyslUwcanFs00IinFrj7_TJ2IY2Q97NYsG2Y-9qqolU,19888
88
88
  codegraphcontext/tools/languages/html.py,sha256=cjzAH55-JYbObGcMiqjuYD6X0Cbs1Kj5ixcZv9BzMns,5595
89
89
  codegraphcontext/tools/languages/java.py,sha256=dpyHBGPhL1FaYP_unh-ncRDOlmmA2nBqnkLc1tacYm0,52024
90
- codegraphcontext/tools/languages/javascript.py,sha256=PXOawNitB8B3dJMODkg9T_CKWQQ6hIphMA3RvWpwZQk,30769
90
+ codegraphcontext/tools/languages/javascript.py,sha256=MJ2NjuR6v2xBoWK63ztL4gliNPZwnl2ofNyK6Z8ufo0,31491
91
91
  codegraphcontext/tools/languages/kotlin.py,sha256=VzeGru-cK7TjtA_wigND5J74LUzXuvZLyIvYDsQvx5Y,96012
92
92
  codegraphcontext/tools/languages/lua.py,sha256=qviWaQ3XCa3xu64UnzukHTot8izc5CgFSi1dTVseWvI,16755
93
93
  codegraphcontext/tools/languages/maven.py,sha256=yQjrdSRZJPy6tUopZ7x5qYp8Rtbug4PPbBjCdl9FMDY,6393
@@ -103,7 +103,7 @@ codegraphcontext/tools/languages/solidity.py,sha256=VEbVNiSXSGcdXz2X1vpb0_oXYjlA
103
103
  codegraphcontext/tools/languages/solidity_remappings.py,sha256=thuGyJfGAQ6tfPnRKdFWmdfIZYzVJU8alBE1SoHsedI,5233
104
104
  codegraphcontext/tools/languages/svelte.py,sha256=yemTEjYF1YBLkIm2R9Mfc6gT6ZbDnS3KiAg_xtxd4BA,1486
105
105
  codegraphcontext/tools/languages/swift.py,sha256=nbDEpf5NHC25R3lz5bK-G-4l2Y4WmJuXTl_Ldgxkz1U,25873
106
- codegraphcontext/tools/languages/typescript.py,sha256=AWWkIiyK5zbDN5TMHP6UD-lyLnfS3wi6ZGu59MDT4TQ,29659
106
+ codegraphcontext/tools/languages/typescript.py,sha256=1HLw4BwdnwjZeDW-r1p753abhfFvByfkj6k8Dx0cLKc,30644
107
107
  codegraphcontext/tools/languages/typescriptjsx.py,sha256=b-XkR26fhFY8-0UBlayx7FYPAORqik7_LBTVZRvOhLE,7592
108
108
  codegraphcontext/tools/languages/vue.py,sha256=XKBoFea_4xMZaDStfkA52wgqc18yQ6COHDBHRduOe-0,1479
109
109
  codegraphcontext/tools/query_tool_languages/c_toolkit.py,sha256=kp-CFCOsFZa3sr3qOrH2Bh-ASwI-aaUCbqJSJZMt_Bs,271
@@ -124,7 +124,7 @@ codegraphcontext/tools/query_tool_languages/solidity_toolkit.py,sha256=wyLALYbUQ
124
124
  codegraphcontext/tools/query_tool_languages/swift_toolkit.py,sha256=l8TJa_LxYhN1eoXzFiSqra7KajUAfE6_SncXyVwlDvQ,279
125
125
  codegraphcontext/tools/query_tool_languages/typescript_toolkit.py,sha256=xV7nPSp08d9uBBknbyA3BUI95_jsgQfbnxOmR1kGRvc,289
126
126
  codegraphcontext/utils/cypher_ddl.py,sha256=SuFcCCnHtbyBMoEi6-vWLxt7WdOmRoJC5VAM025iX5I,2767
127
- codegraphcontext/utils/cypher_readonly.py,sha256=ZlgmFN2_78ME5N8kvgmW82CdvbQTtXVE1vO_I6kPnk0,3119
127
+ codegraphcontext/utils/cypher_readonly.py,sha256=RyFBlAbQsNZtFdCN4jzf_WMNnzLIt2O8sG7SCoWQ7cM,4175
128
128
  codegraphcontext/utils/debug_log.py,sha256=eFKQmaB4iTGzcdytfwZszhcMJCK6jIPxPXKsJOncl4A,3023
129
129
  codegraphcontext/utils/gcf_encoder.py,sha256=H6G66BCqbOZpyM_4JOFne5F3YrZRA8fiMnT4S_gRCk8,1806
130
130
  codegraphcontext/utils/git_utils.py,sha256=D7ve2gpZaEHk4y6K4ga-o2ka89DVFX1acafD31YAyJM,1383
@@ -174,9 +174,9 @@ codegraphcontext/viz/dist/wasm/tree-sitter-typescript.wasm,sha256=hRVATc7tOOHthq
174
174
  codegraphcontext/viz/dist/wasm/tree-sitter.wasm,sha256=CCeVuI_hXktkBD-DW01xYPv5XoAYVRIqzJUJI5te-RY,196763
175
175
  codegraphcontext/viz/dist/wasm/web-tree-sitter.js,sha256=DIaCNqRylrT_PBVw8g4ImeSnhP9uXNe_ycOlUiVGPko,153666
176
176
  codegraphcontext/viz/dist/wasm/web-tree-sitter.wasm,sha256=CCeVuI_hXktkBD-DW01xYPv5XoAYVRIqzJUJI5te-RY,196763
177
- codegraphcontext-0.6.0.dist-info/licenses/LICENSE,sha256=rh8M-bJpQYJnw2vtRVgt0t7piMZXh5QzaKeNEI0vqqA,1061
178
- codegraphcontext-0.6.0.dist-info/METADATA,sha256=9vp4gWhYe_xyphjjQFcdRN7cm6ep8odDFRnoT96aP7g,33422
179
- codegraphcontext-0.6.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
180
- codegraphcontext-0.6.0.dist-info/entry_points.txt,sha256=LCxWCWMshdvYGoHBPuQZ8C-e4CiNSHCLXofrNSGHkoE,103
181
- codegraphcontext-0.6.0.dist-info/top_level.txt,sha256=CBgc6LAPZIO5FS0nSYYkylDifHsZTIqw3Gf5UwDxeGI,17
182
- codegraphcontext-0.6.0.dist-info/RECORD,,
177
+ codegraphcontext-0.6.1.dist-info/licenses/LICENSE,sha256=rh8M-bJpQYJnw2vtRVgt0t7piMZXh5QzaKeNEI0vqqA,1061
178
+ codegraphcontext-0.6.1.dist-info/METADATA,sha256=nBcEmRNjpr0p4qu4-umRhZlF79XICLP4VzvwQ1FQO0E,33422
179
+ codegraphcontext-0.6.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
180
+ codegraphcontext-0.6.1.dist-info/entry_points.txt,sha256=LCxWCWMshdvYGoHBPuQZ8C-e4CiNSHCLXofrNSGHkoE,103
181
+ codegraphcontext-0.6.1.dist-info/top_level.txt,sha256=CBgc6LAPZIO5FS0nSYYkylDifHsZTIqw3Gf5UwDxeGI,17
182
+ codegraphcontext-0.6.1.dist-info/RECORD,,