memstack-skill-loader 4.15.0__tar.gz → 4.16.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.15.0/src/memstack_skill_loader.egg-info → memstack_skill_loader-4.16.0}/PKG-INFO +11 -5
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/README.md +10 -4
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/pyproject.toml +1 -1
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/__init__.py +1 -1
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/config.py +28 -2
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/dashboard.html +21 -1
- memstack_skill_loader-4.16.0/src/memstack_skill_loader/diary_ingest.py +467 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/server.py +72 -3
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0/src/memstack_skill_loader.egg-info}/PKG-INFO +11 -5
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader.egg-info/SOURCES.txt +1 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_diary_ingest.py +249 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_memory_tools.py +32 -0
- memstack_skill_loader-4.16.0/tests/test_pro_source_resolution.py +227 -0
- memstack_skill_loader-4.15.0/src/memstack_skill_loader/diary_ingest.py +0 -278
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/MANIFEST.in +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/setup.cfg +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/__main__.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/agent_runner.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/categories.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/compression.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/dashboard.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/goal.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/goal_engine.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/hooks/__init__.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/hooks/deny_git.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/hooks/deny_manager_write.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/hooks/deny_reviewer_git.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/hooks/git_policy.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/index_meta.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/indexer.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/license.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/memory_db.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/memory_engine.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/proxy/__init__.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/proxy/_diag.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/proxy/body_parser.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/proxy/compressor.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/proxy/forwarder.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/proxy/pro_compressor.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/proxy/server.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/proxy/stats_tracker.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/search.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/session_context.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/skill_config.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/skill_descriptions.json +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/stats.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/tfidf_search.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/version_check.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader.egg-info/dependency_links.txt +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader.egg-info/entry_points.txt +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader.egg-info/requires.txt +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader.egg-info/top_level.txt +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_advisor_strategy.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_body_parser_metric.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_builder_scope.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_code_read_savings.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_dashscan.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_failed_approaches.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_git_policy.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_index_meta_guard.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_license_environment.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_license_grace.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_memory_engine.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_memory_inspector.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_memory_scoring.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_pro_compressor.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_pro_skills_update.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_project_dir_canonical.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_search_memory.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_session_context.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_skill_drift.py +0 -0
- {memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/tests/test_wheel_contents.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memstack-skill-loader
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.16.0
|
|
4
4
|
Summary: MCP server that vector-indexes MemStack Pro skills for on-demand loading
|
|
5
5
|
Project-URL: Homepage, https://memstack.pro
|
|
6
6
|
Project-URL: Documentation, https://memstack.pro/docs
|
|
@@ -72,7 +72,7 @@ activate_license(key="your-key", email="you@example.com")
|
|
|
72
72
|
```
|
|
73
73
|
Use `key="free"` for the free tier, or your Pro key from [memstack.pro](https://memstack.pro) to unlock all 44 Pro skills (86 free + 44 Pro = 130 total). Then type `list skills` to verify.
|
|
74
74
|
|
|
75
|
-
> **The first start is slow, and that is normal.** On the very first run after installing or upgrading, the server builds the skill index before it answers anything.
|
|
75
|
+
> **The first start is slow, and that is normal.** On the very first run after installing or upgrading, the server builds the skill index before it answers anything. Nearly all of that time is a one-time download of the ~90 MB embedding model, so it tracks your network speed rather than the size of your skill library: indexing 86 skills itself takes about a second. On a fast connection the whole first start is around half a minute; on a slow one it is longer. **The server will look unresponsive for that time.** Let it finish. Every later start reuses the cached model and index and is not affected.
|
|
76
76
|
|
|
77
77
|
> To override the skills path, set `MEMSTACK_SKILLS_DIR=/path/to/your/memstack/skills`.
|
|
78
78
|
|
|
@@ -80,7 +80,7 @@ Use `key="free"` for the free tier, or your Pro key from [memstack.pro](https://
|
|
|
80
80
|
|
|
81
81
|
## Troubleshooting
|
|
82
82
|
|
|
83
|
-
**Nothing responds after a fresh install, and it does not seem to be failing either (during Step 4):** the first start builds the skill index before the server answers anything
|
|
83
|
+
**Nothing responds after a fresh install, and it does not seem to be failing either (during Step 4):** the first start builds the skill index before the server answers anything. Most of that is a one-time ~90 MB embedding-model download, not reading your skills, so the wait depends on your connection: around half a minute on a fast one, longer on a slow one. There is no progress output, so a working first start and a hung one look identical. Wait it out before changing anything. If it is still silent well past a few minutes, then treat it as the interpreter mismatch below. Later starts reuse the cached model and index and respond immediately.
|
|
84
84
|
|
|
85
85
|
**`error: externally-managed-environment` (during Step 2)** — pip refuses to install on a system-managed Python. Add `--break-system-packages` · (in terminal):
|
|
86
86
|
```bash
|
|
@@ -111,7 +111,7 @@ MCP server that vector-indexes all 130 MemStack™ skills so Claude Code can cal
|
|
|
111
111
|
|
|
112
112
|
- **No Anthropic API key required:** skill search and indexing run locally and never leave your machine. Three small calls happen on their own at session start — license validation, a Pro-bundle version probe, and a PyPI update check — and every other outbound call is one you trigger ([Data and privacy](#data-and-privacy))
|
|
113
113
|
- **Pro skills auto-detected:** once activated, the Pro skills directory is added to your sources automatically, with no `config.json` edit
|
|
114
|
-
- **Auto-reindex on start:** skills stay current without manual rebuilds. Only startup ever rebuilds, never a search. The first start pays a one-time build
|
|
114
|
+
- **Auto-reindex on start:** skills stay current without manual rebuilds. Only startup ever rebuilds, never a search. The first start pays a one-time build dominated by the embedding-model download (see [Quick Start](#quick-start-5-minutes)); after that a rebuild happens in the background while the existing index keeps serving, so later starts are not delayed
|
|
115
115
|
- **Memory Engine:** an append-only, versioned fact store with query-time recall scoring — facts decay with age and decay more slowly the more they are recalled. Facts flow in from the diary's `## FACTS` block and are exposed to Claude through five `mem_*` tools (see [Available Tools](#available-tools))
|
|
116
116
|
- **Living memory at session start:** the SessionStart hook injects a compact, token-budgeted digest of the project's top recall-scored facts into context. It fails open — a missing, empty, or unreachable store never blocks startup
|
|
117
117
|
- **8-page localhost dashboard:** Overview, Skills Manager, Burn Report, Memory Browser (project-aware diary reader), Memory Inspector (read-only Memory Engine fact views), Agent Monitor, Referrals, and Settings
|
|
@@ -248,9 +248,15 @@ The `pattern` field controls how skills are discovered:
|
|
|
248
248
|
|
|
249
249
|
## Release Notes
|
|
250
250
|
|
|
251
|
+
### 4.15.1 (August 2026)
|
|
252
|
+
|
|
253
|
+
- **Fixed: activating a Pro license on a PyPI install downloaded the Pro skills and never indexed them.** The skills landed in `~/.memstack/pro-skills`, activation reported success, and the catalog still showed only the 86 free skills. Setting `MEMSTACK_PRO_LICENSE_KEY` was the only workaround. Both of the paths that decide whether to attach the Pro source now share one predicate.
|
|
254
|
+
- **Activation now takes effect immediately.** The reindex that follows an activation rebuilds with the Pro skills included, and the confirmation reports the post-activation count, so a restart is no longer needed.
|
|
255
|
+
- First-start timing in these docs was reworded: it is dominated by a one-time embedding-model download and therefore varies with network speed, rather than being the fixed "roughly a minute" previously quoted.
|
|
256
|
+
|
|
251
257
|
### 4.15.0 (August 2026)
|
|
252
258
|
|
|
253
|
-
- The skill index moved to the canonical state root, so a relative `vector_db_path` no longer depends on which directory the server happened to start in. **The first start after installing or upgrading rebuilds the index once
|
|
259
|
+
- The skill index moved to the canonical state root, so a relative `vector_db_path` no longer depends on which directory the server happened to start in. **The first start after installing or upgrading rebuilds the index once**, nearly all of that time being a one-time embedding-model download. Later starts are unaffected.
|
|
254
260
|
- New index guard classifies the index as current, drift, stale, absent, or rebuilding, and reports that verdict at startup and in the dashboard. Only startup may rebuild on its own, so no search request ever blocks on one.
|
|
255
261
|
- Agent Runner git policy rewritten as an argv-level classifier, replacing a substring match that could not tell `git status` from `git push`.
|
|
256
262
|
|
|
@@ -55,7 +55,7 @@ activate_license(key="your-key", email="you@example.com")
|
|
|
55
55
|
```
|
|
56
56
|
Use `key="free"` for the free tier, or your Pro key from [memstack.pro](https://memstack.pro) to unlock all 44 Pro skills (86 free + 44 Pro = 130 total). Then type `list skills` to verify.
|
|
57
57
|
|
|
58
|
-
> **The first start is slow, and that is normal.** On the very first run after installing or upgrading, the server builds the skill index before it answers anything.
|
|
58
|
+
> **The first start is slow, and that is normal.** On the very first run after installing or upgrading, the server builds the skill index before it answers anything. Nearly all of that time is a one-time download of the ~90 MB embedding model, so it tracks your network speed rather than the size of your skill library: indexing 86 skills itself takes about a second. On a fast connection the whole first start is around half a minute; on a slow one it is longer. **The server will look unresponsive for that time.** Let it finish. Every later start reuses the cached model and index and is not affected.
|
|
59
59
|
|
|
60
60
|
> To override the skills path, set `MEMSTACK_SKILLS_DIR=/path/to/your/memstack/skills`.
|
|
61
61
|
|
|
@@ -63,7 +63,7 @@ Use `key="free"` for the free tier, or your Pro key from [memstack.pro](https://
|
|
|
63
63
|
|
|
64
64
|
## Troubleshooting
|
|
65
65
|
|
|
66
|
-
**Nothing responds after a fresh install, and it does not seem to be failing either (during Step 4):** the first start builds the skill index before the server answers anything
|
|
66
|
+
**Nothing responds after a fresh install, and it does not seem to be failing either (during Step 4):** the first start builds the skill index before the server answers anything. Most of that is a one-time ~90 MB embedding-model download, not reading your skills, so the wait depends on your connection: around half a minute on a fast one, longer on a slow one. There is no progress output, so a working first start and a hung one look identical. Wait it out before changing anything. If it is still silent well past a few minutes, then treat it as the interpreter mismatch below. Later starts reuse the cached model and index and respond immediately.
|
|
67
67
|
|
|
68
68
|
**`error: externally-managed-environment` (during Step 2)** — pip refuses to install on a system-managed Python. Add `--break-system-packages` · (in terminal):
|
|
69
69
|
```bash
|
|
@@ -94,7 +94,7 @@ MCP server that vector-indexes all 130 MemStack™ skills so Claude Code can cal
|
|
|
94
94
|
|
|
95
95
|
- **No Anthropic API key required:** skill search and indexing run locally and never leave your machine. Three small calls happen on their own at session start — license validation, a Pro-bundle version probe, and a PyPI update check — and every other outbound call is one you trigger ([Data and privacy](#data-and-privacy))
|
|
96
96
|
- **Pro skills auto-detected:** once activated, the Pro skills directory is added to your sources automatically, with no `config.json` edit
|
|
97
|
-
- **Auto-reindex on start:** skills stay current without manual rebuilds. Only startup ever rebuilds, never a search. The first start pays a one-time build
|
|
97
|
+
- **Auto-reindex on start:** skills stay current without manual rebuilds. Only startup ever rebuilds, never a search. The first start pays a one-time build dominated by the embedding-model download (see [Quick Start](#quick-start-5-minutes)); after that a rebuild happens in the background while the existing index keeps serving, so later starts are not delayed
|
|
98
98
|
- **Memory Engine:** an append-only, versioned fact store with query-time recall scoring — facts decay with age and decay more slowly the more they are recalled. Facts flow in from the diary's `## FACTS` block and are exposed to Claude through five `mem_*` tools (see [Available Tools](#available-tools))
|
|
99
99
|
- **Living memory at session start:** the SessionStart hook injects a compact, token-budgeted digest of the project's top recall-scored facts into context. It fails open — a missing, empty, or unreachable store never blocks startup
|
|
100
100
|
- **8-page localhost dashboard:** Overview, Skills Manager, Burn Report, Memory Browser (project-aware diary reader), Memory Inspector (read-only Memory Engine fact views), Agent Monitor, Referrals, and Settings
|
|
@@ -231,9 +231,15 @@ The `pattern` field controls how skills are discovered:
|
|
|
231
231
|
|
|
232
232
|
## Release Notes
|
|
233
233
|
|
|
234
|
+
### 4.15.1 (August 2026)
|
|
235
|
+
|
|
236
|
+
- **Fixed: activating a Pro license on a PyPI install downloaded the Pro skills and never indexed them.** The skills landed in `~/.memstack/pro-skills`, activation reported success, and the catalog still showed only the 86 free skills. Setting `MEMSTACK_PRO_LICENSE_KEY` was the only workaround. Both of the paths that decide whether to attach the Pro source now share one predicate.
|
|
237
|
+
- **Activation now takes effect immediately.** The reindex that follows an activation rebuilds with the Pro skills included, and the confirmation reports the post-activation count, so a restart is no longer needed.
|
|
238
|
+
- First-start timing in these docs was reworded: it is dominated by a one-time embedding-model download and therefore varies with network speed, rather than being the fixed "roughly a minute" previously quoted.
|
|
239
|
+
|
|
234
240
|
### 4.15.0 (August 2026)
|
|
235
241
|
|
|
236
|
-
- The skill index moved to the canonical state root, so a relative `vector_db_path` no longer depends on which directory the server happened to start in. **The first start after installing or upgrading rebuilds the index once
|
|
242
|
+
- The skill index moved to the canonical state root, so a relative `vector_db_path` no longer depends on which directory the server happened to start in. **The first start after installing or upgrading rebuilds the index once**, nearly all of that time being a one-time embedding-model download. Later starts are unaffected.
|
|
237
243
|
- New index guard classifies the index as current, drift, stale, absent, or rebuilding, and reports that verdict at startup and in the dashboard. Only startup may rebuild on its own, so no search request ever blocks on one.
|
|
238
244
|
- Agent Runner git policy rewritten as an argv-level classifier, replacing a substring match that could not tell `git status` from `git push`.
|
|
239
245
|
|
|
@@ -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.16.0"
|
|
8
8
|
description = "MCP server that vector-indexes MemStack Pro skills for on-demand loading"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
{memstack_skill_loader-4.15.0 → memstack_skill_loader-4.16.0}/src/memstack_skill_loader/config.py
RENAMED
|
@@ -126,6 +126,32 @@ def _auto_discover_skills() -> SkillSource | None:
|
|
|
126
126
|
return None
|
|
127
127
|
|
|
128
128
|
|
|
129
|
+
def _pro_license_present() -> bool:
|
|
130
|
+
"""Return True if this installation has a Pro license on either supported path.
|
|
131
|
+
|
|
132
|
+
Both call sites in load_config must ask this question the same way. They did
|
|
133
|
+
not: the env-var-only form was written once, copied into the auto-discovery
|
|
134
|
+
branch, and then fixed in only one of the two copies (07676eb, 2026-05-20).
|
|
135
|
+
For the two and a half months after that, every PyPI install (which always
|
|
136
|
+
takes the auto-discovery branch, because a wheel has no config.json beside
|
|
137
|
+
the package) downloaded Pro skills on activation and never indexed them.
|
|
138
|
+
Keep this predicate the single source of truth so a third copy cannot drift.
|
|
139
|
+
|
|
140
|
+
The env var and license.json are both first-class: license.json is the
|
|
141
|
+
documented primary path (activate_license writes it), and the env var is the
|
|
142
|
+
documented alternative. This mirrors get_license_key() in license.py, which
|
|
143
|
+
has always resolved both.
|
|
144
|
+
|
|
145
|
+
Note this answers "is a license present", not "is it valid". Entitlement is
|
|
146
|
+
enforced at serve time against a live validate_license() call, so a stale
|
|
147
|
+
license.json here only affects what gets indexed, never what a caller is
|
|
148
|
+
allowed to read.
|
|
149
|
+
"""
|
|
150
|
+
if os.environ.get("MEMSTACK_PRO_LICENSE_KEY"):
|
|
151
|
+
return True
|
|
152
|
+
return (Path.home() / ".memstack" / "license.json").exists()
|
|
153
|
+
|
|
154
|
+
|
|
129
155
|
def load_config(config_path: Path | None = None) -> Config:
|
|
130
156
|
"""Load config from JSON file. Falls back to auto-discovery if not found."""
|
|
131
157
|
if config_path is None:
|
|
@@ -138,7 +164,7 @@ def load_config(config_path: Path | None = None) -> Config:
|
|
|
138
164
|
auto_reindex_on_start=True,
|
|
139
165
|
config_source="auto-discovery",
|
|
140
166
|
)
|
|
141
|
-
if
|
|
167
|
+
if _pro_license_present():
|
|
142
168
|
config = config.with_pro_skills()
|
|
143
169
|
return config
|
|
144
170
|
|
|
@@ -184,7 +210,7 @@ def load_config(config_path: Path | None = None) -> Config:
|
|
|
184
210
|
)
|
|
185
211
|
|
|
186
212
|
# Auto-detect pro-skills if license key is set (env var or license.json)
|
|
187
|
-
if
|
|
213
|
+
if _pro_license_present():
|
|
188
214
|
config = config.with_pro_skills()
|
|
189
215
|
|
|
190
216
|
return config
|
|
@@ -2141,7 +2141,7 @@
|
|
|
2141
2141
|
<button class="mcp-tools-save-btn" style="background:#30363d;" onclick="verifyLicenseKey()">Verify</button>
|
|
2142
2142
|
<span id="licenseKeyStatus" style="font-size:0.75rem;color:#484f58;"></span>
|
|
2143
2143
|
</div>
|
|
2144
|
-
<p style="color:#484f58;font-size:0.72rem;margin:0.35rem 0 0;">Unlocks Pro-tier compression and
|
|
2144
|
+
<p style="color:#484f58;font-size:0.72rem;margin:0.35rem 0 0;">Unlocks Pro-tier compression and <span id="settings-pro-skill-count">all</span> exclusive skills. Stored at ~/.memstack/license.json.</p>
|
|
2145
2145
|
</div>
|
|
2146
2146
|
</div>
|
|
2147
2147
|
|
|
@@ -5370,6 +5370,7 @@ async function loadSettings() {
|
|
|
5370
5370
|
loadGitWorkflowGlobal();
|
|
5371
5371
|
loadAgentModes();
|
|
5372
5372
|
loadLicenseStatus();
|
|
5373
|
+
loadProSkillCount();
|
|
5373
5374
|
settingsLoaded = true;
|
|
5374
5375
|
} catch (e) {
|
|
5375
5376
|
console.error('Settings load failed:', e);
|
|
@@ -5396,6 +5397,25 @@ async function loadLicenseStatus() {
|
|
|
5396
5397
|
}
|
|
5397
5398
|
}
|
|
5398
5399
|
|
|
5400
|
+
// Pro skill count in the licence blurb, derived from /api/skills rather than
|
|
5401
|
+
// written into the markup -- a literal here read "42" while the enforced count
|
|
5402
|
+
// was 44. The static text says "all", so a failed or index-less fetch degrades
|
|
5403
|
+
// to a sentence that is still true rather than to a stale number.
|
|
5404
|
+
async function loadProSkillCount() {
|
|
5405
|
+
const el = document.getElementById('settings-pro-skill-count');
|
|
5406
|
+
if (!el) return;
|
|
5407
|
+
try {
|
|
5408
|
+
const res = await fetch('/api/skills', {headers: AUTH_GET});
|
|
5409
|
+
const d = await res.json();
|
|
5410
|
+
// Absent/unreadable index responses omit display_pro_count entirely and
|
|
5411
|
+
// report pro_count 0; neither should overwrite the fallback.
|
|
5412
|
+
const n = d.display_pro_count;
|
|
5413
|
+
if (Number.isFinite(n) && n > 0) el.textContent = n;
|
|
5414
|
+
} catch (e) {
|
|
5415
|
+
/* keep the "all" fallback; a count is not worth a broken panel */
|
|
5416
|
+
}
|
|
5417
|
+
}
|
|
5418
|
+
|
|
5399
5419
|
async function saveLicenseKey() {
|
|
5400
5420
|
const input = document.getElementById('licenseKeyInput');
|
|
5401
5421
|
const statusEl = document.getElementById('licenseKeyStatus');
|