sql-assistant 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 (64) hide show
  1. sql_assistant/__init__.py +3 -0
  2. sql_assistant/api/__init__.py +1 -0
  3. sql_assistant/api/backup.py +116 -0
  4. sql_assistant/api/config.py +183 -0
  5. sql_assistant/api/conversation.py +71 -0
  6. sql_assistant/api/dependencies.py +22 -0
  7. sql_assistant/api/history.py +61 -0
  8. sql_assistant/api/models.py +221 -0
  9. sql_assistant/api/query.py +275 -0
  10. sql_assistant/api/routes.py +19 -0
  11. sql_assistant/api/schema.py +21 -0
  12. sql_assistant/config.py +144 -0
  13. sql_assistant/database/__init__.py +1 -0
  14. sql_assistant/database/backup.py +568 -0
  15. sql_assistant/database/connectors/__init__.py +1 -0
  16. sql_assistant/database/connectors/base.py +185 -0
  17. sql_assistant/database/connectors/exceptions.py +88 -0
  18. sql_assistant/database/connectors/mongodb.py +194 -0
  19. sql_assistant/database/connectors/mysql.py +110 -0
  20. sql_assistant/database/connectors/postgresql.py +133 -0
  21. sql_assistant/database/connectors/redis.py +132 -0
  22. sql_assistant/database/connectors/sqlserver.py +140 -0
  23. sql_assistant/database/history.py +290 -0
  24. sql_assistant/database/manager.py +178 -0
  25. sql_assistant/database/security.py +230 -0
  26. sql_assistant/llm/__init__.py +1 -0
  27. sql_assistant/llm/base.py +28 -0
  28. sql_assistant/llm/exceptions.py +96 -0
  29. sql_assistant/llm/manager.py +82 -0
  30. sql_assistant/llm/prompts.py +29 -0
  31. sql_assistant/llm/providers/__init__.py +1 -0
  32. sql_assistant/llm/providers/claude.py +132 -0
  33. sql_assistant/llm/providers/gemini.py +127 -0
  34. sql_assistant/llm/providers/openai_compatible.py +103 -0
  35. sql_assistant/llm/retry.py +88 -0
  36. sql_assistant/main.py +94 -0
  37. sql_assistant/settings.py +219 -0
  38. sql_assistant/web/__init__.py +1 -0
  39. sql_assistant/web/static/css/base.css +25 -0
  40. sql_assistant/web/static/css/components/backup.css +146 -0
  41. sql_assistant/web/static/css/components/chat.css +465 -0
  42. sql_assistant/web/static/css/components/modal.css +143 -0
  43. sql_assistant/web/static/css/components/settings.css +358 -0
  44. sql_assistant/web/static/css/components/sidebar.css +235 -0
  45. sql_assistant/web/static/css/components/toast.css +30 -0
  46. sql_assistant/web/static/css/style.css +10 -0
  47. sql_assistant/web/static/css/theme.css +200 -0
  48. sql_assistant/web/static/js/api.js +38 -0
  49. sql_assistant/web/static/js/app.js +161 -0
  50. sql_assistant/web/static/js/backup.js +216 -0
  51. sql_assistant/web/static/js/chat.js +238 -0
  52. sql_assistant/web/static/js/color-theme-manager.js +121 -0
  53. sql_assistant/web/static/js/confirm.js +95 -0
  54. sql_assistant/web/static/js/conversations.js +182 -0
  55. sql_assistant/web/static/js/settings.js +425 -0
  56. sql_assistant/web/static/js/state.js +43 -0
  57. sql_assistant/web/static/js/theme-manager.js +64 -0
  58. sql_assistant/web/static/js/ui.js +53 -0
  59. sql_assistant/web/templates/index.html +373 -0
  60. sql_assistant-1.0.0.dist-info/METADATA +24 -0
  61. sql_assistant-1.0.0.dist-info/RECORD +64 -0
  62. sql_assistant-1.0.0.dist-info/WHEEL +4 -0
  63. sql_assistant-1.0.0.dist-info/entry_points.txt +2 -0
  64. sql_assistant-1.0.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,465 @@
1
+ /* === Chat === */
2
+ .main-content {
3
+ flex: 1;
4
+ display: flex;
5
+ overflow: hidden;
6
+ }
7
+
8
+ .chat-container {
9
+ flex: 1;
10
+ display: flex;
11
+ flex-direction: column;
12
+ max-width: 1000px;
13
+ margin: 0 auto;
14
+ width: 100%;
15
+ }
16
+
17
+ .chat-messages {
18
+ flex: 1;
19
+ overflow-y: auto;
20
+ padding: 24px 32px;
21
+ }
22
+
23
+ /* Welcome */
24
+ .welcome-message {
25
+ text-align: center;
26
+ padding: 60px 20px;
27
+ }
28
+
29
+ .welcome-icon { font-size: 48px; margin-bottom: 16px; }
30
+
31
+ .welcome-message h2 {
32
+ font-size: 28px;
33
+ margin-bottom: 8px;
34
+ }
35
+
36
+ .welcome-message p {
37
+ color: var(--text-secondary);
38
+ margin-bottom: 8px;
39
+ }
40
+
41
+ .welcome-hint {
42
+ color: var(--warning) !important;
43
+ font-size: 14px;
44
+ margin-bottom: 20px !important;
45
+ }
46
+
47
+ .welcome-examples {
48
+ display: flex;
49
+ flex-wrap: wrap;
50
+ gap: 8px;
51
+ justify-content: center;
52
+ }
53
+
54
+ .example-tag {
55
+ padding: 8px 16px;
56
+ background: var(--bg-tertiary);
57
+ border: 1px solid var(--border-color);
58
+ border-radius: 20px;
59
+ font-size: 13px;
60
+ cursor: pointer;
61
+ transition: all var(--transition);
62
+ color: var(--text-secondary);
63
+ }
64
+
65
+ .example-tag:hover {
66
+ background: var(--bg-hover);
67
+ color: var(--text-primary);
68
+ border-color: var(--accent);
69
+ }
70
+
71
+ /* Chat Messages */
72
+ .message {
73
+ margin-bottom: 20px;
74
+ animation: fadeIn 200ms ease;
75
+ }
76
+
77
+ @keyframes fadeIn {
78
+ from { opacity: 0; transform: translateY(8px); }
79
+ to { opacity: 1; transform: translateY(0); }
80
+ }
81
+
82
+ .message.user .message-content {
83
+ background: var(--bg-tertiary);
84
+ border: 1px solid var(--border-color);
85
+ padding: 12px 16px;
86
+ border-radius: var(--radius);
87
+ max-width: 80%;
88
+ margin-left: auto;
89
+ }
90
+
91
+ .message.assistant .message-content {
92
+ max-width: 100%;
93
+ }
94
+
95
+ .message-label {
96
+ font-size: 11px;
97
+ font-weight: 600;
98
+ text-transform: uppercase;
99
+ letter-spacing: 0.5px;
100
+ color: var(--text-muted);
101
+ margin-bottom: 6px;
102
+ }
103
+
104
+ .sql-block {
105
+ background: var(--bg-secondary);
106
+ border: 1px solid var(--border-color);
107
+ border-radius: var(--radius);
108
+ margin: 8px 0;
109
+ overflow: hidden;
110
+ }
111
+
112
+ .sql-block-header {
113
+ display: flex;
114
+ justify-content: space-between;
115
+ align-items: center;
116
+ padding: 8px 12px;
117
+ background: var(--bg-tertiary);
118
+ font-size: 12px;
119
+ color: var(--text-muted);
120
+ }
121
+
122
+ .sql-block pre {
123
+ padding: 12px;
124
+ overflow-x: auto;
125
+ font-family: var(--font-mono);
126
+ font-size: 13px;
127
+ line-height: 1.6;
128
+ color: var(--success);
129
+ white-space: pre-wrap;
130
+ word-break: break-all;
131
+ background: inherit !important;
132
+ }
133
+
134
+ .sql-block code {
135
+ background: inherit !important;
136
+ }
137
+
138
+ /* Highlight.js SQL Syntax Colors - Dark Theme */
139
+ [data-theme="dark"] .hljs-keyword,
140
+ [data-theme="dark"] .hljs-selector-tag,
141
+ [data-theme="dark"] .hljs-built_in,
142
+ [data-theme="dark"] .hljs-name {
143
+ color: #ff7b72 !important;
144
+ }
145
+
146
+ [data-theme="dark"] .hljs-string,
147
+ [data-theme="dark"] .hljs-title,
148
+ [data-theme="dark"] .hljs-literal {
149
+ color: #a5d6ff !important;
150
+ }
151
+
152
+ [data-theme="dark"] .hljs-number,
153
+ [data-theme="dark"] .hljs-punctuation {
154
+ color: #79c0ff !important;
155
+ }
156
+
157
+ [data-theme="dark"] .hljs-comment {
158
+ color: #8b949e !important;
159
+ font-style: italic;
160
+ }
161
+
162
+ [data-theme="dark"] .hljs-function,
163
+ [data-theme="dark"] .hljs-title.function {
164
+ color: #d2a8ff !important;
165
+ }
166
+
167
+ [data-theme="dark"] .hljs-operator {
168
+ color: #ff7b72 !important;
169
+ }
170
+
171
+ [data-theme="dark"] .hljs-attr {
172
+ color: #79c0ff !important;
173
+ }
174
+
175
+ /* Highlight.js SQL Syntax Colors - Light Theme */
176
+ [data-theme="light"] .hljs-keyword,
177
+ [data-theme="light"] .hljs-selector-tag,
178
+ [data-theme="light"] .hljs-built_in,
179
+ [data-theme="light"] .hljs-name {
180
+ color: #cf222e !important;
181
+ }
182
+
183
+ [data-theme="light"] .hljs-string,
184
+ [data-theme="light"] .hljs-title,
185
+ [data-theme="light"] .hljs-literal {
186
+ color: #0a3069 !important;
187
+ }
188
+
189
+ [data-theme="light"] .hljs-number,
190
+ [data-theme="light"] .hljs-punctuation {
191
+ color: #0550ae !important;
192
+ }
193
+
194
+ [data-theme="light"] .hljs-comment {
195
+ color: #6e7781 !important;
196
+ font-style: italic;
197
+ }
198
+
199
+ [data-theme="light"] .hljs-function,
200
+ [data-theme="light"] .hljs-title.function {
201
+ color: #8250df !important;
202
+ }
203
+
204
+ [data-theme="light"] .hljs-operator {
205
+ color: #cf222e !important;
206
+ }
207
+
208
+ [data-theme="light"] .hljs-attr {
209
+ color: #0550ae !important;
210
+ }
211
+
212
+ /* Highlight.js fallback for :root (default dark) */
213
+ :root .hljs-keyword,
214
+ .hljs-keyword {
215
+ color: var(--hl-keyword, #ff7b72);
216
+ }
217
+
218
+ :root .hljs-string,
219
+ .hljs-string {
220
+ color: var(--hl-string, #a5d6ff);
221
+ }
222
+
223
+ :root .hljs-number,
224
+ .hljs-number {
225
+ color: var(--hl-number, #79c0ff);
226
+ }
227
+
228
+ :root .hljs-comment,
229
+ .hljs-comment {
230
+ color: var(--hl-comment, #8b949e);
231
+ }
232
+
233
+ :root .hljs-function,
234
+ .hljs-function {
235
+ color: var(--hl-function, #d2a8ff);
236
+ }
237
+
238
+ :root .hljs-operator,
239
+ .hljs-operator {
240
+ color: var(--hl-operator, #ff7b72);
241
+ }
242
+
243
+ :root .hljs-attr,
244
+ .hljs-attr {
245
+ color: var(--hl-type, #79c0ff);
246
+ }
247
+
248
+ .btn-copy {
249
+ background: none;
250
+ border: 1px solid var(--border-color);
251
+ color: var(--text-secondary);
252
+ cursor: pointer;
253
+ padding: 2px 8px;
254
+ border-radius: var(--radius-sm);
255
+ font-size: 12px;
256
+ }
257
+
258
+ .btn-copy:hover { background: var(--bg-hover); }
259
+
260
+ /* Results Table */
261
+ .result-table-wrapper {
262
+ overflow-x: auto;
263
+ border: 1px solid var(--border-color);
264
+ border-radius: var(--radius);
265
+ margin: 8px 0;
266
+ }
267
+
268
+ .result-table {
269
+ width: 100%;
270
+ border-collapse: collapse;
271
+ font-size: 13px;
272
+ }
273
+
274
+ .result-table th {
275
+ background: var(--bg-tertiary);
276
+ padding: 8px 12px;
277
+ text-align: left;
278
+ font-weight: 600;
279
+ color: var(--text-secondary);
280
+ border-bottom: 1px solid var(--border-color);
281
+ white-space: nowrap;
282
+ }
283
+
284
+ .result-table td {
285
+ padding: 8px 12px;
286
+ border-bottom: 1px solid var(--border-color);
287
+ font-family: var(--font-mono);
288
+ font-size: 13px;
289
+ color: var(--text-primary);
290
+ }
291
+
292
+ .result-table tr:hover td { background: var(--bg-hover); }
293
+ .result-table tr:last-child td { border-bottom: none; }
294
+
295
+ .result-meta {
296
+ font-size: 12px;
297
+ color: var(--text-muted);
298
+ margin-top: 8px;
299
+ }
300
+
301
+ .error-message {
302
+ padding: 12px;
303
+ background: rgba(248,81,73,0.1);
304
+ border: 1px solid rgba(248,81,73,0.3);
305
+ border-radius: var(--radius);
306
+ color: var(--danger);
307
+ font-size: 13px;
308
+ margin: 8px 0;
309
+ }
310
+
311
+ .loading-dots {
312
+ display: inline-flex;
313
+ gap: 4px;
314
+ padding: 12px 0;
315
+ }
316
+
317
+ .loading-dots span {
318
+ width: 8px;
319
+ height: 8px;
320
+ background: var(--accent);
321
+ border-radius: 50%;
322
+ animation: bounce 1.4s infinite ease-in-out both;
323
+ }
324
+
325
+ .loading-dots span:nth-child(1) { animation-delay: -0.32s; }
326
+ .loading-dots span:nth-child(2) { animation-delay: -0.16s; }
327
+
328
+ @keyframes bounce {
329
+ 0%, 80%, 100% { transform: scale(0); }
330
+ 40% { transform: scale(1); }
331
+ }
332
+
333
+ /* Input */
334
+ .chat-input-container {
335
+ padding: 16px 32px 24px;
336
+ border-top: 1px solid var(--border-color);
337
+ background: var(--bg-primary);
338
+ }
339
+
340
+ .chat-input-form {
341
+ display: flex;
342
+ gap: 8px;
343
+ align-items: flex-end;
344
+ }
345
+
346
+ .chat-input-form textarea {
347
+ flex: 1;
348
+ background: var(--bg-secondary);
349
+ border: 1px solid var(--border-color);
350
+ border-radius: var(--radius);
351
+ padding: 12px 16px;
352
+ color: var(--text-primary);
353
+ font-family: var(--font-sans);
354
+ font-size: 14px;
355
+ resize: none;
356
+ max-height: 120px;
357
+ outline: none;
358
+ transition: border-color var(--transition);
359
+ }
360
+
361
+ .chat-input-form textarea:focus {
362
+ border-color: var(--accent);
363
+ }
364
+
365
+ .chat-input-form textarea::placeholder {
366
+ color: var(--text-muted);
367
+ }
368
+
369
+ .btn-send {
370
+ width: 44px;
371
+ height: 44px;
372
+ min-width: 44px;
373
+ background: var(--accent);
374
+ border: none;
375
+ border-radius: var(--radius);
376
+ color: white;
377
+ cursor: pointer;
378
+ display: flex;
379
+ align-items: center;
380
+ justify-content: center;
381
+ transition: all var(--transition);
382
+ }
383
+
384
+ .btn-send:hover:not(:disabled) { background: var(--accent-hover); }
385
+ .btn-send:disabled { opacity: 0.4; cursor: not-allowed; }
386
+
387
+ .input-hint {
388
+ font-size: 11px;
389
+ color: var(--text-muted);
390
+ margin-top: 6px;
391
+ text-align: right;
392
+ }
393
+
394
+ /* SQL Block Streaming Cursor */
395
+ .sql-block.streaming .sql-content::after {
396
+ content: '▋';
397
+ animation: blink 1s step-end infinite;
398
+ color: var(--accent);
399
+ }
400
+
401
+ @keyframes blink {
402
+ 50% { opacity: 0; }
403
+ }
404
+
405
+ /* Result Pagination */
406
+ .result-pagination {
407
+ display: flex;
408
+ align-items: center;
409
+ justify-content: center;
410
+ gap: 12px;
411
+ margin-top: 12px;
412
+ padding-top: 12px;
413
+ border-top: 1px solid var(--border-color);
414
+ }
415
+
416
+ .btn-page {
417
+ padding: 6px 16px;
418
+ background: var(--bg-secondary);
419
+ border: 1px solid var(--border-color);
420
+ border-radius: var(--radius);
421
+ color: var(--text-primary);
422
+ font-size: 13px;
423
+ cursor: pointer;
424
+ transition: all var(--transition);
425
+ }
426
+
427
+ .btn-page:hover:not(:disabled) {
428
+ background: var(--bg-hover);
429
+ border-color: var(--accent);
430
+ }
431
+
432
+ .btn-page:disabled {
433
+ opacity: 0.5;
434
+ cursor: not-allowed;
435
+ }
436
+
437
+ .page-info {
438
+ font-size: 13px;
439
+ color: var(--text-secondary);
440
+ }
441
+
442
+ /* Streaming Indicator */
443
+ .streaming-indicator {
444
+ color: var(--text-secondary);
445
+ font-size: 13px;
446
+ margin-bottom: 8px;
447
+ display: flex;
448
+ align-items: center;
449
+ gap: 6px;
450
+ }
451
+
452
+ .streaming-indicator::before {
453
+ content: '';
454
+ display: inline-block;
455
+ width: 12px;
456
+ height: 12px;
457
+ border: 2px solid var(--border-color);
458
+ border-top-color: var(--accent);
459
+ border-radius: 50%;
460
+ animation: spin 0.8s linear infinite;
461
+ }
462
+
463
+ @keyframes spin {
464
+ to { transform: rotate(360deg); }
465
+ }
@@ -0,0 +1,143 @@
1
+ /* === Modal === */
2
+ .modal-overlay {
3
+ display: none;
4
+ position: fixed;
5
+ inset: 0;
6
+ background: rgba(0,0,0,0.6);
7
+ z-index: 1000;
8
+ align-items: center;
9
+ justify-content: center;
10
+ }
11
+
12
+ .modal-overlay.active { display: flex; }
13
+
14
+ .modal-container {
15
+ background: var(--bg-secondary);
16
+ border: 1px solid var(--border-color);
17
+ border-radius: 12px;
18
+ width: 640px;
19
+ max-width: 90vw;
20
+ max-height: 80vh;
21
+ display: flex;
22
+ flex-direction: column;
23
+ box-shadow: 0 0 40px rgba(0,0,0,0.5);
24
+ }
25
+
26
+ .modal-header {
27
+ display: flex;
28
+ justify-content: space-between;
29
+ align-items: center;
30
+ padding: 20px 24px;
31
+ border-bottom: 1px solid var(--border-color);
32
+ }
33
+
34
+ .modal-header h2 { font-size: 18px; }
35
+
36
+ .modal-body {
37
+ flex: 1;
38
+ overflow-y: auto;
39
+ padding: 20px 24px;
40
+ }
41
+
42
+ /* Settings Tabs */
43
+ .settings-tabs {
44
+ display: flex;
45
+ gap: 4px;
46
+ margin-bottom: 20px;
47
+ background: var(--bg-tertiary);
48
+ padding: 4px;
49
+ border-radius: var(--radius);
50
+ }
51
+
52
+ .tab-btn {
53
+ flex: 1;
54
+ padding: 8px 16px;
55
+ border: none;
56
+ background: none;
57
+ color: var(--text-secondary);
58
+ font-size: 13px;
59
+ cursor: pointer;
60
+ border-radius: var(--radius-sm);
61
+ transition: all var(--transition);
62
+ font-family: var(--font-sans);
63
+ }
64
+
65
+ .tab-btn:hover { color: var(--text-primary); }
66
+
67
+ .tab-btn.active {
68
+ background: var(--bg-secondary);
69
+ color: var(--text-primary);
70
+ box-shadow: 0 1px 3px rgba(0,0,0,0.2);
71
+ }
72
+
73
+ .tab-panel { display: none; }
74
+ .tab-panel.active { display: block; }
75
+
76
+ /* SQL 确认对话框 */
77
+ .sql-warning-box {
78
+ padding: 12px 16px;
79
+ background: rgba(248, 81, 73, 0.1);
80
+ border: 1px solid rgba(248, 81, 73, 0.3);
81
+ border-radius: 8px;
82
+ margin-bottom: 16px;
83
+ color: var(--danger);
84
+ font-size: 14px;
85
+ }
86
+
87
+ .sql-warning-box.medium {
88
+ background: rgba(255, 149, 0, 0.1);
89
+ border-color: rgba(255, 149, 0, 0.3);
90
+ color: #ff9500;
91
+ }
92
+
93
+ .sql-warning-box.high {
94
+ background: rgba(248, 81, 73, 0.15);
95
+ border-color: rgba(248, 81, 73, 0.4);
96
+ }
97
+
98
+ .sql-reason-box {
99
+ padding: 12px 16px;
100
+ background: var(--bg-tertiary);
101
+ border-radius: 8px;
102
+ margin-bottom: 16px;
103
+ font-size: 14px;
104
+ color: var(--text-primary);
105
+ }
106
+
107
+ .sql-preview-box {
108
+ background: var(--bg-tertiary);
109
+ border-radius: 8px;
110
+ overflow: hidden;
111
+ }
112
+
113
+ .sql-preview-header {
114
+ display: flex;
115
+ justify-content: space-between;
116
+ align-items: center;
117
+ padding: 10px 16px;
118
+ background: var(--bg-secondary);
119
+ border-bottom: 1px solid var(--border-color);
120
+ font-size: 13px;
121
+ color: var(--text-secondary);
122
+ }
123
+
124
+ .sql-preview-box pre {
125
+ margin: 0;
126
+ padding: 16px;
127
+ overflow-x: auto;
128
+ max-height: 300px;
129
+ }
130
+
131
+ .sql-preview-box code {
132
+ font-family: var(--font-mono);
133
+ font-size: 13px;
134
+ line-height: 1.6;
135
+ }
136
+
137
+ .btn-primary.danger {
138
+ background: var(--danger);
139
+ }
140
+
141
+ .btn-primary.danger:hover {
142
+ background: #d73a30;
143
+ }