mirror of
https://github.com/hanzoai/python-sdk.git
synced 2026-10-23 20:23:00 +00:00
fix: lint — ruff format and fix for hanzo-tools-ui and hanzo-mcp
This commit is contained in:
@@ -116,9 +116,7 @@ class SQLiteBackendPlugin:
|
||||
conn.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_memories_namespace ON memories(namespace);"
|
||||
)
|
||||
conn.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_memories_key ON memories(key);"
|
||||
)
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_memories_key ON memories(key);")
|
||||
conn.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_memories_ns_key ON memories(namespace, key);"
|
||||
)
|
||||
@@ -473,7 +471,9 @@ class SQLiteBackendPlugin:
|
||||
self._conn.commit()
|
||||
return True
|
||||
|
||||
async def history(self, key: str, namespace: str = "default") -> List[Dict[str, Any]]:
|
||||
async def history(
|
||||
self, key: str, namespace: str = "default"
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Show all versions/entries for a key within a namespace, ordered by creation time."""
|
||||
if not self._conn:
|
||||
raise RuntimeError("Plugin not initialized")
|
||||
|
||||
@@ -226,7 +226,9 @@ class PluginMemoryService:
|
||||
plugin = self._get_plugin()
|
||||
return await plugin.namespaces()
|
||||
|
||||
async def history(self, key: str, namespace: str = "default") -> List[Dict[str, Any]]:
|
||||
async def history(
|
||||
self, key: str, namespace: str = "default"
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Show all versions of a key."""
|
||||
await self._ensure_init()
|
||||
plugin = self._get_plugin()
|
||||
|
||||
@@ -15,18 +15,18 @@ import time
|
||||
from typing import Any, Awaitable, Callable
|
||||
|
||||
from zap.protocol import (
|
||||
HEADER_SIZE,
|
||||
MAX_MESSAGE_SIZE,
|
||||
MSG_HANDSHAKE,
|
||||
MSG_HANDSHAKE_OK,
|
||||
MSG_PING,
|
||||
MSG_PONG,
|
||||
MSG_REQUEST,
|
||||
MSG_RESPONSE,
|
||||
ZAP_PORTS,
|
||||
HEADER_SIZE,
|
||||
MAX_MESSAGE_SIZE,
|
||||
ZAP_MAGIC,
|
||||
encode,
|
||||
ZAP_PORTS,
|
||||
decode,
|
||||
encode,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -88,9 +88,7 @@ class ZapServer:
|
||||
for t in self.tools
|
||||
]
|
||||
|
||||
async def _read_frame(
|
||||
self, reader: asyncio.StreamReader
|
||||
) -> tuple[int, Any] | None:
|
||||
async def _read_frame(self, reader: asyncio.StreamReader) -> tuple[int, Any] | None:
|
||||
"""Read a single ZAP frame from the stream."""
|
||||
try:
|
||||
header = await reader.readexactly(HEADER_SIZE)
|
||||
@@ -102,6 +100,7 @@ class ZapServer:
|
||||
|
||||
msg_type = header[4]
|
||||
import struct
|
||||
|
||||
length = struct.unpack("!L", header[5:9])[0]
|
||||
|
||||
if length > MAX_MESSAGE_SIZE:
|
||||
@@ -113,6 +112,7 @@ class ZapServer:
|
||||
return None
|
||||
|
||||
import json
|
||||
|
||||
try:
|
||||
payload = json.loads(payload_bytes.decode("utf-8"))
|
||||
return (msg_type, payload)
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "hanzo-mcp"
|
||||
version = "0.15.0"
|
||||
version = "0.15.1"
|
||||
description = "The Zen of Hanzo MCP: One server to rule them all. The ultimate MCP that orchestrates all others."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
|
||||
@@ -11,8 +11,8 @@ import pytest
|
||||
@pytest.fixture
|
||||
async def memory_service():
|
||||
"""Create a PluginMemoryService with in-memory SQLite for testing."""
|
||||
from hanzo_mcp.memory_service import PluginMemoryService
|
||||
from hanzo_mcp.backends.sqlite_plugin import SQLiteBackendPlugin
|
||||
from hanzo_mcp.memory_service import PluginMemoryService
|
||||
|
||||
svc = PluginMemoryService()
|
||||
# Use true in-memory db — each test gets a fresh database
|
||||
@@ -152,7 +152,11 @@ class TestKeyBasedRetrieval:
|
||||
content="line1", metadata={}, key="append-key", namespace="test"
|
||||
)
|
||||
await memory_service.store_memory(
|
||||
content="\nline2", metadata={}, key="append-key", namespace="test", append=True
|
||||
content="\nline2",
|
||||
metadata={},
|
||||
key="append-key",
|
||||
namespace="test",
|
||||
append=True,
|
||||
)
|
||||
|
||||
result = await memory_service.get_by_key(key="append-key", namespace="test")
|
||||
@@ -176,7 +180,9 @@ class TestTagsSupport:
|
||||
async def test_list_memories_filter_by_tag(self, memory_service):
|
||||
await memory_service.store_memory(content="a", metadata={}, tags=["blue"])
|
||||
await memory_service.store_memory(content="b", metadata={}, tags=["red"])
|
||||
await memory_service.store_memory(content="c", metadata={}, tags=["blue", "red"])
|
||||
await memory_service.store_memory(
|
||||
content="c", metadata={}, tags=["blue", "red"]
|
||||
)
|
||||
|
||||
results = await memory_service.list_memories(tag="blue")
|
||||
assert len(results) == 2
|
||||
|
||||
@@ -184,9 +184,7 @@ class GitHubAPIClient:
|
||||
else:
|
||||
raise RuntimeError(f"GitHub API error: {resp.status_code}")
|
||||
|
||||
async def get_raw_content(
|
||||
self, owner: str, repo: str, path: str, branch: str
|
||||
) -> str:
|
||||
async def get_raw_content(self, owner: str, repo: str, path: str, branch: str) -> str:
|
||||
url = f"{GITHUB_RAW_BASE}/{owner}/{repo}/{branch}/{path}"
|
||||
cached = self._cache_get(url)
|
||||
if cached is not None:
|
||||
@@ -220,9 +218,7 @@ class GitHubAPIClient:
|
||||
config.owner, config.repo, index_path, config.branch
|
||||
)
|
||||
except FileNotFoundError:
|
||||
raise FileNotFoundError(
|
||||
f"Component '{name}' not found in {framework} repository"
|
||||
)
|
||||
raise FileNotFoundError(f"Component '{name}' not found in {framework} repository")
|
||||
|
||||
async def fetch_component_demo(self, name: str, framework: str = "hanzo") -> str:
|
||||
config = FRAMEWORK_CONFIGS[framework]
|
||||
@@ -246,6 +242,7 @@ class GitHubAPIClient:
|
||||
path = f"{config.components_path}/{name}/metadata.json"
|
||||
try:
|
||||
import json
|
||||
|
||||
content = await self.get_raw_content(config.owner, config.repo, path, config.branch)
|
||||
return json.loads(content)
|
||||
except (FileNotFoundError, Exception):
|
||||
@@ -271,9 +268,7 @@ class GitHubAPIClient:
|
||||
config.owner, config.repo, index_path, config.branch
|
||||
)
|
||||
except FileNotFoundError:
|
||||
raise FileNotFoundError(
|
||||
f"Block '{name}' not found in {framework} repository"
|
||||
)
|
||||
raise FileNotFoundError(f"Block '{name}' not found in {framework} repository")
|
||||
|
||||
async def list_components(self, framework: str = "hanzo") -> list[dict]:
|
||||
config = FRAMEWORK_CONFIGS[framework]
|
||||
@@ -306,9 +301,7 @@ class GitHubAPIClient:
|
||||
|
||||
async def get_directory_structure(self, path: str, framework: str = "hanzo") -> dict:
|
||||
config = FRAMEWORK_CONFIGS[framework]
|
||||
contents = await self.get_directory_contents(
|
||||
config.owner, config.repo, path, config.branch
|
||||
)
|
||||
contents = await self.get_directory_contents(config.owner, config.repo, path, config.branch)
|
||||
children = []
|
||||
for item in contents:
|
||||
entry = {"name": item["name"], "type": item["type"], "path": item["path"]}
|
||||
|
||||
@@ -80,17 +80,21 @@ class LocalUIClient:
|
||||
if entry.name.startswith("index"):
|
||||
continue
|
||||
if entry.is_dir():
|
||||
components.append({
|
||||
"name": entry.name,
|
||||
"type": "dir",
|
||||
"path": str(entry.relative_to(self._ui_path)),
|
||||
})
|
||||
components.append(
|
||||
{
|
||||
"name": entry.name,
|
||||
"type": "dir",
|
||||
"path": str(entry.relative_to(self._ui_path)),
|
||||
}
|
||||
)
|
||||
elif entry.is_file() and entry.suffix in COMPONENT_EXTENSIONS:
|
||||
components.append({
|
||||
"name": entry.stem,
|
||||
"type": "file",
|
||||
"path": str(entry.relative_to(self._ui_path)),
|
||||
})
|
||||
components.append(
|
||||
{
|
||||
"name": entry.stem,
|
||||
"type": "file",
|
||||
"path": str(entry.relative_to(self._ui_path)),
|
||||
}
|
||||
)
|
||||
return components
|
||||
|
||||
async def fetch_component(self, name: str, framework: str = "hanzo") -> str:
|
||||
@@ -279,12 +283,14 @@ class LocalUIClient:
|
||||
|
||||
name = entry.stem if entry.is_file() else entry.name
|
||||
if query_lower in name.lower():
|
||||
results.append({
|
||||
"name": name,
|
||||
"type": "dir" if entry.is_dir() else "file",
|
||||
"path": str(entry.relative_to(self._ui_path)),
|
||||
"match": "name",
|
||||
})
|
||||
results.append(
|
||||
{
|
||||
"name": name,
|
||||
"type": "dir" if entry.is_dir() else "file",
|
||||
"path": str(entry.relative_to(self._ui_path)),
|
||||
"match": "name",
|
||||
}
|
||||
)
|
||||
|
||||
# Also search src modules
|
||||
src_dir = self._ui_path / "pkg" / "ui" / "src"
|
||||
@@ -294,11 +300,13 @@ class LocalUIClient:
|
||||
continue
|
||||
name = entry.stem if entry.is_file() else entry.name
|
||||
if query_lower in name.lower() and name not in [r["name"] for r in results]:
|
||||
results.append({
|
||||
"name": name,
|
||||
"type": "dir" if entry.is_dir() else "file",
|
||||
"path": str(entry.relative_to(self._ui_path)),
|
||||
"match": "name",
|
||||
})
|
||||
results.append(
|
||||
{
|
||||
"name": name,
|
||||
"type": "dir" if entry.is_dir() else "file",
|
||||
"path": str(entry.relative_to(self._ui_path)),
|
||||
"match": "name",
|
||||
}
|
||||
)
|
||||
|
||||
return results
|
||||
|
||||
@@ -140,17 +140,13 @@ class RegistryCache:
|
||||
|
||||
# Metadata
|
||||
try:
|
||||
entry.metadata = await self._github.fetch_component_metadata(
|
||||
name, framework
|
||||
)
|
||||
entry.metadata = await self._github.fetch_component_metadata(name, framework)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Demo
|
||||
try:
|
||||
entry.demo = await self._github.fetch_component_demo(
|
||||
name, framework
|
||||
)
|
||||
entry.demo = await self._github.fetch_component_demo(name, framework)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@@ -175,9 +171,7 @@ class RegistryCache:
|
||||
b_entry = ComponentEntry(name=name, type=block.get("type", "file"))
|
||||
try:
|
||||
async with sem:
|
||||
b_entry.source = await self._github.fetch_block(
|
||||
name, framework
|
||||
)
|
||||
b_entry.source = await self._github.fetch_block(name, framework)
|
||||
except Exception:
|
||||
pass
|
||||
fw_data.blocks[name] = b_entry
|
||||
@@ -260,9 +254,7 @@ class RegistryCache:
|
||||
entry = self._fw(framework).components.get(name)
|
||||
return entry.demo if entry else None
|
||||
|
||||
def get_component_metadata(
|
||||
self, name: str, framework: str = "hanzo"
|
||||
) -> dict | None:
|
||||
def get_component_metadata(self, name: str, framework: str = "hanzo") -> dict | None:
|
||||
entry = self._fw(framework).components.get(name)
|
||||
return entry.metadata if entry else None
|
||||
|
||||
@@ -287,14 +279,10 @@ class RegistryCache:
|
||||
or q in entry.description.lower()
|
||||
or q in entry.category.lower()
|
||||
):
|
||||
results.append(
|
||||
{"name": entry.name, "type": entry.type, "match": "name"}
|
||||
)
|
||||
results.append({"name": entry.name, "type": entry.type, "match": "name"})
|
||||
return results
|
||||
|
||||
def get_structure(
|
||||
self, path: str, framework: str = "hanzo"
|
||||
) -> dict[str, Any] | None:
|
||||
def get_structure(self, path: str, framework: str = "hanzo") -> dict[str, Any] | None:
|
||||
return self._fw(framework).directory_cache.get(path)
|
||||
|
||||
def build_index(self, framework: str = "hanzo") -> dict:
|
||||
|
||||
@@ -29,9 +29,7 @@ class RegistryClient:
|
||||
|
||||
def __init__(self, base_url: str | None = None):
|
||||
self._base_url = (
|
||||
base_url
|
||||
or os.environ.get("HANZO_UI_REGISTRY_URL")
|
||||
or DEFAULT_REGISTRY_URL
|
||||
base_url or os.environ.get("HANZO_UI_REGISTRY_URL") or DEFAULT_REGISTRY_URL
|
||||
).rstrip("/")
|
||||
self._client: httpx.AsyncClient | None = None
|
||||
self._cache: dict[str, tuple[Any, float]] = {}
|
||||
@@ -130,7 +128,7 @@ class RegistryClient:
|
||||
try:
|
||||
data = await self._get("/api/registry/components.json")
|
||||
except Exception:
|
||||
data = await self._get("/api/registry", {"type": f"components:ui"})
|
||||
data = await self._get("/api/registry", {"type": "components:ui"})
|
||||
return data.get("components", [])
|
||||
|
||||
async def fetch_component(self, name: str, framework: str = "hanzo") -> str:
|
||||
@@ -160,9 +158,7 @@ class RegistryClient:
|
||||
raise FileNotFoundError(f"Demo for '{name}' not available")
|
||||
return source
|
||||
|
||||
async def fetch_component_metadata(
|
||||
self, name: str, framework: str = "hanzo"
|
||||
) -> dict:
|
||||
async def fetch_component_metadata(self, name: str, framework: str = "hanzo") -> dict:
|
||||
try:
|
||||
data = await self._get(f"/api/registry/components/{name}.json")
|
||||
except Exception:
|
||||
@@ -183,9 +179,7 @@ class RegistryClient:
|
||||
async def fetch_block(self, name: str, framework: str = "hanzo") -> str:
|
||||
return await self.fetch_component(name, framework)
|
||||
|
||||
async def search_components(
|
||||
self, query: str, framework: str = "hanzo"
|
||||
) -> list[dict]:
|
||||
async def search_components(self, query: str, framework: str = "hanzo") -> list[dict]:
|
||||
try:
|
||||
# Try server-mode search
|
||||
data = await self._get("/api/registry/search", {"q": query})
|
||||
@@ -208,16 +202,12 @@ class RegistryClient:
|
||||
if q in item.get("n", "").lower()
|
||||
]
|
||||
|
||||
async def get_directory_structure(
|
||||
self, path: str, framework: str = "hanzo"
|
||||
) -> dict:
|
||||
async def get_directory_structure(self, path: str, framework: str = "hanzo") -> dict:
|
||||
# Not available as static — return component list as structure
|
||||
comps = await self.list_components(framework)
|
||||
return {
|
||||
"path": path or "/",
|
||||
"children": [
|
||||
{"name": c["name"], "type": "file"} for c in comps
|
||||
],
|
||||
"children": [{"name": c["name"], "type": "file"} for c in comps],
|
||||
}
|
||||
|
||||
async def fetch_full_index(self, framework: str = "hanzo") -> dict:
|
||||
|
||||
@@ -9,14 +9,13 @@ Run:
|
||||
uvicorn hanzo_tools.ui.registry.server:app --port 8787
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from fastapi import FastAPI, HTTPException, Query
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse, ORJSONResponse
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from .cache import RegistryCache
|
||||
|
||||
@@ -105,9 +104,7 @@ async def get_component_demo(name: str, framework: str = Query(default="hanzo"))
|
||||
cache = get_cache()
|
||||
demo = cache.get_component_demo(name, framework)
|
||||
if demo is None:
|
||||
raise HTTPException(
|
||||
404, detail={"error": "Demo not found", "name": name}
|
||||
)
|
||||
raise HTTPException(404, detail={"error": "Demo not found", "name": name})
|
||||
return {"name": name, "demo": demo}
|
||||
|
||||
|
||||
@@ -146,15 +143,11 @@ async def search_components(
|
||||
|
||||
|
||||
@app.get("/api/structure")
|
||||
async def get_structure(
|
||||
path: str = Query(default=""), framework: str = Query(default="hanzo")
|
||||
):
|
||||
async def get_structure(path: str = Query(default=""), framework: str = Query(default="hanzo")):
|
||||
cache = get_cache()
|
||||
structure = cache.get_structure(path, framework)
|
||||
if structure is None:
|
||||
raise HTTPException(
|
||||
404, detail={"error": "Path not found in cache", "path": path}
|
||||
)
|
||||
raise HTTPException(404, detail={"error": "Path not found in cache", "path": path})
|
||||
return structure
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ Actions:
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
from typing import ClassVar
|
||||
|
||||
from mcp.server.fastmcp import Context as MCPContext
|
||||
@@ -131,7 +130,9 @@ Frameworks: hanzo (default), hanzo-native, hanzo-vue, hanzo-svelte,
|
||||
) -> dict:
|
||||
fw = framework or _current_framework
|
||||
if fw not in FRAMEWORK_CONFIGS:
|
||||
return {"error": f"Unknown framework: {fw}. Available: {', '.join(FRAMEWORK_CONFIGS)}"}
|
||||
return {
|
||||
"error": f"Unknown framework: {fw}. Available: {', '.join(FRAMEWORK_CONFIGS)}"
|
||||
}
|
||||
|
||||
if self._use_local(fw):
|
||||
components = await self._local.list_components(fw)
|
||||
@@ -491,7 +492,9 @@ Frameworks: hanzo (default), hanzo-native, hanzo-vue, hanzo-svelte,
|
||||
@self.action("list_packages", "List all UI packages (local only)")
|
||||
async def list_packages(ctx: MCPContext) -> dict:
|
||||
if not self._local.available:
|
||||
return {"error": "Local hanzo/ui repo not found. Set HANZO_UI_PATH or clone to ~/work/hanzo/ui"}
|
||||
return {
|
||||
"error": "Local hanzo/ui repo not found. Set HANZO_UI_PATH or clone to ~/work/hanzo/ui"
|
||||
}
|
||||
|
||||
packages = await self._local.list_packages()
|
||||
return {
|
||||
@@ -511,7 +514,9 @@ Frameworks: hanzo (default), hanzo-native, hanzo-vue, hanzo-svelte,
|
||||
return {"error": "File path is required (relative to hanzo/ui root)"}
|
||||
|
||||
if not self._local.available:
|
||||
return {"error": "Local hanzo/ui repo not found. Set HANZO_UI_PATH or clone to ~/work/hanzo/ui"}
|
||||
return {
|
||||
"error": "Local hanzo/ui repo not found. Set HANZO_UI_PATH or clone to ~/work/hanzo/ui"
|
||||
}
|
||||
|
||||
content = await self._local.read_file(file_path)
|
||||
return {
|
||||
@@ -533,6 +538,7 @@ Frameworks: hanzo (default), hanzo-native, hanzo-vue, hanzo-svelte,
|
||||
return {"error": "Question is required"}
|
||||
|
||||
from .vector_index import chat_about_components
|
||||
|
||||
return await chat_about_components(q)
|
||||
|
||||
@self.action("semantic_search", "Semantic search over UI components (Hanzo Cloud)")
|
||||
@@ -548,17 +554,20 @@ Frameworks: hanzo (default), hanzo-native, hanzo-vue, hanzo-svelte,
|
||||
return {"error": "Query is required"}
|
||||
|
||||
from .vector_index import search_components
|
||||
|
||||
results = await search_components(q, limit=limit, tags=tags)
|
||||
return {"query": q, "results": results}
|
||||
|
||||
@self.action("index_status", "Check search index status")
|
||||
async def index_status(ctx: MCPContext) -> dict:
|
||||
from .vector_index import get_index_stats
|
||||
|
||||
return await get_index_stats()
|
||||
|
||||
@self.action("rebuild_index", "Re-index UI components into Hanzo Cloud search")
|
||||
async def rebuild_index(ctx: MCPContext) -> dict:
|
||||
from .vector_index import index_from_local, index_from_registry
|
||||
|
||||
if self._local.available:
|
||||
return await index_from_local()
|
||||
return await index_from_registry()
|
||||
|
||||
@@ -8,7 +8,6 @@ Uses the Hanzo Cloud RAG pipeline:
|
||||
Authentication: publishable key (pk-*) for read, API key (hk-*) for write.
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from typing import Any
|
||||
@@ -146,15 +145,17 @@ async def index_components(
|
||||
if source:
|
||||
content_parts.append(f"\nSource code:\n{source}")
|
||||
|
||||
documents.append({
|
||||
"id": f"component-{name}",
|
||||
"page_id": name,
|
||||
"title": name.replace("-", " ").title(),
|
||||
"url": f"https://ui.hanzo.ai/components/{name}",
|
||||
"content": "\n".join(content_parts),
|
||||
"section": comp_type.split(":")[-1] if ":" in comp_type else "ui",
|
||||
"tag": comp_type,
|
||||
})
|
||||
documents.append(
|
||||
{
|
||||
"id": f"component-{name}",
|
||||
"page_id": name,
|
||||
"title": name.replace("-", " ").title(),
|
||||
"url": f"https://ui.hanzo.ai/components/{name}",
|
||||
"content": "\n".join(content_parts),
|
||||
"section": comp_type.split(":")[-1] if ":" in comp_type else "ui",
|
||||
"tag": comp_type,
|
||||
}
|
||||
)
|
||||
|
||||
admin_key = ADMIN_KEY or os.environ.get("HANZO_API_KEY", "")
|
||||
if not admin_key:
|
||||
@@ -204,11 +205,13 @@ async def index_from_local(ui_path: str | None = None) -> dict:
|
||||
name = comp["name"]
|
||||
try:
|
||||
source = await local.fetch_component(name)
|
||||
components.append({
|
||||
"name": name,
|
||||
"type": comp.get("type", "file"),
|
||||
"source": source,
|
||||
})
|
||||
components.append(
|
||||
{
|
||||
"name": name,
|
||||
"type": comp.get("type", "file"),
|
||||
"source": source,
|
||||
}
|
||||
)
|
||||
except Exception as e:
|
||||
logger.debug("Skipping %s: %s", name, e)
|
||||
|
||||
@@ -244,13 +247,15 @@ async def index_from_registry(registry_url: str | None = None) -> dict:
|
||||
if isinstance(first, dict):
|
||||
source = first.get("content", "")
|
||||
|
||||
components.append({
|
||||
"name": name,
|
||||
"type": data.get("type", ""),
|
||||
"source": source,
|
||||
"dependencies": data.get("dependencies", []),
|
||||
"registryDependencies": data.get("registryDependencies", []),
|
||||
})
|
||||
components.append(
|
||||
{
|
||||
"name": name,
|
||||
"type": data.get("type", ""),
|
||||
"source": source,
|
||||
"dependencies": data.get("dependencies", []),
|
||||
"registryDependencies": data.get("registryDependencies", []),
|
||||
}
|
||||
)
|
||||
|
||||
await client.close()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user