signalpilot-ai-internal 0.3.1__py3-none-any.whl → 0.3.3__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.

Potentially problematic release.


This version of signalpilot-ai-internal might be problematic. Click here for more details.

Files changed (46) hide show
  1. signalpilot_ai_internal/_version.py +1 -1
  2. signalpilot_ai_internal/cache_handlers.py +383 -0
  3. signalpilot_ai_internal/cache_service.py +552 -0
  4. signalpilot_ai_internal/handlers.py +35 -915
  5. signalpilot_ai_internal/snowflake_schema_service.py +639 -0
  6. signalpilot_ai_internal/unified_database_schema_service.py +742 -0
  7. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/package.json +3 -2
  8. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/schemas/signalpilot-ai-internal/package.json.orig +2 -1
  9. signalpilot_ai_internal-0.3.3.data/data/share/jupyter/labextensions/signalpilot-ai-internal/static/384.fa432bdb7fb6b1c95ad6.js +1 -0
  10. signalpilot_ai_internal-0.3.3.data/data/share/jupyter/labextensions/signalpilot-ai-internal/static/447.0fea0d444fc7ba458d5a.js +1 -0
  11. signalpilot_ai_internal-0.3.3.data/data/share/jupyter/labextensions/signalpilot-ai-internal/static/839.c61f5bc4d0da4a0781d6.js +1 -0
  12. signalpilot_ai_internal-0.3.3.data/data/share/jupyter/labextensions/signalpilot-ai-internal/static/remoteEntry.2e2c6ae0baa591126b0a.js +1 -0
  13. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/third-party-licenses.json +6 -0
  14. {signalpilot_ai_internal-0.3.1.dist-info → signalpilot_ai_internal-0.3.3.dist-info}/METADATA +1 -1
  15. signalpilot_ai_internal-0.3.3.dist-info/RECORD +45 -0
  16. signalpilot_ai_internal-0.3.1.data/data/share/jupyter/labextensions/signalpilot-ai-internal/static/447.45c187b4dc615d9cc073.js +0 -1
  17. signalpilot_ai_internal-0.3.1.data/data/share/jupyter/labextensions/signalpilot-ai-internal/static/839.e2bd05ad6dbdb957683f.js +0 -1
  18. signalpilot_ai_internal-0.3.1.data/data/share/jupyter/labextensions/signalpilot-ai-internal/static/remoteEntry.07bc9bbdead29df455e7.js +0 -1
  19. signalpilot_ai_internal-0.3.1.dist-info/RECORD +0 -40
  20. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/etc/jupyter/jupyter_server_config.d/signalpilot_ai.json +0 -0
  21. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/install.json +0 -0
  22. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/schemas/signalpilot-ai-internal/plugin.json +0 -0
  23. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/104.04e170724f369fcbaf19.js +0 -0
  24. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/104.04e170724f369fcbaf19.js.LICENSE.txt +0 -0
  25. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/122.e2dadf63dc64d7b5f1ee.js +0 -0
  26. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/220.328403b5545f268b95c6.js +0 -0
  27. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/262.726e1da31a50868cb297.js +0 -0
  28. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/280.35d8c8b68815702a5238.js +0 -0
  29. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/280.35d8c8b68815702a5238.js.LICENSE.txt +0 -0
  30. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/353.72484b768a04f89bd3dd.js +0 -0
  31. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/364.dbec4c2dc12e7b050dcc.js +0 -0
  32. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/439.37e271d7a80336daabe2.js +0 -0
  33. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/476.9b4f05a99f5003f82094.js +0 -0
  34. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/481.73c7a9290b7d35a8b9c1.js +0 -0
  35. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/512.b58fc0093d080b8ee61c.js +0 -0
  36. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/553.b4042a795c91d9ff71ef.js +0 -0
  37. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/553.b4042a795c91d9ff71ef.js.LICENSE.txt +0 -0
  38. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/606.90aaaae46b73dc3c08fb.js +0 -0
  39. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/635.9720593ee20b768da3ca.js +0 -0
  40. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/713.8e6edc9a965bdd578ca7.js +0 -0
  41. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/742.91e7b516c8699eea3373.js +0 -0
  42. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/785.3aa564fc148b37d1d719.js +0 -0
  43. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/888.34054db17bcf6e87ec95.js +0 -0
  44. {signalpilot_ai_internal-0.3.1.data → signalpilot_ai_internal-0.3.3.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/style.js +0 -0
  45. {signalpilot_ai_internal-0.3.1.dist-info → signalpilot_ai_internal-0.3.3.dist-info}/WHEEL +0 -0
  46. {signalpilot_ai_internal-0.3.1.dist-info → signalpilot_ai_internal-0.3.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,4 @@
1
1
  # This file is auto-generated by Hatchling. As such, do not:
2
2
  # - modify
3
3
  # - track in version control e.g. be sure to add to .gitignore
4
- __version__ = VERSION = '0.3.1'
4
+ __version__ = VERSION = '0.3.3'
@@ -0,0 +1,383 @@
1
+ """
2
+ Cache endpoint handlers for SignalPilot AI.
3
+ Provides REST API handlers for chat histories and app values caching.
4
+ """
5
+
6
+ import json
7
+ from typing import Any, Dict, Optional
8
+
9
+ from jupyter_server.base.handlers import APIHandler
10
+ import tornado
11
+
12
+ from .cache_service import get_cache_service
13
+
14
+
15
+ class ChatHistoriesHandler(APIHandler):
16
+ """Handler for chat histories cache operations"""
17
+
18
+ @tornado.web.authenticated
19
+ def get(self, chat_id=None):
20
+ """Get chat histories or specific chat history"""
21
+ try:
22
+ cache_service = get_cache_service()
23
+
24
+ if not cache_service.is_available():
25
+ self.set_status(503)
26
+ self.finish(json.dumps({
27
+ "error": "Cache service not available",
28
+ "message": "Persistent storage is not accessible"
29
+ }))
30
+ return
31
+
32
+ if chat_id:
33
+ # Get specific chat history
34
+ history = cache_service.get_chat_history(chat_id)
35
+ if history is None:
36
+ self.set_status(404)
37
+ self.finish(json.dumps({
38
+ "error": "Chat history not found",
39
+ "chat_id": chat_id
40
+ }))
41
+ else:
42
+ self.finish(json.dumps({
43
+ "chat_id": chat_id,
44
+ "history": history
45
+ }))
46
+ else:
47
+ # Get all chat histories
48
+ histories = cache_service.get_chat_histories()
49
+ self.finish(json.dumps({
50
+ "chat_histories": histories,
51
+ "count": len(histories)
52
+ }))
53
+
54
+ except Exception as e:
55
+ self.set_status(500)
56
+ self.finish(json.dumps({
57
+ "error": "Internal server error",
58
+ "message": str(e)
59
+ }))
60
+
61
+ @tornado.web.authenticated
62
+ def post(self, chat_id=None):
63
+ """Create or update chat history"""
64
+ try:
65
+ cache_service = get_cache_service()
66
+
67
+ if not cache_service.is_available():
68
+ self.set_status(503)
69
+ self.finish(json.dumps({
70
+ "error": "Cache service not available",
71
+ "message": "Persistent storage is not accessible"
72
+ }))
73
+ return
74
+
75
+ # Parse request body
76
+ try:
77
+ body = json.loads(self.request.body.decode('utf-8'))
78
+ except json.JSONDecodeError:
79
+ self.set_status(400)
80
+ self.finish(json.dumps({
81
+ "error": "Invalid JSON in request body"
82
+ }))
83
+ return
84
+
85
+ if chat_id:
86
+ # Update specific chat history
87
+ history_data = body.get('history')
88
+ if history_data is None:
89
+ self.set_status(400)
90
+ self.finish(json.dumps({
91
+ "error": "Missing 'history' field in request body"
92
+ }))
93
+ return
94
+
95
+ success = cache_service.set_chat_history(chat_id, history_data)
96
+ if success:
97
+ self.finish(json.dumps({
98
+ "success": True,
99
+ "chat_id": chat_id,
100
+ "message": "Chat history updated successfully"
101
+ }))
102
+ else:
103
+ self.set_status(500)
104
+ self.finish(json.dumps({
105
+ "error": "Failed to save chat history"
106
+ }))
107
+ else:
108
+ # Bulk update operation
109
+ chat_histories = body.get('chat_histories', {})
110
+ if not isinstance(chat_histories, dict):
111
+ self.set_status(400)
112
+ self.finish(json.dumps({
113
+ "error": "'chat_histories' must be an object"
114
+ }))
115
+ return
116
+
117
+ # Update each chat history
118
+ failures = []
119
+ successes = []
120
+
121
+ for cid, history in chat_histories.items():
122
+ if cache_service.set_chat_history(cid, history):
123
+ successes.append(cid)
124
+ else:
125
+ failures.append(cid)
126
+
127
+ self.finish(json.dumps({
128
+ "success": len(failures) == 0,
129
+ "updated": successes,
130
+ "failed": failures,
131
+ "message": f"Updated {len(successes)} chat histories, {len(failures)} failed"
132
+ }))
133
+
134
+ except Exception as e:
135
+ self.set_status(500)
136
+ self.finish(json.dumps({
137
+ "error": "Internal server error",
138
+ "message": str(e)
139
+ }))
140
+
141
+ @tornado.web.authenticated
142
+ def delete(self, chat_id=None):
143
+ """Delete chat history or all chat histories"""
144
+ try:
145
+ cache_service = get_cache_service()
146
+
147
+ if not cache_service.is_available():
148
+ self.set_status(503)
149
+ self.finish(json.dumps({
150
+ "error": "Cache service not available",
151
+ "message": "Persistent storage is not accessible"
152
+ }))
153
+ return
154
+
155
+ if chat_id:
156
+ # Delete specific chat history
157
+ success = cache_service.delete_chat_history(chat_id)
158
+ if success:
159
+ self.finish(json.dumps({
160
+ "success": True,
161
+ "chat_id": chat_id,
162
+ "message": "Chat history deleted successfully"
163
+ }))
164
+ else:
165
+ self.set_status(500)
166
+ self.finish(json.dumps({
167
+ "error": "Failed to delete chat history"
168
+ }))
169
+ else:
170
+ # Clear all chat histories
171
+ success = cache_service.clear_chat_histories()
172
+ if success:
173
+ self.finish(json.dumps({
174
+ "success": True,
175
+ "message": "All chat histories cleared successfully"
176
+ }))
177
+ else:
178
+ self.set_status(500)
179
+ self.finish(json.dumps({
180
+ "error": "Failed to clear chat histories"
181
+ }))
182
+
183
+ except Exception as e:
184
+ self.set_status(500)
185
+ self.finish(json.dumps({
186
+ "error": "Internal server error",
187
+ "message": str(e)
188
+ }))
189
+
190
+
191
+ class AppValuesHandler(APIHandler):
192
+ """Handler for app values cache operations"""
193
+
194
+ @tornado.web.authenticated
195
+ def get(self, key=None):
196
+ """Get app values or specific app value"""
197
+ try:
198
+ cache_service = get_cache_service()
199
+
200
+ if not cache_service.is_available():
201
+ self.set_status(503)
202
+ self.finish(json.dumps({
203
+ "error": "Cache service not available",
204
+ "message": "Persistent storage is not accessible"
205
+ }))
206
+ return
207
+
208
+ if key:
209
+ # Get specific app value
210
+ default = self.get_argument('default', None)
211
+ try:
212
+ if default:
213
+ default = json.loads(default)
214
+ except json.JSONDecodeError:
215
+ pass # Use string default
216
+
217
+ value = cache_service.get_app_value(key, default)
218
+ self.finish(json.dumps({
219
+ "key": key,
220
+ "value": value
221
+ }))
222
+ else:
223
+ # Get all app values
224
+ values = cache_service.get_app_values()
225
+ self.finish(json.dumps({
226
+ "app_values": values,
227
+ "count": len(values)
228
+ }))
229
+
230
+ except Exception as e:
231
+ self.set_status(500)
232
+ self.finish(json.dumps({
233
+ "error": "Internal server error",
234
+ "message": str(e)
235
+ }))
236
+
237
+ @tornado.web.authenticated
238
+ def post(self, key=None):
239
+ """Create or update app value"""
240
+ try:
241
+ cache_service = get_cache_service()
242
+
243
+ if not cache_service.is_available():
244
+ self.set_status(503)
245
+ self.finish(json.dumps({
246
+ "error": "Cache service not available",
247
+ "message": "Persistent storage is not accessible"
248
+ }))
249
+ return
250
+
251
+ # Parse request body
252
+ try:
253
+ body = json.loads(self.request.body.decode('utf-8'))
254
+ except json.JSONDecodeError:
255
+ self.set_status(400)
256
+ self.finish(json.dumps({
257
+ "error": "Invalid JSON in request body"
258
+ }))
259
+ return
260
+
261
+ if key:
262
+ # Update specific app value
263
+ value_data = body.get('value')
264
+ if value_data is None:
265
+ self.set_status(400)
266
+ self.finish(json.dumps({
267
+ "error": "Missing 'value' field in request body"
268
+ }))
269
+ return
270
+
271
+ success = cache_service.set_app_value(key, value_data)
272
+ if success:
273
+ self.finish(json.dumps({
274
+ "success": True,
275
+ "key": key,
276
+ "message": "App value updated successfully"
277
+ }))
278
+ else:
279
+ self.set_status(500)
280
+ self.finish(json.dumps({
281
+ "error": "Failed to save app value"
282
+ }))
283
+ else:
284
+ # Bulk update operation
285
+ app_values = body.get('app_values', {})
286
+ if not isinstance(app_values, dict):
287
+ self.set_status(400)
288
+ self.finish(json.dumps({
289
+ "error": "'app_values' must be an object"
290
+ }))
291
+ return
292
+
293
+ # Update each app value
294
+ failures = []
295
+ successes = []
296
+
297
+ for k, value in app_values.items():
298
+ if cache_service.set_app_value(k, value):
299
+ successes.append(k)
300
+ else:
301
+ failures.append(k)
302
+
303
+ self.finish(json.dumps({
304
+ "success": len(failures) == 0,
305
+ "updated": successes,
306
+ "failed": failures,
307
+ "message": f"Updated {len(successes)} app values, {len(failures)} failed"
308
+ }))
309
+
310
+ except Exception as e:
311
+ self.set_status(500)
312
+ self.finish(json.dumps({
313
+ "error": "Internal server error",
314
+ "message": str(e)
315
+ }))
316
+
317
+ @tornado.web.authenticated
318
+ def delete(self, key=None):
319
+ """Delete app value or all app values"""
320
+ try:
321
+ cache_service = get_cache_service()
322
+
323
+ if not cache_service.is_available():
324
+ self.set_status(503)
325
+ self.finish(json.dumps({
326
+ "error": "Cache service not available",
327
+ "message": "Persistent storage is not accessible"
328
+ }))
329
+ return
330
+
331
+ if key:
332
+ # Delete specific app value
333
+ success = cache_service.delete_app_value(key)
334
+ if success:
335
+ self.finish(json.dumps({
336
+ "success": True,
337
+ "key": key,
338
+ "message": "App value deleted successfully"
339
+ }))
340
+ else:
341
+ self.set_status(500)
342
+ self.finish(json.dumps({
343
+ "error": "Failed to delete app value"
344
+ }))
345
+ else:
346
+ # Clear all app values
347
+ success = cache_service.clear_app_values()
348
+ if success:
349
+ self.finish(json.dumps({
350
+ "success": True,
351
+ "message": "All app values cleared successfully"
352
+ }))
353
+ else:
354
+ self.set_status(500)
355
+ self.finish(json.dumps({
356
+ "error": "Failed to clear app values"
357
+ }))
358
+
359
+ except Exception as e:
360
+ self.set_status(500)
361
+ self.finish(json.dumps({
362
+ "error": "Internal server error",
363
+ "message": str(e)
364
+ }))
365
+
366
+
367
+ class CacheInfoHandler(APIHandler):
368
+ """Handler for cache service information"""
369
+
370
+ @tornado.web.authenticated
371
+ def get(self):
372
+ """Get cache service information and statistics"""
373
+ try:
374
+ cache_service = get_cache_service()
375
+ info = cache_service.get_cache_info()
376
+ self.finish(json.dumps(info))
377
+
378
+ except Exception as e:
379
+ self.set_status(500)
380
+ self.finish(json.dumps({
381
+ "error": "Internal server error",
382
+ "message": str(e)
383
+ }))