runtime-memory 3.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 (54) hide show
  1. runtime_memory/__init__.py +28 -0
  2. runtime_memory/claude_code/__init__.py +48 -0
  3. runtime_memory/claude_code/commands.py +698 -0
  4. runtime_memory/claude_code/daemon.py +852 -0
  5. runtime_memory/claude_code/hooks.py +722 -0
  6. runtime_memory/cli/__init__.py +8 -0
  7. runtime_memory/cli/main.py +1936 -0
  8. runtime_memory/core/__init__.py +216 -0
  9. runtime_memory/core/config.py +473 -0
  10. runtime_memory/core/embeddings.py +908 -0
  11. runtime_memory/core/engine.py +1007 -0
  12. runtime_memory/core/exceptions.py +547 -0
  13. runtime_memory/core/legacy_env.py +39 -0
  14. runtime_memory/core/logging.py +160 -0
  15. runtime_memory/core/models.py +1051 -0
  16. runtime_memory/core/observability.py +725 -0
  17. runtime_memory/core/paths.py +30 -0
  18. runtime_memory/core/resilience.py +511 -0
  19. runtime_memory/core/retrieval.py +819 -0
  20. runtime_memory/core/storage.py +1105 -0
  21. runtime_memory/extraction/__init__.py +36 -0
  22. runtime_memory/extraction/extractor.py +1143 -0
  23. runtime_memory/hermes/__init__.py +39 -0
  24. runtime_memory/hermes/_base.py +154 -0
  25. runtime_memory/hermes/bridge.py +119 -0
  26. runtime_memory/hermes/plugin.yaml +13 -0
  27. runtime_memory/hermes/provider.py +536 -0
  28. runtime_memory/hermes/tools.py +230 -0
  29. runtime_memory/hermes/trace.py +177 -0
  30. runtime_memory/plugin/__init__.py +646 -0
  31. runtime_memory/sdk/__init__.py +97 -0
  32. runtime_memory/sdk/client.py +1577 -0
  33. runtime_memory/server/__init__.py +75 -0
  34. runtime_memory/server/api.py +1665 -0
  35. runtime_memory/server/mcp.py +1574 -0
  36. runtime_memory/server/static/css/styles.css +1110 -0
  37. runtime_memory/server/static/index.html +264 -0
  38. runtime_memory/server/static/js/api.js +294 -0
  39. runtime_memory/server/static/js/app.js +771 -0
  40. runtime_memory/tasks/__init__.py +114 -0
  41. runtime_memory/tasks/adapter.py +501 -0
  42. runtime_memory/tasks/claude_code_adapter.py +495 -0
  43. runtime_memory/tasks/claude_code_parser.py +339 -0
  44. runtime_memory/tasks/cli_bridge.py +415 -0
  45. runtime_memory/tasks/linking.py +397 -0
  46. runtime_memory/tasks/models.py +520 -0
  47. runtime_memory/tasks/outcomes.py +320 -0
  48. runtime_memory/tasks/parser.py +305 -0
  49. runtime_memory/tasks/unified_adapter.py +661 -0
  50. runtime_memory-3.0.0.dist-info/METADATA +497 -0
  51. runtime_memory-3.0.0.dist-info/RECORD +54 -0
  52. runtime_memory-3.0.0.dist-info/WHEEL +4 -0
  53. runtime_memory-3.0.0.dist-info/entry_points.txt +6 -0
  54. runtime_memory-3.0.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,264 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" data-theme="dark">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Runtime Memory</title>
7
+ <link rel="stylesheet" href="/static/css/styles.css?v=8">
8
+ </head>
9
+ <body>
10
+ <div id="app">
11
+ <!-- Header -->
12
+ <header class="header">
13
+ <div class="header-inner">
14
+ <div class="header-brand">
15
+ <h1>Runtime Memory</h1>
16
+ <span class="version">v2.0</span>
17
+ </div>
18
+ <nav class="nav">
19
+ <button class="nav-btn active" data-view="dashboard">Dashboard</button>
20
+ <button class="nav-btn" data-view="memories">Memories</button>
21
+ <button class="nav-btn" data-view="search">Search</button>
22
+ <button class="nav-btn" data-view="add">Add Memory</button>
23
+ <button class="nav-btn" data-view="beads">Tasks</button>
24
+ </nav>
25
+ <div class="header-actions">
26
+ <button id="theme-toggle" class="icon-btn" title="Toggle theme">
27
+ <span class="theme-icon">&#9790;</span>
28
+ </button>
29
+ </div>
30
+ </div>
31
+ </header>
32
+
33
+ <!-- Main Content -->
34
+ <main class="main">
35
+ <!-- Dashboard View -->
36
+ <section id="view-dashboard" class="view active">
37
+ <h2>Dashboard</h2>
38
+ <div class="stats-grid">
39
+ <div class="stat-card">
40
+ <div class="stat-value" id="stat-total">-</div>
41
+ <div class="stat-label">Total Memories</div>
42
+ </div>
43
+ <div class="stat-card">
44
+ <div class="stat-value" id="stat-active">-</div>
45
+ <div class="stat-label">Active</div>
46
+ </div>
47
+ <div class="stat-card">
48
+ <div class="stat-value" id="stat-archived">-</div>
49
+ <div class="stat-label">Archived</div>
50
+ </div>
51
+ <div class="stat-card">
52
+ <div class="stat-value" id="stat-avg-score">-</div>
53
+ <div class="stat-label">Avg Score</div>
54
+ </div>
55
+ </div>
56
+
57
+ <div class="dashboard-grid">
58
+ <div class="card">
59
+ <h3>Memories by Category</h3>
60
+ <div id="category-chart" class="chart-container">
61
+ <div class="category-bars" id="category-bars"></div>
62
+ </div>
63
+ </div>
64
+ <div class="card">
65
+ <h3>Recent Memories</h3>
66
+ <div id="recent-memories" class="recent-list"></div>
67
+ </div>
68
+ </div>
69
+
70
+ <div class="card">
71
+ <h3>Quick Actions</h3>
72
+ <div class="quick-actions">
73
+ <button class="btn btn-primary" onclick="app.showView('add')">Add Memory</button>
74
+ <button class="btn btn-secondary" onclick="app.showView('search')">Search</button>
75
+ <button class="btn btn-secondary" onclick="app.exportMemories()">Export All</button>
76
+ </div>
77
+ </div>
78
+ </section>
79
+
80
+ <!-- Memories List View -->
81
+ <section id="view-memories" class="view">
82
+ <div class="view-header">
83
+ <h2>Memories</h2>
84
+ <div class="filters">
85
+ <select id="filter-category" class="filter-select">
86
+ <option value="">All Categories</option>
87
+ <option value="architecture">Architecture</option>
88
+ <option value="convention">Convention</option>
89
+ <option value="decision">Decision</option>
90
+ <option value="pattern">Pattern</option>
91
+ <option value="gotcha">Gotcha</option>
92
+ <option value="workaround">Workaround</option>
93
+ <option value="troubleshooting">Troubleshooting</option>
94
+ <option value="command">Command</option>
95
+ <option value="preference">Preference</option>
96
+ <option value="general">General</option>
97
+ </select>
98
+ <select id="filter-project" class="filter-select">
99
+ <option value="">All Projects</option>
100
+ </select>
101
+ <input type="text" id="filter-search" class="filter-input" placeholder="Filter...">
102
+ </div>
103
+ </div>
104
+ <div class="table-container">
105
+ <table class="memory-table">
106
+ <thead>
107
+ <tr>
108
+ <th>Category</th>
109
+ <th>Content</th>
110
+ <th>Score</th>
111
+ <th>Project</th>
112
+ <th>Created</th>
113
+ <th>Actions</th>
114
+ </tr>
115
+ </thead>
116
+ <tbody id="memories-tbody"></tbody>
117
+ </table>
118
+ </div>
119
+ <div class="pagination" id="pagination"></div>
120
+ </section>
121
+
122
+ <!-- Search View -->
123
+ <section id="view-search" class="view">
124
+ <h2>Search Memories</h2>
125
+ <div class="search-box">
126
+ <input type="text" id="search-input" class="search-input" placeholder="Search for memories..." autofocus>
127
+ <select id="search-type" class="filter-select">
128
+ <option value="semantic">Semantic (related concepts)</option>
129
+ <option value="keyword">Keyword (exact match)</option>
130
+ </select>
131
+ <button class="btn btn-primary" onclick="app.performSearch()">Search</button>
132
+ </div>
133
+ <div class="search-filters">
134
+ <label><input type="checkbox" class="search-cat" value="architecture" checked> Architecture</label>
135
+ <label><input type="checkbox" class="search-cat" value="pattern" checked> Patterns</label>
136
+ <label><input type="checkbox" class="search-cat" value="convention" checked> Conventions</label>
137
+ <label><input type="checkbox" class="search-cat" value="gotcha" checked> Gotchas</label>
138
+ <label><input type="checkbox" class="search-cat" value="troubleshooting" checked> Troubleshooting</label>
139
+ <label><input type="checkbox" class="search-cat" value="decision" checked> Decisions</label>
140
+ <label><input type="checkbox" class="search-cat" value="workaround" checked> Workarounds</label>
141
+ <label><input type="checkbox" class="search-cat" value="command" checked> Commands</label>
142
+ <label><input type="checkbox" class="search-cat" value="preference" checked> Preferences</label>
143
+ <label><input type="checkbox" class="search-cat" value="general" checked> General</label>
144
+ </div>
145
+ <div id="search-results" class="search-results"></div>
146
+ </section>
147
+
148
+ <!-- Beads Tasks View -->
149
+ <section id="view-beads" class="view">
150
+ <div class="view-header">
151
+ <h2>Beads Tasks</h2>
152
+ <div class="header-actions">
153
+ <button class="btn btn-primary" onclick="app.syncBeads()">Sync Tasks</button>
154
+ </div>
155
+ </div>
156
+
157
+ <!-- Beads Stats -->
158
+ <div class="beads-stats-grid" id="beads-stats">
159
+ <div class="stat-card">
160
+ <div class="stat-value" id="beads-total">-</div>
161
+ <div class="stat-label">Total Tasks</div>
162
+ </div>
163
+ <div class="stat-card">
164
+ <div class="stat-value" id="beads-in-progress">-</div>
165
+ <div class="stat-label">In Progress</div>
166
+ </div>
167
+ <div class="stat-card">
168
+ <div class="stat-value" id="beads-pending">-</div>
169
+ <div class="stat-label">Pending</div>
170
+ </div>
171
+ <div class="stat-card">
172
+ <div class="stat-value" id="beads-done">-</div>
173
+ <div class="stat-label">Done</div>
174
+ </div>
175
+ </div>
176
+
177
+ <!-- Task List -->
178
+ <div class="card">
179
+ <h3>Task List</h3>
180
+ <div id="beads-task-list" class="task-list"></div>
181
+ </div>
182
+
183
+ <!-- Task Context Modal -->
184
+ <div id="task-context" class="card" style="display: none;">
185
+ <div class="task-context-header">
186
+ <h3 id="task-context-title">Task Context</h3>
187
+ <button class="btn btn-secondary btn-sm" onclick="app.closeTaskContext()">Close</button>
188
+ </div>
189
+ <div id="task-context-content" class="task-context-content"></div>
190
+ </div>
191
+ </section>
192
+
193
+ <!-- Add Memory View -->
194
+ <section id="view-add" class="view">
195
+ <h2>Add Memory</h2>
196
+ <form id="add-memory-form" class="memory-form">
197
+ <div class="form-group">
198
+ <label for="memory-content">Content *</label>
199
+ <textarea id="memory-content" rows="4" required placeholder="Enter the memory content..."></textarea>
200
+ </div>
201
+ <div class="form-row">
202
+ <div class="form-group">
203
+ <label for="memory-category">Category</label>
204
+ <select id="memory-category">
205
+ <option value="general">General</option>
206
+ <option value="architecture">Architecture - System design decisions</option>
207
+ <option value="convention">Convention - Coding standards</option>
208
+ <option value="decision">Decision - Technical choices</option>
209
+ <option value="pattern">Pattern - Reusable solutions</option>
210
+ <option value="gotcha">Gotcha - Pitfalls to avoid</option>
211
+ <option value="workaround">Workaround - Temporary fixes</option>
212
+ <option value="troubleshooting">Troubleshooting - Error solutions</option>
213
+ <option value="command">Command - Useful commands</option>
214
+ <option value="preference">Preference - User preferences</option>
215
+ </select>
216
+ </div>
217
+ <div class="form-group">
218
+ <label for="memory-project">Project</label>
219
+ <input type="text" id="memory-project" placeholder="Leave empty for global">
220
+ </div>
221
+ </div>
222
+ <div class="form-group">
223
+ <label for="memory-tags">Tags (comma-separated)</label>
224
+ <input type="text" id="memory-tags" placeholder="python, async, database">
225
+ </div>
226
+ <div class="form-actions">
227
+ <button type="submit" class="btn btn-primary">Save Memory</button>
228
+ <button type="reset" class="btn btn-secondary">Clear</button>
229
+ </div>
230
+ </form>
231
+ </section>
232
+ </main>
233
+
234
+ <!-- Memory Detail Modal -->
235
+ <div id="memory-modal" class="modal">
236
+ <div class="modal-content">
237
+ <div class="modal-header">
238
+ <h3>Memory Details</h3>
239
+ <button class="close-btn" onclick="app.closeModal()">&times;</button>
240
+ </div>
241
+ <div class="modal-body" id="modal-body"></div>
242
+ <div class="modal-footer">
243
+ <div class="outcome-buttons">
244
+ <span>Record Outcome:</span>
245
+ <button class="btn btn-success" onclick="app.recordOutcome('worked')">Worked</button>
246
+ <button class="btn btn-warning" onclick="app.recordOutcome('partial')">Partial</button>
247
+ <button class="btn btn-danger" onclick="app.recordOutcome('failed')">Failed</button>
248
+ </div>
249
+ <div class="modal-actions">
250
+ <button class="btn btn-secondary" onclick="app.closeModal()">Close</button>
251
+ <button class="btn btn-danger" onclick="app.deleteMemory()">Delete</button>
252
+ </div>
253
+ </div>
254
+ </div>
255
+ </div>
256
+
257
+ <!-- Toast Notifications -->
258
+ <div id="toast-container" class="toast-container"></div>
259
+ </div>
260
+
261
+ <script src="/static/js/api.js?v=7"></script>
262
+ <script src="/static/js/app.js?v=7"></script>
263
+ </body>
264
+ </html>
@@ -0,0 +1,294 @@
1
+ /**
2
+ * Runtime Memory API Client
3
+ *
4
+ * Provides methods for interacting with the Runtime Memory REST API.
5
+ */
6
+
7
+ class MemoryLayerAPI {
8
+ constructor(baseUrl = '') {
9
+ this.baseUrl = baseUrl;
10
+ }
11
+
12
+ /**
13
+ * Make an API request
14
+ */
15
+ async request(endpoint, options = {}) {
16
+ const url = `${this.baseUrl}${endpoint}`;
17
+ const config = {
18
+ headers: {
19
+ 'Content-Type': 'application/json',
20
+ ...options.headers
21
+ },
22
+ ...options
23
+ };
24
+
25
+ try {
26
+ const response = await fetch(url, config);
27
+
28
+ if (!response.ok) {
29
+ const error = await response.json().catch(() => ({}));
30
+ throw new Error(error.detail || `HTTP ${response.status}: ${response.statusText}`);
31
+ }
32
+
33
+ // Handle empty responses
34
+ const text = await response.text();
35
+ return text ? JSON.parse(text) : null;
36
+ } catch (error) {
37
+ console.error(`API Error: ${endpoint}`, error);
38
+ throw error;
39
+ }
40
+ }
41
+
42
+ // =========================================================================
43
+ // Memory Operations
44
+ // =========================================================================
45
+
46
+ /**
47
+ * Get all memories with optional filters
48
+ */
49
+ async getMemories(params = {}) {
50
+ const query = new URLSearchParams();
51
+ if (params.category) query.set('category', params.category);
52
+ if (params.project) query.set('project', params.project);
53
+ if (params.limit) query.set('limit', params.limit);
54
+ if (params.offset) query.set('offset', params.offset);
55
+
56
+ const queryStr = query.toString();
57
+ const response = await this.request(`/memories${queryStr ? '?' + queryStr : ''}`);
58
+ // API returns {count, memories} - extract the array
59
+ return response.memories || response;
60
+ }
61
+
62
+ /**
63
+ * Get a single memory by ID
64
+ */
65
+ async getMemory(id) {
66
+ return this.request(`/memories/${id}`);
67
+ }
68
+
69
+ /**
70
+ * Create a new memory
71
+ */
72
+ async createMemory(data) {
73
+ return this.request('/memories', {
74
+ method: 'POST',
75
+ body: JSON.stringify(data)
76
+ });
77
+ }
78
+
79
+ /**
80
+ * Update a memory
81
+ */
82
+ async updateMemory(id, data) {
83
+ return this.request(`/memories/${id}`, {
84
+ method: 'PATCH',
85
+ body: JSON.stringify(data)
86
+ });
87
+ }
88
+
89
+ /**
90
+ * Delete a memory
91
+ */
92
+ async deleteMemory(id) {
93
+ return this.request(`/memories/${id}`, {
94
+ method: 'DELETE'
95
+ });
96
+ }
97
+
98
+ // =========================================================================
99
+ // Search
100
+ // =========================================================================
101
+
102
+ /**
103
+ * Search memories
104
+ * @param {string} query - Search query
105
+ * @param {Object} options - Search options
106
+ * @param {string} options.searchType - 'semantic' or 'keyword'
107
+ */
108
+ async search(query, options = {}) {
109
+ const body = {
110
+ query,
111
+ limit: options.limit || 20,
112
+ categories: options.categories || null,
113
+ project: options.project || null,
114
+ search_type: options.searchType || 'semantic'
115
+ };
116
+ console.log('API search request:', body);
117
+ const response = await this.request('/memories/search', {
118
+ method: 'POST',
119
+ body: JSON.stringify(body)
120
+ });
121
+ console.log('API search response:', response);
122
+ // API returns {count, results} - extract the array
123
+ return response.results || response;
124
+ }
125
+
126
+ // =========================================================================
127
+ // Outcomes
128
+ // =========================================================================
129
+
130
+ /**
131
+ * Record an outcome for memories
132
+ */
133
+ async recordOutcome(memoryIds, outcome) {
134
+ return this.request('/memories/outcome', {
135
+ method: 'POST',
136
+ body: JSON.stringify({
137
+ memory_ids: Array.isArray(memoryIds) ? memoryIds : [memoryIds],
138
+ outcome
139
+ })
140
+ });
141
+ }
142
+
143
+ // =========================================================================
144
+ // Stats & Health
145
+ // =========================================================================
146
+
147
+ /**
148
+ * Get memory statistics
149
+ */
150
+ async getStats(project = null) {
151
+ const query = project ? `?project=${encodeURIComponent(project)}` : '';
152
+ return this.request(`/stats${query}`);
153
+ }
154
+
155
+ /**
156
+ * Health check
157
+ */
158
+ async healthCheck() {
159
+ return this.request('/health');
160
+ }
161
+
162
+ // =========================================================================
163
+ // Context
164
+ // =========================================================================
165
+
166
+ /**
167
+ * Get context
168
+ */
169
+ async getContext(project = null) {
170
+ const query = project ? `?project=${encodeURIComponent(project)}` : '';
171
+ return this.request(`/context${query}`);
172
+ }
173
+
174
+ // =========================================================================
175
+ // Beads Integration (Legacy - use unified tasks API instead)
176
+ // =========================================================================
177
+
178
+ /**
179
+ * Sync Beads tasks
180
+ */
181
+ async beadsSync() {
182
+ return this.request('/beads/sync', { method: 'POST' });
183
+ }
184
+
185
+ /**
186
+ * Get Beads context
187
+ */
188
+ async beadsContext(taskId = null) {
189
+ const query = taskId ? `?task_id=${encodeURIComponent(taskId)}` : '';
190
+ return this.request(`/beads/context${query}`);
191
+ }
192
+
193
+ /**
194
+ * Get Beads tasks
195
+ */
196
+ async beadsTasks() {
197
+ return this.request('/beads/tasks');
198
+ }
199
+
200
+ /**
201
+ * Get Beads stats
202
+ */
203
+ async beadsStats() {
204
+ return this.request('/beads/stats');
205
+ }
206
+
207
+ // =========================================================================
208
+ // Unified Tasks Integration (Phase 7 - Claude Code Tasks Adapter)
209
+ // =========================================================================
210
+
211
+ /**
212
+ * Get tasks from all sources (Beads and Claude Code)
213
+ * @param {Object} options - Filter options
214
+ * @param {string} options.source - Filter by source: 'beads' or 'claude_code'
215
+ * @param {string} options.status - Filter by status
216
+ * @param {number} options.limit - Max tasks to return
217
+ */
218
+ async getTasks(options = {}) {
219
+ const query = new URLSearchParams();
220
+ if (options.source) query.set('source', options.source);
221
+ if (options.status) query.set('task_status', options.status);
222
+ if (options.limit) query.set('limit', options.limit);
223
+
224
+ const queryStr = query.toString();
225
+ return this.request(`/tasks${queryStr ? '?' + queryStr : ''}`);
226
+ }
227
+
228
+ /**
229
+ * Get a specific task by ID
230
+ */
231
+ async getTask(taskId) {
232
+ return this.request(`/tasks/${encodeURIComponent(taskId)}`);
233
+ }
234
+
235
+ /**
236
+ * Sync task outcomes
237
+ * @param {Object} options - Sync options
238
+ * @param {string} options.source - Sync specific source only
239
+ * @param {string} options.taskId - Sync specific task only
240
+ */
241
+ async syncTasks(options = {}) {
242
+ const body = {};
243
+ if (options.source) body.source = options.source;
244
+ if (options.taskId) body.task_id = options.taskId;
245
+
246
+ return this.request('/tasks/sync', {
247
+ method: 'POST',
248
+ body: JSON.stringify(body)
249
+ });
250
+ }
251
+
252
+ /**
253
+ * Get unified task context
254
+ * @param {string} taskId - Task ID (optional, uses current if not provided)
255
+ * @param {string} source - Source filter (optional)
256
+ */
257
+ async getTaskContext(taskId = null, source = null) {
258
+ const query = new URLSearchParams();
259
+ if (taskId) query.set('task_id', taskId);
260
+ if (source) query.set('source', source);
261
+
262
+ const queryStr = query.toString();
263
+ return this.request(`/tasks/context${queryStr ? '?' + queryStr : ''}`);
264
+ }
265
+
266
+ /**
267
+ * Get memories linked to a task
268
+ */
269
+ async getTaskMemories(taskId) {
270
+ return this.request(`/tasks/${encodeURIComponent(taskId)}/memories`);
271
+ }
272
+
273
+ /**
274
+ * Get unified task statistics
275
+ */
276
+ async getTasksStats() {
277
+ return this.request('/tasks/stats');
278
+ }
279
+
280
+ // =========================================================================
281
+ // Export
282
+ // =========================================================================
283
+
284
+ /**
285
+ * Export memories as JSON
286
+ */
287
+ async exportMemories(options = {}) {
288
+ const memories = await this.getMemories({ limit: 100 });
289
+ return memories;
290
+ }
291
+ }
292
+
293
+ // Global API instance
294
+ const api = new MemoryLayerAPI();