omni-cortex 1.17.3__py3-none-any.whl → 1.17.4__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 (74) hide show
  1. omni_cortex/_bundled/dashboard/backend/main.py +2 -2
  2. omni_cortex/_bundled/dashboard/backend/test_database.py +301 -0
  3. omni_cortex/_bundled/dashboard/backend/tmpclaude-2dfa-cwd +1 -0
  4. omni_cortex/_bundled/dashboard/backend/tmpclaude-c460-cwd +1 -0
  5. omni_cortex/_bundled/dashboard/frontend/dist/assets/index-CQlQK3nE.js +551 -0
  6. omni_cortex/_bundled/dashboard/frontend/dist/assets/index-CmUNNfe4.css +1 -0
  7. omni_cortex/_bundled/dashboard/frontend/dist/index.html +14 -0
  8. omni_cortex/_bundled/hooks/user_prompt.py +113 -2
  9. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/main.py +2 -2
  10. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/hooks/user_prompt.py +113 -2
  11. {omni_cortex-1.17.3.dist-info → omni_cortex-1.17.4.dist-info}/METADATA +6 -1
  12. omni_cortex-1.17.4.dist-info/RECORD +53 -0
  13. omni_cortex/__init__.py +0 -3
  14. omni_cortex/categorization/__init__.py +0 -9
  15. omni_cortex/categorization/auto_tags.py +0 -166
  16. omni_cortex/categorization/auto_type.py +0 -165
  17. omni_cortex/config.py +0 -141
  18. omni_cortex/dashboard.py +0 -238
  19. omni_cortex/database/__init__.py +0 -24
  20. omni_cortex/database/connection.py +0 -137
  21. omni_cortex/database/migrations.py +0 -210
  22. omni_cortex/database/schema.py +0 -212
  23. omni_cortex/database/sync.py +0 -421
  24. omni_cortex/decay/__init__.py +0 -7
  25. omni_cortex/decay/importance.py +0 -147
  26. omni_cortex/embeddings/__init__.py +0 -35
  27. omni_cortex/embeddings/local.py +0 -442
  28. omni_cortex/models/__init__.py +0 -20
  29. omni_cortex/models/activity.py +0 -265
  30. omni_cortex/models/agent.py +0 -144
  31. omni_cortex/models/memory.py +0 -395
  32. omni_cortex/models/relationship.py +0 -206
  33. omni_cortex/models/session.py +0 -290
  34. omni_cortex/resources/__init__.py +0 -1
  35. omni_cortex/search/__init__.py +0 -22
  36. omni_cortex/search/hybrid.py +0 -197
  37. omni_cortex/search/keyword.py +0 -204
  38. omni_cortex/search/ranking.py +0 -127
  39. omni_cortex/search/semantic.py +0 -232
  40. omni_cortex/server.py +0 -360
  41. omni_cortex/setup.py +0 -284
  42. omni_cortex/tools/__init__.py +0 -13
  43. omni_cortex/tools/activities.py +0 -453
  44. omni_cortex/tools/memories.py +0 -536
  45. omni_cortex/tools/sessions.py +0 -311
  46. omni_cortex/tools/utilities.py +0 -477
  47. omni_cortex/utils/__init__.py +0 -13
  48. omni_cortex/utils/formatting.py +0 -282
  49. omni_cortex/utils/ids.py +0 -72
  50. omni_cortex/utils/timestamps.py +0 -129
  51. omni_cortex/utils/truncation.py +0 -111
  52. omni_cortex-1.17.3.dist-info/RECORD +0 -86
  53. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/.env.example +0 -0
  54. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/backfill_summaries.py +0 -0
  55. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/chat_service.py +0 -0
  56. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/database.py +0 -0
  57. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/image_service.py +0 -0
  58. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/logging_config.py +0 -0
  59. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/models.py +0 -0
  60. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/project_config.py +0 -0
  61. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/project_scanner.py +0 -0
  62. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/prompt_security.py +0 -0
  63. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/pyproject.toml +0 -0
  64. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/security.py +0 -0
  65. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/uv.lock +0 -0
  66. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/websocket_manager.py +0 -0
  67. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/hooks/post_tool_use.py +0 -0
  68. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/hooks/pre_tool_use.py +0 -0
  69. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/hooks/session_utils.py +0 -0
  70. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/hooks/stop.py +0 -0
  71. {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/hooks/subagent_stop.py +0 -0
  72. {omni_cortex-1.17.3.dist-info → omni_cortex-1.17.4.dist-info}/WHEEL +0 -0
  73. {omni_cortex-1.17.3.dist-info → omni_cortex-1.17.4.dist-info}/entry_points.txt +0 -0
  74. {omni_cortex-1.17.3.dist-info → omni_cortex-1.17.4.dist-info}/licenses/LICENSE +0 -0
@@ -131,10 +131,10 @@ class SecurityHeadersMiddleware(BaseHTTPMiddleware):
131
131
  response.headers["Content-Security-Policy"] = (
132
132
  "default-src 'self'; "
133
133
  "script-src 'self' 'unsafe-inline' 'unsafe-eval'; " # Vue needs these
134
- "style-src 'self' 'unsafe-inline'; " # Tailwind needs inline
134
+ "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " # Tailwind + Google Fonts
135
135
  "img-src 'self' data: blob: https:; " # Allow AI-generated images
136
136
  "connect-src 'self' ws: wss: https://generativelanguage.googleapis.com; "
137
- "font-src 'self'; "
137
+ "font-src 'self' https://fonts.gstatic.com; " # Google Fonts
138
138
  "frame-ancestors 'none';"
139
139
  )
140
140
 
@@ -0,0 +1,301 @@
1
+ """Unit tests for dashboard database functions.
2
+
3
+ Run with: cd dashboard/backend && .venv/Scripts/python -m pytest test_database.py -v
4
+ """
5
+
6
+ import json
7
+ import os
8
+ import sqlite3
9
+ import tempfile
10
+ from pathlib import Path
11
+
12
+ import pytest
13
+
14
+ from database import create_memory, get_memories
15
+
16
+
17
+ @pytest.fixture
18
+ def test_db():
19
+ """Create a temporary database with the required schema."""
20
+ with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as f:
21
+ db_path = f.name
22
+
23
+ # Create the database schema
24
+ conn = sqlite3.connect(db_path)
25
+ conn.execute("""
26
+ CREATE TABLE memories (
27
+ id TEXT PRIMARY KEY,
28
+ content TEXT NOT NULL,
29
+ context TEXT,
30
+ type TEXT DEFAULT 'other',
31
+ status TEXT DEFAULT 'fresh',
32
+ importance_score INTEGER DEFAULT 50,
33
+ access_count INTEGER DEFAULT 0,
34
+ created_at TEXT NOT NULL,
35
+ last_accessed TEXT NOT NULL,
36
+ updated_at TEXT NOT NULL,
37
+ tags TEXT
38
+ )
39
+ """)
40
+ conn.execute("""
41
+ CREATE TABLE memory_relationships (
42
+ source_memory_id TEXT NOT NULL,
43
+ target_memory_id TEXT NOT NULL,
44
+ relationship_type TEXT NOT NULL,
45
+ strength REAL DEFAULT 0.5,
46
+ PRIMARY KEY (source_memory_id, target_memory_id)
47
+ )
48
+ """)
49
+ conn.commit()
50
+ conn.close()
51
+
52
+ yield db_path
53
+
54
+ # Cleanup
55
+ os.unlink(db_path)
56
+
57
+
58
+ class TestCreateMemory:
59
+ """Tests for the create_memory function."""
60
+
61
+ def test_create_memory_basic(self, test_db):
62
+ """Test basic memory creation with minimal fields."""
63
+ memory_id = create_memory(
64
+ db_path=test_db,
65
+ content="Test memory content",
66
+ )
67
+
68
+ assert memory_id is not None
69
+ assert memory_id.startswith("mem_")
70
+
71
+ def test_create_memory_with_type(self, test_db):
72
+ """Test memory creation with custom type."""
73
+ memory_id = create_memory(
74
+ db_path=test_db,
75
+ content="A decision was made",
76
+ memory_type="decision",
77
+ )
78
+
79
+ # Verify the type was saved
80
+ conn = sqlite3.connect(test_db)
81
+ conn.row_factory = sqlite3.Row
82
+ row = conn.execute(
83
+ "SELECT * FROM memories WHERE id = ?", (memory_id,)
84
+ ).fetchone()
85
+ conn.close()
86
+
87
+ assert row["type"] == "decision"
88
+
89
+ def test_create_memory_with_tags(self, test_db):
90
+ """Test memory creation with tags."""
91
+ tags = ["python", "testing", "database"]
92
+ memory_id = create_memory(
93
+ db_path=test_db,
94
+ content="Tagged memory",
95
+ tags=tags,
96
+ )
97
+
98
+ # Verify tags were saved as JSON
99
+ conn = sqlite3.connect(test_db)
100
+ conn.row_factory = sqlite3.Row
101
+ row = conn.execute(
102
+ "SELECT * FROM memories WHERE id = ?", (memory_id,)
103
+ ).fetchone()
104
+ conn.close()
105
+
106
+ saved_tags = json.loads(row["tags"])
107
+ assert saved_tags == tags
108
+
109
+ def test_create_memory_with_importance(self, test_db):
110
+ """Test memory creation with custom importance score."""
111
+ memory_id = create_memory(
112
+ db_path=test_db,
113
+ content="Important memory",
114
+ importance_score=95,
115
+ )
116
+
117
+ conn = sqlite3.connect(test_db)
118
+ conn.row_factory = sqlite3.Row
119
+ row = conn.execute(
120
+ "SELECT * FROM memories WHERE id = ?", (memory_id,)
121
+ ).fetchone()
122
+ conn.close()
123
+
124
+ assert row["importance_score"] == 95
125
+
126
+ def test_create_memory_has_updated_at(self, test_db):
127
+ """Test that created memory has updated_at field (regression test for bug)."""
128
+ memory_id = create_memory(
129
+ db_path=test_db,
130
+ content="Memory with updated_at",
131
+ )
132
+
133
+ conn = sqlite3.connect(test_db)
134
+ conn.row_factory = sqlite3.Row
135
+ row = conn.execute(
136
+ "SELECT * FROM memories WHERE id = ?", (memory_id,)
137
+ ).fetchone()
138
+ conn.close()
139
+
140
+ # This was the bug - updated_at was missing from INSERT
141
+ assert row["updated_at"] is not None
142
+ assert len(row["updated_at"]) > 0
143
+
144
+ def test_create_memory_with_context(self, test_db):
145
+ """Test memory creation with context."""
146
+ memory_id = create_memory(
147
+ db_path=test_db,
148
+ content="Memory with context",
149
+ context="This is additional context",
150
+ )
151
+
152
+ conn = sqlite3.connect(test_db)
153
+ conn.row_factory = sqlite3.Row
154
+ row = conn.execute(
155
+ "SELECT * FROM memories WHERE id = ?", (memory_id,)
156
+ ).fetchone()
157
+ conn.close()
158
+
159
+ assert row["context"] == "This is additional context"
160
+
161
+ def test_create_memory_default_status_is_fresh(self, test_db):
162
+ """Test that new memories have 'fresh' status by default."""
163
+ memory_id = create_memory(
164
+ db_path=test_db,
165
+ content="Fresh memory",
166
+ )
167
+
168
+ conn = sqlite3.connect(test_db)
169
+ conn.row_factory = sqlite3.Row
170
+ row = conn.execute(
171
+ "SELECT * FROM memories WHERE id = ?", (memory_id,)
172
+ ).fetchone()
173
+ conn.close()
174
+
175
+ assert row["status"] == "fresh"
176
+
177
+ def test_create_memory_default_access_count_is_zero(self, test_db):
178
+ """Test that new memories have access_count of 0."""
179
+ memory_id = create_memory(
180
+ db_path=test_db,
181
+ content="New memory",
182
+ )
183
+
184
+ conn = sqlite3.connect(test_db)
185
+ conn.row_factory = sqlite3.Row
186
+ row = conn.execute(
187
+ "SELECT * FROM memories WHERE id = ?", (memory_id,)
188
+ ).fetchone()
189
+ conn.close()
190
+
191
+ assert row["access_count"] == 0
192
+
193
+ def test_create_memory_all_fields(self, test_db):
194
+ """Test memory creation with all fields populated."""
195
+ memory_id = create_memory(
196
+ db_path=test_db,
197
+ content="Complete memory",
198
+ memory_type="solution",
199
+ context="Full context here",
200
+ tags=["tag1", "tag2"],
201
+ importance_score=80,
202
+ )
203
+
204
+ conn = sqlite3.connect(test_db)
205
+ conn.row_factory = sqlite3.Row
206
+ row = conn.execute(
207
+ "SELECT * FROM memories WHERE id = ?", (memory_id,)
208
+ ).fetchone()
209
+ conn.close()
210
+
211
+ assert row["content"] == "Complete memory"
212
+ assert row["type"] == "solution"
213
+ assert row["context"] == "Full context here"
214
+ assert json.loads(row["tags"]) == ["tag1", "tag2"]
215
+ assert row["importance_score"] == 80
216
+ assert row["status"] == "fresh"
217
+ assert row["access_count"] == 0
218
+ assert row["created_at"] is not None
219
+ assert row["last_accessed"] is not None
220
+ assert row["updated_at"] is not None
221
+
222
+
223
+ class TestCreateMemoryEdgeCases:
224
+ """Edge case tests for create_memory."""
225
+
226
+ def test_create_memory_empty_tags_list(self, test_db):
227
+ """Test memory creation with empty tags list.
228
+
229
+ Note: Current behavior stores empty list as None (falsy check in code).
230
+ This is intentional - empty tags are treated same as no tags.
231
+ """
232
+ memory_id = create_memory(
233
+ db_path=test_db,
234
+ content="Memory with empty tags",
235
+ tags=[],
236
+ )
237
+
238
+ conn = sqlite3.connect(test_db)
239
+ conn.row_factory = sqlite3.Row
240
+ row = conn.execute(
241
+ "SELECT * FROM memories WHERE id = ?", (memory_id,)
242
+ ).fetchone()
243
+ conn.close()
244
+
245
+ # Empty list is treated as None (falsy) in the code
246
+ assert row["tags"] is None
247
+
248
+ def test_create_memory_none_tags(self, test_db):
249
+ """Test memory creation with None tags (default)."""
250
+ memory_id = create_memory(
251
+ db_path=test_db,
252
+ content="Memory with no tags",
253
+ tags=None,
254
+ )
255
+
256
+ conn = sqlite3.connect(test_db)
257
+ conn.row_factory = sqlite3.Row
258
+ row = conn.execute(
259
+ "SELECT * FROM memories WHERE id = ?", (memory_id,)
260
+ ).fetchone()
261
+ conn.close()
262
+
263
+ assert row["tags"] is None
264
+
265
+ def test_create_memory_unicode_content(self, test_db):
266
+ """Test memory creation with unicode content."""
267
+ content = "Memory with unicode: 日本語 🚀 émojis"
268
+ memory_id = create_memory(
269
+ db_path=test_db,
270
+ content=content,
271
+ )
272
+
273
+ conn = sqlite3.connect(test_db)
274
+ conn.row_factory = sqlite3.Row
275
+ row = conn.execute(
276
+ "SELECT * FROM memories WHERE id = ?", (memory_id,)
277
+ ).fetchone()
278
+ conn.close()
279
+
280
+ assert row["content"] == content
281
+
282
+ def test_create_memory_long_content(self, test_db):
283
+ """Test memory creation with very long content."""
284
+ content = "A" * 100000 # 100KB of content
285
+ memory_id = create_memory(
286
+ db_path=test_db,
287
+ content=content,
288
+ )
289
+
290
+ conn = sqlite3.connect(test_db)
291
+ conn.row_factory = sqlite3.Row
292
+ row = conn.execute(
293
+ "SELECT * FROM memories WHERE id = ?", (memory_id,)
294
+ ).fetchone()
295
+ conn.close()
296
+
297
+ assert len(row["content"]) == 100000
298
+
299
+
300
+ if __name__ == "__main__":
301
+ pytest.main([__file__, "-v"])
@@ -0,0 +1 @@
1
+ /d/Projects/omni-cortex/dashboard/backend
@@ -0,0 +1 @@
1
+ /d/Projects/omni-cortex/dashboard/backend