hipcortex 0.3.0__tar.gz → 0.3.2__tar.gz
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.
- {hipcortex-0.3.0 → hipcortex-0.3.2}/PKG-INFO +1 -1
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex/cli.py +83 -16
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex/client.py +60 -0
- hipcortex-0.3.2/hipcortex/indexer.py +219 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex.egg-info/PKG-INFO +1 -1
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex.egg-info/SOURCES.txt +1 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/pyproject.toml +49 -49
- {hipcortex-0.3.0 → hipcortex-0.3.2}/README.md +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex/__init__.py +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex/adapters/__init__.py +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex/adapters/autogen.py +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex/adapters/crewai.py +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex/async_client.py +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex/install/SKILL.md +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex/install/__init__.py +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex/langchain_memory.py +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex/llamaindex_storage.py +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex.egg-info/dependency_links.txt +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex.egg-info/entry_points.txt +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex.egg-info/requires.txt +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/hipcortex.egg-info/top_level.txt +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/setup.cfg +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/setup.py +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/tests/test_async_client.py +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/tests/test_async_langchain.py +0 -0
- {hipcortex-0.3.0 → hipcortex-0.3.2}/tests/test_cli_install.py +0 -0
|
@@ -696,22 +696,29 @@ def _getch() -> str:
|
|
|
696
696
|
|
|
697
697
|
def _run_wizard(agents: list) -> list:
|
|
698
698
|
"""Interactive multi-select. Skips section headers. Returns selected agent dicts."""
|
|
699
|
-
|
|
699
|
+
import re as _re
|
|
700
700
|
selectable = [i for i, a in enumerate(agents) if a["type"] != "section"]
|
|
701
701
|
n_all = len(agents)
|
|
702
702
|
selected: set = set()
|
|
703
|
-
sel_cursor = 0
|
|
703
|
+
sel_cursor = 0
|
|
704
704
|
|
|
705
705
|
def _display_name(a: dict) -> str:
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
706
|
+
return _re.sub(r'\033\[[^m]*m', '', a["name"])
|
|
707
|
+
|
|
708
|
+
# On Windows, cursor-up ANSI codes corrupt the display.
|
|
709
|
+
# Use cls-style redraw: print a blank separator then full list.
|
|
710
|
+
_is_windows = platform.system() == "Windows"
|
|
709
711
|
|
|
710
712
|
def render():
|
|
711
|
-
|
|
713
|
+
cur_real = selectable[sel_cursor] if selectable else -1
|
|
714
|
+
if _is_windows:
|
|
715
|
+
# Windows: no cursor-up — just reprint with blank line separator
|
|
716
|
+
print()
|
|
717
|
+
else:
|
|
718
|
+
# Unix: move cursor up to overwrite previous render
|
|
719
|
+
print(f"\033[{n_all + 3}A", end="")
|
|
712
720
|
print(f" {_BOLD}Select what to configure:{_RESET} {_GRAY}(Space toggle · Enter confirm · q quit){_RESET}")
|
|
713
721
|
print()
|
|
714
|
-
cur_real = selectable[sel_cursor] if selectable else -1
|
|
715
722
|
for i, agent in enumerate(agents):
|
|
716
723
|
if agent["type"] == "section":
|
|
717
724
|
print(f" {_DIM}{agent['name']}{_RESET}")
|
|
@@ -734,15 +741,17 @@ def _run_wizard(agents: list) -> list:
|
|
|
734
741
|
count = len(selected)
|
|
735
742
|
print(f"\n {_GREEN}{count} selected{_RESET}" if count else f"\n {_GRAY}none selected{_RESET}")
|
|
736
743
|
|
|
737
|
-
# Initial draw
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
744
|
+
# Initial draw
|
|
745
|
+
if not _is_windows:
|
|
746
|
+
# Reserve lines for cursor-up redraw on Unix
|
|
747
|
+
print(f" {_BOLD}Select what to configure:{_RESET}")
|
|
748
|
+
print()
|
|
749
|
+
for agent in agents:
|
|
750
|
+
if agent["type"] == "section":
|
|
751
|
+
print(f" {_DIM}{agent['name']}{_RESET}")
|
|
752
|
+
else:
|
|
753
|
+
print(f" ○ {_display_name(agent):<20} {_DIM}{agent['desc']}{_RESET}")
|
|
754
|
+
print()
|
|
746
755
|
|
|
747
756
|
render()
|
|
748
757
|
|
|
@@ -1087,6 +1096,55 @@ def cmd_restore(args: argparse.Namespace) -> None:
|
|
|
1087
1096
|
__import__('sys').exit(1)
|
|
1088
1097
|
|
|
1089
1098
|
|
|
1099
|
+
def cmd_index(args: argparse.Namespace) -> None:
|
|
1100
|
+
"""Index a codebase into HipCortex symbolic knowledge graph."""
|
|
1101
|
+
url = args.url or os.environ.get("HIPCORTEX_URL", DEFAULT_URL)
|
|
1102
|
+
path = args.path or "."
|
|
1103
|
+
actor = args.actor or "codebase"
|
|
1104
|
+
|
|
1105
|
+
# Check server is reachable
|
|
1106
|
+
try:
|
|
1107
|
+
with urllib.request.urlopen(f"{url}/health", timeout=5) as r:
|
|
1108
|
+
if r.status != 200:
|
|
1109
|
+
print(f"✗ Server not reachable at {url}")
|
|
1110
|
+
sys.exit(1)
|
|
1111
|
+
except Exception:
|
|
1112
|
+
print(f"✗ Server not reachable at {url}")
|
|
1113
|
+
print(f" Start it with: hipcortex start")
|
|
1114
|
+
sys.exit(1)
|
|
1115
|
+
|
|
1116
|
+
try:
|
|
1117
|
+
from .client import HipCortexClient
|
|
1118
|
+
from .indexer import CodeIndexer
|
|
1119
|
+
except ImportError:
|
|
1120
|
+
from hipcortex.client import HipCortexClient
|
|
1121
|
+
from hipcortex.indexer import CodeIndexer
|
|
1122
|
+
|
|
1123
|
+
client = HipCortexClient(base_url=url)
|
|
1124
|
+
indexer = CodeIndexer(client=client)
|
|
1125
|
+
|
|
1126
|
+
extensions = None
|
|
1127
|
+
if args.extensions:
|
|
1128
|
+
extensions = [e if e.startswith(".") else f".{e}" for e in args.extensions.split(",")]
|
|
1129
|
+
|
|
1130
|
+
print(f"Indexing {path} into HipCortex symbolic graph...")
|
|
1131
|
+
print(f" Server: {url}")
|
|
1132
|
+
print(f" Actor: {actor}")
|
|
1133
|
+
if extensions:
|
|
1134
|
+
print(f" File types: {extensions}")
|
|
1135
|
+
print()
|
|
1136
|
+
|
|
1137
|
+
stats = indexer.index(path=path, actor=actor, extensions=extensions)
|
|
1138
|
+
|
|
1139
|
+
print(f" ✓ {stats['files']} files processed")
|
|
1140
|
+
print(f" ✓ {stats['nodes']} symbol nodes created")
|
|
1141
|
+
print(f" ✓ {stats['edges']} relationships created")
|
|
1142
|
+
print()
|
|
1143
|
+
print(f"Query code graph: GET {url}/graph")
|
|
1144
|
+
print(f"Search symbols: GET {url}/graph/search?q=<name>")
|
|
1145
|
+
print(f"In Claude Code: /hipcortex recall validate_token")
|
|
1146
|
+
|
|
1147
|
+
|
|
1090
1148
|
# ─── Argument parser ──────────────────────────────────────────────────────────
|
|
1091
1149
|
|
|
1092
1150
|
def build_parser() -> argparse.ArgumentParser:
|
|
@@ -1126,6 +1184,13 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1126
1184
|
p_restore.add_argument("file", help="Backup file path (.json)")
|
|
1127
1185
|
p_restore.add_argument("--url", help="Server URL")
|
|
1128
1186
|
|
|
1187
|
+
# index
|
|
1188
|
+
p_index = sub.add_parser("index", help="Index a codebase into the HipCortex knowledge graph")
|
|
1189
|
+
p_index.add_argument("path", nargs="?", default=".", help="Directory or file to index (default: current dir)")
|
|
1190
|
+
p_index.add_argument("--url", help="Server URL")
|
|
1191
|
+
p_index.add_argument("--actor", help="Actor label for this codebase (default: codebase)")
|
|
1192
|
+
p_index.add_argument("--extensions", help="Comma-separated file extensions (default: .py,.ts,.js)")
|
|
1193
|
+
|
|
1129
1194
|
return parser
|
|
1130
1195
|
|
|
1131
1196
|
|
|
@@ -1145,6 +1210,8 @@ def main() -> None:
|
|
|
1145
1210
|
cmd_backup(args)
|
|
1146
1211
|
elif args.command == "restore":
|
|
1147
1212
|
cmd_restore(args)
|
|
1213
|
+
elif args.command == "index":
|
|
1214
|
+
cmd_index(args)
|
|
1148
1215
|
else:
|
|
1149
1216
|
parser.print_help()
|
|
1150
1217
|
sys.exit(1)
|
|
@@ -203,6 +203,66 @@ class HipCortexClient:
|
|
|
203
203
|
resp.raise_for_status()
|
|
204
204
|
return resp.json()
|
|
205
205
|
|
|
206
|
+
def set_state(
|
|
207
|
+
self,
|
|
208
|
+
actor: str,
|
|
209
|
+
key: str,
|
|
210
|
+
value: str,
|
|
211
|
+
confidence: float = 1.0,
|
|
212
|
+
) -> Dict[str, Any]:
|
|
213
|
+
"""Store a structured state value for an actor.
|
|
214
|
+
|
|
215
|
+
Structured state is permanent (no TTL), high-confidence, pinned.
|
|
216
|
+
Use for: current goal, chosen stack, constraints, key decisions.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
actor: Scope identifier (e.g. project name)
|
|
220
|
+
key: State key (e.g. "goal", "stack", "constraint:no-redis")
|
|
221
|
+
value: State value (free text or JSON string)
|
|
222
|
+
confidence: How confident (default 1.0)
|
|
223
|
+
|
|
224
|
+
Returns: stored record info
|
|
225
|
+
"""
|
|
226
|
+
return self.add_memory(
|
|
227
|
+
actor=actor,
|
|
228
|
+
action=f"state:{key}",
|
|
229
|
+
target=value,
|
|
230
|
+
record_type="Symbolic",
|
|
231
|
+
priority="pinned",
|
|
232
|
+
metadata={"confidence": str(confidence), "source": "user-state"},
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
def get_state(
|
|
236
|
+
self,
|
|
237
|
+
actor: str,
|
|
238
|
+
key: Optional[str] = None,
|
|
239
|
+
) -> Dict[str, Any]:
|
|
240
|
+
"""Retrieve structured state for an actor.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
actor: Scope identifier
|
|
244
|
+
key: Optional specific key (e.g. "goal"). If None, returns all state.
|
|
245
|
+
|
|
246
|
+
Returns: dict of {key: value} or latest value string if key specified
|
|
247
|
+
"""
|
|
248
|
+
action_filter = f"state:{key}" if key else None
|
|
249
|
+
records = self.query_memory(actor=actor, action=action_filter, limit=50)
|
|
250
|
+
|
|
251
|
+
if key:
|
|
252
|
+
# Return latest value for this specific key
|
|
253
|
+
if records:
|
|
254
|
+
return {"key": key, "value": records[-1].get("target", ""), "actor": actor}
|
|
255
|
+
return {"key": key, "value": None, "actor": actor}
|
|
256
|
+
|
|
257
|
+
# Return all state as dict
|
|
258
|
+
state: Dict[str, Any] = {}
|
|
259
|
+
for rec in records:
|
|
260
|
+
action = rec.get("action", "")
|
|
261
|
+
if action.startswith("state:"):
|
|
262
|
+
k = action[len("state:"):]
|
|
263
|
+
state[k] = rec.get("target", "")
|
|
264
|
+
return state
|
|
265
|
+
|
|
206
266
|
def consolidate(self, actor: Optional[str] = None, threshold: float = 0.8, dry_run: bool = True) -> Dict[str, Any]:
|
|
207
267
|
"""Find near-duplicate memories and optionally merge them."""
|
|
208
268
|
params: Dict[str, Any] = {"threshold": threshold, "dry_run": dry_run}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"""
|
|
2
|
+
HipCortex Code Intelligence Indexer
|
|
3
|
+
Uses Python stdlib ast + optional tree-sitter for multi-language support.
|
|
4
|
+
No external deps required for Python files.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import ast
|
|
8
|
+
import os
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Optional, Dict, List, Any
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CodeIndexer:
|
|
14
|
+
"""Walks a codebase, extracts symbols, feeds into HipCortex symbolic graph."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, client, base_url: str = "http://localhost:3030", api_key: Optional[str] = None):
|
|
17
|
+
"""
|
|
18
|
+
Args:
|
|
19
|
+
client: HipCortexClient instance
|
|
20
|
+
base_url: HipCortex server URL (only needed if client not provided)
|
|
21
|
+
api_key: optional API key
|
|
22
|
+
"""
|
|
23
|
+
self._client = client
|
|
24
|
+
self._node_cache: Dict[str, str] = {} # qualified_name -> node_id
|
|
25
|
+
|
|
26
|
+
def index(self, path: str, actor: str = "codebase",
|
|
27
|
+
extensions: Optional[List[str]] = None,
|
|
28
|
+
exclude_dirs: Optional[List[str]] = None) -> Dict[str, int]:
|
|
29
|
+
"""
|
|
30
|
+
Index a directory or file into HipCortex symbolic graph.
|
|
31
|
+
|
|
32
|
+
Returns: {"nodes": N, "edges": N, "files": N}
|
|
33
|
+
"""
|
|
34
|
+
if extensions is None:
|
|
35
|
+
extensions = [".py", ".ts", ".js"]
|
|
36
|
+
if exclude_dirs is None:
|
|
37
|
+
exclude_dirs = ["node_modules", ".git", "__pycache__", ".venv", "venv", "dist", "build"]
|
|
38
|
+
|
|
39
|
+
stats = {"nodes": 0, "edges": 0, "files": 0}
|
|
40
|
+
root = Path(path).resolve()
|
|
41
|
+
|
|
42
|
+
if root.is_file():
|
|
43
|
+
files = [root]
|
|
44
|
+
else:
|
|
45
|
+
files = [
|
|
46
|
+
f for f in root.rglob("*")
|
|
47
|
+
if f.suffix in extensions
|
|
48
|
+
and not any(ex in f.parts for ex in exclude_dirs)
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
for f in files:
|
|
52
|
+
try:
|
|
53
|
+
n = self._index_file(f, root, actor)
|
|
54
|
+
stats["files"] += 1
|
|
55
|
+
stats["nodes"] += n.get("nodes", 0)
|
|
56
|
+
stats["edges"] += n.get("edges", 0)
|
|
57
|
+
except Exception:
|
|
58
|
+
pass # skip unparseable files
|
|
59
|
+
|
|
60
|
+
return stats
|
|
61
|
+
|
|
62
|
+
def _make_node(self, label: str, props: Dict[str, str]) -> Optional[str]:
|
|
63
|
+
"""Create a node, return its ID. Cache by label to avoid duplicates."""
|
|
64
|
+
if label in self._node_cache:
|
|
65
|
+
return self._node_cache[label]
|
|
66
|
+
try:
|
|
67
|
+
result = self._client.create_node(label=label, properties=props)
|
|
68
|
+
node_id = result.get("id")
|
|
69
|
+
if node_id:
|
|
70
|
+
self._node_cache[label] = node_id
|
|
71
|
+
return node_id
|
|
72
|
+
except Exception:
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
def _make_edge(self, from_id: str, to_id: str, relation: str) -> bool:
|
|
76
|
+
try:
|
|
77
|
+
self._client.create_edge(from_id=from_id, to_id=to_id, relation=relation)
|
|
78
|
+
return True
|
|
79
|
+
except Exception:
|
|
80
|
+
return False
|
|
81
|
+
|
|
82
|
+
def _index_file(self, file: Path, root: Path, actor: str) -> Dict[str, int]:
|
|
83
|
+
"""Index a single file. Returns {"nodes": N, "edges": N}."""
|
|
84
|
+
rel = str(file.relative_to(root))
|
|
85
|
+
suffix = file.suffix
|
|
86
|
+
|
|
87
|
+
if suffix == ".py":
|
|
88
|
+
return self._index_python(file, rel, actor)
|
|
89
|
+
elif suffix in (".ts", ".js"):
|
|
90
|
+
return self._index_js_simple(file, rel, actor)
|
|
91
|
+
return {"nodes": 0, "edges": 0}
|
|
92
|
+
|
|
93
|
+
def _index_python(self, file: Path, rel_path: str, actor: str) -> Dict[str, int]:
|
|
94
|
+
"""Parse Python file with ast, extract classes + functions + imports."""
|
|
95
|
+
try:
|
|
96
|
+
source = file.read_text(encoding="utf-8", errors="ignore")
|
|
97
|
+
tree = ast.parse(source, filename=str(file))
|
|
98
|
+
except SyntaxError:
|
|
99
|
+
return {"nodes": 0, "edges": 0}
|
|
100
|
+
|
|
101
|
+
nodes = 0
|
|
102
|
+
edges = 0
|
|
103
|
+
|
|
104
|
+
# File node
|
|
105
|
+
file_label = f"file:{rel_path}"
|
|
106
|
+
file_id = self._make_node(file_label, {
|
|
107
|
+
"type": "file", "path": rel_path, "language": "python"
|
|
108
|
+
})
|
|
109
|
+
if file_id:
|
|
110
|
+
nodes += 1
|
|
111
|
+
|
|
112
|
+
for node in ast.walk(tree):
|
|
113
|
+
# Class definitions
|
|
114
|
+
if isinstance(node, ast.ClassDef):
|
|
115
|
+
label = f"class:{rel_path}:{node.name}"
|
|
116
|
+
props = {
|
|
117
|
+
"type": "class",
|
|
118
|
+
"name": node.name,
|
|
119
|
+
"file": rel_path,
|
|
120
|
+
"line": str(node.lineno),
|
|
121
|
+
}
|
|
122
|
+
# Base classes
|
|
123
|
+
bases = [ast.unparse(b) for b in node.bases if isinstance(b, (ast.Name, ast.Attribute))]
|
|
124
|
+
if bases:
|
|
125
|
+
props["bases"] = ", ".join(bases[:3])
|
|
126
|
+
|
|
127
|
+
class_id = self._make_node(label, props)
|
|
128
|
+
if class_id:
|
|
129
|
+
nodes += 1
|
|
130
|
+
if file_id:
|
|
131
|
+
if self._make_edge(file_id, class_id, "defines"):
|
|
132
|
+
edges += 1
|
|
133
|
+
# Inheritance edges
|
|
134
|
+
for base in bases:
|
|
135
|
+
base_label = f"class:*:{base}"
|
|
136
|
+
# try to find existing base node
|
|
137
|
+
if base_label in self._node_cache:
|
|
138
|
+
if self._make_edge(class_id, self._node_cache[base_label], "inherits"):
|
|
139
|
+
edges += 1
|
|
140
|
+
|
|
141
|
+
# Function / method definitions
|
|
142
|
+
elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
143
|
+
# Get parent context by checking if this is inside a class
|
|
144
|
+
label = f"fn:{rel_path}:{node.name}"
|
|
145
|
+
|
|
146
|
+
# Build signature
|
|
147
|
+
args = []
|
|
148
|
+
for a in node.args.args:
|
|
149
|
+
if a.annotation:
|
|
150
|
+
args.append(f"{a.arg}: {ast.unparse(a.annotation)}")
|
|
151
|
+
else:
|
|
152
|
+
args.append(a.arg)
|
|
153
|
+
|
|
154
|
+
return_ann = ""
|
|
155
|
+
if node.returns:
|
|
156
|
+
return_ann = ast.unparse(node.returns)
|
|
157
|
+
|
|
158
|
+
props = {
|
|
159
|
+
"type": "function",
|
|
160
|
+
"name": node.name,
|
|
161
|
+
"file": rel_path,
|
|
162
|
+
"line": str(node.lineno),
|
|
163
|
+
"signature": f"def {node.name}({', '.join(args[:5])})" + (f" -> {return_ann}" if return_ann else ""),
|
|
164
|
+
}
|
|
165
|
+
if any(d.id == "property" if isinstance(d, ast.Name) else False for d in node.decorator_list):
|
|
166
|
+
props["is_property"] = "true"
|
|
167
|
+
|
|
168
|
+
fn_id = self._make_node(label, props)
|
|
169
|
+
if fn_id:
|
|
170
|
+
nodes += 1
|
|
171
|
+
if file_id:
|
|
172
|
+
if self._make_edge(file_id, fn_id, "defines"):
|
|
173
|
+
edges += 1
|
|
174
|
+
|
|
175
|
+
return {"nodes": nodes, "edges": edges}
|
|
176
|
+
|
|
177
|
+
def _index_js_simple(self, file: Path, rel_path: str, actor: str) -> Dict[str, int]:
|
|
178
|
+
"""Simple regex-based JS/TS indexing (no AST parser for JS in stdlib)."""
|
|
179
|
+
import re
|
|
180
|
+
try:
|
|
181
|
+
source = file.read_text(encoding="utf-8", errors="ignore")
|
|
182
|
+
except Exception:
|
|
183
|
+
return {"nodes": 0, "edges": 0}
|
|
184
|
+
|
|
185
|
+
nodes = 0
|
|
186
|
+
edges = 0
|
|
187
|
+
|
|
188
|
+
file_label = f"file:{rel_path}"
|
|
189
|
+
file_id = self._make_node(file_label, {
|
|
190
|
+
"type": "file", "path": rel_path,
|
|
191
|
+
"language": "typescript" if rel_path.endswith(".ts") else "javascript"
|
|
192
|
+
})
|
|
193
|
+
if file_id:
|
|
194
|
+
nodes += 1
|
|
195
|
+
|
|
196
|
+
# Extract exported functions/classes
|
|
197
|
+
patterns = [
|
|
198
|
+
(r'export\s+(?:async\s+)?function\s+(\w+)', "function"),
|
|
199
|
+
(r'export\s+class\s+(\w+)', "class"),
|
|
200
|
+
(r'export\s+const\s+(\w+)\s*=\s*(?:async\s+)?\(', "function"),
|
|
201
|
+
(r'export\s+interface\s+(\w+)', "interface"),
|
|
202
|
+
(r'export\s+type\s+(\w+)', "type"),
|
|
203
|
+
]
|
|
204
|
+
|
|
205
|
+
for pat, kind in patterns:
|
|
206
|
+
for m in re.finditer(pat, source):
|
|
207
|
+
name = m.group(1)
|
|
208
|
+
label = f"{kind}:{rel_path}:{name}"
|
|
209
|
+
sym_id = self._make_node(label, {
|
|
210
|
+
"type": kind, "name": name, "file": rel_path,
|
|
211
|
+
"line": str(source[:m.start()].count("\n") + 1),
|
|
212
|
+
})
|
|
213
|
+
if sym_id:
|
|
214
|
+
nodes += 1
|
|
215
|
+
if file_id:
|
|
216
|
+
if self._make_edge(file_id, sym_id, "defines"):
|
|
217
|
+
edges += 1
|
|
218
|
+
|
|
219
|
+
return {"nodes": nodes, "edges": edges}
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
requires = ["setuptools>=68", "wheel"]
|
|
3
|
-
build-backend = "setuptools.build_meta"
|
|
4
|
-
|
|
5
|
-
[project]
|
|
6
|
-
name = "hipcortex"
|
|
7
|
-
version = "0.3.
|
|
8
|
-
description = "Persistent causal memory for AI agents -- LangChain, LlamaIndex, AutoGen, CrewAI"
|
|
9
|
-
readme = "README.md"
|
|
10
|
-
license = {text = "Apache-2.0"}
|
|
11
|
-
requires-python = ">=3.9"
|
|
12
|
-
authors = [{name = "HipCortex Contributors"}]
|
|
13
|
-
keywords = ["ai", "memory", "langchain", "autogen", "crewai", "llm", "agents", "rag"]
|
|
14
|
-
classifiers = [
|
|
15
|
-
"Programming Language :: Python :: 3",
|
|
16
|
-
"License :: OSI Approved :: Apache Software License",
|
|
17
|
-
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
18
|
-
"Intended Audience :: Developers",
|
|
19
|
-
]
|
|
20
|
-
dependencies = ["requests>=2.28", "httpx>=0.27"]
|
|
21
|
-
|
|
22
|
-
[project.optional-dependencies]
|
|
23
|
-
langchain = ["langchain-core>=0.1"]
|
|
24
|
-
llamaindex = ["llama-index-core>=0.10"]
|
|
25
|
-
crewai = ["crewai>=0.28", "crewai-tools>=0.1"]
|
|
26
|
-
autogen = ["pyautogen>=0.2"]
|
|
27
|
-
benchmark = ["mem0ai>=0.1", "tabulate>=0.9"]
|
|
28
|
-
all = ["langchain-core>=0.1", "llama-index-core>=0.10",
|
|
29
|
-
"crewai>=0.28", "crewai-tools>=0.1",
|
|
30
|
-
"pyautogen>=0.2", "mem0ai>=0.1", "tabulate>=0.9"]
|
|
31
|
-
|
|
32
|
-
[project.scripts]
|
|
33
|
-
hipcortex = "hipcortex.cli:main"
|
|
34
|
-
|
|
35
|
-
[project.urls]
|
|
36
|
-
Homepage = "https://github.com/farmountain/HipCortex"
|
|
37
|
-
Repository = "https://github.com/farmountain/HipCortex"
|
|
38
|
-
Issues = "https://github.com/farmountain/HipCortex/issues"
|
|
39
|
-
Benchmark = "https://github.com/farmountain/HipCortex/blob/main/BENCHMARK.md"
|
|
40
|
-
|
|
41
|
-
[tool.setuptools.packages.find]
|
|
42
|
-
where = ["."]
|
|
43
|
-
include = ["hipcortex*"]
|
|
44
|
-
|
|
45
|
-
[tool.setuptools.package-data]
|
|
46
|
-
"hipcortex.install" = ["SKILL.md"]
|
|
47
|
-
|
|
48
|
-
[tool.pytest.ini_options]
|
|
49
|
-
asyncio_mode = "auto"
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "hipcortex"
|
|
7
|
+
version = "0.3.2"
|
|
8
|
+
description = "Persistent causal memory for AI agents -- LangChain, LlamaIndex, AutoGen, CrewAI"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "Apache-2.0"}
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [{name = "HipCortex Contributors"}]
|
|
13
|
+
keywords = ["ai", "memory", "langchain", "autogen", "crewai", "llm", "agents", "rag"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: Apache Software License",
|
|
17
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
]
|
|
20
|
+
dependencies = ["requests>=2.28", "httpx>=0.27"]
|
|
21
|
+
|
|
22
|
+
[project.optional-dependencies]
|
|
23
|
+
langchain = ["langchain-core>=0.1"]
|
|
24
|
+
llamaindex = ["llama-index-core>=0.10"]
|
|
25
|
+
crewai = ["crewai>=0.28", "crewai-tools>=0.1"]
|
|
26
|
+
autogen = ["pyautogen>=0.2"]
|
|
27
|
+
benchmark = ["mem0ai>=0.1", "tabulate>=0.9"]
|
|
28
|
+
all = ["langchain-core>=0.1", "llama-index-core>=0.10",
|
|
29
|
+
"crewai>=0.28", "crewai-tools>=0.1",
|
|
30
|
+
"pyautogen>=0.2", "mem0ai>=0.1", "tabulate>=0.9"]
|
|
31
|
+
|
|
32
|
+
[project.scripts]
|
|
33
|
+
hipcortex = "hipcortex.cli:main"
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Homepage = "https://github.com/farmountain/HipCortex"
|
|
37
|
+
Repository = "https://github.com/farmountain/HipCortex"
|
|
38
|
+
Issues = "https://github.com/farmountain/HipCortex/issues"
|
|
39
|
+
Benchmark = "https://github.com/farmountain/HipCortex/blob/main/BENCHMARK.md"
|
|
40
|
+
|
|
41
|
+
[tool.setuptools.packages.find]
|
|
42
|
+
where = ["."]
|
|
43
|
+
include = ["hipcortex*"]
|
|
44
|
+
|
|
45
|
+
[tool.setuptools.package-data]
|
|
46
|
+
"hipcortex.install" = ["SKILL.md"]
|
|
47
|
+
|
|
48
|
+
[tool.pytest.ini_options]
|
|
49
|
+
asyncio_mode = "auto"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|