brainlayer 1.0.0__py3-none-any.whl

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.
Files changed (53) hide show
  1. brainlayer/__init__.py +3 -0
  2. brainlayer/cli/__init__.py +1545 -0
  3. brainlayer/cli/wizard.py +132 -0
  4. brainlayer/cli_new.py +151 -0
  5. brainlayer/client.py +164 -0
  6. brainlayer/clustering.py +736 -0
  7. brainlayer/daemon.py +1105 -0
  8. brainlayer/dashboard/README.md +129 -0
  9. brainlayer/dashboard/__init__.py +5 -0
  10. brainlayer/dashboard/app.py +151 -0
  11. brainlayer/dashboard/search.py +229 -0
  12. brainlayer/dashboard/views.py +230 -0
  13. brainlayer/embeddings.py +131 -0
  14. brainlayer/engine.py +550 -0
  15. brainlayer/index_new.py +87 -0
  16. brainlayer/mcp/__init__.py +1558 -0
  17. brainlayer/migrate.py +205 -0
  18. brainlayer/paths.py +43 -0
  19. brainlayer/pipeline/__init__.py +47 -0
  20. brainlayer/pipeline/analyze_communication.py +508 -0
  21. brainlayer/pipeline/brain_graph.py +567 -0
  22. brainlayer/pipeline/chat_tags.py +63 -0
  23. brainlayer/pipeline/chunk.py +422 -0
  24. brainlayer/pipeline/classify.py +472 -0
  25. brainlayer/pipeline/cluster_sampling.py +73 -0
  26. brainlayer/pipeline/enrichment.py +810 -0
  27. brainlayer/pipeline/extract.py +66 -0
  28. brainlayer/pipeline/extract_claude_desktop.py +149 -0
  29. brainlayer/pipeline/extract_corrections.py +231 -0
  30. brainlayer/pipeline/extract_markdown.py +195 -0
  31. brainlayer/pipeline/extract_whatsapp.py +227 -0
  32. brainlayer/pipeline/git_overlay.py +301 -0
  33. brainlayer/pipeline/longitudinal_analyzer.py +568 -0
  34. brainlayer/pipeline/obsidian_export.py +455 -0
  35. brainlayer/pipeline/operation_grouping.py +486 -0
  36. brainlayer/pipeline/plan_linking.py +313 -0
  37. brainlayer/pipeline/sanitize.py +549 -0
  38. brainlayer/pipeline/semantic_style.py +574 -0
  39. brainlayer/pipeline/session_enrichment.py +472 -0
  40. brainlayer/pipeline/style_embed.py +67 -0
  41. brainlayer/pipeline/style_index.py +139 -0
  42. brainlayer/pipeline/temporal_chains.py +203 -0
  43. brainlayer/pipeline/time_batcher.py +248 -0
  44. brainlayer/pipeline/unified_timeline.py +569 -0
  45. brainlayer/storage.py +66 -0
  46. brainlayer/store.py +155 -0
  47. brainlayer/taxonomy.json +80 -0
  48. brainlayer/vector_store.py +1891 -0
  49. brainlayer-1.0.0.dist-info/METADATA +313 -0
  50. brainlayer-1.0.0.dist-info/RECORD +53 -0
  51. brainlayer-1.0.0.dist-info/WHEEL +4 -0
  52. brainlayer-1.0.0.dist-info/entry_points.txt +4 -0
  53. brainlayer-1.0.0.dist-info/licenses/LICENSE +190 -0
brainlayer/store.py ADDED
@@ -0,0 +1,155 @@
1
+ """brainlayer_store — Write-side memory for BrainLayer.
2
+
3
+ Store ideas, mistakes, decisions, learnings, todos, and bookmarks
4
+ into the BrainLayer knowledge base. Items are embedded at write time
5
+ and searchable immediately.
6
+
7
+ Usage:
8
+ from brainlayer.store import store_memory
9
+
10
+ result = store_memory(
11
+ store=vector_store,
12
+ embed_fn=model.embed_query,
13
+ content="Always use exponential backoff for retries",
14
+ memory_type="learning",
15
+ project="my-project",
16
+ tags=["reliability", "api"],
17
+ )
18
+ """
19
+
20
+ import json
21
+ import logging
22
+ import uuid
23
+ from datetime import datetime, timezone
24
+ from typing import Any, Callable, Dict, List, Optional
25
+
26
+ from .vector_store import VectorStore, serialize_f32
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+ VALID_MEMORY_TYPES = ["idea", "mistake", "decision", "learning", "todo", "bookmark", "note", "journal"]
31
+
32
+
33
+ def store_memory(
34
+ store: VectorStore,
35
+ embed_fn: Callable[[str], List[float]],
36
+ content: str,
37
+ memory_type: str,
38
+ project: Optional[str] = None,
39
+ tags: Optional[List[str]] = None,
40
+ importance: Optional[int] = None,
41
+ ) -> Dict[str, Any]:
42
+ """Persistently store a memory into BrainLayer.
43
+
44
+ Args:
45
+ store: VectorStore instance.
46
+ embed_fn: Function that takes text and returns a 1024-dim embedding vector.
47
+ content: The text content to store.
48
+ memory_type: One of VALID_MEMORY_TYPES.
49
+ project: Optional project name to scope the memory.
50
+ tags: Optional list of tags for categorization.
51
+ importance: Optional importance score (1-10, clamped).
52
+
53
+ Returns:
54
+ Dict with 'id' (chunk ID) and 'related' (list of similar existing memories).
55
+
56
+ Raises:
57
+ ValueError: If content is empty or memory_type is invalid.
58
+ """
59
+ # Validate
60
+ if not content or not content.strip():
61
+ raise ValueError("content must be non-empty")
62
+ if memory_type not in VALID_MEMORY_TYPES:
63
+ raise ValueError(f"type must be one of: {', '.join(VALID_MEMORY_TYPES)}")
64
+
65
+ content = content.strip()
66
+
67
+ # Clamp importance
68
+ if importance is not None:
69
+ importance = max(1, min(10, importance))
70
+
71
+ # Generate chunk ID and timestamps
72
+ chunk_id = f"manual-{uuid.uuid4().hex[:16]}"
73
+ now = datetime.now(timezone.utc).isoformat()
74
+
75
+ # Embed at write time
76
+ embedding = embed_fn(content)
77
+
78
+ # Search for related existing memories BEFORE inserting
79
+ related = _find_related(store, embedding, project=project, limit=3)
80
+
81
+ # Insert into chunks table
82
+ cursor = store.conn.cursor()
83
+ cursor.execute(
84
+ """
85
+ INSERT INTO chunks
86
+ (id, content, metadata, source_file, project, content_type,
87
+ value_type, char_count, source, created_at, enriched_at,
88
+ summary, tags, importance)
89
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
90
+ """,
91
+ (
92
+ chunk_id,
93
+ content,
94
+ json.dumps({"memory_type": memory_type}),
95
+ "brainlayer-store",
96
+ project,
97
+ memory_type, # content_type = memory_type for easy filtering
98
+ "HIGH",
99
+ len(content),
100
+ "manual",
101
+ now,
102
+ now, # enriched_at = now (user-provided content is pre-enriched)
103
+ content[:200], # summary = first 200 chars
104
+ json.dumps(tags) if tags else None,
105
+ float(importance) if importance is not None else None,
106
+ ),
107
+ )
108
+
109
+ # Insert embedding into chunk_vectors
110
+ cursor.execute("DELETE FROM chunk_vectors WHERE chunk_id = ?", (chunk_id,))
111
+ cursor.execute(
112
+ "INSERT INTO chunk_vectors (chunk_id, embedding) VALUES (?, ?)",
113
+ (chunk_id, serialize_f32(embedding)),
114
+ )
115
+
116
+ # Also insert into FTS5 for keyword search
117
+ # (The trigger handles this for INSERT INTO chunks, but since we bypass
118
+ # the normal upsert_chunks flow, verify it's there)
119
+
120
+ return {
121
+ "id": chunk_id,
122
+ "related": related,
123
+ }
124
+
125
+
126
+ def _find_related(
127
+ store: VectorStore,
128
+ embedding: List[float],
129
+ project: Optional[str] = None,
130
+ limit: int = 3,
131
+ ) -> List[Dict[str, Any]]:
132
+ """Find related existing memories by vector similarity."""
133
+ try:
134
+ results = store.search(
135
+ query_embedding=embedding,
136
+ n_results=limit,
137
+ project_filter=project,
138
+ )
139
+ related = []
140
+ for doc, meta in zip(results["documents"][0], results["metadatas"][0]):
141
+ item: Dict[str, Any] = {"content": doc[:300]}
142
+ if meta.get("summary"):
143
+ item["summary"] = meta["summary"]
144
+ if meta.get("project"):
145
+ item["project"] = meta["project"]
146
+ if meta.get("content_type"):
147
+ item["type"] = meta["content_type"]
148
+ if meta.get("created_at"):
149
+ item["date"] = meta["created_at"][:10]
150
+ related.append(item)
151
+ return related
152
+ except Exception as e:
153
+ # Don't let related search failure block the store — intentionally broad
154
+ logger.warning("Related memory search failed: %s", e)
155
+ return []
@@ -0,0 +1,80 @@
1
+ {
2
+ "version": 1,
3
+ "description": "Hierarchical topic labels for BrainLayer chunks. 5 categories, ~50 labels.",
4
+ "categories": {
5
+ "tech": {
6
+ "description": "Technical content — code, debugging, architecture",
7
+ "labels": {
8
+ "tech/code-snippet": "Code written or reviewed",
9
+ "tech/debug/error-trace": "Stack traces, error messages, crash logs",
10
+ "tech/debug/investigation": "Debugging discussion, root cause analysis",
11
+ "tech/architecture": "System design, architectural decisions",
12
+ "tech/config": "Configuration files, env vars, settings",
13
+ "tech/testing": "Test code, test strategies, CI/CD",
14
+ "tech/refactor": "Code refactoring, cleanup, migration",
15
+ "tech/performance": "Performance optimization, profiling",
16
+ "tech/security": "Auth, secrets, security concerns",
17
+ "tech/devops": "Deployment, Docker, Railway, infra",
18
+ "tech/database": "SQL, migrations, schema design",
19
+ "tech/api": "API endpoints, HTTP, REST, GraphQL",
20
+ "tech/frontend": "UI components, CSS, React, Next.js",
21
+ "tech/mobile": "React Native, Expo, mobile-specific",
22
+ "tech/ai-ml": "LLM integration, embeddings, RAG, agents"
23
+ }
24
+ },
25
+ "pm": {
26
+ "description": "Project management — planning, decisions, requirements",
27
+ "labels": {
28
+ "pm/planning": "Roadmap, sprint planning, task breakdown",
29
+ "pm/decision": "Architecture decisions, tool choices, trade-offs",
30
+ "pm/requirements": "Feature specs, user stories, PRDs",
31
+ "pm/review": "Code review, PR discussion, feedback",
32
+ "pm/retrospective": "What worked, what didn't, lessons learned"
33
+ }
34
+ },
35
+ "personal": {
36
+ "description": "Personal/career — job search, learning, communication",
37
+ "labels": {
38
+ "personal/job-search": "Job applications, interviews, outreach",
39
+ "personal/learning": "Tutorials, research, skill development",
40
+ "personal/writing": "Blog posts, documentation, content creation",
41
+ "personal/communication": "Email drafts, message style, social posts",
42
+ "personal/finance": "Expenses, invoices, tax, payments"
43
+ }
44
+ },
45
+ "platform": {
46
+ "description": "Platform-specific — which tool/service the content is about",
47
+ "labels": {
48
+ "platform/claude": "Claude Code, Claude API, Anthropic",
49
+ "platform/github": "GitHub issues, PRs, Actions, repos",
50
+ "platform/supabase": "Supabase DB, auth, storage, edge functions",
51
+ "platform/telegram": "Telegram bot, grammy, messaging",
52
+ "platform/convex": "Convex backend, functions, schema",
53
+ "platform/vercel": "Vercel deployment, Next.js hosting",
54
+ "platform/railway": "Railway deployment, services",
55
+ "platform/obsidian": "Obsidian vault, notes, sync",
56
+ "platform/linear": "Linear issues, project management"
57
+ }
58
+ },
59
+ "project": {
60
+ "description": "Project-specific — which codebase/product",
61
+ "labels": {
62
+ "project/my-project": "Example project",
63
+ "project/brainlayer": "BrainLayer memory pipeline",
64
+ "project/app-a": "Example application A",
65
+ "project/app-b": "Example application B",
66
+ "project/personal-site": "Personal website, admin dashboard",
67
+ "project/union": "Union platform"
68
+ }
69
+ },
70
+ "meta": {
71
+ "description": "Meta labels — content quality, noise, empty",
72
+ "labels": {
73
+ "meta/noise": "Noise, irrelevant, or garbage content",
74
+ "meta/empty": "Empty or near-empty content (nothing useful)",
75
+ "meta/context-only": "Only useful as context for surrounding chunks",
76
+ "meta/duplicate": "Duplicate or near-duplicate of another chunk"
77
+ }
78
+ }
79
+ }
80
+ }