memstack-skill-loader 4.1.1__tar.gz → 4.3.0__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.
- {memstack_skill_loader-4.1.1/src/memstack_skill_loader.egg-info → memstack_skill_loader-4.3.0}/PKG-INFO +2 -1
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/pyproject.toml +2 -1
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/__init__.py +1 -1
- memstack_skill_loader-4.3.0/src/memstack_skill_loader/__main__.py +183 -0
- memstack_skill_loader-4.3.0/src/memstack_skill_loader/agent_runner.py +2153 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/config.py +14 -3
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/dashboard.html +465 -122
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/dashboard.py +174 -116
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/license.py +46 -0
- memstack_skill_loader-4.3.0/src/memstack_skill_loader/proxy/__init__.py +2 -0
- memstack_skill_loader-4.3.0/src/memstack_skill_loader/proxy/body_parser.py +127 -0
- memstack_skill_loader-4.3.0/src/memstack_skill_loader/proxy/compressor.py +77 -0
- memstack_skill_loader-4.3.0/src/memstack_skill_loader/proxy/forwarder.py +47 -0
- memstack_skill_loader-4.3.0/src/memstack_skill_loader/proxy/pro_compressor.py +312 -0
- memstack_skill_loader-4.3.0/src/memstack_skill_loader/proxy/server.py +287 -0
- memstack_skill_loader-4.3.0/src/memstack_skill_loader/proxy/stats_tracker.py +125 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/stats.py +161 -6
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0/src/memstack_skill_loader.egg-info}/PKG-INFO +2 -1
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader.egg-info/SOURCES.txt +9 -1
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader.egg-info/requires.txt +1 -0
- memstack_skill_loader-4.3.0/tests/test_pro_compressor.py +382 -0
- memstack_skill_loader-4.1.1/src/memstack_skill_loader/__main__.py +0 -90
- memstack_skill_loader-4.1.1/src/memstack_skill_loader/agent_runner.py +0 -1243
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/MANIFEST.in +0 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/README.md +0 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/setup.cfg +0 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/categories.py +0 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/compression.py +0 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/indexer.py +0 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/memory_db.py +0 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/search.py +0 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/server.py +0 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/skill_config.py +0 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/tfidf_search.py +0 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader/version_check.py +0 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader.egg-info/dependency_links.txt +0 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader.egg-info/entry_points.txt +0 -0
- {memstack_skill_loader-4.1.1 → memstack_skill_loader-4.3.0}/src/memstack_skill_loader.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memstack-skill-loader
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.3.0
|
|
4
4
|
Summary: MCP server that vector-indexes MemStack Pro skills for on-demand loading
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Requires-Dist: mcp>=1.0.0
|
|
@@ -8,3 +8,4 @@ Requires-Dist: lancedb>=0.6.0
|
|
|
8
8
|
Requires-Dist: sentence-transformers>=2.2.0
|
|
9
9
|
Requires-Dist: pyarrow>=14.0.0
|
|
10
10
|
Requires-Dist: httpx>=0.24.0
|
|
11
|
+
Requires-Dist: aiohttp>=3.9
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "memstack-skill-loader"
|
|
7
|
-
version = "4.
|
|
7
|
+
version = "4.3.0"
|
|
8
8
|
description = "MCP server that vector-indexes MemStack Pro skills for on-demand loading"
|
|
9
9
|
requires-python = ">=3.10"
|
|
10
10
|
dependencies = [
|
|
@@ -13,6 +13,7 @@ dependencies = [
|
|
|
13
13
|
"sentence-transformers>=2.2.0",
|
|
14
14
|
"pyarrow>=14.0.0",
|
|
15
15
|
"httpx>=0.24.0",
|
|
16
|
+
"aiohttp>=3.9",
|
|
16
17
|
]
|
|
17
18
|
|
|
18
19
|
[project.scripts]
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"""Entry point for python -m memstack_skill_loader."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import os
|
|
5
|
+
import signal
|
|
6
|
+
import sys
|
|
7
|
+
import time
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from .server import run
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _run_agents(task: str) -> None:
|
|
14
|
+
"""Start agent runner and print live message log until done."""
|
|
15
|
+
from . import agent_runner
|
|
16
|
+
|
|
17
|
+
print(f"\033[1;36m{'='*60}\033[0m")
|
|
18
|
+
print(f"\033[1;36m Agent Runner — Task Orchestration\033[0m")
|
|
19
|
+
print(f"\033[1;36m{'='*60}\033[0m")
|
|
20
|
+
print(f"\n Task: {task}")
|
|
21
|
+
print(f" Working dir: {sys.argv[3] if len(sys.argv) > 3 else '.'}")
|
|
22
|
+
print(f"\n Press Ctrl+C to stop all agents.\n")
|
|
23
|
+
|
|
24
|
+
working_dir = sys.argv[3] if len(sys.argv) > 3 else None
|
|
25
|
+
result = agent_runner.start_run(task=task, working_dir=working_dir)
|
|
26
|
+
|
|
27
|
+
if "error" in result:
|
|
28
|
+
print(f"\033[31mError: {result['error']}\033[0m", file=sys.stderr)
|
|
29
|
+
sys.exit(1)
|
|
30
|
+
|
|
31
|
+
print(f" Session: {result['session_id']}\n")
|
|
32
|
+
print(f"\033[90m{'─'*60}\033[0m")
|
|
33
|
+
|
|
34
|
+
seen_messages = 0
|
|
35
|
+
try:
|
|
36
|
+
while True:
|
|
37
|
+
time.sleep(2)
|
|
38
|
+
status = agent_runner.get_status()
|
|
39
|
+
|
|
40
|
+
# Print new messages
|
|
41
|
+
messages = status.get("messages", [])
|
|
42
|
+
for msg in messages[seen_messages:]:
|
|
43
|
+
from_name = msg.get("from", "?")
|
|
44
|
+
to_name = msg.get("to", "?")
|
|
45
|
+
content = msg.get("content", "")[:200]
|
|
46
|
+
ts = msg.get("timestamp", "")
|
|
47
|
+
|
|
48
|
+
color = "\033[35m" if from_name == "manager" else \
|
|
49
|
+
"\033[36m" if from_name == "builder" else \
|
|
50
|
+
"\033[32m" if from_name == "reviewer" else "\033[90m"
|
|
51
|
+
|
|
52
|
+
print(f" {color}{from_name}\033[0m → \033[37m{to_name}\033[0m")
|
|
53
|
+
for line in content.split("\n")[:5]:
|
|
54
|
+
print(f" {line}")
|
|
55
|
+
print()
|
|
56
|
+
|
|
57
|
+
seen_messages = len(messages)
|
|
58
|
+
|
|
59
|
+
# Check if done
|
|
60
|
+
session_status = status.get("status", "")
|
|
61
|
+
if session_status in ("completed", "error", "stopped"):
|
|
62
|
+
print(f"\033[90m{'─'*60}\033[0m")
|
|
63
|
+
color = "\033[32m" if session_status == "completed" else "\033[31m"
|
|
64
|
+
print(f"\n {color}Status: {session_status}\033[0m")
|
|
65
|
+
result_text = status.get("result", "")
|
|
66
|
+
if result_text:
|
|
67
|
+
print(f" {result_text[:300]}")
|
|
68
|
+
print()
|
|
69
|
+
break
|
|
70
|
+
|
|
71
|
+
except KeyboardInterrupt:
|
|
72
|
+
print("\n\n Stopping agents...")
|
|
73
|
+
agent_runner.stop_all()
|
|
74
|
+
print(" All agents stopped.")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _stop() -> None:
|
|
78
|
+
"""Stop the MemStack dashboard and any agent runner claude.exe processes."""
|
|
79
|
+
pid_file = Path.home() / ".memstack" / "dashboard.pid"
|
|
80
|
+
if not pid_file.exists():
|
|
81
|
+
print("No MemStack dashboard running.")
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
pid = int(pid_file.read_text().strip())
|
|
86
|
+
except (ValueError, OSError):
|
|
87
|
+
print("No MemStack dashboard running (corrupt PID file).")
|
|
88
|
+
pid_file.unlink(missing_ok=True)
|
|
89
|
+
return
|
|
90
|
+
|
|
91
|
+
# Check if the process is alive
|
|
92
|
+
try:
|
|
93
|
+
os.kill(pid, 0)
|
|
94
|
+
except OSError:
|
|
95
|
+
print("No MemStack dashboard running (process not found).")
|
|
96
|
+
pid_file.unlink(missing_ok=True)
|
|
97
|
+
return
|
|
98
|
+
|
|
99
|
+
# Kill any claude.exe processes spawned by agent runner
|
|
100
|
+
killed_agents = 0
|
|
101
|
+
try:
|
|
102
|
+
import subprocess
|
|
103
|
+
if sys.platform == "win32":
|
|
104
|
+
result = subprocess.run(
|
|
105
|
+
["wmic", "process", "where",
|
|
106
|
+
f"ParentProcessId={pid} and Name='claude.exe'",
|
|
107
|
+
"get", "ProcessId"],
|
|
108
|
+
capture_output=True, text=True, timeout=10,
|
|
109
|
+
)
|
|
110
|
+
for line in result.stdout.splitlines():
|
|
111
|
+
line = line.strip()
|
|
112
|
+
if line.isdigit():
|
|
113
|
+
try:
|
|
114
|
+
os.kill(int(line), signal.SIGTERM)
|
|
115
|
+
killed_agents += 1
|
|
116
|
+
except OSError:
|
|
117
|
+
pass
|
|
118
|
+
else:
|
|
119
|
+
result = subprocess.run(
|
|
120
|
+
["pgrep", "-P", str(pid), "-x", "claude"],
|
|
121
|
+
capture_output=True, text=True, timeout=10,
|
|
122
|
+
)
|
|
123
|
+
for line in result.stdout.splitlines():
|
|
124
|
+
line = line.strip()
|
|
125
|
+
if line.isdigit():
|
|
126
|
+
try:
|
|
127
|
+
os.kill(int(line), signal.SIGTERM)
|
|
128
|
+
killed_agents += 1
|
|
129
|
+
except OSError:
|
|
130
|
+
pass
|
|
131
|
+
except Exception:
|
|
132
|
+
pass
|
|
133
|
+
|
|
134
|
+
# Kill the dashboard process
|
|
135
|
+
try:
|
|
136
|
+
if sys.platform == "win32":
|
|
137
|
+
os.kill(pid, signal.SIGTERM)
|
|
138
|
+
else:
|
|
139
|
+
os.kill(pid, signal.SIGTERM)
|
|
140
|
+
print(f"MemStack dashboard stopped (PID {pid}).")
|
|
141
|
+
if killed_agents:
|
|
142
|
+
print(f"Stopped {killed_agents} agent process(es).")
|
|
143
|
+
except OSError as exc:
|
|
144
|
+
print(f"Failed to stop dashboard (PID {pid}): {exc}")
|
|
145
|
+
|
|
146
|
+
pid_file.unlink(missing_ok=True)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def main():
|
|
150
|
+
if len(sys.argv) > 1 and sys.argv[1] == "stop":
|
|
151
|
+
_stop()
|
|
152
|
+
return
|
|
153
|
+
if len(sys.argv) > 1 and sys.argv[1] == "dashboard":
|
|
154
|
+
import argparse
|
|
155
|
+
parser = argparse.ArgumentParser(prog="memstack dashboard")
|
|
156
|
+
parser.add_argument("--with-proxy", action="store_true", help="Start TokenStack proxy on background thread")
|
|
157
|
+
parser.add_argument("--proxy-port", type=int, default=8787, help="Proxy port (default 8787)")
|
|
158
|
+
args = parser.parse_args(sys.argv[2:])
|
|
159
|
+
from .dashboard import start_dashboard
|
|
160
|
+
start_dashboard(with_proxy=args.with_proxy, proxy_port=args.proxy_port)
|
|
161
|
+
elif len(sys.argv) > 2 and sys.argv[1] == "run":
|
|
162
|
+
task = " ".join(sys.argv[2:])
|
|
163
|
+
_run_agents(task)
|
|
164
|
+
elif len(sys.argv) > 1 and sys.argv[1] == "proxy":
|
|
165
|
+
import argparse
|
|
166
|
+
parser = argparse.ArgumentParser(prog="memstack proxy")
|
|
167
|
+
parser.add_argument("--port", type=int, default=8787)
|
|
168
|
+
parser.add_argument("--host", default="127.0.0.1")
|
|
169
|
+
parser.add_argument("--verbose", action="store_true", help="Show parser diagnostics")
|
|
170
|
+
parser.add_argument("--pro", action="store_true", help="Force pro tier transforms (testing without license file)")
|
|
171
|
+
args = parser.parse_args(sys.argv[2:])
|
|
172
|
+
from .proxy.server import start_proxy
|
|
173
|
+
start_proxy(host=args.host, port=args.port, verbose=args.verbose, force_pro=args.pro)
|
|
174
|
+
elif len(sys.argv) > 1 and sys.argv[1] == "run":
|
|
175
|
+
print("Usage: python -m memstack_skill_loader run \"Your task description\"",
|
|
176
|
+
file=sys.stderr)
|
|
177
|
+
sys.exit(1)
|
|
178
|
+
else:
|
|
179
|
+
asyncio.run(run())
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
if __name__ == "__main__":
|
|
183
|
+
main()
|