compass-code 0.1.0__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.
- compass_cli/__init__.py +0 -0
- compass_cli/commands/__init__.py +0 -0
- compass_cli/commands/ingest.py +310 -0
- compass_cli/commands/mcp.py +25 -0
- compass_cli/commands/query.py +181 -0
- compass_cli/commands/serve.py +123 -0
- compass_cli/commands/setup.py +171 -0
- compass_cli/display.py +231 -0
- compass_cli/errors.py +30 -0
- compass_cli/main.py +54 -0
- compass_cli/progress.py +191 -0
- compass_cli/result_views.py +389 -0
- compass_cli/types.py +41 -0
- compass_code-0.1.0.dist-info/METADATA +72 -0
- compass_code-0.1.0.dist-info/RECORD +137 -0
- compass_code-0.1.0.dist-info/WHEEL +4 -0
- compass_code-0.1.0.dist-info/entry_points.txt +2 -0
- compass_core/__init__.py +1 -0
- compass_core/contract/__init__.py +6 -0
- compass_core/contract/errors.py +116 -0
- compass_core/contract/models.py +204 -0
- compass_core/contract/params.py +99 -0
- compass_core/contract/results.py +370 -0
- compass_core/contract/serialize.py +59 -0
- compass_core/contract/types.py +76 -0
- compass_core/errors.py +148 -0
- compass_core/graph/__init__.py +0 -0
- compass_core/graph/db.py +205 -0
- compass_core/graph/schema.py +165 -0
- compass_core/graph/stored_ids.py +133 -0
- compass_core/graph/writer.py +482 -0
- compass_core/index/__init__.py +1 -0
- compass_core/index/freshness.py +55 -0
- compass_core/index/locate.py +155 -0
- compass_core/index/metadata.py +107 -0
- compass_core/ir/__init__.py +0 -0
- compass_core/ir/graph.py +65 -0
- compass_core/ir/models.py +75 -0
- compass_core/languages/__init__.py +1 -0
- compass_core/languages/base.py +26 -0
- compass_core/languages/python/__init__.py +6 -0
- compass_core/languages/python/extractor.py +670 -0
- compass_core/languages/python/import_resolver.py +107 -0
- compass_core/languages/registry.py +89 -0
- compass_core/logger.py +42 -0
- compass_core/phases/__init__.py +0 -0
- compass_core/phases/base.py +58 -0
- compass_core/phases/discovery.py +167 -0
- compass_core/phases/parse.py +80 -0
- compass_core/phases/persistence.py +33 -0
- compass_core/phases/pipeline.py +152 -0
- compass_core/phases/resolution.py +572 -0
- compass_core/phases/symbol_table.py +36 -0
- compass_core/phases/validation.py +76 -0
- compass_core/progress.py +45 -0
- compass_core/py.typed +0 -0
- compass_core/query/__init__.py +1 -0
- compass_core/query/cypher.py +92 -0
- compass_core/query/detail.py +241 -0
- compass_core/query/graph_map.py +127 -0
- compass_core/query/impact.py +273 -0
- compass_core/query/impact_walk.py +352 -0
- compass_core/query/overview.py +221 -0
- compass_core/query/references.py +235 -0
- compass_core/query/rows.py +378 -0
- compass_core/query/search.py +183 -0
- compass_core/query/status.py +49 -0
- compass_core/query/walk_queries.py +202 -0
- compass_core/render.py +408 -0
- compass_core/settings.py +61 -0
- compass_core/shared_types.py +78 -0
- compass_mcp/__init__.py +0 -0
- compass_mcp/guide.py +45 -0
- compass_mcp/py.typed +0 -0
- compass_mcp/server.py +261 -0
- compass_server/__init__.py +5 -0
- compass_server/errors.py +84 -0
- compass_server/main.py +42 -0
- compass_server/py.typed +0 -0
- compass_server/routers/__init__.py +0 -0
- compass_server/routers/query.py +182 -0
- compass_server/settings.py +37 -0
- compass_server/static/404.html +1 -0
- compass_server/static/_next/static/chunks/1629039a.eed2a06658ec4f9c.js +1 -0
- compass_server/static/_next/static/chunks/1ff282bf-bb7c483245264fc9.js +1 -0
- compass_server/static/_next/static/chunks/223.f881a22f446259bf.js +508 -0
- compass_server/static/_next/static/chunks/51fa5c19.6396973222c9d6fd.js +485 -0
- compass_server/static/_next/static/chunks/556.443c1682b6b20128.js +1 -0
- compass_server/static/_next/static/chunks/684-1aa0170f59baf77e.js +1 -0
- compass_server/static/_next/static/chunks/92e71660.3a42d4f70d017951.js +342 -0
- compass_server/static/_next/static/chunks/937-8692224bb6d1b605.js +1 -0
- compass_server/static/_next/static/chunks/app/_not-found/page-2c96ddf295eb6a86.js +1 -0
- compass_server/static/_next/static/chunks/app/layout-4bd0ba4a7d18aff9.js +1 -0
- compass_server/static/_next/static/chunks/app/page-5376a0a98bbd1faa.js +1 -0
- compass_server/static/_next/static/chunks/framework-96dcd958cfe08bd4.js +1 -0
- compass_server/static/_next/static/chunks/main-6dee8e626b16731a.js +1 -0
- compass_server/static/_next/static/chunks/main-app-460e8bc670818718.js +1 -0
- compass_server/static/_next/static/chunks/pages/_app-638a3e7363f92b80.js +1 -0
- compass_server/static/_next/static/chunks/pages/_error-6a72dbbb45cae743.js +1 -0
- compass_server/static/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- compass_server/static/_next/static/chunks/webpack-597057bf48ce4111.js +1 -0
- compass_server/static/_next/static/css/1b0fbfd8dd653f37.css +3 -0
- compass_server/static/_next/static/ctUZeD9K7jQUgLqmBas2L/_buildManifest.js +1 -0
- compass_server/static/_next/static/ctUZeD9K7jQUgLqmBas2L/_ssgManifest.js +1 -0
- compass_server/static/_next/static/media/0086f8992871c45b-s.woff2 +0 -0
- compass_server/static/_next/static/media/034d78ad42e9620c-s.woff2 +0 -0
- compass_server/static/_next/static/media/03b436aa846269de-s.woff2 +0 -0
- compass_server/static/_next/static/media/0484562807a97172-s.p.woff2 +0 -0
- compass_server/static/_next/static/media/08aedeceaf1dcd57-s.woff2 +0 -0
- compass_server/static/_next/static/media/0aa834ed78bf6d07-s.woff2 +0 -0
- compass_server/static/_next/static/media/29a4aea02fdee119-s.woff2 +0 -0
- compass_server/static/_next/static/media/29e7bbdce9332268-s.woff2 +0 -0
- compass_server/static/_next/static/media/36008747766f78c6-s.woff2 +0 -0
- compass_server/static/_next/static/media/39969fcf98a3026e-s.woff2 +0 -0
- compass_server/static/_next/static/media/4de1fea1a954a5b6-s.p.woff2 +0 -0
- compass_server/static/_next/static/media/5c0c2bcbaa4149ca-s.p.woff2 +0 -0
- compass_server/static/_next/static/media/67957d42bae0796d-s.woff2 +0 -0
- compass_server/static/_next/static/media/6d38f9d4e0f4772b-s.woff2 +0 -0
- compass_server/static/_next/static/media/6d664cce900333ee-s.p.woff2 +0 -0
- compass_server/static/_next/static/media/886030b0b59bc5a7-s.woff2 +0 -0
- compass_server/static/_next/static/media/8888a3826f4a3af4-s.p.woff2 +0 -0
- compass_server/static/_next/static/media/939c4f875ee75fbb-s.woff2 +0 -0
- compass_server/static/_next/static/media/a1386beebedccca4-s.woff2 +0 -0
- compass_server/static/_next/static/media/ab00a911ac2adf48-s.woff2 +0 -0
- compass_server/static/_next/static/media/b957ea75a84b6ea7-s.p.woff2 +0 -0
- compass_server/static/_next/static/media/bb3ef058b751a6ad-s.p.woff2 +0 -0
- compass_server/static/_next/static/media/c3bc380753a8436c-s.woff2 +0 -0
- compass_server/static/_next/static/media/cce080f35d014443-s.woff2 +0 -0
- compass_server/static/_next/static/media/db911767852bc875-s.woff2 +0 -0
- compass_server/static/_next/static/media/eafabf029ad39a43-s.p.woff2 +0 -0
- compass_server/static/_next/static/media/f10b8e9d91f3edcb-s.woff2 +0 -0
- compass_server/static/_next/static/media/f911b923c6adde36-s.woff2 +0 -0
- compass_server/static/_next/static/media/fe0777f1195381cb-s.woff2 +0 -0
- compass_server/static/index.html +1 -0
- compass_server/static/index.txt +25 -0
- compass_server/web_bundle.py +27 -0
- compass_server/web_limits.py +48 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"""``/api`` routes: thin HTTP adapters over the read-only query layer.
|
|
2
|
+
|
|
3
|
+
Each route parses its parameters, calls one ``compass_core.query`` function and returns
|
|
4
|
+
its ``compass_core.contract`` result. Status codes for failures come from
|
|
5
|
+
``ERROR_MAPPINGS``, the table every adapter shares.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from collections.abc import Iterator
|
|
11
|
+
from typing import Annotated, Any, TypeVar
|
|
12
|
+
|
|
13
|
+
from fastapi import APIRouter, Depends, Query, Response
|
|
14
|
+
|
|
15
|
+
from compass_core.contract.errors import ERROR_MAPPINGS, ErrorResponse
|
|
16
|
+
from compass_core.contract.models import IndexStatus
|
|
17
|
+
from compass_core.contract.params import (
|
|
18
|
+
DEFAULT_IMPACT_DEPTH,
|
|
19
|
+
DEFAULT_LIMIT,
|
|
20
|
+
DEFAULT_MIN_CONFIDENCE,
|
|
21
|
+
MAX_DEPTH,
|
|
22
|
+
MAX_LIMIT,
|
|
23
|
+
MAX_TEXT_LENGTH,
|
|
24
|
+
ImpactParams,
|
|
25
|
+
SearchParams,
|
|
26
|
+
)
|
|
27
|
+
from compass_core.contract.results import (
|
|
28
|
+
AmbiguousReference,
|
|
29
|
+
GraphMap,
|
|
30
|
+
ImpactResult,
|
|
31
|
+
Lookup,
|
|
32
|
+
NodeDetail,
|
|
33
|
+
OverviewResult,
|
|
34
|
+
SearchResult,
|
|
35
|
+
SymbolNotFound,
|
|
36
|
+
)
|
|
37
|
+
from compass_core.contract.serialize import to_json
|
|
38
|
+
from compass_core.errors import ErrorCode
|
|
39
|
+
from compass_core.graph.db import GraphDB
|
|
40
|
+
from compass_core.index.locate import IndexLocation, locate_index
|
|
41
|
+
from compass_core.query.detail import describe
|
|
42
|
+
from compass_core.query.graph_map import graph_map
|
|
43
|
+
from compass_core.query.impact import impact
|
|
44
|
+
from compass_core.query.overview import overview
|
|
45
|
+
from compass_core.query.search import find_symbols
|
|
46
|
+
from compass_core.query.status import index_status
|
|
47
|
+
from compass_core.shared_types import SymbolKind
|
|
48
|
+
|
|
49
|
+
router = APIRouter(tags=["query"])
|
|
50
|
+
|
|
51
|
+
R = TypeVar("R")
|
|
52
|
+
|
|
53
|
+
_AMBIGUOUS_STATUS = ERROR_MAPPINGS[ErrorCode.AMBIGUOUS].http_status
|
|
54
|
+
_NOT_FOUND_STATUS = ERROR_MAPPINGS[ErrorCode.NOT_FOUND].http_status
|
|
55
|
+
_ERRORS: dict[int | str, dict[str, Any]] = {
|
|
56
|
+
ERROR_MAPPINGS[ErrorCode.INVALID_ARGUMENT].http_status: {
|
|
57
|
+
"model": ErrorResponse,
|
|
58
|
+
"description": "Invalid argument",
|
|
59
|
+
},
|
|
60
|
+
ERROR_MAPPINGS[ErrorCode.INDEX_NOT_FOUND].http_status: {
|
|
61
|
+
"model": ErrorResponse,
|
|
62
|
+
"description": "Index missing, busy or incompatible",
|
|
63
|
+
},
|
|
64
|
+
ERROR_MAPPINGS[ErrorCode.QUERY_TIMEOUT].http_status: {
|
|
65
|
+
"model": ErrorResponse,
|
|
66
|
+
"description": "Query timed out",
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
_LOOKUP_ERRORS: dict[int | str, dict[str, Any]] = {
|
|
70
|
+
_NOT_FOUND_STATUS: {"model": SymbolNotFound, "description": "Reference matched nothing"},
|
|
71
|
+
_AMBIGUOUS_STATUS: {
|
|
72
|
+
"model": AmbiguousReference,
|
|
73
|
+
"description": "Reference matched several symbols",
|
|
74
|
+
},
|
|
75
|
+
**_ERRORS,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def get_index() -> IndexLocation:
|
|
80
|
+
"""FastAPI dependency for the index; the lookup rule lives in ``locate_index``.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
The index location.
|
|
84
|
+
|
|
85
|
+
Raises:
|
|
86
|
+
IndexNotFoundError: If no index can be found.
|
|
87
|
+
IndexIncompatibleError: If the index must be rebuilt with ``compass ingest``.
|
|
88
|
+
"""
|
|
89
|
+
return locate_index()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def get_db(location: Annotated[IndexLocation, Depends(get_index)]) -> Iterator[GraphDB]:
|
|
93
|
+
"""Yield a read-only database handle that is always closed afterwards.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
location: The located index.
|
|
97
|
+
|
|
98
|
+
Yields:
|
|
99
|
+
A read-only ``GraphDB``.
|
|
100
|
+
"""
|
|
101
|
+
with GraphDB(location.db_path, read_only=True) as db:
|
|
102
|
+
yield db
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _lookup_response(result: Lookup[R]) -> R | Response:
|
|
106
|
+
"""Return a found result as is; an ambiguous or missing reference as its status code.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
result: What a reference-taking operation returned.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
``result`` itself, or a JSON response with the status ``ERROR_MAPPINGS`` gives
|
|
113
|
+
``AMBIGUOUS`` or ``NOT_FOUND`` and the outcome as its body.
|
|
114
|
+
|
|
115
|
+
Example:
|
|
116
|
+
``_lookup_response(SymbolNotFound(reference="x", suggestions=()))`` is a 404 whose
|
|
117
|
+
body is ``{"outcome":"not_found","reference":"x","suggestions":[]}``.
|
|
118
|
+
"""
|
|
119
|
+
if isinstance(result, AmbiguousReference):
|
|
120
|
+
status = _AMBIGUOUS_STATUS
|
|
121
|
+
elif isinstance(result, SymbolNotFound):
|
|
122
|
+
status = _NOT_FOUND_STATUS
|
|
123
|
+
else:
|
|
124
|
+
return result
|
|
125
|
+
return Response(to_json(result), status_code=status, media_type="application/json")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
Location = Annotated[IndexLocation, Depends(get_index)]
|
|
129
|
+
Db = Annotated[GraphDB, Depends(get_db)]
|
|
130
|
+
# Free text: 1..MAX_TEXT_LENGTH characters with at least one non-whitespace character;
|
|
131
|
+
# anything else is a 422 INVALID_ARGUMENT naming the parameter.
|
|
132
|
+
_TEXT = Query(min_length=1, max_length=MAX_TEXT_LENGTH, pattern=r"\S")
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@router.get("/search", response_model=SearchResult, responses=_ERRORS)
|
|
136
|
+
def search(
|
|
137
|
+
db: Db,
|
|
138
|
+
location: Location,
|
|
139
|
+
q: Annotated[str, _TEXT],
|
|
140
|
+
kind: SymbolKind | None = None,
|
|
141
|
+
limit: Annotated[int, Query(ge=1, le=MAX_LIMIT)] = DEFAULT_LIMIT,
|
|
142
|
+
) -> SearchResult:
|
|
143
|
+
"""Search files, classes, functions and methods by name."""
|
|
144
|
+
return find_symbols(db, location, SearchParams(query=q, kind=kind, limit=limit))
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@router.get("/impact", response_model=ImpactResult, responses=_LOOKUP_ERRORS)
|
|
148
|
+
def impact_of(
|
|
149
|
+
db: Db,
|
|
150
|
+
location: Location,
|
|
151
|
+
ref: Annotated[str, _TEXT],
|
|
152
|
+
depth: Annotated[int, Query(ge=1, le=MAX_DEPTH)] = DEFAULT_IMPACT_DEPTH,
|
|
153
|
+
min_confidence: Annotated[float, Query(ge=0, le=1)] = DEFAULT_MIN_CONFIDENCE,
|
|
154
|
+
limit: Annotated[int, Query(ge=1, le=MAX_LIMIT)] = DEFAULT_LIMIT,
|
|
155
|
+
) -> ImpactResult | Response:
|
|
156
|
+
"""List what may be affected by changing a file or symbol."""
|
|
157
|
+
params = ImpactParams(depth=depth, min_confidence=min_confidence, limit=limit)
|
|
158
|
+
return _lookup_response(impact(db, location, ref, params))
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@router.get("/status", response_model=IndexStatus, responses=_ERRORS)
|
|
162
|
+
def status(db: Db, location: Location) -> IndexStatus:
|
|
163
|
+
"""Describe the index: which repository, when it was built and how many files changed since."""
|
|
164
|
+
return index_status(location, db)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@router.get("/describe", response_model=NodeDetail, responses=_LOOKUP_ERRORS)
|
|
168
|
+
def describe_node(db: Db, location: Location, ref: Annotated[str, _TEXT]) -> NodeDetail | Response:
|
|
169
|
+
"""Describe one file, class, function or method: docstring, source and neighbours."""
|
|
170
|
+
return _lookup_response(describe(db, location, ref))
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@router.get("/overview", response_model=OverviewResult, responses=_ERRORS)
|
|
174
|
+
def repo_overview(db: Db, location: Location) -> OverviewResult:
|
|
175
|
+
"""Summarise the index: totals, entry points and ranked hot spots."""
|
|
176
|
+
return overview(db, location)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@router.get("/graph/map", response_model=GraphMap, responses=_ERRORS)
|
|
180
|
+
def graph(db: Db) -> GraphMap:
|
|
181
|
+
"""Every file, class, function and method, and the edges between them, for drawing."""
|
|
182
|
+
return graph_map(db)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Settings of the HTTP server: where it binds and which frontend may call it."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pydantic import Field, computed_field
|
|
6
|
+
|
|
7
|
+
from compass_core.settings import Settings
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ServerSettings(Settings):
|
|
11
|
+
"""Engine settings plus the server's own, from the same environment and ``.env``.
|
|
12
|
+
|
|
13
|
+
Attributes:
|
|
14
|
+
API_HOST: Host the FastAPI server binds to.
|
|
15
|
+
API_PORT: Port the FastAPI server listens on.
|
|
16
|
+
FRONTEND_HOST: Host of the frontend dev server.
|
|
17
|
+
FRONTEND_PORT: Port of the frontend dev server.
|
|
18
|
+
FRONTEND_URL: Origin allowed by CORS, built from the two fields above.
|
|
19
|
+
|
|
20
|
+
Example:
|
|
21
|
+
``API_PORT=9000 compass serve`` gives ``ServerSettings().API_PORT == 9000``;
|
|
22
|
+
the defaults give ``FRONTEND_URL == "http://localhost:3000"``.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
API_HOST: str = Field(default="127.0.0.1", description="Host the FastAPI server binds to")
|
|
26
|
+
API_PORT: int = Field(default=8000, description="Port the FastAPI server listens on")
|
|
27
|
+
|
|
28
|
+
FRONTEND_HOST: str = Field(default="localhost", description="Host of the frontend dev server")
|
|
29
|
+
FRONTEND_PORT: int = Field(default=3000, description="Port of the frontend dev server")
|
|
30
|
+
|
|
31
|
+
@computed_field # type: ignore[prop-decorator] # known mypy/pydantic limitation: mypy flags any decorator stacked on @property before the pydantic plugin can special-case @computed_field
|
|
32
|
+
@property
|
|
33
|
+
def FRONTEND_URL(self) -> str:
|
|
34
|
+
return f"http://{self.FRONTEND_HOST}:{self.FRONTEND_PORT}"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
server_settings = ServerSettings()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<!DOCTYPE html><!--ctUZeD9K7jQUgLqmBas2L--><html lang="en" class="__variable_97b0d3 __variable_c19f6d __variable_cf84ab __variable_4dc837 h-full"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/_next/static/media/0484562807a97172-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/4de1fea1a954a5b6-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/5c0c2bcbaa4149ca-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/6d664cce900333ee-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/8888a3826f4a3af4-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/b957ea75a84b6ea7-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/bb3ef058b751a6ad-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/eafabf029ad39a43-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/css/1b0fbfd8dd653f37.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-597057bf48ce4111.js"/><script src="/_next/static/chunks/1ff282bf-bb7c483245264fc9.js" async=""></script><script src="/_next/static/chunks/937-8692224bb6d1b605.js" async=""></script><script src="/_next/static/chunks/main-app-460e8bc670818718.js" async=""></script><meta name="robots" content="noindex"/><meta name="next-size-adjust" content=""/><title>404: This page could not be found.</title><title>Code Compass</title><meta name="description" content="Visualize your codebase as a knowledge graph"/><script>(function(){try{var s=localStorage.getItem("compass-theme");var t=s==="light"||s==="dark"?s:(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light");document.documentElement.dataset.theme=t}catch(e){document.documentElement.dataset.theme="light"}})();</script><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body class="font-sans h-svh overflow-hidden flex flex-col"><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/webpack-597057bf48ce4111.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[42712,[],\"\"]\n3:I[63566,[],\"\"]\n4:I[4373,[],\"OutletBoundary\"]\n6:I[10656,[],\"AsyncMetadataOutlet\"]\n8:I[4373,[],\"ViewportBoundary\"]\na:I[4373,[],\"MetadataBoundary\"]\nb:\"$Sreact.suspense\"\nd:I[22388,[],\"\"]\n:HL[\"/_next/static/media/0484562807a97172-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/4de1fea1a954a5b6-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/5c0c2bcbaa4149ca-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/6d664cce900333ee-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/8888a3826f4a3af4-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/b957ea75a84b6ea7-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/bb3ef058b751a6ad-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/eafabf029ad39a43-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/css/1b0fbfd8dd653f37.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"ctUZeD9K7jQUgLqmBas2L\",\"p\":\"\",\"c\":[\"\",\"_not-found\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/1b0fbfd8dd653f37.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"__variable_97b0d3 __variable_c19f6d __variable_cf84ab __variable_4dc837 h-full\",\"suppressHydrationWarning\":true,\"children\":[[\"$\",\"head\",null,{\"children\":[\"$\",\"script\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"(function(){try{var s=localStorage.getItem(\\\"compass-theme\\\");var t=s===\\\"light\\\"||s===\\\"dark\\\"?s:(window.matchMedia(\\\"(prefers-color-scheme: dark)\\\").matches?\\\"dark\\\":\\\"light\\\");document.documentElement.dataset.theme=t}catch(e){document.documentElement.dataset.theme=\\\"light\\\"}})();\"}}]}],[\"$\",\"body\",null,{\"className\":\"font-sans h-svh overflow-hidden flex flex-col\",\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]]}]]}],{\"children\":[\"/_not-found\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L4\",null,{\"children\":[\"$L5\",[\"$\",\"$L6\",null,{\"promise\":\"$@7\"}]]}]]}],{},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[[\"$\",\"$L8\",null,{\"children\":\"$L9\"}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]],[\"$\",\"$La\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$b\",null,{\"fallback\":null,\"children\":\"$Lc\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$d\",[]],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"9:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n5:null\n"])</script><script>self.__next_f.push([1,"7:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Code Compass\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Visualize your codebase as a knowledge graph\"}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"c:\"$7:metadata\"\n"])</script></body></html>
|