memstack-skill-loader 4.5.0__tar.gz → 4.6.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.
Potentially problematic release.
This version of memstack-skill-loader might be problematic. Click here for more details.
- {memstack_skill_loader-4.5.0/src/memstack_skill_loader.egg-info → memstack_skill_loader-4.6.0}/PKG-INFO +1 -1
- memstack_skill_loader-4.6.0/README.md +207 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/pyproject.toml +1 -1
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/__init__.py +1 -1
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/categories.py +40 -13
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/dashboard.html +21 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/dashboard.py +9 -1
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/proxy/body_parser.py +24 -1
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/proxy/pro_compressor.py +174 -45
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/proxy/stats_tracker.py +58 -3
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/server.py +2 -2
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0/src/memstack_skill_loader.egg-info}/PKG-INFO +1 -1
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader.egg-info/SOURCES.txt +2 -0
- memstack_skill_loader-4.6.0/tests/test_body_parser_metric.py +138 -0
- memstack_skill_loader-4.6.0/tests/test_code_read_savings.py +64 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/tests/test_license_grace.py +604 -604
- memstack_skill_loader-4.6.0/tests/test_pro_compressor.py +688 -0
- memstack_skill_loader-4.5.0/README.md +0 -152
- memstack_skill_loader-4.5.0/tests/test_pro_compressor.py +0 -384
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/MANIFEST.in +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/setup.cfg +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/__main__.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/agent_runner.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/compression.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/config.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/indexer.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/license.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/memory_db.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/proxy/__init__.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/proxy/_diag.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/proxy/compressor.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/proxy/forwarder.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/proxy/server.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/search.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/skill_config.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/stats.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/tfidf_search.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/version_check.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader.egg-info/dependency_links.txt +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader.egg-info/entry_points.txt +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader.egg-info/requires.txt +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader.egg-info/top_level.txt +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/tests/test_pro_skills_update.py +0 -0
- {memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/tests/test_skill_drift.py +0 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# MemStack™ Skill Loader
|
|
2
|
+
|
|
3
|
+
**128 skills for Claude Code:** 85 free + 43 Pro exclusive. Vector-indexed so CC loads only the skill it needs, saving your context window.
|
|
4
|
+
|
|
5
|
+
## Quick Start (5 minutes)
|
|
6
|
+
|
|
7
|
+
MemStack installs in two parts: the **skills** (via the Claude Code plugin marketplace) and the **engine** (this loader, via PyPI). You need both. Every command below is labeled **(in Claude Code)** or **(in terminal)** — running one in the wrong place is the most common setup mistake.
|
|
8
|
+
|
|
9
|
+
**Step 1 — Install the free skills · (in Claude Code):**
|
|
10
|
+
```
|
|
11
|
+
/plugin marketplace add cwinvestments/memstack
|
|
12
|
+
/plugin install memstack@cwinvestments-memstack
|
|
13
|
+
```
|
|
14
|
+
Run both commands. This unlocks the 85 free skills right away.
|
|
15
|
+
|
|
16
|
+
> **SSH error?** ("Host key verification failed" on a fresh server that's never used GitHub over SSH.)
|
|
17
|
+
> **Default fix · (in terminal)** — rewrite GitHub to HTTPS, then retry Step 1:
|
|
18
|
+
> ```bash
|
|
19
|
+
> git config --global url."https://github.com/".insteadOf "git@github.com:"
|
|
20
|
+
> ```
|
|
21
|
+
> **Backup fix · (in terminal)** — add GitHub's host key, then retry Step 1:
|
|
22
|
+
> ```bash
|
|
23
|
+
> mkdir -p ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
|
|
24
|
+
> ```
|
|
25
|
+
|
|
26
|
+
**Step 2 — Install the engine · (in terminal):**
|
|
27
|
+
|
|
28
|
+
Windows:
|
|
29
|
+
```bash
|
|
30
|
+
pip install memstack-skill-loader
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Linux / Mac — use the explicit interpreter (the same one you register in Step 3):
|
|
34
|
+
```bash
|
|
35
|
+
/usr/bin/python3 -m pip install memstack-skill-loader --break-system-packages
|
|
36
|
+
```
|
|
37
|
+
Find yours with `which python3` and substitute it if it isn't `/usr/bin/python3`. The `--break-system-packages` flag is required on newer externally-managed Python. No pip for that interpreter? Run `sudo apt install python3-pip` first (Debian/Ubuntu).
|
|
38
|
+
|
|
39
|
+
**Step 3 — Register the MCP server · (in terminal):** register against the **same interpreter you installed onto in Step 2.**
|
|
40
|
+
|
|
41
|
+
Windows:
|
|
42
|
+
```bash
|
|
43
|
+
claude mcp add --scope user memstack-skills -- python -m memstack_skill_loader
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Linux / Mac:
|
|
47
|
+
```bash
|
|
48
|
+
claude mcp add --scope user memstack-skills -- /usr/bin/python3 -m memstack_skill_loader
|
|
49
|
+
```
|
|
50
|
+
If this doesn't match Step 2's interpreter, the server won't launch (you'll see a "failed to reconnect" error and `activate_license` will be missing).
|
|
51
|
+
|
|
52
|
+
**Step 4 — Activate your license · (in Claude Code, after a full restart):** fully quit and reopen Claude Code first so it picks up the new MCP server, then run:
|
|
53
|
+
```
|
|
54
|
+
activate_license(key="your-key", email="you@example.com")
|
|
55
|
+
```
|
|
56
|
+
Use `key="free"` for the free tier, or your Pro key from [memstack.pro](https://memstack.pro) to unlock all 43 Pro skills (85 free + 43 Pro = 128 total). Then type `list skills` to verify.
|
|
57
|
+
|
|
58
|
+
> To override the skills path, set `MEMSTACK_SKILLS_DIR=/path/to/your/memstack/skills`.
|
|
59
|
+
|
|
60
|
+
> See [QUICKSTART.md](QUICKSTART.md) for detailed setup, [QUICK-REFERENCE.md](QUICK-REFERENCE.md) for the full skill catalog, and [TROUBLESHOOTING.md](TROUBLESHOOTING.md) if you hit issues.
|
|
61
|
+
|
|
62
|
+
## Troubleshooting
|
|
63
|
+
|
|
64
|
+
**`error: externally-managed-environment` (during Step 2)** — pip refuses to install on a system-managed Python. Add `--break-system-packages` · (in terminal):
|
|
65
|
+
```bash
|
|
66
|
+
/usr/bin/python3 -m pip install memstack-skill-loader --break-system-packages
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Plugin clone fails: "Host key verification failed" (during Step 1)** — a fresh server that's never connected to GitHub over SSH. **Default fix · (in terminal):** `git config --global url."https://github.com/".insteadOf "git@github.com:"` then retry Step 1. **Backup fix · (in terminal):** `mkdir -p ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts` then retry Step 1.
|
|
70
|
+
|
|
71
|
+
**`activate_license` not found, or MCP "failed to reconnect (-32000)"** — the loader was installed onto a **different Python interpreter** than the one Claude Code launches (the classic bare-`python` mismatch on Linux/Mac). Check · (in terminal):
|
|
72
|
+
```bash
|
|
73
|
+
/usr/bin/python3 -c "import memstack_skill_loader; print('ok')"
|
|
74
|
+
```
|
|
75
|
+
If it prints `ok`, make sure Step 3 registered that exact path, then fully restart Claude Code. If it errors with `ModuleNotFoundError`, reinstall onto the explicit interpreter and re-register against that same path · (in terminal):
|
|
76
|
+
```bash
|
|
77
|
+
/usr/bin/python3 -m pip install memstack-skill-loader --break-system-packages
|
|
78
|
+
claude mcp add --scope user memstack-skills -- /usr/bin/python3 -m memstack_skill_loader
|
|
79
|
+
```
|
|
80
|
+
Then fully restart Claude Code. Rule of thumb: whatever interpreter you `import`-check as `ok` is the path that must appear in your `claude mcp add` command.
|
|
81
|
+
|
|
82
|
+
**`No module named pip` (during Step 2)** — that interpreter ships without pip (common on minimal Debian/Ubuntu server images). Install it, then retry the Step 2 install · (in terminal):
|
|
83
|
+
```bash
|
|
84
|
+
sudo apt install python3-pip
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## How It Works
|
|
88
|
+
|
|
89
|
+
MCP server that vector-indexes all 128 MemStack™ skills so Claude Code can call `find_skill("deploy to Railway")` and load **only** the relevant skill on demand, instead of all skills consuming context window.
|
|
90
|
+
|
|
91
|
+
- **No API keys required:** everything runs locally
|
|
92
|
+
- **Pro skills auto-detected:** set your license key and they appear automatically
|
|
93
|
+
- **Auto-reindex on start:** skills stay current without manual rebuilds
|
|
94
|
+
|
|
95
|
+
### Environment Variable Override
|
|
96
|
+
|
|
97
|
+
Set `MEMSTACK_SKILLS_DIR` to override the skills path in `config.json`:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
export MEMSTACK_SKILLS_DIR=/path/to/your/memstack/skills
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Stack
|
|
104
|
+
|
|
105
|
+
- Python 3.12+
|
|
106
|
+
- [MCP SDK](https://pypi.org/project/mcp/) (stdio transport)
|
|
107
|
+
- [LanceDB](https://lancedb.com/) (vector storage, zero external dependencies)
|
|
108
|
+
- [sentence-transformers](https://www.sbert.net/) with `all-MiniLM-L6-v2` (384-dim local embeddings)
|
|
109
|
+
|
|
110
|
+
## Available Tools
|
|
111
|
+
|
|
112
|
+
### `find_skill`
|
|
113
|
+
Search skills by describing what you need. Returns the most relevant skill(s) with full instructions.
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
find_skill(query="deploy to Railway", top_k=3)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### `list_skills`
|
|
120
|
+
Browse the full skill catalog with names and descriptions.
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
list_skills()
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### `get_skill`
|
|
127
|
+
Load a specific skill by exact name.
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
get_skill(name="railway deploy")
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### `reindex_skills`
|
|
134
|
+
Rebuild the vector index after adding or modifying skills.
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
reindex_skills()
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Configuration
|
|
141
|
+
|
|
142
|
+
The `config.json` file controls where skills are loaded from:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"skill_sources": [
|
|
147
|
+
{
|
|
148
|
+
"type": "local",
|
|
149
|
+
"path": "C:\\Projects\\memstack\\skills",
|
|
150
|
+
"pattern": "**/SKILL.md",
|
|
151
|
+
"label": "MemStack"
|
|
152
|
+
}
|
|
153
|
+
],
|
|
154
|
+
"embedding_model": "all-MiniLM-L6-v2",
|
|
155
|
+
"default_top_k": 3,
|
|
156
|
+
"vector_db_path": "./vectors",
|
|
157
|
+
"auto_reindex_on_start": true
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Pro skills are **auto-detected** when `MEMSTACK_PRO_LICENSE_KEY` is set, no need to add them to `config.json`.
|
|
162
|
+
|
|
163
|
+
Add entries to `skill_sources` to index skills from multiple directories:
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"skill_sources": [
|
|
168
|
+
{
|
|
169
|
+
"type": "local",
|
|
170
|
+
"path": "C:\\Projects\\memstack\\skills",
|
|
171
|
+
"pattern": "**/SKILL.md",
|
|
172
|
+
"label": "MemStack"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"type": "local",
|
|
176
|
+
"path": "/home/user/custom-skills",
|
|
177
|
+
"pattern": "*.md",
|
|
178
|
+
"label": "My Custom Skills"
|
|
179
|
+
}
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
The `pattern` field controls how skills are discovered:
|
|
185
|
+
- `**/SKILL.md`: Subdirectory structure (e.g., `category/skill-name/SKILL.md`)
|
|
186
|
+
- `*.md`: Flat directory (each `.md` file is a skill)
|
|
187
|
+
|
|
188
|
+
## Release Notes
|
|
189
|
+
|
|
190
|
+
### v4.0.0 (May 2026)
|
|
191
|
+
|
|
192
|
+
- Dashboard: 6-page localhost dashboard (Overview, Skills Manager, Burn Report, Memory Browser, Agent Monitor, Settings)
|
|
193
|
+
- Agent Runner: 3-agent orchestration (Manager/Builder/Reviewer) with per-agent model selection
|
|
194
|
+
- 17 MCP tools
|
|
195
|
+
- 127 skills (84 free + 43 Pro)
|
|
196
|
+
- Real-time context window monitoring per agent
|
|
197
|
+
- Session diary with AI-authored markdown narratives
|
|
198
|
+
- Safe git staging (prevents accidental commits of secrets/runtime data)
|
|
199
|
+
- Task completion notifications (browser, tab flash, audio)
|
|
200
|
+
- Token usage tracking with estimated costs
|
|
201
|
+
- TokenStack™ proxy integration (~35-40% token savings)
|
|
202
|
+
|
|
203
|
+
**[v3.4.0](https://github.com/cwinvestments/memstack-skill-loader/releases/tag/v3.4.0)**: 100 Skills Milestone (18 new Pro skills, auto-detection, display name fixes)
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
Proprietary. Part of MemStack™ Pro by CW Affiliate Investments LLC.
|
{memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/categories.py
RENAMED
|
@@ -12,7 +12,8 @@ CATEGORY_MAP = {
|
|
|
12
12
|
"quill": "Business", "scan": "Business", "governor": "Business",
|
|
13
13
|
"client-onboarding": "Business", "contract-template": "Business", "financial-model": "Business",
|
|
14
14
|
"freelancer-toolkit": "Business", "invoice-generator": "Business", "scope-of-work": "Business",
|
|
15
|
-
"sop-builder": "Business", "proposal-writer": "Business",
|
|
15
|
+
"sop-builder": "Business", "proposal-writer": "Business", "gdpr": "Business",
|
|
16
|
+
"licensing": "Business",
|
|
16
17
|
# Content
|
|
17
18
|
"humanize": "Content", "blog-post": "Content", "email-sequence": "Content",
|
|
18
19
|
"landing-page-copy": "Content", "newsletter": "Content", "product-description": "Content",
|
|
@@ -26,7 +27,7 @@ CATEGORY_MAP = {
|
|
|
26
27
|
"forge": "Development", "shard": "Development",
|
|
27
28
|
"state": "Development", "work": "Development", "verify": "Development",
|
|
28
29
|
"project": "Development", "familiar": "Development", "api-designer": "Development",
|
|
29
|
-
"code-reviewer": "Development", "
|
|
30
|
+
"code-reviewer": "Development", "migration-planner": "Development",
|
|
30
31
|
"performance-audit": "Development", "refactor-planner": "Development", "test-writer": "Development",
|
|
31
32
|
"changelog-generator": "Development", "mentor": "Development", "webapp-testing": "Development",
|
|
32
33
|
# Core
|
|
@@ -45,20 +46,46 @@ CATEGORY_MAP = {
|
|
|
45
46
|
"user-story-generator": "Product", "mvp-scoper": "Product", "roadmap-builder": "Product",
|
|
46
47
|
"feedback-analyzer": "Product",
|
|
47
48
|
# Security
|
|
48
|
-
"advanced-security": "Security", "env-manager-pro": "Security",
|
|
49
49
|
"api-audit": "Security", "csp-headers": "Security", "dependency-audit": "Security",
|
|
50
50
|
"owasp-top10": "Security", "owasp-top-10": "Security",
|
|
51
51
|
"rls-checker": "Security", "rls-guardian": "Security",
|
|
52
|
-
"secrets-scanner": "Security",
|
|
53
|
-
# Pro skills (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
"
|
|
52
|
+
"secrets-scanner": "Security", "git-guard": "Security",
|
|
53
|
+
# ── Pro-exclusive skills (43) — CANONICAL category map ─────────────────
|
|
54
|
+
# Must cover every slug in PRO_EXCLUSIVE_SKILLS (license.py) exactly; no Pro
|
|
55
|
+
# slug may fall through to "Other". Enforced by scripts/check_skill_drift.py
|
|
56
|
+
# (Check C / F-3). Core = MemStack's own session/memory/agent/efficiency
|
|
57
|
+
# meta-skills ONLY; anything that operates on the user's code/docs is
|
|
58
|
+
# Development, not Core.
|
|
59
|
+
# Core (9)
|
|
60
|
+
"burn": "Core", "checkpoint": "Core", "consolidate": "Core",
|
|
61
|
+
"context-db": "Core", "council": "Core", "governor-pro": "Core",
|
|
62
|
+
"model-router": "Core", "multi-agent": "Core", "session-restore": "Core",
|
|
63
|
+
# Development (21)
|
|
64
|
+
"api-docs": "Development", "api-load-tester": "Development",
|
|
65
|
+
"branching": "Development", "claude-api-helper": "Development",
|
|
66
|
+
"codebase-index": "Development", "database-architect": "Development",
|
|
67
|
+
"database-migration": "Development", "developer-growth-analysis": "Development",
|
|
68
|
+
"diagram-generator": "Development", "doc-index": "Development",
|
|
69
|
+
"drift-detection": "Development", "error-handler": "Development",
|
|
70
|
+
"frontend-design": "Development", "git-worktrees": "Development",
|
|
71
|
+
"log-analyzer": "Development", "mcp-builder": "Development",
|
|
72
|
+
"nextjs-conventions": "Development", "performance-profiler": "Development",
|
|
73
|
+
"python-conventions": "Development", "rag-builder": "Development",
|
|
74
|
+
"test-generator": "Development",
|
|
75
|
+
# Security (4)
|
|
76
|
+
"advanced-security": "Security", "config-audit": "Security",
|
|
77
|
+
"dependency-auditor": "Security", "env-manager-pro": "Security",
|
|
78
|
+
# Automation (4)
|
|
79
|
+
"browser-use": "Automation", "hooks-integration": "Automation",
|
|
80
|
+
"video-pipeline": "Automation", "web-scraper": "Automation",
|
|
81
|
+
# Business (2)
|
|
82
|
+
"meeting-insights-analyzer": "Business", "us-privacy-compliance": "Business",
|
|
83
|
+
# Content (1)
|
|
84
|
+
"social-media": "Content",
|
|
85
|
+
# Deployment (1)
|
|
86
|
+
"ios-app-store": "Deployment",
|
|
87
|
+
# Marketing (1)
|
|
88
|
+
"gtm-validator": "Marketing",
|
|
62
89
|
}
|
|
63
90
|
|
|
64
91
|
|
{memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/dashboard.html
RENAMED
|
@@ -1564,6 +1564,10 @@
|
|
|
1564
1564
|
<div class="card">
|
|
1565
1565
|
<div class="value stat-green" id="ts-avg-savings">-</div>
|
|
1566
1566
|
<div class="label">Avg Savings</div>
|
|
1567
|
+
<div id="ts-code-read" style="display:none;font-size:0.62rem;color:#6e7681;margin-top:0.35rem;line-height:1.3">
|
|
1568
|
+
<span id="ts-code-read-text"></span>
|
|
1569
|
+
<span id="ts-code-read-info" style="cursor:help;border-bottom:1px dotted #6e7681">ⓘ</span>
|
|
1570
|
+
</div>
|
|
1567
1571
|
</div>
|
|
1568
1572
|
<div class="card">
|
|
1569
1573
|
<div class="value" style="color:#58a6ff" id="ts-requests">-</div>
|
|
@@ -5216,6 +5220,21 @@ async function loadTokenStackSavings() {
|
|
|
5216
5220
|
avgEl.textContent = (d.avg_savings_pct || 0).toFixed(1) + '%';
|
|
5217
5221
|
reqEl.textContent = fmt(d.total_requests || 0);
|
|
5218
5222
|
|
|
5223
|
+
// Secondary, clearly-subordinate stat: all-time p95 of the AST-fired
|
|
5224
|
+
// (code-read) slice. Hidden unless the slice is big enough to be meaningful.
|
|
5225
|
+
const crEl = document.getElementById('ts-code-read');
|
|
5226
|
+
const crText = document.getElementById('ts-code-read-text');
|
|
5227
|
+
const crInfo = document.getElementById('ts-code-read-info');
|
|
5228
|
+
if (d.code_read_display_pct != null && (d.code_read_sample_size || 0) >= 50) {
|
|
5229
|
+
crText.textContent = 'up to ~' + d.code_read_display_pct + '% on code-heavy reads';
|
|
5230
|
+
crInfo.title = 'Code-heavy = requests where AST truncation fires (file reads of '
|
|
5231
|
+
+ 'source code). p95 of that slice (n=' + fmt(d.code_read_sample_size)
|
|
5232
|
+
+ ') — not the typical case.';
|
|
5233
|
+
crEl.style.display = '';
|
|
5234
|
+
} else {
|
|
5235
|
+
crEl.style.display = 'none';
|
|
5236
|
+
}
|
|
5237
|
+
|
|
5219
5238
|
const labels = {free: 'Free', ast: 'AST', json: 'JSON', log: 'Log', path: 'Path',
|
|
5220
5239
|
system: 'System Prompt', dedup: 'Conversation Dedup', markdown: 'Markdown'};
|
|
5221
5240
|
const order = ['free', 'ast', 'json', 'log', 'path', 'system', 'dedup', 'markdown'];
|
|
@@ -5230,6 +5249,8 @@ async function loadTokenStackSavings() {
|
|
|
5230
5249
|
savedEl.textContent = '-';
|
|
5231
5250
|
avgEl.textContent = '-';
|
|
5232
5251
|
reqEl.textContent = '-';
|
|
5252
|
+
const crEl = document.getElementById('ts-code-read');
|
|
5253
|
+
if (crEl) crEl.style.display = 'none';
|
|
5233
5254
|
tbody.innerHTML = '<tr><td colspan="2"><span class="empty-state">No compression data yet. Start the dashboard with --with-proxy.</span></td></tr>';
|
|
5234
5255
|
}
|
|
5235
5256
|
}
|
{memstack_skill_loader-4.5.0 → memstack_skill_loader-4.6.0}/src/memstack_skill_loader/dashboard.py
RENAMED
|
@@ -30,7 +30,11 @@ from . import agent_runner
|
|
|
30
30
|
import subprocess
|
|
31
31
|
from .skill_config import load_skill_config, save_skill_config, toggle_skill, set_mode, SkillConfig
|
|
32
32
|
from .stats import DB_PATH, get_dashboard_data, get_project_details, get_skill_fire_counts, get_burn_report_data, get_api_costs
|
|
33
|
-
from .proxy.stats_tracker import
|
|
33
|
+
from .proxy.stats_tracker import (
|
|
34
|
+
get_tokenstack_stats,
|
|
35
|
+
get_lifetime_avg_savings,
|
|
36
|
+
get_code_read_savings,
|
|
37
|
+
)
|
|
34
38
|
|
|
35
39
|
_HTML_PATH = Path(__file__).parent / "dashboard.html"
|
|
36
40
|
_LAST_WORKDIR_FILE = Path.home() / ".memstack" / "agent-runner" / "last-workdir.txt"
|
|
@@ -795,6 +799,10 @@ class _Handler(BaseHTTPRequestHandler):
|
|
|
795
799
|
rng = "all"
|
|
796
800
|
try:
|
|
797
801
|
data = get_tokenstack_stats(rng)
|
|
802
|
+
# All-time code-read (AST-fired) p95 capability stat. Merged here
|
|
803
|
+
# rather than inside the range-scoped aggregate so it stays a
|
|
804
|
+
# stable claim independent of the selected time window.
|
|
805
|
+
data.update(get_code_read_savings())
|
|
798
806
|
except Exception as exc:
|
|
799
807
|
data = {"error": str(exc)}
|
|
800
808
|
body = json.dumps(data).encode()
|
|
@@ -154,8 +154,31 @@ def parse_and_compress(body_dict: dict, tier: str = "free", force_pro: bool = Fa
|
|
|
154
154
|
_diag.body_transform("dedup", dedup_saved,
|
|
155
155
|
note="(cross-message repeated-block removal)")
|
|
156
156
|
|
|
157
|
+
# Body-level transforms (system-prompt compression + conversation dedup) remove
|
|
158
|
+
# tokens from content that is already inside total_compressed (the post-block
|
|
159
|
+
# forwarded text), but they run *after* total_compressed was tallied in the
|
|
160
|
+
# message loop. Credit their savings in savings_pct by computing it against the
|
|
161
|
+
# reduced "forwarded" size — but DO NOT mutate total_compressed itself: the
|
|
162
|
+
# stored compressed_tokens must stay a BLOCK-ONLY base so historical (backfilled)
|
|
163
|
+
# and new rows share exactly one convention. The read path (get_tokenstack_stats
|
|
164
|
+
# / get_proxy_stats) reconstructs the body-inclusive tokens-saved total from this
|
|
165
|
+
# same block-only base plus the dedup/system columns, so the headline % and the
|
|
166
|
+
# absolute token count stay consistent. The removals are disjoint from the
|
|
167
|
+
# block-transform deltas (sequential) and from each other, so no double-count;
|
|
168
|
+
# clamp >=0 for the rare sub-threshold case. total_original stays block-scope —
|
|
169
|
+
# folding the system prompt's original size into the denominator is
|
|
170
|
+
# unreproducible by the column-only backfill (sys_orig is not stored) and would
|
|
171
|
+
# dilute the headline. See scripts/verify_metric_fix.py for the live-data proof.
|
|
172
|
+
body_saved = 0
|
|
173
|
+
if pro:
|
|
174
|
+
if sys_t is not None and sys_t.enabled:
|
|
175
|
+
body_saved += savings.get(sys_t.stat_key, 0)
|
|
176
|
+
if dedup_t is not None and dedup_t.enabled:
|
|
177
|
+
body_saved += savings.get(dedup_t.stat_key, 0)
|
|
178
|
+
forwarded = max(0, total_compressed - body_saved)
|
|
179
|
+
|
|
157
180
|
if total_original > 0:
|
|
158
|
-
savings_pct = round((1 -
|
|
181
|
+
savings_pct = round((1 - forwarded / total_original) * 100, 1)
|
|
159
182
|
else:
|
|
160
183
|
savings_pct = 0.0
|
|
161
184
|
|