mcp-vector-search 0.9.3__py3-none-any.whl → 0.12.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.
Potentially problematic release.
This version of mcp-vector-search might be problematic. Click here for more details.
- mcp_vector_search/__init__.py +2 -2
- mcp_vector_search/cli/commands/index.py +44 -22
- mcp_vector_search/cli/commands/install.py +502 -523
- mcp_vector_search/cli/commands/install_old.py +696 -0
- mcp_vector_search/cli/commands/status.py +7 -5
- mcp_vector_search/cli/commands/uninstall.py +485 -0
- mcp_vector_search/cli/commands/visualize.py +677 -53
- mcp_vector_search/cli/didyoumean.py +10 -0
- mcp_vector_search/cli/main.py +39 -21
- mcp_vector_search/core/connection_pool.py +49 -11
- mcp_vector_search/core/database.py +61 -28
- mcp_vector_search/core/directory_index.py +318 -0
- mcp_vector_search/core/indexer.py +146 -19
- mcp_vector_search/core/models.py +61 -0
- mcp_vector_search/core/project.py +16 -5
- mcp_vector_search/parsers/base.py +54 -18
- mcp_vector_search/parsers/javascript.py +41 -20
- mcp_vector_search/parsers/python.py +19 -11
- mcp_vector_search/parsers/registry.py +3 -2
- mcp_vector_search/utils/gitignore.py +17 -5
- mcp_vector_search/visualization/index.html +658 -0
- {mcp_vector_search-0.9.3.dist-info → mcp_vector_search-0.12.1.dist-info}/METADATA +87 -24
- {mcp_vector_search-0.9.3.dist-info → mcp_vector_search-0.12.1.dist-info}/RECORD +26 -22
- {mcp_vector_search-0.9.3.dist-info → mcp_vector_search-0.12.1.dist-info}/WHEEL +0 -0
- {mcp_vector_search-0.9.3.dist-info → mcp_vector_search-0.12.1.dist-info}/entry_points.txt +0 -0
- {mcp_vector_search-0.9.3.dist-info → mcp_vector_search-0.12.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -57,6 +57,11 @@ class EnhancedDidYouMeanTyper(typer.Typer):
|
|
|
57
57
|
# Get the underlying click group
|
|
58
58
|
click_group = super().__call__(*args, **kwargs)
|
|
59
59
|
|
|
60
|
+
# If click_group is None (command already executed), return None
|
|
61
|
+
# This happens after command execution completes successfully
|
|
62
|
+
if click_group is None:
|
|
63
|
+
return None
|
|
64
|
+
|
|
60
65
|
# Create enhanced DYM group with original group's properties
|
|
61
66
|
enhanced_group = EnhancedDidYouMeanGroup(
|
|
62
67
|
name=click_group.name,
|
|
@@ -161,6 +166,11 @@ def enhance_existing_typer(app: typer.Typer) -> typer.Typer:
|
|
|
161
166
|
"""Enhanced call that uses EnhancedDidYouMeanGroup."""
|
|
162
167
|
click_group = original_call(*args, **kwargs)
|
|
163
168
|
|
|
169
|
+
# If click_group is None (command already executed), return None
|
|
170
|
+
# This happens after command execution completes successfully
|
|
171
|
+
if click_group is None:
|
|
172
|
+
return None
|
|
173
|
+
|
|
164
174
|
# Create enhanced group
|
|
165
175
|
enhanced_group = EnhancedDidYouMeanGroup(
|
|
166
176
|
name=click_group.name,
|
mcp_vector_search/cli/main.py
CHANGED
|
@@ -33,13 +33,15 @@ unfamiliar codebases, finding similar patterns, and integrating with AI tools.
|
|
|
33
33
|
3. Check status: [green]mcp-vector-search status[/green]
|
|
34
34
|
|
|
35
35
|
[bold cyan]Main Commands:[/bold cyan]
|
|
36
|
-
|
|
36
|
+
install 📦 Install project and MCP integrations
|
|
37
|
+
uninstall 🗑️ Remove MCP integrations
|
|
38
|
+
init 🔧 Initialize project (simple)
|
|
37
39
|
demo 🎬 Run interactive demo
|
|
38
40
|
doctor 🩺 Check system health
|
|
39
41
|
status 📊 Show project status
|
|
40
42
|
search 🔍 Search code semantically
|
|
41
43
|
index 📇 Index codebase
|
|
42
|
-
mcp
|
|
44
|
+
mcp 🔌 MCP server operations
|
|
43
45
|
config ⚙️ Configure settings
|
|
44
46
|
visualize 📊 Visualize code relationships
|
|
45
47
|
help ❓ Get help
|
|
@@ -56,48 +58,61 @@ from .commands.config import config_app # noqa: E402
|
|
|
56
58
|
from .commands.demo import demo_app # noqa: E402
|
|
57
59
|
from .commands.index import index_app # noqa: E402
|
|
58
60
|
from .commands.init import init_app # noqa: E402
|
|
61
|
+
from .commands.install import install_app # noqa: E402
|
|
59
62
|
from .commands.mcp import mcp_app # noqa: E402
|
|
60
63
|
from .commands.search import search_app, search_main # noqa: E402, F401
|
|
61
64
|
from .commands.status import main as status_main # noqa: E402
|
|
65
|
+
from .commands.uninstall import uninstall_app # noqa: E402
|
|
62
66
|
from .commands.visualize import app as visualize_app # noqa: E402
|
|
63
67
|
|
|
64
68
|
# ============================================================================
|
|
65
69
|
# MAIN COMMANDS - Clean hierarchy
|
|
66
70
|
# ============================================================================
|
|
67
71
|
|
|
68
|
-
# 1.
|
|
72
|
+
# 1. INSTALL - Install project and MCP integrations (NEW!)
|
|
73
|
+
app.add_typer(
|
|
74
|
+
install_app, name="install", help="📦 Install project and MCP integrations"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# 2. UNINSTALL - Remove MCP integrations (NEW!)
|
|
78
|
+
app.add_typer(uninstall_app, name="uninstall", help="🗑️ Remove MCP integrations")
|
|
79
|
+
app.add_typer(uninstall_app, name="remove", help="🗑️ Remove MCP integrations (alias)")
|
|
80
|
+
|
|
81
|
+
# 3. INIT - Initialize project (simplified)
|
|
69
82
|
# Use Typer group for init to support both direct call and subcommands
|
|
70
83
|
app.add_typer(init_app, name="init", help="🔧 Initialize project for semantic search")
|
|
71
84
|
|
|
72
|
-
#
|
|
85
|
+
# 4. DEMO - Interactive demo
|
|
73
86
|
app.add_typer(demo_app, name="demo", help="🎬 Run interactive demo with sample project")
|
|
74
87
|
|
|
75
|
-
#
|
|
88
|
+
# 5. DOCTOR - System health check
|
|
76
89
|
# (defined below inline)
|
|
77
90
|
|
|
78
|
-
#
|
|
91
|
+
# 6. STATUS - Project status
|
|
79
92
|
app.command("status", help="📊 Show project status and statistics")(status_main)
|
|
80
93
|
|
|
81
|
-
#
|
|
94
|
+
# 7. SEARCH - Search code
|
|
82
95
|
# Register search as both a command and a typer group
|
|
83
96
|
app.add_typer(search_app, name="search", help="🔍 Search code semantically")
|
|
84
97
|
|
|
85
|
-
#
|
|
98
|
+
# 8. INDEX - Index codebase
|
|
86
99
|
app.add_typer(index_app, name="index", help="📇 Index codebase for semantic search")
|
|
87
100
|
|
|
88
|
-
#
|
|
89
|
-
app.add_typer(mcp_app, name="mcp", help="
|
|
101
|
+
# 9. MCP - MCP server operations (RESERVED for server ops only!)
|
|
102
|
+
app.add_typer(mcp_app, name="mcp", help="🔌 MCP server operations")
|
|
90
103
|
|
|
91
|
-
#
|
|
104
|
+
# 10. CONFIG - Configuration
|
|
92
105
|
app.add_typer(config_app, name="config", help="⚙️ Manage project configuration")
|
|
93
106
|
|
|
94
|
-
#
|
|
95
|
-
app.add_typer(
|
|
107
|
+
# 11. VISUALIZE - Code graph visualization
|
|
108
|
+
app.add_typer(
|
|
109
|
+
visualize_app, name="visualize", help="📊 Visualize code chunk relationships"
|
|
110
|
+
)
|
|
96
111
|
|
|
97
|
-
#
|
|
112
|
+
# 12. HELP - Enhanced help
|
|
98
113
|
# (defined below inline)
|
|
99
114
|
|
|
100
|
-
#
|
|
115
|
+
# 13. VERSION - Version info
|
|
101
116
|
# (defined below inline)
|
|
102
117
|
|
|
103
118
|
|
|
@@ -120,11 +135,9 @@ def _deprecated_command(old_cmd: str, new_cmd: str):
|
|
|
120
135
|
return wrapper
|
|
121
136
|
|
|
122
137
|
|
|
123
|
-
#
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
"""[DEPRECATED] Use 'init' instead."""
|
|
127
|
-
_deprecated_command("install", "init")()
|
|
138
|
+
# NOTE: 'install' command is now the primary command for project installation
|
|
139
|
+
# Old 'install' was deprecated in favor of 'init' in v0.7.0
|
|
140
|
+
# Now 'install' is back as the hierarchical installation command in v0.13.0
|
|
128
141
|
|
|
129
142
|
|
|
130
143
|
# Deprecated: find -> search
|
|
@@ -432,7 +445,12 @@ def cli_with_suggestions():
|
|
|
432
445
|
except Exception as e:
|
|
433
446
|
# For other exceptions, show error and exit if verbose logging is enabled
|
|
434
447
|
# Suppress internal framework errors in normal operation
|
|
435
|
-
|
|
448
|
+
|
|
449
|
+
# Suppress harmless didyoumean framework AttributeError (known issue)
|
|
450
|
+
# This occurs during Click/Typer cleanup after successful command completion
|
|
451
|
+
if isinstance(e, AttributeError) and "attribute" in str(e) and "name" in str(e):
|
|
452
|
+
pass # Ignore - this is a harmless framework cleanup error
|
|
453
|
+
elif "--verbose" in sys.argv or "-v" in sys.argv:
|
|
436
454
|
click.echo(f"Unexpected error: {e}", err=True)
|
|
437
455
|
sys.exit(1)
|
|
438
456
|
# Otherwise, just exit silently to avoid confusing error messages
|
|
@@ -24,6 +24,16 @@ class PooledConnection:
|
|
|
24
24
|
in_use: bool = False
|
|
25
25
|
use_count: int = 0
|
|
26
26
|
|
|
27
|
+
@property
|
|
28
|
+
def age(self) -> float:
|
|
29
|
+
"""Get the age of this connection in seconds."""
|
|
30
|
+
return time.time() - self.created_at
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def idle_time(self) -> float:
|
|
34
|
+
"""Get the idle time of this connection in seconds."""
|
|
35
|
+
return time.time() - self.last_used
|
|
36
|
+
|
|
27
37
|
|
|
28
38
|
class ChromaConnectionPool:
|
|
29
39
|
"""Connection pool for ChromaDB operations."""
|
|
@@ -209,18 +219,18 @@ class ChromaConnectionPool:
|
|
|
209
219
|
logger.debug(f"Created new connection (pool size: {len(self._pool)})")
|
|
210
220
|
return conn
|
|
211
221
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
"Connection pool exhausted, waiting for available connection"
|
|
216
|
-
)
|
|
222
|
+
# Pool is full, wait for a connection to become available (outside lock)
|
|
223
|
+
self._stats["pool_misses"] += 1
|
|
224
|
+
logger.warning("Connection pool exhausted, waiting for available connection")
|
|
217
225
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
226
|
+
# Wait for a connection (with timeout) - release lock during wait
|
|
227
|
+
timeout = 30.0 # 30 seconds
|
|
228
|
+
start_time = time.time()
|
|
221
229
|
|
|
222
|
-
|
|
223
|
-
|
|
230
|
+
while time.time() - start_time < timeout:
|
|
231
|
+
await asyncio.sleep(0.1)
|
|
232
|
+
# Re-acquire lock to check for available connections
|
|
233
|
+
async with self._lock:
|
|
224
234
|
for conn in self._pool:
|
|
225
235
|
if not conn.in_use and self._is_connection_valid(conn):
|
|
226
236
|
conn.in_use = True
|
|
@@ -229,7 +239,7 @@ class ChromaConnectionPool:
|
|
|
229
239
|
self._stats["connections_reused"] += 1
|
|
230
240
|
return conn
|
|
231
241
|
|
|
232
|
-
|
|
242
|
+
raise DatabaseError("Connection pool timeout: no connections available")
|
|
233
243
|
|
|
234
244
|
async def _release_connection(self, conn: PooledConnection) -> None:
|
|
235
245
|
"""Release a connection back to the pool."""
|
|
@@ -320,3 +330,31 @@ class ChromaConnectionPool:
|
|
|
320
330
|
except Exception as e:
|
|
321
331
|
logger.error(f"Connection pool health check failed: {e}")
|
|
322
332
|
return False
|
|
333
|
+
|
|
334
|
+
# Backward compatibility aliases for old test API
|
|
335
|
+
async def cleanup(self) -> None:
|
|
336
|
+
"""Alias for close() method (backward compatibility)."""
|
|
337
|
+
await self.close()
|
|
338
|
+
|
|
339
|
+
def _validate_connection(self, conn: PooledConnection) -> bool:
|
|
340
|
+
"""Alias for _is_connection_valid() method (backward compatibility)."""
|
|
341
|
+
return self._is_connection_valid(conn)
|
|
342
|
+
|
|
343
|
+
async def _cleanup_idle_connections(self) -> None:
|
|
344
|
+
"""Alias for _cleanup_expired_connections() method (backward compatibility)."""
|
|
345
|
+
await self._cleanup_expired_connections()
|
|
346
|
+
|
|
347
|
+
@property
|
|
348
|
+
def _connections(self) -> list[PooledConnection]:
|
|
349
|
+
"""Alias for _pool attribute (backward compatibility)."""
|
|
350
|
+
return self._pool
|
|
351
|
+
|
|
352
|
+
@property
|
|
353
|
+
def _max_connections(self) -> int:
|
|
354
|
+
"""Alias for max_connections attribute (backward compatibility)."""
|
|
355
|
+
return self.max_connections
|
|
356
|
+
|
|
357
|
+
@property
|
|
358
|
+
def _min_connections(self) -> int:
|
|
359
|
+
"""Alias for min_connections attribute (backward compatibility)."""
|
|
360
|
+
return self.min_connections
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Database abstraction and ChromaDB implementation for MCP Vector Search."""
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
+
import json
|
|
4
5
|
import shutil
|
|
5
6
|
from abc import ABC, abstractmethod
|
|
6
7
|
from pathlib import Path
|
|
@@ -273,16 +274,16 @@ class ChromaVectorDatabase(VectorDatabase):
|
|
|
273
274
|
"class_name": chunk.class_name or "",
|
|
274
275
|
"docstring": chunk.docstring or "",
|
|
275
276
|
"complexity_score": chunk.complexity_score,
|
|
276
|
-
# Hierarchy fields
|
|
277
|
+
# Hierarchy fields (convert lists to JSON strings for ChromaDB)
|
|
277
278
|
"chunk_id": chunk.chunk_id or "",
|
|
278
279
|
"parent_chunk_id": chunk.parent_chunk_id or "",
|
|
279
|
-
"child_chunk_ids": chunk.child_chunk_ids or [],
|
|
280
|
+
"child_chunk_ids": json.dumps(chunk.child_chunk_ids or []),
|
|
280
281
|
"chunk_depth": chunk.chunk_depth,
|
|
281
|
-
# Additional metadata
|
|
282
|
-
"decorators": chunk.decorators or [],
|
|
283
|
-
"parameters": chunk.parameters or [],
|
|
282
|
+
# Additional metadata (convert lists/dicts to JSON strings)
|
|
283
|
+
"decorators": json.dumps(chunk.decorators or []),
|
|
284
|
+
"parameters": json.dumps(chunk.parameters or []),
|
|
284
285
|
"return_type": chunk.return_type or "",
|
|
285
|
-
"type_annotations": chunk.type_annotations or {},
|
|
286
|
+
"type_annotations": json.dumps(chunk.type_annotations or {}),
|
|
286
287
|
# Monorepo support
|
|
287
288
|
"subproject_name": chunk.subproject_name or "",
|
|
288
289
|
"subproject_path": chunk.subproject_path or "",
|
|
@@ -500,16 +501,31 @@ class ChromaVectorDatabase(VectorDatabase):
|
|
|
500
501
|
|
|
501
502
|
try:
|
|
502
503
|
# Get all documents from collection
|
|
503
|
-
results = self._collection.get(
|
|
504
|
-
include=["metadatas", "documents"]
|
|
505
|
-
)
|
|
504
|
+
results = self._collection.get(include=["metadatas", "documents"])
|
|
506
505
|
|
|
507
506
|
chunks = []
|
|
508
507
|
if results and results.get("ids"):
|
|
509
|
-
for i,
|
|
508
|
+
for i, _chunk_id in enumerate(results["ids"]):
|
|
510
509
|
metadata = results["metadatas"][i]
|
|
511
510
|
content = results["documents"][i]
|
|
512
511
|
|
|
512
|
+
# Parse JSON strings back to lists/dicts
|
|
513
|
+
child_chunk_ids = metadata.get("child_chunk_ids", "[]")
|
|
514
|
+
if isinstance(child_chunk_ids, str):
|
|
515
|
+
child_chunk_ids = json.loads(child_chunk_ids)
|
|
516
|
+
|
|
517
|
+
decorators = metadata.get("decorators", "[]")
|
|
518
|
+
if isinstance(decorators, str):
|
|
519
|
+
decorators = json.loads(decorators)
|
|
520
|
+
|
|
521
|
+
parameters = metadata.get("parameters", "[]")
|
|
522
|
+
if isinstance(parameters, str):
|
|
523
|
+
parameters = json.loads(parameters)
|
|
524
|
+
|
|
525
|
+
type_annotations = metadata.get("type_annotations", "{}")
|
|
526
|
+
if isinstance(type_annotations, str):
|
|
527
|
+
type_annotations = json.loads(type_annotations)
|
|
528
|
+
|
|
513
529
|
chunk = CodeChunk(
|
|
514
530
|
content=content,
|
|
515
531
|
file_path=Path(metadata["file_path"]),
|
|
@@ -524,12 +540,12 @@ class ChromaVectorDatabase(VectorDatabase):
|
|
|
524
540
|
complexity_score=metadata.get("complexity_score", 0.0),
|
|
525
541
|
chunk_id=metadata.get("chunk_id"),
|
|
526
542
|
parent_chunk_id=metadata.get("parent_chunk_id"),
|
|
527
|
-
child_chunk_ids=
|
|
543
|
+
child_chunk_ids=child_chunk_ids,
|
|
528
544
|
chunk_depth=metadata.get("chunk_depth", 0),
|
|
529
|
-
decorators=
|
|
530
|
-
parameters=
|
|
545
|
+
decorators=decorators,
|
|
546
|
+
parameters=parameters,
|
|
531
547
|
return_type=metadata.get("return_type"),
|
|
532
|
-
type_annotations=
|
|
548
|
+
type_annotations=type_annotations,
|
|
533
549
|
subproject_name=metadata.get("subproject_name"),
|
|
534
550
|
subproject_path=metadata.get("subproject_path"),
|
|
535
551
|
)
|
|
@@ -775,16 +791,18 @@ class PooledChromaVectorDatabase(VectorDatabase):
|
|
|
775
791
|
"class_name": chunk.class_name or "",
|
|
776
792
|
"docstring": chunk.docstring or "",
|
|
777
793
|
"complexity_score": chunk.complexity_score,
|
|
778
|
-
# Hierarchy fields
|
|
794
|
+
# Hierarchy fields (convert lists to JSON strings for ChromaDB)
|
|
779
795
|
"chunk_id": chunk.chunk_id or "",
|
|
780
796
|
"parent_chunk_id": chunk.parent_chunk_id or "",
|
|
781
|
-
"child_chunk_ids": chunk.child_chunk_ids or [],
|
|
797
|
+
"child_chunk_ids": json.dumps(chunk.child_chunk_ids or []),
|
|
782
798
|
"chunk_depth": chunk.chunk_depth,
|
|
783
|
-
# Additional metadata
|
|
784
|
-
"decorators": chunk.decorators or [],
|
|
785
|
-
"parameters": chunk.parameters or [],
|
|
799
|
+
# Additional metadata (convert lists/dicts to JSON strings)
|
|
800
|
+
"decorators": json.dumps(chunk.decorators or []),
|
|
801
|
+
"parameters": json.dumps(chunk.parameters or []),
|
|
786
802
|
"return_type": chunk.return_type or "",
|
|
787
|
-
"type_annotations":
|
|
803
|
+
"type_annotations": json.dumps(
|
|
804
|
+
chunk.type_annotations or {}
|
|
805
|
+
),
|
|
788
806
|
# Monorepo support
|
|
789
807
|
"subproject_name": chunk.subproject_name or "",
|
|
790
808
|
"subproject_path": chunk.subproject_path or "",
|
|
@@ -1013,16 +1031,31 @@ class PooledChromaVectorDatabase(VectorDatabase):
|
|
|
1013
1031
|
try:
|
|
1014
1032
|
async with self._pool.get_connection() as conn:
|
|
1015
1033
|
# Get all documents from collection
|
|
1016
|
-
results = conn.collection.get(
|
|
1017
|
-
include=["metadatas", "documents"]
|
|
1018
|
-
)
|
|
1034
|
+
results = conn.collection.get(include=["metadatas", "documents"])
|
|
1019
1035
|
|
|
1020
1036
|
chunks = []
|
|
1021
1037
|
if results and results.get("ids"):
|
|
1022
|
-
for i,
|
|
1038
|
+
for i, _chunk_id in enumerate(results["ids"]):
|
|
1023
1039
|
metadata = results["metadatas"][i]
|
|
1024
1040
|
content = results["documents"][i]
|
|
1025
1041
|
|
|
1042
|
+
# Parse JSON strings back to lists/dicts
|
|
1043
|
+
child_chunk_ids = metadata.get("child_chunk_ids", "[]")
|
|
1044
|
+
if isinstance(child_chunk_ids, str):
|
|
1045
|
+
child_chunk_ids = json.loads(child_chunk_ids)
|
|
1046
|
+
|
|
1047
|
+
decorators = metadata.get("decorators", "[]")
|
|
1048
|
+
if isinstance(decorators, str):
|
|
1049
|
+
decorators = json.loads(decorators)
|
|
1050
|
+
|
|
1051
|
+
parameters = metadata.get("parameters", "[]")
|
|
1052
|
+
if isinstance(parameters, str):
|
|
1053
|
+
parameters = json.loads(parameters)
|
|
1054
|
+
|
|
1055
|
+
type_annotations = metadata.get("type_annotations", "{}")
|
|
1056
|
+
if isinstance(type_annotations, str):
|
|
1057
|
+
type_annotations = json.loads(type_annotations)
|
|
1058
|
+
|
|
1026
1059
|
chunk = CodeChunk(
|
|
1027
1060
|
content=content,
|
|
1028
1061
|
file_path=Path(metadata["file_path"]),
|
|
@@ -1037,12 +1070,12 @@ class PooledChromaVectorDatabase(VectorDatabase):
|
|
|
1037
1070
|
complexity_score=metadata.get("complexity_score", 0.0),
|
|
1038
1071
|
chunk_id=metadata.get("chunk_id"),
|
|
1039
1072
|
parent_chunk_id=metadata.get("parent_chunk_id"),
|
|
1040
|
-
child_chunk_ids=
|
|
1073
|
+
child_chunk_ids=child_chunk_ids,
|
|
1041
1074
|
chunk_depth=metadata.get("chunk_depth", 0),
|
|
1042
|
-
decorators=
|
|
1043
|
-
parameters=
|
|
1075
|
+
decorators=decorators,
|
|
1076
|
+
parameters=parameters,
|
|
1044
1077
|
return_type=metadata.get("return_type"),
|
|
1045
|
-
type_annotations=
|
|
1078
|
+
type_annotations=type_annotations,
|
|
1046
1079
|
subproject_name=metadata.get("subproject_name"),
|
|
1047
1080
|
subproject_path=metadata.get("subproject_path"),
|
|
1048
1081
|
)
|