superlocalmemory 3.6.22 → 3.7.0
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.
- package/CHANGELOG.md +52 -0
- package/README.md +275 -72
- package/bin/slm-npm +43 -89
- package/docs/pi-dev-integration.md +43 -0
- package/ide/configs/antigravity-mcp.json +2 -2
- package/ide/configs/chatgpt-desktop-mcp.json +1 -1
- package/ide/configs/claude-desktop-mcp.json +2 -2
- package/ide/configs/windsurf-mcp.json +2 -2
- package/ide/hooks/context-hook.js +6 -2
- package/ide/hooks/post-recall-hook.js +7 -3
- package/ide/hooks/tool-event-hook.sh +2 -1
- package/package.json +19 -10
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/_GENERATED.md +1 -1
- package/plugin/agents/slm-memory-advisor.md +1 -1
- package/plugin/requirements.txt +1 -1
- package/plugin/skills/slm-session/SKILL.md +1 -1
- package/plugin-src/rules/AGENTS.md +1 -1
- package/pyproject.toml +40 -8
- package/scripts/postinstall-interactive.js +17 -94
- package/scripts/postinstall.js +185 -258
- package/scripts/preuninstall.js +9 -50
- package/src/superlocalmemory/__init__.py +2 -2
- package/src/superlocalmemory/attribution/mathematical_dna.py +1 -1
- package/src/superlocalmemory/attribution/signer.py +34 -19
- package/src/superlocalmemory/attribution/watermark.py +1 -1
- package/src/superlocalmemory/cli/_lazy_init.py +3 -5
- package/src/superlocalmemory/cli/commands.py +490 -195
- package/src/superlocalmemory/cli/context_commands.py +5 -4
- package/src/superlocalmemory/cli/daemon.py +282 -187
- package/src/superlocalmemory/cli/db_migrate.py +3 -1
- package/src/superlocalmemory/cli/diagnostics_cmd.py +28 -0
- package/src/superlocalmemory/cli/evidence_cmd.py +103 -0
- package/src/superlocalmemory/cli/ingest_cmd.py +7 -3
- package/src/superlocalmemory/cli/main.py +128 -31
- package/src/superlocalmemory/cli/pending_store.py +54 -38
- package/src/superlocalmemory/cli/scale_engine_cmd.py +37 -0
- package/src/superlocalmemory/cli/service_installer.py +57 -52
- package/src/superlocalmemory/cli/setup_wizard.py +142 -88
- package/src/superlocalmemory/cli/version_banner.py +2 -1
- package/src/superlocalmemory/code_graph/config.py +3 -1
- package/src/superlocalmemory/core/backend_orchestrator.py +81 -21
- package/src/superlocalmemory/core/config.py +65 -20
- package/src/superlocalmemory/core/consolidation_engine.py +9 -7
- package/src/superlocalmemory/core/context_cache.py +56 -8
- package/src/superlocalmemory/core/derivation_lineage.py +246 -0
- package/src/superlocalmemory/core/embedding_worker.py +32 -20
- package/src/superlocalmemory/core/embeddings.py +54 -18
- package/src/superlocalmemory/core/engine.py +150 -104
- package/src/superlocalmemory/core/engine_ingestion.py +513 -0
- package/src/superlocalmemory/core/engine_wiring.py +2 -0
- package/src/superlocalmemory/core/evidence_bundle.py +526 -0
- package/src/superlocalmemory/core/fact_consolidator.py +5 -11
- package/src/superlocalmemory/core/graph_analyzer.py +2 -2
- package/src/superlocalmemory/core/health_monitor.py +4 -2
- package/src/superlocalmemory/core/ingestion_command.py +636 -0
- package/src/superlocalmemory/core/injection.py +69 -18
- package/src/superlocalmemory/core/lifecycle_state.py +153 -0
- package/src/superlocalmemory/core/maintenance.py +23 -22
- package/src/superlocalmemory/core/maintenance_scheduler.py +51 -35
- package/src/superlocalmemory/core/mutations.py +143 -0
- package/src/superlocalmemory/core/platform_utils.py +7 -4
- package/src/superlocalmemory/core/ram_lock.py +16 -5
- package/src/superlocalmemory/core/rate_limit.py +1 -1
- package/src/superlocalmemory/core/recall_pipeline.py +60 -101
- package/src/superlocalmemory/core/recall_worker.py +76 -59
- package/src/superlocalmemory/core/registry.py +1 -1
- package/src/superlocalmemory/core/scale_engine.py +293 -0
- package/src/superlocalmemory/core/score_contract.py +62 -0
- package/src/superlocalmemory/core/security_primitives.py +3 -1
- package/src/superlocalmemory/core/slm_disabled.py +3 -5
- package/src/superlocalmemory/core/store_pipeline.py +172 -40
- package/src/superlocalmemory/core/tier_manager.py +32 -20
- package/src/superlocalmemory/core/worker_pool.py +13 -4
- package/src/superlocalmemory/dynamics/activation_guided_quantization.py +1 -1
- package/src/superlocalmemory/dynamics/eap_scheduler.py +10 -3
- package/src/superlocalmemory/dynamics/ebbinghaus_langevin_coupling.py +1 -1
- package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +1 -1
- package/src/superlocalmemory/encoding/auto_linker.py +1 -1
- package/src/superlocalmemory/encoding/cognitive_consolidator.py +7 -16
- package/src/superlocalmemory/encoding/consolidator.py +22 -5
- package/src/superlocalmemory/encoding/fact_extractor.py +1 -1
- package/src/superlocalmemory/encoding/foresight.py +2 -0
- package/src/superlocalmemory/encoding/graph_builder.py +1 -1
- package/src/superlocalmemory/encoding/temporal_parser.py +2 -0
- package/src/superlocalmemory/evaluation/__init__.py +13 -0
- package/src/superlocalmemory/evaluation/calibration.py +308 -0
- package/src/superlocalmemory/evolution/skill_evolver.py +2 -1
- package/src/superlocalmemory/graph/cozo_backend.py +256 -23
- package/src/superlocalmemory/hooks/_outcome_common.py +21 -11
- package/src/superlocalmemory/hooks/antigravity_adapter.py +10 -31
- package/src/superlocalmemory/hooks/auto_invoker.py +25 -27
- package/src/superlocalmemory/hooks/auto_recall.py +31 -6
- package/src/superlocalmemory/hooks/auto_recall_hook.py +13 -33
- package/src/superlocalmemory/hooks/before_web_hook.py +9 -7
- package/src/superlocalmemory/hooks/claude_code_hooks.py +126 -39
- package/src/superlocalmemory/hooks/codex_assets.py +59 -0
- package/src/superlocalmemory/hooks/codex_hooks.py +186 -0
- package/src/superlocalmemory/hooks/context_payload.py +1 -1
- package/src/superlocalmemory/hooks/copilot_adapter.py +9 -24
- package/src/superlocalmemory/hooks/cursor_adapter.py +10 -32
- package/src/superlocalmemory/hooks/hook_daemon.py +4 -2
- package/src/superlocalmemory/hooks/hook_handlers.py +241 -55
- package/src/superlocalmemory/hooks/memory_protocol.py +5 -3
- package/src/superlocalmemory/hooks/post_tool_async_hook.py +4 -2
- package/src/superlocalmemory/hooks/session_registry.py +15 -8
- package/src/superlocalmemory/hooks/stop_outcome_hook.py +10 -6
- package/src/superlocalmemory/hooks/topic_shift_hook.py +42 -12
- package/src/superlocalmemory/hooks/user_prompt_hook.py +9 -14
- package/src/superlocalmemory/hooks/user_prompt_rehash_hook.py +19 -11
- package/src/superlocalmemory/infra/auth_middleware.py +38 -5
- package/src/superlocalmemory/infra/backup.py +7 -5
- package/src/superlocalmemory/infra/cloud_backup.py +18 -8
- package/src/superlocalmemory/infra/daemon_identity.py +248 -0
- package/src/superlocalmemory/infra/data_root.py +199 -0
- package/src/superlocalmemory/infra/event_bus.py +3 -1
- package/src/superlocalmemory/infra/local_diagnostics.py +327 -0
- package/src/superlocalmemory/infra/process_reaper.py +23 -0
- package/src/superlocalmemory/ingestion/adapter_manager.py +27 -9
- package/src/superlocalmemory/ingestion/base_adapter.py +25 -31
- package/src/superlocalmemory/ingestion/calendar_adapter.py +13 -4
- package/src/superlocalmemory/ingestion/credentials.py +14 -7
- package/src/superlocalmemory/ingestion/gmail_adapter.py +13 -4
- package/src/superlocalmemory/ingestion/transcript_adapter.py +7 -2
- package/src/superlocalmemory/learning/consolidation_quantization_worker.py +1 -1
- package/src/superlocalmemory/learning/ensemble.py +11 -0
- package/src/superlocalmemory/learning/entity_compiler.py +1 -1
- package/src/superlocalmemory/learning/feedback.py +1 -1
- package/src/superlocalmemory/learning/forgetting_scheduler.py +12 -7
- package/src/superlocalmemory/learning/quantization_scheduler.py +1 -1
- package/src/superlocalmemory/learning/ranker.py +4 -1
- package/src/superlocalmemory/learning/source_quality.py +1 -1
- package/src/superlocalmemory/learning/trigram_index.py +3 -2
- package/src/superlocalmemory/llm/backbone.py +13 -8
- package/src/superlocalmemory/math/ebbinghaus.py +1 -1
- package/src/superlocalmemory/math/fisher.py +1 -1
- package/src/superlocalmemory/math/fisher_quantized.py +1 -1
- package/src/superlocalmemory/math/hopfield.py +1 -1
- package/src/superlocalmemory/math/langevin.py +1 -1
- package/src/superlocalmemory/math/polar_quant.py +3 -4
- package/src/superlocalmemory/math/qjl.py +1 -1
- package/src/superlocalmemory/math/sheaf.py +1 -1
- package/src/superlocalmemory/math/turbo_quant.py +3 -2
- package/src/superlocalmemory/mcp/_daemon_proxy.py +12 -11
- package/src/superlocalmemory/mcp/_pool_adapter.py +27 -0
- package/src/superlocalmemory/mcp/http_transport.py +53 -0
- package/src/superlocalmemory/mcp/server.py +39 -13
- package/src/superlocalmemory/mcp/shared.py +69 -3
- package/src/superlocalmemory/mcp/tools_active.py +141 -31
- package/src/superlocalmemory/mcp/tools_core.py +128 -29
- package/src/superlocalmemory/mcp/tools_evolution.py +5 -7
- package/src/superlocalmemory/mcp/tools_learning.py +42 -2
- package/src/superlocalmemory/mcp/tools_mesh.py +7 -23
- package/src/superlocalmemory/mcp/tools_optimize.py +8 -1
- package/src/superlocalmemory/mcp/tools_v28.py +23 -2
- package/src/superlocalmemory/mcp/tools_v3.py +26 -1
- package/src/superlocalmemory/mcp/tools_v33.py +56 -17
- package/src/superlocalmemory/mesh/broker.py +2 -0
- package/src/superlocalmemory/mesh/remote_sync.py +50 -12
- package/src/superlocalmemory/optimize/cache/manager.py +77 -1
- package/src/superlocalmemory/optimize/cache/semantic.py +23 -3
- package/src/superlocalmemory/optimize/compress/ccr.py +4 -0
- package/src/superlocalmemory/optimize/compress/router.py +6 -1
- package/src/superlocalmemory/optimize/config/__init__.py +5 -0
- package/src/superlocalmemory/optimize/config/store.py +6 -4
- package/src/superlocalmemory/optimize/proxy/_helpers.py +15 -5
- package/src/superlocalmemory/optimize/proxy/capture.py +3 -2
- package/src/superlocalmemory/optimize/proxy/server.py +2 -2
- package/src/superlocalmemory/optimize/storage/db.py +14 -13
- package/src/superlocalmemory/retrieval/agentic.py +1 -1
- package/src/superlocalmemory/retrieval/ann_index.py +1 -1
- package/src/superlocalmemory/retrieval/bm25_channel.py +35 -11
- package/src/superlocalmemory/retrieval/bridge_discovery.py +73 -8
- package/src/superlocalmemory/retrieval/engine.py +169 -79
- package/src/superlocalmemory/retrieval/entity_channel.py +289 -67
- package/src/superlocalmemory/retrieval/forgetting_filter.py +1 -1
- package/src/superlocalmemory/retrieval/fusion.py +1 -1
- package/src/superlocalmemory/retrieval/hopfield_channel.py +118 -30
- package/src/superlocalmemory/retrieval/profile_channel.py +1 -1
- package/src/superlocalmemory/retrieval/quantization_aware_search.py +16 -10
- package/src/superlocalmemory/retrieval/reranker.py +56 -20
- package/src/superlocalmemory/retrieval/scope_policy.py +85 -0
- package/src/superlocalmemory/retrieval/semantic_channel.py +122 -14
- package/src/superlocalmemory/retrieval/spreading_activation.py +141 -25
- package/src/superlocalmemory/retrieval/strategy.py +1 -1
- package/src/superlocalmemory/retrieval/temporal_channel.py +30 -15
- package/src/superlocalmemory/retrieval/vector_store.py +1 -1
- package/src/superlocalmemory/server/api.py +10 -7
- package/src/superlocalmemory/server/bandit_loops.py +4 -2
- package/src/superlocalmemory/server/recall_serializer.py +24 -0
- package/src/superlocalmemory/server/route_mutations.py +84 -0
- package/src/superlocalmemory/server/routes/agents.py +8 -6
- package/src/superlocalmemory/server/routes/brain.py +14 -12
- package/src/superlocalmemory/server/routes/chat.py +29 -12
- package/src/superlocalmemory/server/routes/data_io.py +55 -24
- package/src/superlocalmemory/server/routes/helpers.py +29 -4
- package/src/superlocalmemory/server/routes/ingest.py +53 -36
- package/src/superlocalmemory/server/routes/memories.py +104 -43
- package/src/superlocalmemory/server/routes/mesh.py +31 -0
- package/src/superlocalmemory/server/routes/profiles.py +26 -4
- package/src/superlocalmemory/server/routes/tiers.py +43 -11
- package/src/superlocalmemory/server/routes/timeline.py +5 -1
- package/src/superlocalmemory/server/routes/v3_api.py +76 -21
- package/src/superlocalmemory/server/security_middleware.py +1 -1
- package/src/superlocalmemory/server/ui.py +6 -3
- package/src/superlocalmemory/server/unified_daemon.py +680 -293
- package/src/superlocalmemory/server/write_identity.py +147 -0
- package/src/superlocalmemory/storage/access_log.py +4 -3
- package/src/superlocalmemory/storage/database.py +118 -25
- package/src/superlocalmemory/storage/migration_runner.py +84 -1
- package/src/superlocalmemory/storage/migration_v33.py +1 -1
- package/src/superlocalmemory/storage/migrations/M002_model_state_history.py +6 -60
- package/src/superlocalmemory/storage/migrations/M018_ingestion_operations.py +120 -0
- package/src/superlocalmemory/storage/migrations/M019_derivation_lineage.py +54 -0
- package/src/superlocalmemory/storage/migrations/M020_model_state_integrity.py +52 -0
- package/src/superlocalmemory/storage/migrations/__init__.py +5 -0
- package/src/superlocalmemory/storage/models.py +16 -0
- package/src/superlocalmemory/storage/quantized_store.py +20 -3
- package/src/superlocalmemory/storage/v2_migrator.py +5 -3
- package/src/superlocalmemory/ui/favicon.svg +5 -0
- package/src/superlocalmemory/ui/index.html +1 -0
- package/src/superlocalmemory/ui/js/compliance.js +1 -1
- package/src/superlocalmemory/ui/js/core.js +49 -8
- package/src/superlocalmemory/ui/js/dashboard.js +23 -2
- package/src/superlocalmemory/ui/js/feedback.js +1 -1
- package/src/superlocalmemory/ui/js/graph-filters.js +1 -1
- package/src/superlocalmemory/ui/js/graph-ui.js +1 -1
- package/src/superlocalmemory/ui/js/lifecycle.js +1 -1
- package/src/superlocalmemory/ui/js/ng-mesh.js +15 -49
- package/src/superlocalmemory/ui/js/settings.js +4 -2
- package/src/superlocalmemory/vector/lancedb_backend.py +57 -9
- package/bin/slm +0 -59
- package/bin/slm.bat +0 -77
- package/bin/slm.cmd +0 -5
- package/ide/integrations/langchain/README.md +0 -106
- package/ide/integrations/langchain/langchain_superlocalmemory/__init__.py +0 -9
- package/ide/integrations/langchain/langchain_superlocalmemory/chat_message_history.py +0 -201
- package/ide/integrations/langchain/pyproject.toml +0 -38
- package/ide/integrations/langchain/tests/__init__.py +0 -3
- package/ide/integrations/langchain/tests/test_chat_message_history.py +0 -215
- package/ide/integrations/langchain/tests/test_security.py +0 -117
- package/ide/integrations/llamaindex/README.md +0 -81
- package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/__init__.py +0 -9
- package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/base.py +0 -316
- package/ide/integrations/llamaindex/pyproject.toml +0 -43
- package/ide/integrations/llamaindex/tests/__init__.py +0 -3
- package/ide/integrations/llamaindex/tests/test_chat_store.py +0 -294
- package/ide/integrations/llamaindex/tests/test_security.py +0 -241
- package/plugin-src/.mcp.json +0 -12
- package/plugin-src/agents/slm-memory-advisor.md +0 -44
- package/plugin-src/agents/slm-optimize-advisor.md +0 -38
- package/plugin-src/hooks/.gitkeep +0 -0
- package/plugin-src/hooks/hooks.json +0 -23
- package/plugin-src/manifest.json +0 -25
- package/plugin-src/requirements.txt +0 -1
- package/plugin-src/rules/CLAUDE.md.fragment +0 -44
- package/plugin-src/scripts/ensure-venv.bat +0 -122
- package/plugin-src/scripts/ensure-venv.sh +0 -105
- package/plugin-src/scripts/slm-launch +0 -15
- package/plugin-src/scripts/slm-launch.bat +0 -17
- package/plugin-src/settings.json +0 -16
- package/plugin-src/skills/slm-cache/SKILL.md +0 -140
- package/plugin-src/skills/slm-compress/SKILL.md +0 -143
- package/plugin-src/skills/slm-graph/SKILL.md +0 -300
- package/plugin-src/skills/slm-recall/SKILL.md +0 -204
- package/plugin-src/skills/slm-remember/SKILL.md +0 -194
- package/plugin-src/skills/slm-session/SKILL.md +0 -207
- package/plugin-src/skills/slm-status/SKILL.md +0 -149
- package/scripts/__tests__/build-plugin.test.mjs +0 -613
- package/scripts/_savings_math.py +0 -270
- package/scripts/build-dmg.sh +0 -417
- package/scripts/build-plugin.js +0 -742
- package/scripts/build-slm-hook.ps1 +0 -40
- package/scripts/build-slm-hook.sh +0 -45
- package/scripts/build_entry.py +0 -452
- package/scripts/ci/stage5b_gate.sh +0 -50
- package/scripts/dogfood_savings.py +0 -490
- package/scripts/generate-thumbnails.py +0 -218
- package/scripts/install-skills.ps1 +0 -4
- package/scripts/install-skills.sh +0 -5
- package/scripts/install.ps1 +0 -701
- package/scripts/install.sh +0 -1015
- package/scripts/postinstall_binary.js +0 -287
- package/scripts/prepack.js +0 -33
- package/scripts/release_manifest.py +0 -273
- package/scripts/slm-hook.spec +0 -56
- package/scripts/start-dashboard.ps1 +0 -52
- package/scripts/start-dashboard.sh +0 -41
- package/scripts/sync-wiki.ps1 +0 -127
- package/scripts/sync-wiki.sh +0 -82
- package/scripts/test-dmg.sh +0 -161
- package/scripts/test-npm-package.ps1 +0 -252
- package/scripts/test-npm-package.sh +0 -207
- package/scripts/verify-install.ps1 +0 -294
- package/scripts/verify-install.sh +0 -266
- package/scripts/verify-v27.ps1 +0 -301
- package/scripts/verify-v27.sh +0 -233
- package/src/superlocalmemory.egg-info/PKG-INFO +0 -513
- package/src/superlocalmemory.egg-info/SOURCES.txt +0 -529
- package/src/superlocalmemory.egg-info/dependency_links.txt +0 -1
- package/src/superlocalmemory.egg-info/entry_points.txt +0 -2
- package/src/superlocalmemory.egg-info/requires.txt +0 -71
- package/src/superlocalmemory.egg-info/top_level.txt +0 -1
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# SPDX-License-Identifier: Elastic-2.0
|
|
3
|
-
# Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
|
|
4
|
-
"""SuperLocalMemory V2 - Thumbnail Generator
|
|
5
|
-
|
|
6
|
-
Generates optimized thumbnail versions of all screenshots.
|
|
7
|
-
- Size: 320×180px (16:9 ratio)
|
|
8
|
-
- Format: PNG (for wiki/docs) and WebP (for website)
|
|
9
|
-
- Quality: High enough to recognize content
|
|
10
|
-
- File size: < 50KB per thumbnail
|
|
11
|
-
"""
|
|
12
|
-
import os
|
|
13
|
-
import json
|
|
14
|
-
from pathlib import Path
|
|
15
|
-
from PIL import Image, ImageFilter, ImageOps
|
|
16
|
-
from datetime import datetime
|
|
17
|
-
|
|
18
|
-
# Configuration
|
|
19
|
-
SCREENSHOT_DIR = Path(__file__).parent.parent / "assets" / "screenshots"
|
|
20
|
-
THUMBNAIL_DIR = Path(__file__).parent.parent / "assets" / "thumbnails"
|
|
21
|
-
THUMBNAIL_SIZE = (320, 180) # 16:9 ratio
|
|
22
|
-
QUALITY_PNG = 95
|
|
23
|
-
QUALITY_WEBP = 85
|
|
24
|
-
MAX_FILESIZE = 50 * 1024 # 50KB
|
|
25
|
-
|
|
26
|
-
# Category mapping based on filename patterns
|
|
27
|
-
CATEGORY_MAP = {
|
|
28
|
-
"overview": "dashboard",
|
|
29
|
-
"timeline": "timeline",
|
|
30
|
-
"agents": "agents",
|
|
31
|
-
"patterns": "patterns",
|
|
32
|
-
"clusters": "clusters",
|
|
33
|
-
"memories": "memories",
|
|
34
|
-
"graph": "graph",
|
|
35
|
-
"filtered": "search",
|
|
36
|
-
"live-events": "events",
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
def get_category(filename):
|
|
40
|
-
"""Extract category from filename."""
|
|
41
|
-
for pattern, category in CATEGORY_MAP.items():
|
|
42
|
-
if pattern in filename.lower():
|
|
43
|
-
return category
|
|
44
|
-
return "general"
|
|
45
|
-
|
|
46
|
-
def get_title(filename):
|
|
47
|
-
"""Generate human-readable title from filename."""
|
|
48
|
-
# Remove extensions and convert dashes/underscores to spaces
|
|
49
|
-
name = Path(filename).stem
|
|
50
|
-
# Remove 'dashboard-' prefix if present
|
|
51
|
-
if name.startswith("dashboard-"):
|
|
52
|
-
name = name[9:]
|
|
53
|
-
# Remove '-dark' suffix
|
|
54
|
-
name = name.replace("-dark", "")
|
|
55
|
-
# Convert to title case
|
|
56
|
-
return " ".join(word.capitalize() for word in name.split("-"))
|
|
57
|
-
|
|
58
|
-
def get_description(filename, category):
|
|
59
|
-
"""Generate description based on filename and category."""
|
|
60
|
-
descriptions = {
|
|
61
|
-
"overview": "Main dashboard with memory statistics and knowledge graph overview",
|
|
62
|
-
"timeline": "Chronological timeline of all stored memories and events",
|
|
63
|
-
"agents": "Agent connections and activity tracking",
|
|
64
|
-
"patterns": "Learned coding patterns and user preferences",
|
|
65
|
-
"clusters": "Knowledge graph clusters and relationships",
|
|
66
|
-
"memories": "Detailed memory list with search and filtering",
|
|
67
|
-
"graph": "Interactive knowledge graph visualization",
|
|
68
|
-
"search": "Advanced memory search and filtering interface",
|
|
69
|
-
"events": "Real-time live event stream from memory operations",
|
|
70
|
-
}
|
|
71
|
-
is_dark = "-dark" in filename.lower()
|
|
72
|
-
base_desc = descriptions.get(category, "Dashboard interface")
|
|
73
|
-
if is_dark:
|
|
74
|
-
base_desc += " (dark mode)"
|
|
75
|
-
return base_desc
|
|
76
|
-
|
|
77
|
-
def resize_and_crop(image, target_size):
|
|
78
|
-
"""
|
|
79
|
-
Resize image to target size while maintaining aspect ratio.
|
|
80
|
-
Crops if necessary to achieve exact dimensions.
|
|
81
|
-
"""
|
|
82
|
-
img_ratio = image.width / image.height
|
|
83
|
-
target_ratio = target_size[0] / target_size[1]
|
|
84
|
-
|
|
85
|
-
if img_ratio > target_ratio:
|
|
86
|
-
# Image is wider, crop width
|
|
87
|
-
new_height = target_size[1]
|
|
88
|
-
new_width = int(new_height * img_ratio)
|
|
89
|
-
resized = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
|
90
|
-
left = (resized.width - target_size[0]) // 2
|
|
91
|
-
return resized.crop((left, 0, left + target_size[0], target_size[1]))
|
|
92
|
-
else:
|
|
93
|
-
# Image is taller, crop height
|
|
94
|
-
new_width = target_size[0]
|
|
95
|
-
new_height = int(new_width / img_ratio)
|
|
96
|
-
resized = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
|
97
|
-
top = (resized.height - target_size[1]) // 2
|
|
98
|
-
return resized.crop((0, top, target_size[0], top + target_size[1]))
|
|
99
|
-
|
|
100
|
-
def apply_sharpening(image):
|
|
101
|
-
"""Apply subtle sharpening to enhance detail."""
|
|
102
|
-
# Use UNSHARP_MASK equivalent with subtle settings
|
|
103
|
-
return image.filter(ImageFilter.UnsharpMask(radius=1, percent=100, threshold=3))
|
|
104
|
-
|
|
105
|
-
def generate_thumbnail(source_path, dest_dir, metadata):
|
|
106
|
-
"""Generate PNG and WebP thumbnails for a single source image."""
|
|
107
|
-
try:
|
|
108
|
-
# Open image
|
|
109
|
-
with Image.open(source_path) as img:
|
|
110
|
-
# Convert RGBA to RGB if necessary (for PNG/WebP)
|
|
111
|
-
if img.mode == "RGBA":
|
|
112
|
-
background = Image.new("RGB", img.size, (255, 255, 255))
|
|
113
|
-
background.paste(img, mask=img.split()[3])
|
|
114
|
-
img = background
|
|
115
|
-
elif img.mode != "RGB":
|
|
116
|
-
img = img.convert("RGB")
|
|
117
|
-
|
|
118
|
-
# Resize and crop
|
|
119
|
-
thumbnail = resize_and_crop(img, THUMBNAIL_SIZE)
|
|
120
|
-
|
|
121
|
-
# Apply sharpening
|
|
122
|
-
thumbnail = apply_sharpening(thumbnail)
|
|
123
|
-
|
|
124
|
-
filename = source_path.stem
|
|
125
|
-
|
|
126
|
-
# Save PNG version
|
|
127
|
-
png_path = dest_dir / f"{filename}-thumb.png"
|
|
128
|
-
thumbnail.save(png_path, "PNG", quality=QUALITY_PNG, optimize=True)
|
|
129
|
-
png_size = png_path.stat().st_size
|
|
130
|
-
|
|
131
|
-
# Save WebP version
|
|
132
|
-
webp_path = dest_dir / f"{filename}-thumb.webp"
|
|
133
|
-
thumbnail.save(webp_path, "WEBP", quality=QUALITY_WEBP, method=6)
|
|
134
|
-
webp_size = webp_path.stat().st_size
|
|
135
|
-
|
|
136
|
-
# Check file sizes
|
|
137
|
-
if png_size > MAX_FILESIZE:
|
|
138
|
-
print(f"⚠️ PNG {filename}: {png_size/1024:.1f}KB (exceeds limit)")
|
|
139
|
-
if webp_size > MAX_FILESIZE:
|
|
140
|
-
print(f"⚠️ WebP {filename}: {webp_size/1024:.1f}KB (exceeds limit)")
|
|
141
|
-
|
|
142
|
-
print(f"✓ {filename}")
|
|
143
|
-
print(f" PNG: {png_size/1024:.1f}KB | WebP: {webp_size/1024:.1f}KB")
|
|
144
|
-
|
|
145
|
-
# Store metadata
|
|
146
|
-
category = get_category(filename)
|
|
147
|
-
metadata[filename] = {
|
|
148
|
-
"title": get_title(filename),
|
|
149
|
-
"description": get_description(source_path.name, category),
|
|
150
|
-
"category": category,
|
|
151
|
-
"full_image": f"../screenshots/dashboard/{source_path.name}",
|
|
152
|
-
"thumbnail_png": f"{filename}-thumb.png",
|
|
153
|
-
"thumbnail_webp": f"{filename}-thumb.webp",
|
|
154
|
-
"created": datetime.now().isoformat(),
|
|
155
|
-
"original_size": f"{img.width}×{img.height}",
|
|
156
|
-
"thumbnail_size": f"{THUMBNAIL_SIZE[0]}×{THUMBNAIL_SIZE[1]}",
|
|
157
|
-
"png_size_kb": round(png_size / 1024, 2),
|
|
158
|
-
"webp_size_kb": round(webp_size / 1024, 2),
|
|
159
|
-
}
|
|
160
|
-
return True
|
|
161
|
-
except Exception as e:
|
|
162
|
-
print(f"✗ {source_path.name}: {str(e)}")
|
|
163
|
-
return False
|
|
164
|
-
|
|
165
|
-
def main():
|
|
166
|
-
"""Generate all thumbnails."""
|
|
167
|
-
# Ensure thumbnail directory exists
|
|
168
|
-
THUMBNAIL_DIR.mkdir(parents=True, exist_ok=True)
|
|
169
|
-
|
|
170
|
-
# Verify screenshot directory exists
|
|
171
|
-
if not SCREENSHOT_DIR.exists():
|
|
172
|
-
print(f"Error: Screenshot directory not found: {SCREENSHOT_DIR}")
|
|
173
|
-
return 1
|
|
174
|
-
|
|
175
|
-
# Find all images in screenshot directory
|
|
176
|
-
image_extensions = {".png", ".jpg", ".jpeg", ".webp"}
|
|
177
|
-
sources = sorted([
|
|
178
|
-
f for f in SCREENSHOT_DIR.glob("**/*")
|
|
179
|
-
if f.is_file() and f.suffix.lower() in image_extensions and not f.name.startswith(".")
|
|
180
|
-
])
|
|
181
|
-
|
|
182
|
-
if not sources:
|
|
183
|
-
print(f"No images found in {SCREENSHOT_DIR}")
|
|
184
|
-
return 1
|
|
185
|
-
|
|
186
|
-
print(f"Found {len(sources)} images in {SCREENSHOT_DIR}")
|
|
187
|
-
print(f"Generating thumbnails to {THUMBNAIL_DIR}\n")
|
|
188
|
-
|
|
189
|
-
metadata = {}
|
|
190
|
-
successful = 0
|
|
191
|
-
failed = 0
|
|
192
|
-
|
|
193
|
-
for source in sources:
|
|
194
|
-
if generate_thumbnail(source, THUMBNAIL_DIR, metadata):
|
|
195
|
-
successful += 1
|
|
196
|
-
else:
|
|
197
|
-
failed += 1
|
|
198
|
-
|
|
199
|
-
# Save metadata index
|
|
200
|
-
index_path = THUMBNAIL_DIR / "index.json"
|
|
201
|
-
with open(index_path, "w") as f:
|
|
202
|
-
json.dump(metadata, f, indent=2, sort_keys=True)
|
|
203
|
-
print(f"\n✓ Saved metadata index to {index_path}")
|
|
204
|
-
|
|
205
|
-
# Print summary
|
|
206
|
-
print(f"\n{'='*60}")
|
|
207
|
-
print(f"Summary:")
|
|
208
|
-
print(f" Total processed: {len(sources)}")
|
|
209
|
-
print(f" Successful: {successful}")
|
|
210
|
-
print(f" Failed: {failed}")
|
|
211
|
-
print(f" PNG thumbnails: {len(list(THUMBNAIL_DIR.glob('*-thumb.png')))}")
|
|
212
|
-
print(f" WebP thumbnails: {len(list(THUMBNAIL_DIR.glob('*-thumb.webp')))}")
|
|
213
|
-
print(f" Total size: {sum(f.stat().st_size for f in THUMBNAIL_DIR.glob('*-thumb.*')) / 1024:.1f}KB")
|
|
214
|
-
|
|
215
|
-
return 0 if failed == 0 else 1
|
|
216
|
-
|
|
217
|
-
if __name__ == "__main__":
|
|
218
|
-
exit(main())
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
# DEPRECATED in v3.6.14 — skills are now delivered via the Claude Code plugin.
|
|
2
|
-
# Use: claude plugin install superlocalmemory@qualixar
|
|
3
|
-
Write-Output "SLM skills are now delivered via the Claude Code plugin (/plugin install) — standalone skill install is retired in v3.6.14."
|
|
4
|
-
exit 0
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# DEPRECATED in v3.6.14 — skills are now delivered via the Claude Code plugin.
|
|
3
|
-
# Use: claude plugin install superlocalmemory@qualixar
|
|
4
|
-
echo "SLM skills are now delivered via the Claude Code plugin (/plugin install) — standalone skill install is retired in v3.6.14."
|
|
5
|
-
exit 0
|