luckyd-code 1.2.2__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 (127) hide show
  1. luckyd_code/__init__.py +54 -0
  2. luckyd_code/__main__.py +5 -0
  3. luckyd_code/_agent_loop.py +551 -0
  4. luckyd_code/_data_dir.py +73 -0
  5. luckyd_code/agent.py +38 -0
  6. luckyd_code/analytics/__init__.py +18 -0
  7. luckyd_code/analytics/reporter.py +195 -0
  8. luckyd_code/analytics/scanner.py +443 -0
  9. luckyd_code/analytics/smells.py +316 -0
  10. luckyd_code/analytics/trends.py +303 -0
  11. luckyd_code/api.py +473 -0
  12. luckyd_code/audit_daemon.py +845 -0
  13. luckyd_code/autonomous_fixer.py +473 -0
  14. luckyd_code/background.py +159 -0
  15. luckyd_code/backup.py +237 -0
  16. luckyd_code/brain/__init__.py +84 -0
  17. luckyd_code/brain/assembler.py +100 -0
  18. luckyd_code/brain/chunker.py +345 -0
  19. luckyd_code/brain/constants.py +73 -0
  20. luckyd_code/brain/embedder.py +163 -0
  21. luckyd_code/brain/graph.py +311 -0
  22. luckyd_code/brain/indexer.py +316 -0
  23. luckyd_code/brain/parser.py +140 -0
  24. luckyd_code/brain/retriever.py +234 -0
  25. luckyd_code/cli.py +894 -0
  26. luckyd_code/cli_commands/__init__.py +1 -0
  27. luckyd_code/cli_commands/audit.py +120 -0
  28. luckyd_code/cli_commands/background.py +83 -0
  29. luckyd_code/cli_commands/brain.py +87 -0
  30. luckyd_code/cli_commands/config.py +75 -0
  31. luckyd_code/cli_commands/dispatcher.py +695 -0
  32. luckyd_code/cli_commands/sessions.py +41 -0
  33. luckyd_code/cli_entry.py +147 -0
  34. luckyd_code/cli_utils.py +112 -0
  35. luckyd_code/config.py +205 -0
  36. luckyd_code/context.py +214 -0
  37. luckyd_code/cost_tracker.py +209 -0
  38. luckyd_code/error_reporter.py +508 -0
  39. luckyd_code/exceptions.py +39 -0
  40. luckyd_code/export.py +126 -0
  41. luckyd_code/feedback_analyzer.py +290 -0
  42. luckyd_code/file_watcher.py +258 -0
  43. luckyd_code/git/__init__.py +11 -0
  44. luckyd_code/git/auto_commit.py +157 -0
  45. luckyd_code/git/tools.py +85 -0
  46. luckyd_code/hooks.py +236 -0
  47. luckyd_code/indexer.py +280 -0
  48. luckyd_code/init.py +39 -0
  49. luckyd_code/keybindings.py +77 -0
  50. luckyd_code/log.py +55 -0
  51. luckyd_code/mcp/__init__.py +6 -0
  52. luckyd_code/mcp/client.py +184 -0
  53. luckyd_code/memory/__init__.py +19 -0
  54. luckyd_code/memory/manager.py +339 -0
  55. luckyd_code/metrics/__init__.py +5 -0
  56. luckyd_code/model_registry.py +131 -0
  57. luckyd_code/orchestrator.py +204 -0
  58. luckyd_code/permissions/__init__.py +1 -0
  59. luckyd_code/permissions/manager.py +103 -0
  60. luckyd_code/planner.py +361 -0
  61. luckyd_code/plugins.py +91 -0
  62. luckyd_code/py.typed +0 -0
  63. luckyd_code/retry.py +57 -0
  64. luckyd_code/router.py +417 -0
  65. luckyd_code/sandbox.py +156 -0
  66. luckyd_code/self_critique.py +2 -0
  67. luckyd_code/self_improve.py +274 -0
  68. luckyd_code/sessions.py +114 -0
  69. luckyd_code/settings.py +72 -0
  70. luckyd_code/skills/__init__.py +8 -0
  71. luckyd_code/skills/review.py +22 -0
  72. luckyd_code/skills/security.py +17 -0
  73. luckyd_code/tasks/__init__.py +1 -0
  74. luckyd_code/tasks/manager.py +102 -0
  75. luckyd_code/templates/icon-192.png +0 -0
  76. luckyd_code/templates/icon-512.png +0 -0
  77. luckyd_code/templates/index.html +1965 -0
  78. luckyd_code/templates/manifest.json +14 -0
  79. luckyd_code/templates/src/app.js +694 -0
  80. luckyd_code/templates/src/body.html +767 -0
  81. luckyd_code/templates/src/cdn.txt +2 -0
  82. luckyd_code/templates/src/style.css +474 -0
  83. luckyd_code/templates/sw.js +31 -0
  84. luckyd_code/templates/test.html +6 -0
  85. luckyd_code/themes.py +48 -0
  86. luckyd_code/tools/__init__.py +97 -0
  87. luckyd_code/tools/agent_tools.py +65 -0
  88. luckyd_code/tools/bash.py +360 -0
  89. luckyd_code/tools/brain_tools.py +137 -0
  90. luckyd_code/tools/browser.py +369 -0
  91. luckyd_code/tools/datetime_tool.py +34 -0
  92. luckyd_code/tools/dockerfile_gen.py +212 -0
  93. luckyd_code/tools/file_ops.py +381 -0
  94. luckyd_code/tools/game_gen.py +360 -0
  95. luckyd_code/tools/git_tools.py +130 -0
  96. luckyd_code/tools/git_worktree.py +63 -0
  97. luckyd_code/tools/path_validate.py +64 -0
  98. luckyd_code/tools/project_gen.py +187 -0
  99. luckyd_code/tools/readme_gen.py +227 -0
  100. luckyd_code/tools/registry.py +157 -0
  101. luckyd_code/tools/shell_detect.py +109 -0
  102. luckyd_code/tools/web.py +89 -0
  103. luckyd_code/tools/youtube.py +187 -0
  104. luckyd_code/tools_bridge.py +144 -0
  105. luckyd_code/undo.py +126 -0
  106. luckyd_code/update.py +60 -0
  107. luckyd_code/verify.py +360 -0
  108. luckyd_code/web_app.py +176 -0
  109. luckyd_code/web_routes/__init__.py +23 -0
  110. luckyd_code/web_routes/background.py +73 -0
  111. luckyd_code/web_routes/brain.py +109 -0
  112. luckyd_code/web_routes/cost.py +12 -0
  113. luckyd_code/web_routes/files.py +133 -0
  114. luckyd_code/web_routes/memories.py +94 -0
  115. luckyd_code/web_routes/misc.py +67 -0
  116. luckyd_code/web_routes/project.py +48 -0
  117. luckyd_code/web_routes/review.py +20 -0
  118. luckyd_code/web_routes/sessions.py +44 -0
  119. luckyd_code/web_routes/settings.py +43 -0
  120. luckyd_code/web_routes/static.py +70 -0
  121. luckyd_code/web_routes/update.py +19 -0
  122. luckyd_code/web_routes/ws.py +237 -0
  123. luckyd_code-1.2.2.dist-info/METADATA +297 -0
  124. luckyd_code-1.2.2.dist-info/RECORD +127 -0
  125. luckyd_code-1.2.2.dist-info/WHEEL +4 -0
  126. luckyd_code-1.2.2.dist-info/entry_points.txt +3 -0
  127. luckyd_code-1.2.2.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,2 @@
1
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.2/marked.min.js"></script>
2
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
@@ -0,0 +1,474 @@
1
+ /* === Auto-generated by build_html.py v202604281724 === */
2
+ /* === Auto-generated by build_html.py v202604281723 === */
3
+ /* === Auto-generated by build_html.py v202604281723 === */
4
+ :root {
5
+ --bg: #1a1a2e;
6
+ --surface: #16213e;
7
+ --surface2: #1f2b47;
8
+ --border: #2a3a5e;
9
+ --text: #e0e0e0;
10
+ --text-dim: #8892b0;
11
+ --accent: #4fc3f7;
12
+ --accent2: #81c784;
13
+ --accent3: #ffb74d;
14
+ --danger: #ef5350;
15
+ --msg-user: #1e3a5f;
16
+ --msg-assistant: #1a1a2e;
17
+ --sidebar-w: 280px;
18
+ --header-h: 52px;
19
+ --radius: 8px;
20
+ }
21
+
22
+ /* Light theme overrides */
23
+ .light {
24
+ --bg: #f5f5f5;
25
+ --surface: #ffffff;
26
+ --surface2: #e8e8e8;
27
+ --border: #d0d0d0;
28
+ --text: #1a1a2e;
29
+ --text-dim: #666;
30
+ --accent: #1976d2;
31
+ --accent2: #388e3c;
32
+ --accent3: #f57c00;
33
+ --danger: #d32f2f;
34
+ --msg-user: #e3f2fd;
35
+ --msg-assistant: #ffffff;
36
+ }
37
+
38
+ * { margin: 0; padding: 0; box-sizing: border-box; }
39
+
40
+ body {
41
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
42
+ background: var(--bg);
43
+ color: var(--text);
44
+ height: 100vh;
45
+ overflow: hidden;
46
+ }
47
+
48
+ /* Layout */
49
+ .app { display: flex; height: 100vh; }
50
+
51
+ /* Sidebar */
52
+ .sidebar {
53
+ width: var(--sidebar-w);
54
+ background: var(--surface);
55
+ border-right: 1px solid var(--border);
56
+ display: flex;
57
+ flex-direction: column;
58
+ flex-shrink: 0;
59
+ transition: transform .3s;
60
+ }
61
+ .sidebar-header {
62
+ padding: 14px 16px;
63
+ border-bottom: 1px solid var(--border);
64
+ font-weight: 600;
65
+ font-size: 14px;
66
+ color: var(--text-dim);
67
+ display: flex;
68
+ justify-content: space-between;
69
+ align-items: center;
70
+ }
71
+ .sidebar-header button {
72
+ background: none; border: none; color: var(--text-dim); cursor: pointer; font-size: 14px;
73
+ }
74
+ .sidebar-content {
75
+ flex: 1;
76
+ overflow-y: auto;
77
+ padding: 8px;
78
+ }
79
+ .file-item {
80
+ display: flex;
81
+ align-items: center;
82
+ gap: 8px;
83
+ padding: 6px 10px;
84
+ border-radius: 4px;
85
+ cursor: pointer;
86
+ font-size: 13px;
87
+ color: var(--text-dim);
88
+ transition: background .15s;
89
+ }
90
+ .file-item:hover { background: var(--surface2); color: var(--text); }
91
+ .file-item .icon { font-size: 14px; }
92
+ .file-item.dir { color: var(--accent); }
93
+ .file-path { padding: 6px 10px; font-size: 11px; color: var(--text-dim); border-top: 1px solid var(--border); word-break: break-all; }
94
+
95
+ .sidebar-toggle {
96
+ display: none;
97
+ background: none;
98
+ border: none;
99
+ color: var(--text);
100
+ font-size: 20px;
101
+ cursor: pointer;
102
+ padding: 8px;
103
+ }
104
+
105
+ /* Main area */
106
+ .main {
107
+ flex: 1;
108
+ display: flex;
109
+ flex-direction: column;
110
+ min-width: 0;
111
+ }
112
+
113
+ /* Header */
114
+ .header {
115
+ height: var(--header-h);
116
+ display: flex;
117
+ align-items: center;
118
+ padding: 0 16px;
119
+ border-bottom: 1px solid var(--border);
120
+ gap: 12px;
121
+ flex-shrink: 0;
122
+ }
123
+ .header h1 {
124
+ font-size: 16px;
125
+ font-weight: 600;
126
+ }
127
+ .header .model-badge {
128
+ font-size: 11px;
129
+ color: var(--accent);
130
+ background: rgba(79,195,247,.15);
131
+ padding: 2px 8px;
132
+ border-radius: 10px;
133
+ }
134
+ .header-actions {
135
+ margin-left: auto;
136
+ display: flex;
137
+ gap: 8px;
138
+ }
139
+ .header-actions button {
140
+ background: none; border: none; color: var(--text-dim); cursor: pointer;
141
+ padding: 4px 8px; border-radius: 4px; font-size: 13px;
142
+ }
143
+ .header-actions button:hover { background: var(--surface2); color: var(--text); }
144
+
145
+ /* Messages */
146
+ .messages {
147
+ flex: 1;
148
+ overflow-y: auto;
149
+ padding: 16px;
150
+ display: flex;
151
+ flex-direction: column;
152
+ gap: 12px;
153
+ }
154
+ .message {
155
+ max-width: 85%;
156
+ padding: 12px 16px;
157
+ border-radius: var(--radius);
158
+ line-height: 1.5;
159
+ font-size: 14px;
160
+ animation: fadeIn .2s;
161
+ }
162
+ @keyframes fadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }
163
+
164
+ .message.user {
165
+ align-self: flex-end;
166
+ background: var(--msg-user);
167
+ border-bottom-right-radius: 2px;
168
+ }
169
+ .message.assistant {
170
+ align-self: flex-start;
171
+ background: var(--msg-assistant);
172
+ border: 1px solid var(--border);
173
+ border-bottom-left-radius: 2px;
174
+ }
175
+ .message.tool-call {
176
+ align-self: flex-start;
177
+ background: rgba(255,183,77,.08);
178
+ border: 1px solid rgba(255,183,77,.2);
179
+ font-size: 13px;
180
+ color: var(--accent3);
181
+ width: 100%;
182
+ max-width: 100%;
183
+ }
184
+ .message.tool-call .tool-name { font-weight: 600; }
185
+ .message.tool-call .tool-result { color: var(--text-dim); margin-top: 4px; font-family: monospace; font-size: 12px; }
186
+ .message.error {
187
+ align-self: center;
188
+ background: rgba(239,83,80,.1);
189
+ border: 1px solid rgba(239,83,80,.3);
190
+ color: var(--danger);
191
+ font-size: 13px;
192
+ }
193
+
194
+ /* Message content markdown */
195
+ .message p { margin-bottom: 8px; }
196
+ .message p:last-child { margin-bottom: 0; }
197
+ .message ul, .message ol { margin: 4px 0 8px 20px; }
198
+ .message li { margin-bottom: 2px; }
199
+ .message code {
200
+ background: rgba(255,255,255,.08);
201
+ padding: 2px 6px;
202
+ border-radius: 3px;
203
+ font-size: 13px;
204
+ font-family: 'JetBrains Mono', 'Fira Code', monospace;
205
+ }
206
+ .message pre {
207
+ margin: 8px 0;
208
+ border-radius: 6px;
209
+ overflow-x: auto;
210
+ }
211
+ .message pre code {
212
+ background: none;
213
+ padding: 0;
214
+ font-size: 13px;
215
+ }
216
+ .message h1, .message h2, .message h3, .message h4 {
217
+ margin: 12px 0 6px;
218
+ color: var(--accent);
219
+ }
220
+ .message h1 { font-size: 18px; }
221
+ .message h2 { font-size: 16px; }
222
+ .message h3 { font-size: 15px; }
223
+ .message blockquote {
224
+ border-left: 3px solid var(--accent);
225
+ padding-left: 12px;
226
+ color: var(--text-dim);
227
+ margin: 8px 0;
228
+ }
229
+ .message table {
230
+ border-collapse: collapse;
231
+ margin: 8px 0;
232
+ font-size: 13px;
233
+ }
234
+ .message th, .message td {
235
+ border: 1px solid var(--border);
236
+ padding: 6px 10px;
237
+ text-align: left;
238
+ }
239
+ .message th { background: var(--surface2); }
240
+
241
+ /* Typing indicator */
242
+ .typing {
243
+ align-self: flex-start;
244
+ display: flex;
245
+ gap: 4px;
246
+ padding: 12px 16px;
247
+ background: var(--msg-assistant);
248
+ border: 1px solid var(--border);
249
+ border-radius: var(--radius);
250
+ }
251
+ .typing span {
252
+ width: 8px; height: 8px; border-radius: 50%;
253
+ background: var(--text-dim);
254
+ animation: typingDot 1.4s infinite;
255
+ }
256
+ .typing span:nth-child(2) { animation-delay: .2s; }
257
+ .typing span:nth-child(3) { animation-delay: .4s; }
258
+ @keyframes typingDot { 0%,60%,100% { opacity: .3; transform: scale(1); } 30% { opacity: 1; transform: scale(1.2); } }
259
+
260
+ /* Input area */
261
+ .input-area {
262
+ padding: 12px 16px;
263
+ border-top: 1px solid var(--border);
264
+ background: var(--surface);
265
+ flex-shrink: 0;
266
+ }
267
+ .input-row {
268
+ display: flex;
269
+ gap: 8px;
270
+ align-items: flex-end;
271
+ }
272
+ .input-row textarea {
273
+ flex: 1;
274
+ background: var(--surface2);
275
+ border: 1px solid var(--border);
276
+ border-radius: var(--radius);
277
+ color: var(--text);
278
+ padding: 10px 14px;
279
+ font-size: 14px;
280
+ font-family: inherit;
281
+ resize: none;
282
+ outline: none;
283
+ min-height: 42px;
284
+ max-height: 150px;
285
+ line-height: 1.4;
286
+ }
287
+ .input-row textarea:focus { border-color: var(--accent); }
288
+ .input-row textarea::placeholder { color: var(--text-dim); }
289
+
290
+ .input-row button {
291
+ background: var(--accent);
292
+ border: none;
293
+ color: #0d1117;
294
+ width: 42px;
295
+ height: 42px;
296
+ border-radius: 50%;
297
+ cursor: pointer;
298
+ font-size: 18px;
299
+ display: flex;
300
+ align-items: center;
301
+ justify-content: center;
302
+ transition: background .15s, opacity .15s;
303
+ flex-shrink: 0;
304
+ }
305
+ .input-row button:hover { background: #39b0e8; }
306
+ .input-row button:disabled { opacity: .4; cursor: not-allowed; }
307
+ .input-row button.voice { background: var(--surface2); color: var(--text); }
308
+ .input-row button.voice:hover { background: var(--border); }
309
+ .input-row button.voice.listening { background: var(--danger); color: white; animation: pulse 1s infinite; }
310
+ @keyframes pulse { 0%,100% { box-shadow: 0 0 0 0 rgba(239,83,80,.4); } 50% { box-shadow: 0 0 0 8px rgba(239,83,80,0); } }
311
+
312
+ .input-hint {
313
+ font-size: 11px;
314
+ color: var(--text-dim);
315
+ margin-top: 6px;
316
+ text-align: center;
317
+ }
318
+ .input-hint kbd {
319
+ background: var(--surface2);
320
+ padding: 1px 5px;
321
+ border-radius: 3px;
322
+ font-size: 10px;
323
+ font-family: inherit;
324
+ border: 1px solid var(--border);
325
+ }
326
+
327
+ /* Scrollbar */
328
+ ::-webkit-scrollbar { width: 6px; }
329
+ ::-webkit-scrollbar-track { background: transparent; }
330
+ ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
331
+ ::-webkit-scrollbar-thumb:hover { background: var(--text-dim); }
332
+
333
+ /* Mobile responsive */
334
+ @media (max-width: 768px) {
335
+ .sidebar {
336
+ position: fixed;
337
+ left: 0;
338
+ top: 0;
339
+ bottom: 0;
340
+ z-index: 100;
341
+ transform: translateX(-100%);
342
+ }
343
+ .sidebar.open { transform: translateX(0); }
344
+ .sidebar-toggle { display: block; }
345
+ .message { max-width: 95%; }
346
+ .overlay {
347
+ display: none;
348
+ position: fixed;
349
+ inset: 0;
350
+ background: rgba(0,0,0,.5);
351
+ z-index: 99;
352
+ }
353
+ .overlay.show { display: block; }
354
+ }
355
+
356
+ /* Copy button for code blocks */
357
+ .copy-btn {
358
+ position: absolute;
359
+ top: 6px;
360
+ right: 6px;
361
+ background: rgba(255,255,255,.1);
362
+ border: 1px solid var(--border);
363
+ color: var(--text-dim);
364
+ padding: 4px 8px;
365
+ border-radius: 4px;
366
+ cursor: pointer;
367
+ font-size: 12px;
368
+ opacity: 0;
369
+ transition: opacity .2s;
370
+ }
371
+ pre:hover .copy-btn { opacity: 1; }
372
+ .copy-btn:hover { background: rgba(255,255,255,.2); color: var(--text); }
373
+
374
+ /* File editor */
375
+ .editor-overlay {
376
+ display: none;
377
+ position: fixed;
378
+ inset: 0;
379
+ background: rgba(0,0,0,.6);
380
+ z-index: 200;
381
+ align-items: center;
382
+ justify-content: center;
383
+ padding: 20px;
384
+ }
385
+ .editor-overlay.show { display: flex; }
386
+ .editor-panel {
387
+ background: var(--surface);
388
+ border: 1px solid var(--border);
389
+ border-radius: var(--radius);
390
+ width: 100%;
391
+ max-width: 800px;
392
+ max-height: 85vh;
393
+ display: flex;
394
+ flex-direction: column;
395
+ box-shadow: 0 8px 32px rgba(0,0,0,.4);
396
+ }
397
+ .editor-header {
398
+ display: flex;
399
+ align-items: center;
400
+ justify-content: space-between;
401
+ padding: 12px 16px;
402
+ border-bottom: 1px solid var(--border);
403
+ }
404
+ .editor-header h3 { font-size: 14px; font-weight: 600; word-break: break-all; }
405
+ .editor-actions { display: flex; gap: 6px; }
406
+ .editor-actions button {
407
+ background: var(--surface2);
408
+ border: 1px solid var(--border);
409
+ color: var(--text);
410
+ padding: 6px 14px;
411
+ border-radius: 4px;
412
+ cursor: pointer;
413
+ font-size: 13px;
414
+ transition: background .15s;
415
+ }
416
+ .editor-actions button:hover { background: var(--border); }
417
+ .editor-actions button.save {
418
+ background: var(--accent);
419
+ color: #0d1117;
420
+ border-color: var(--accent);
421
+ font-weight: 600;
422
+ }
423
+ .editor-actions button.save:hover { opacity: .85; }
424
+ .editor-actions button.save:disabled { opacity: .4; cursor: not-allowed; }
425
+ .editor-body {
426
+ flex: 1;
427
+ overflow-y: auto;
428
+ padding: 0;
429
+ }
430
+ .editor-body textarea {
431
+ width: 100%;
432
+ min-height: 300px;
433
+ max-height: 65vh;
434
+ border: none;
435
+ background: var(--bg);
436
+ color: var(--text);
437
+ font-family: 'JetBrains Mono', 'Fira Code', monospace;
438
+ font-size: 13px;
439
+ line-height: 1.5;
440
+ padding: 16px;
441
+ resize: vertical;
442
+ outline: none;
443
+ tab-size: 2;
444
+ }
445
+ .editor-body .readonly-view {
446
+ padding: 16px;
447
+ font-family: 'JetBrains Mono', 'Fira Code', monospace;
448
+ font-size: 13px;
449
+ line-height: 1.5;
450
+ white-space: pre-wrap;
451
+ overflow-x: auto;
452
+ color: var(--text);
453
+ }
454
+ .editor-footer {
455
+ padding: 10px 16px;
456
+ border-top: 1px solid var(--border);
457
+ font-size: 12px;
458
+ color: var(--text-dim);
459
+ display: flex;
460
+ justify-content: space-between;
461
+ }
462
+ .editor-footer .modified { color: var(--accent3); }
463
+
464
+ /* Connection status */
465
+ .status-dot {
466
+ width: 8px;
467
+ height: 8px;
468
+ border-radius: 50%;
469
+ display: inline-block;
470
+ margin-right: 6px;
471
+ }
472
+ .status-dot.connected { background: var(--accent2); }
473
+ .status-dot.disconnected { background: var(--danger); }
474
+ .status-dot.connecting { background: var(--accent3); }
@@ -0,0 +1,31 @@
1
+ // DeepSeek Code Service Worker
2
+ const CACHE = 'ds-code-v1.1.0';
3
+
4
+ self.addEventListener('install', function(e) {
5
+ e.waitUntil(
6
+ caches.open(CACHE).then(function(cache) {
7
+ return cache.addAll([
8
+ '/',
9
+ ]);
10
+ })
11
+ );
12
+ });
13
+
14
+ self.addEventListener('fetch', function(e) {
15
+ // Network-first for API, cache-first for static
16
+ if (e.request.url.includes('/api/')) {
17
+ e.respondWith(
18
+ fetch(e.request).catch(function() {
19
+ return new Response(JSON.stringify({error: 'offline'}), {
20
+ status: 503, headers: {'Content-Type': 'application/json'}
21
+ });
22
+ })
23
+ );
24
+ } else {
25
+ e.respondWith(
26
+ caches.match(e.request).then(function(r) {
27
+ return r || fetch(e.request);
28
+ })
29
+ );
30
+ }
31
+ });
@@ -0,0 +1,6 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <body>
4
+ <h1>Test</h1>
5
+ </body>
6
+ </html>
luckyd_code/themes.py ADDED
@@ -0,0 +1,48 @@
1
+ """Theme support for DeepSeek Code."""
2
+
3
+ from rich.theme import Theme
4
+
5
+ DARK_THEME = Theme({
6
+ "info": "cyan",
7
+ "warning": "yellow",
8
+ "error": "bold red",
9
+ "success": "green",
10
+ "dim": "dim white",
11
+ "code": "green",
12
+ "title": "bold cyan",
13
+ "subtitle": "dim white",
14
+ "tool": "bold green",
15
+ "tool_result": "yellow",
16
+ "prompt": "bold",
17
+ "hl": "bold cyan",
18
+ "path": "underline blue",
19
+ "number": "bold yellow",
20
+ "keyword": "bold magenta",
21
+ })
22
+
23
+ LIGHT_THEME = Theme({
24
+ "info": "blue",
25
+ "warning": "orange3",
26
+ "error": "bold red",
27
+ "success": "green",
28
+ "dim": "grey58",
29
+ "code": "green",
30
+ "title": "bold blue",
31
+ "subtitle": "grey58",
32
+ "tool": "bold green",
33
+ "tool_result": "orange3",
34
+ "prompt": "bold",
35
+ "hl": "bold blue",
36
+ "path": "underline blue",
37
+ "number": "bold orange3",
38
+ "keyword": "bold magenta",
39
+ })
40
+
41
+ THEMES = {
42
+ "dark": DARK_THEME,
43
+ "light": LIGHT_THEME,
44
+ }
45
+
46
+
47
+ def get_theme(name: str = "dark") -> Theme:
48
+ return THEMES.get(name, DARK_THEME)
@@ -0,0 +1,97 @@
1
+ from .registry import ToolRegistry, Tool
2
+ from .file_ops import ReadTool, WriteTool, EditTool, GlobTool, GrepTool
3
+ from .bash import BashTool
4
+ from .datetime_tool import DateTimeTool
5
+ from .web import WebFetchTool, WebSearchTool
6
+ from .browser import (
7
+ BrowserNavigateTool, BrowserClickTool, BrowserTypeTool,
8
+ BrowserSnapshotTool, BrowserScreenshotTool,
9
+ BrowserEvaluateTool, BrowserCloseTool, OpenInBrowserTool,
10
+ )
11
+ from .git_tools import (
12
+ GitStatusTool, GitDiffTool, GitLogTool,
13
+ GitCommitTool, GitAddTool, GitBranchTool,
14
+ GitPRTool, GitPushTool,
15
+ )
16
+ from .git_worktree import GitWorktreeTool
17
+ from .agent_tools import SubAgentTool, AgentHandoffTool
18
+ from .brain_tools import BrainSearchTool, BrainStatusTool
19
+ from .youtube import YouTubePlaylistTool
20
+ from .game_gen import GameGenTool
21
+ from .project_gen import ProjectGenTool
22
+ from .readme_gen import ReadmeGenTool
23
+ from .dockerfile_gen import DockerfileGenTool
24
+
25
+ __all__ = [
26
+ "ToolRegistry", "Tool",
27
+ "ReadTool", "WriteTool", "EditTool", "GlobTool", "GrepTool",
28
+ "BashTool", "DateTimeTool",
29
+ "WebFetchTool", "WebSearchTool",
30
+ "BrowserNavigateTool", "BrowserClickTool", "BrowserTypeTool",
31
+ "BrowserSnapshotTool", "BrowserScreenshotTool",
32
+ "BrowserEvaluateTool", "BrowserCloseTool", "OpenInBrowserTool",
33
+ "GitStatusTool", "GitDiffTool", "GitLogTool",
34
+ "GitCommitTool", "GitAddTool", "GitBranchTool",
35
+ "GitPRTool", "GitPushTool",
36
+ "GitWorktreeTool",
37
+ "SubAgentTool", "AgentHandoffTool",
38
+ "BrainSearchTool", "BrainStatusTool",
39
+ "YouTubePlaylistTool",
40
+ "GameGenTool",
41
+ "ProjectGenTool",
42
+ "ReadmeGenTool",
43
+ "DockerfileGenTool",
44
+ "get_default_registry",
45
+ ]
46
+
47
+
48
+ def get_default_registry():
49
+ registry = ToolRegistry()
50
+ registry.register(ReadTool())
51
+ registry.register(WriteTool())
52
+ registry.register(EditTool())
53
+ registry.register(GlobTool())
54
+ registry.register(GrepTool())
55
+ registry.register(BashTool())
56
+ registry.register(DateTimeTool())
57
+ registry.register(WebFetchTool())
58
+ registry.register(WebSearchTool())
59
+ registry.register(GitStatusTool())
60
+ registry.register(GitDiffTool())
61
+ registry.register(GitLogTool())
62
+ registry.register(GitCommitTool())
63
+ registry.register(GitAddTool())
64
+ registry.register(GitBranchTool())
65
+ registry.register(GitPRTool())
66
+ registry.register(GitPushTool())
67
+ registry.register(GitWorktreeTool())
68
+ registry.register(SubAgentTool())
69
+ registry.register(AgentHandoffTool())
70
+ registry.register(BrainSearchTool())
71
+ registry.register(BrainStatusTool())
72
+ registry.register(BrowserNavigateTool())
73
+ registry.register(BrowserClickTool())
74
+ registry.register(BrowserTypeTool())
75
+ registry.register(BrowserSnapshotTool())
76
+ registry.register(BrowserScreenshotTool())
77
+ registry.register(BrowserEvaluateTool())
78
+ registry.register(BrowserCloseTool())
79
+ registry.register(OpenInBrowserTool())
80
+ registry.register(YouTubePlaylistTool())
81
+ registry.register(GameGenTool())
82
+ registry.register(ProjectGenTool())
83
+ registry.register(ReadmeGenTool())
84
+ registry.register(DockerfileGenTool())
85
+
86
+ # Load external plugins from ~/.claude/plugins/
87
+ try:
88
+ from ..plugins import load_all_plugins
89
+ n = load_all_plugins(registry)
90
+ if n:
91
+ logger = __import__("logging").getLogger("luckyd_code")
92
+ logger.info("Loaded %d plugin(s)", n)
93
+ except Exception:
94
+ logger = __import__("logging").getLogger("luckyd_code")
95
+ logger.warning("Failed to load plugins", exc_info=True)
96
+
97
+ return registry