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.
- luckyd_code/__init__.py +54 -0
- luckyd_code/__main__.py +5 -0
- luckyd_code/_agent_loop.py +551 -0
- luckyd_code/_data_dir.py +73 -0
- luckyd_code/agent.py +38 -0
- luckyd_code/analytics/__init__.py +18 -0
- luckyd_code/analytics/reporter.py +195 -0
- luckyd_code/analytics/scanner.py +443 -0
- luckyd_code/analytics/smells.py +316 -0
- luckyd_code/analytics/trends.py +303 -0
- luckyd_code/api.py +473 -0
- luckyd_code/audit_daemon.py +845 -0
- luckyd_code/autonomous_fixer.py +473 -0
- luckyd_code/background.py +159 -0
- luckyd_code/backup.py +237 -0
- luckyd_code/brain/__init__.py +84 -0
- luckyd_code/brain/assembler.py +100 -0
- luckyd_code/brain/chunker.py +345 -0
- luckyd_code/brain/constants.py +73 -0
- luckyd_code/brain/embedder.py +163 -0
- luckyd_code/brain/graph.py +311 -0
- luckyd_code/brain/indexer.py +316 -0
- luckyd_code/brain/parser.py +140 -0
- luckyd_code/brain/retriever.py +234 -0
- luckyd_code/cli.py +894 -0
- luckyd_code/cli_commands/__init__.py +1 -0
- luckyd_code/cli_commands/audit.py +120 -0
- luckyd_code/cli_commands/background.py +83 -0
- luckyd_code/cli_commands/brain.py +87 -0
- luckyd_code/cli_commands/config.py +75 -0
- luckyd_code/cli_commands/dispatcher.py +695 -0
- luckyd_code/cli_commands/sessions.py +41 -0
- luckyd_code/cli_entry.py +147 -0
- luckyd_code/cli_utils.py +112 -0
- luckyd_code/config.py +205 -0
- luckyd_code/context.py +214 -0
- luckyd_code/cost_tracker.py +209 -0
- luckyd_code/error_reporter.py +508 -0
- luckyd_code/exceptions.py +39 -0
- luckyd_code/export.py +126 -0
- luckyd_code/feedback_analyzer.py +290 -0
- luckyd_code/file_watcher.py +258 -0
- luckyd_code/git/__init__.py +11 -0
- luckyd_code/git/auto_commit.py +157 -0
- luckyd_code/git/tools.py +85 -0
- luckyd_code/hooks.py +236 -0
- luckyd_code/indexer.py +280 -0
- luckyd_code/init.py +39 -0
- luckyd_code/keybindings.py +77 -0
- luckyd_code/log.py +55 -0
- luckyd_code/mcp/__init__.py +6 -0
- luckyd_code/mcp/client.py +184 -0
- luckyd_code/memory/__init__.py +19 -0
- luckyd_code/memory/manager.py +339 -0
- luckyd_code/metrics/__init__.py +5 -0
- luckyd_code/model_registry.py +131 -0
- luckyd_code/orchestrator.py +204 -0
- luckyd_code/permissions/__init__.py +1 -0
- luckyd_code/permissions/manager.py +103 -0
- luckyd_code/planner.py +361 -0
- luckyd_code/plugins.py +91 -0
- luckyd_code/py.typed +0 -0
- luckyd_code/retry.py +57 -0
- luckyd_code/router.py +417 -0
- luckyd_code/sandbox.py +156 -0
- luckyd_code/self_critique.py +2 -0
- luckyd_code/self_improve.py +274 -0
- luckyd_code/sessions.py +114 -0
- luckyd_code/settings.py +72 -0
- luckyd_code/skills/__init__.py +8 -0
- luckyd_code/skills/review.py +22 -0
- luckyd_code/skills/security.py +17 -0
- luckyd_code/tasks/__init__.py +1 -0
- luckyd_code/tasks/manager.py +102 -0
- luckyd_code/templates/icon-192.png +0 -0
- luckyd_code/templates/icon-512.png +0 -0
- luckyd_code/templates/index.html +1965 -0
- luckyd_code/templates/manifest.json +14 -0
- luckyd_code/templates/src/app.js +694 -0
- luckyd_code/templates/src/body.html +767 -0
- luckyd_code/templates/src/cdn.txt +2 -0
- luckyd_code/templates/src/style.css +474 -0
- luckyd_code/templates/sw.js +31 -0
- luckyd_code/templates/test.html +6 -0
- luckyd_code/themes.py +48 -0
- luckyd_code/tools/__init__.py +97 -0
- luckyd_code/tools/agent_tools.py +65 -0
- luckyd_code/tools/bash.py +360 -0
- luckyd_code/tools/brain_tools.py +137 -0
- luckyd_code/tools/browser.py +369 -0
- luckyd_code/tools/datetime_tool.py +34 -0
- luckyd_code/tools/dockerfile_gen.py +212 -0
- luckyd_code/tools/file_ops.py +381 -0
- luckyd_code/tools/game_gen.py +360 -0
- luckyd_code/tools/git_tools.py +130 -0
- luckyd_code/tools/git_worktree.py +63 -0
- luckyd_code/tools/path_validate.py +64 -0
- luckyd_code/tools/project_gen.py +187 -0
- luckyd_code/tools/readme_gen.py +227 -0
- luckyd_code/tools/registry.py +157 -0
- luckyd_code/tools/shell_detect.py +109 -0
- luckyd_code/tools/web.py +89 -0
- luckyd_code/tools/youtube.py +187 -0
- luckyd_code/tools_bridge.py +144 -0
- luckyd_code/undo.py +126 -0
- luckyd_code/update.py +60 -0
- luckyd_code/verify.py +360 -0
- luckyd_code/web_app.py +176 -0
- luckyd_code/web_routes/__init__.py +23 -0
- luckyd_code/web_routes/background.py +73 -0
- luckyd_code/web_routes/brain.py +109 -0
- luckyd_code/web_routes/cost.py +12 -0
- luckyd_code/web_routes/files.py +133 -0
- luckyd_code/web_routes/memories.py +94 -0
- luckyd_code/web_routes/misc.py +67 -0
- luckyd_code/web_routes/project.py +48 -0
- luckyd_code/web_routes/review.py +20 -0
- luckyd_code/web_routes/sessions.py +44 -0
- luckyd_code/web_routes/settings.py +43 -0
- luckyd_code/web_routes/static.py +70 -0
- luckyd_code/web_routes/update.py +19 -0
- luckyd_code/web_routes/ws.py +237 -0
- luckyd_code-1.2.2.dist-info/METADATA +297 -0
- luckyd_code-1.2.2.dist-info/RECORD +127 -0
- luckyd_code-1.2.2.dist-info/WHEEL +4 -0
- luckyd_code-1.2.2.dist-info/entry_points.txt +3 -0
- luckyd_code-1.2.2.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"""WebSocket chat handler with tool execution, model fallback, and streaming."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import json
|
|
5
|
+
|
|
6
|
+
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
|
|
7
|
+
|
|
8
|
+
from ..api import _repair_json
|
|
9
|
+
from ..log import get_logger
|
|
10
|
+
|
|
11
|
+
logger = get_logger()
|
|
12
|
+
router = APIRouter()
|
|
13
|
+
|
|
14
|
+
MAX_MESSAGE_LENGTH = 10000
|
|
15
|
+
MAX_TOOL_LOOPS = 100
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@router.websocket("/ws")
|
|
19
|
+
async def websocket_endpoint(ws: WebSocket):
|
|
20
|
+
await ws.accept()
|
|
21
|
+
from ..web_app import stream_chat
|
|
22
|
+
|
|
23
|
+
state = ws.app.state.web_state
|
|
24
|
+
config = state.config
|
|
25
|
+
context = state.context
|
|
26
|
+
registry = state.registry
|
|
27
|
+
mcp = state.mcp
|
|
28
|
+
memory_module = state.memory_module
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
while True:
|
|
32
|
+
data = await asyncio.wait_for(ws.receive_text(), timeout=300.0)
|
|
33
|
+
msg = json.loads(data)
|
|
34
|
+
msg_type = msg.get("type", "message")
|
|
35
|
+
|
|
36
|
+
if msg_type == "message":
|
|
37
|
+
user_text = msg.get("content", "").strip()
|
|
38
|
+
if not user_text:
|
|
39
|
+
continue
|
|
40
|
+
|
|
41
|
+
if len(user_text) > MAX_MESSAGE_LENGTH:
|
|
42
|
+
await ws.send_json({
|
|
43
|
+
"type": "error",
|
|
44
|
+
"content": f"Message too long (max {MAX_MESSAGE_LENGTH} characters)",
|
|
45
|
+
})
|
|
46
|
+
continue
|
|
47
|
+
|
|
48
|
+
context.add_user_message(user_text)
|
|
49
|
+
|
|
50
|
+
text_buffer = ""
|
|
51
|
+
pending_tool_calls = None
|
|
52
|
+
tool_loop_count = 0
|
|
53
|
+
tool_call_count = 0
|
|
54
|
+
active_model = config.model
|
|
55
|
+
current_tier = 2
|
|
56
|
+
|
|
57
|
+
from .. import settings as cfg
|
|
58
|
+
web_settings = cfg.load_settings()
|
|
59
|
+
auto_route = web_settings.get("auto_route", True)
|
|
60
|
+
from ..router import resolve_initial_route, escalate_tier
|
|
61
|
+
routing = resolve_initial_route(
|
|
62
|
+
user_text, 0, config.provider, config.model, auto_route,
|
|
63
|
+
)
|
|
64
|
+
if routing.tier_changed:
|
|
65
|
+
active_model = routing.model
|
|
66
|
+
await ws.send_json({
|
|
67
|
+
"type": "text",
|
|
68
|
+
"content": f"[Routing: {routing.tier_description} → {active_model}]\n\n",
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
all_tools = registry.list_tools()
|
|
72
|
+
all_tools.extend(mcp.get_all_tools())
|
|
73
|
+
|
|
74
|
+
while tool_loop_count < MAX_TOOL_LOOPS:
|
|
75
|
+
messages = context.get_messages()
|
|
76
|
+
text_buffer = ""
|
|
77
|
+
pending_tool_calls = None
|
|
78
|
+
tool_reasoning = ""
|
|
79
|
+
|
|
80
|
+
if auto_route:
|
|
81
|
+
escalation = escalate_tier(
|
|
82
|
+
user_text, tool_call_count, config.provider,
|
|
83
|
+
config.model, active_model, current_tier, auto_route,
|
|
84
|
+
)
|
|
85
|
+
if escalation.tier_changed:
|
|
86
|
+
active_model = escalation.model
|
|
87
|
+
current_tier = escalation.tier
|
|
88
|
+
await ws.send_json({
|
|
89
|
+
"type": "text",
|
|
90
|
+
"content": f"[Escalating: {escalation.tier_description} → {active_model}]\n\n",
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
for event_type, evt_data in stream_chat(
|
|
94
|
+
messages=messages,
|
|
95
|
+
tools=all_tools,
|
|
96
|
+
model=active_model,
|
|
97
|
+
api_key=config.api_key,
|
|
98
|
+
base_url=config.base_url,
|
|
99
|
+
max_tokens=config.max_tokens,
|
|
100
|
+
temperature=config.temperature,
|
|
101
|
+
):
|
|
102
|
+
if event_type == "text":
|
|
103
|
+
text_buffer += evt_data
|
|
104
|
+
await ws.send_json({
|
|
105
|
+
"type": "text",
|
|
106
|
+
"content": evt_data,
|
|
107
|
+
})
|
|
108
|
+
elif event_type == "tool_calls":
|
|
109
|
+
pending_tool_calls, tool_reasoning = evt_data
|
|
110
|
+
elif event_type == "model_not_found":
|
|
111
|
+
await ws.send_json({
|
|
112
|
+
"type": "error",
|
|
113
|
+
"content": f"Model not found: {evt_data[:300]}",
|
|
114
|
+
})
|
|
115
|
+
break
|
|
116
|
+
elif event_type == "error":
|
|
117
|
+
await ws.send_json({
|
|
118
|
+
"type": "error",
|
|
119
|
+
"content": f"API error: {evt_data[:500]}",
|
|
120
|
+
})
|
|
121
|
+
break
|
|
122
|
+
elif event_type == "done":
|
|
123
|
+
content, reasoning = evt_data
|
|
124
|
+
if reasoning:
|
|
125
|
+
context.add_assistant_message(content=content or text_buffer, reasoning_content=reasoning)
|
|
126
|
+
elif content or text_buffer:
|
|
127
|
+
context.add_assistant_message(content=content or text_buffer)
|
|
128
|
+
text_buffer = ""
|
|
129
|
+
|
|
130
|
+
if pending_tool_calls:
|
|
131
|
+
context.add_assistant_message(
|
|
132
|
+
text_buffer or None,
|
|
133
|
+
tool_calls=pending_tool_calls,
|
|
134
|
+
reasoning_content=tool_reasoning or None,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
for tc in pending_tool_calls:
|
|
138
|
+
name = tc["function"]["name"]
|
|
139
|
+
raw_args = tc["function"]["arguments"]
|
|
140
|
+
try:
|
|
141
|
+
args = json.loads(_repair_json(raw_args)) if raw_args else {}
|
|
142
|
+
except json.JSONDecodeError:
|
|
143
|
+
await ws.send_json({
|
|
144
|
+
"type": "tool",
|
|
145
|
+
"name": name,
|
|
146
|
+
"content": f"Invalid JSON arguments: {raw_args[:200]}",
|
|
147
|
+
})
|
|
148
|
+
context.add_tool_result(
|
|
149
|
+
tool_call_id=tc["id"], tool_name=name,
|
|
150
|
+
result=f"Error: invalid JSON in tool arguments: {raw_args[:200]}",
|
|
151
|
+
)
|
|
152
|
+
continue
|
|
153
|
+
|
|
154
|
+
await ws.send_json({
|
|
155
|
+
"type": "tool",
|
|
156
|
+
"name": name,
|
|
157
|
+
"content": f"Running {name}...",
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
try:
|
|
161
|
+
if name.startswith("mcp_"):
|
|
162
|
+
result = mcp.execute(name, args)
|
|
163
|
+
else:
|
|
164
|
+
result = registry.execute(name, args)
|
|
165
|
+
except Exception as e:
|
|
166
|
+
result = f"Error executing {name}: {e}"
|
|
167
|
+
|
|
168
|
+
result_preview = result[:300].replace("\n", " ")
|
|
169
|
+
if len(result) > 300:
|
|
170
|
+
result_preview += "..."
|
|
171
|
+
|
|
172
|
+
await ws.send_json({
|
|
173
|
+
"type": "tool_result",
|
|
174
|
+
"name": name,
|
|
175
|
+
"content": result_preview,
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
context.add_tool_result(
|
|
179
|
+
tool_call_id=tc["id"],
|
|
180
|
+
tool_name=name,
|
|
181
|
+
result=result,
|
|
182
|
+
)
|
|
183
|
+
tool_call_count += 1
|
|
184
|
+
|
|
185
|
+
tool_loop_count += 1
|
|
186
|
+
continue
|
|
187
|
+
|
|
188
|
+
if text_buffer:
|
|
189
|
+
context.add_assistant_message(content=text_buffer)
|
|
190
|
+
await ws.send_json({"type": "done"})
|
|
191
|
+
break
|
|
192
|
+
|
|
193
|
+
if tool_loop_count >= MAX_TOOL_LOOPS:
|
|
194
|
+
await ws.send_json({
|
|
195
|
+
"type": "error",
|
|
196
|
+
"content": "Max tool loop iterations reached",
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
elif msg_type == "clear":
|
|
200
|
+
context.reset()
|
|
201
|
+
md = memory_module.load_claude_md()
|
|
202
|
+
session_memories = state.web_memory_mgr.get_all_memories_formatted()
|
|
203
|
+
if md and session_memories:
|
|
204
|
+
merged = md + "\n\n" + session_memories
|
|
205
|
+
elif session_memories:
|
|
206
|
+
merged = session_memories
|
|
207
|
+
else:
|
|
208
|
+
merged = md or ""
|
|
209
|
+
if merged:
|
|
210
|
+
context.messages.insert(1, {
|
|
211
|
+
"role": "user",
|
|
212
|
+
"content": f"<claude-md>{merged}</claude-md>",
|
|
213
|
+
})
|
|
214
|
+
await ws.send_json({"type": "cleared"})
|
|
215
|
+
|
|
216
|
+
except asyncio.TimeoutError:
|
|
217
|
+
try:
|
|
218
|
+
await ws.send_json({"type": "error", "content": "Request timed out (300s)"})
|
|
219
|
+
except Exception:
|
|
220
|
+
logger.warning("WebSocket send_json (timeout) failed", exc_info=True)
|
|
221
|
+
try:
|
|
222
|
+
await ws.close(code=1001)
|
|
223
|
+
except Exception:
|
|
224
|
+
logger.warning("WebSocket close failed", exc_info=True)
|
|
225
|
+
except WebSocketDisconnect:
|
|
226
|
+
pass
|
|
227
|
+
except json.JSONDecodeError:
|
|
228
|
+
try:
|
|
229
|
+
await ws.send_json({"type": "error", "content": "Invalid JSON"})
|
|
230
|
+
except Exception:
|
|
231
|
+
logger.warning("WebSocket send_json (invalid JSON) failed", exc_info=True)
|
|
232
|
+
except Exception as e:
|
|
233
|
+
logger.warning(f"WebSocket error: {e}")
|
|
234
|
+
try:
|
|
235
|
+
await ws.send_json({"type": "error", "content": f"Server error: {str(e)[:200]}"})
|
|
236
|
+
except Exception:
|
|
237
|
+
logger.warning("WebSocket send_json (error notification) failed", exc_info=True)
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: luckyd-code
|
|
3
|
+
Version: 1.2.2
|
|
4
|
+
Summary: LuckyD Code — AI coding assistant powered by DeepSeek
|
|
5
|
+
Project-URL: Homepage, https://github.com/Dylanchess0320/LuckyD-Code
|
|
6
|
+
Project-URL: BugTracker, https://github.com/Dylanchess0320/LuckyD-Code/issues
|
|
7
|
+
Author-email: Dylan Kaye <dylanchess0320@users.noreply.github.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: ai,assistant,cli,coding,luckyd
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development
|
|
20
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: aiofiles>=23.0
|
|
23
|
+
Requires-Dist: beautifulsoup4>=4.12.0
|
|
24
|
+
Requires-Dist: fastapi>=0.100.0
|
|
25
|
+
Requires-Dist: httpx>=0.25.0
|
|
26
|
+
Requires-Dist: nest-asyncio>=1.5.0
|
|
27
|
+
Requires-Dist: openai>=1.0.0
|
|
28
|
+
Requires-Dist: prompt-toolkit>=3.0.0
|
|
29
|
+
Requires-Dist: pyyaml>=6.0
|
|
30
|
+
Requires-Dist: rich>=13.0.0
|
|
31
|
+
Requires-Dist: tiktoken>=0.5.0
|
|
32
|
+
Requires-Dist: uvicorn>=0.23.0
|
|
33
|
+
Requires-Dist: websockets>=11.0
|
|
34
|
+
Provides-Extra: browser
|
|
35
|
+
Requires-Dist: playwright>=1.40.0; extra == 'browser'
|
|
36
|
+
Provides-Extra: dev
|
|
37
|
+
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
39
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
40
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
41
|
+
Requires-Dist: types-aiofiles; extra == 'dev'
|
|
42
|
+
Requires-Dist: types-beautifulsoup4; extra == 'dev'
|
|
43
|
+
Requires-Dist: types-pyyaml; extra == 'dev'
|
|
44
|
+
Provides-Extra: rag
|
|
45
|
+
Requires-Dist: numpy>=1.24.0; extra == 'rag'
|
|
46
|
+
Requires-Dist: sentence-transformers>=2.2.0; extra == 'rag'
|
|
47
|
+
Provides-Extra: rag-full
|
|
48
|
+
Requires-Dist: faiss-cpu>=1.7.0; extra == 'rag-full'
|
|
49
|
+
Requires-Dist: numpy>=1.24.0; extra == 'rag-full'
|
|
50
|
+
Requires-Dist: sentence-transformers>=2.2.0; extra == 'rag-full'
|
|
51
|
+
Requires-Dist: watchdog>=3.0.0; extra == 'rag-full'
|
|
52
|
+
Description-Content-Type: text/markdown
|
|
53
|
+
|
|
54
|
+
# LuckyD Code
|
|
55
|
+
|
|
56
|
+
[](https://github.com/Dylanchess0320/LuckyD-Code/actions/workflows/ci.yml)
|
|
57
|
+
[](https://www.python.org/)
|
|
58
|
+
[](LICENSE)
|
|
59
|
+
[](https://pypi.org/project/luckyd-code/)
|
|
60
|
+
|
|
61
|
+
A full-featured AI coding assistant for your terminal and browser, powered by the DeepSeek API. Features 35+ built-in tools, a semantic knowledge graph, Playwright browser automation, multi-agent orchestration, Docker sandboxing, and a live Web UI.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Features
|
|
66
|
+
|
|
67
|
+
- **AI Chat** — Conversational coding assistant with streaming responses and thinking/reasoning mode
|
|
68
|
+
- **Smart Model Routing** — Auto-classifies prompt complexity into 4 tiers, escalating from cheap/fast to powerful/reasoning models
|
|
69
|
+
- **Knowledge Graph** — Automatically indexes your codebase into a searchable vector graph; falls back to a keyword graph if vector dependencies aren't installed
|
|
70
|
+
- **Memory System** — Persistent memory across sessions with auto-save and relevance search
|
|
71
|
+
- **Cost Tracking** — Per-session and cumulative cost tracking across models
|
|
72
|
+
- **Web UI** — Browser-based interface with cost panel, memory management, and model routing info
|
|
73
|
+
- **35+ Built-in Tools** — File operations, search, code analysis, shell commands, and more
|
|
74
|
+
- **MCP Support** — Model Context Protocol for extending with custom tools
|
|
75
|
+
- **Plugin System** — Drop Python files into `~/.claude/plugins/` to register additional tools at runtime
|
|
76
|
+
- **Context Management** — Auto-compaction with summarization to stay within context windows
|
|
77
|
+
- **Background Agents** — Run tasks asynchronously while continuing to chat
|
|
78
|
+
- **Orchestrator** — Researcher → Coder → Reviewer pipeline for complex tasks
|
|
79
|
+
- **Hooks System** — Pre/post tool use, pre/post chat, and session lifecycle hooks
|
|
80
|
+
- **Sandboxing** — Docker-based secure command execution
|
|
81
|
+
- **Session Management** — Save and load conversations
|
|
82
|
+
- **Undo** — Revert file writes and edits
|
|
83
|
+
- **Export** — Export conversations to Markdown or HTML
|
|
84
|
+
- **Shell Detection** — Auto-detects Git Bash → WSL → cmd.exe on Windows; rewrites interactive commands so the correct shell is always used
|
|
85
|
+
- **Analytics** — Code health scoring, code smell detection, and trend tracking
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Prerequisites
|
|
90
|
+
|
|
91
|
+
- **Python 3.10+**
|
|
92
|
+
- **DeepSeek API key** — Get one free at [platform.deepseek.com/api_keys](https://platform.deepseek.com/api_keys)
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Quick Start — No setup required
|
|
97
|
+
|
|
98
|
+
**Windows** — double-click one of these:
|
|
99
|
+
- `Install and Run - Windows.bat` — CLI mode
|
|
100
|
+
- `Install and Run Web UI - Windows.bat` — browser UI
|
|
101
|
+
|
|
102
|
+
**Mac** — double-click `Install and Run - Mac.command`
|
|
103
|
+
*(first time: right-click → Open to bypass Gatekeeper)*
|
|
104
|
+
|
|
105
|
+
**Linux** — run in terminal:
|
|
106
|
+
```bash
|
|
107
|
+
chmod +x "Install and Run - Linux.sh"
|
|
108
|
+
"./Install and Run - Linux.sh"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The launcher automatically creates a virtual environment, installs dependencies, and prompts for your API key on first run.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Installation
|
|
116
|
+
|
|
117
|
+
### From PyPI
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
pip install luckyd-code
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### From source
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
git clone https://github.com/Dylanchess0320/LuckyD-Code
|
|
127
|
+
cd luckyd-code
|
|
128
|
+
python -m venv .venv
|
|
129
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
130
|
+
pip install -e .
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Optional dependencies
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# RAG support (semantic memory search)
|
|
137
|
+
pip install -e ".[rag]"
|
|
138
|
+
|
|
139
|
+
# Full RAG with FAISS vector search and file watching
|
|
140
|
+
pip install -e ".[rag-full]"
|
|
141
|
+
|
|
142
|
+
# Browser automation (Playwright)
|
|
143
|
+
pip install -e ".[browser]"
|
|
144
|
+
|
|
145
|
+
# Development dependencies
|
|
146
|
+
pip install -e ".[dev]"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Usage
|
|
152
|
+
|
|
153
|
+
### CLI mode
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
luckyd-code
|
|
157
|
+
# or
|
|
158
|
+
ldc
|
|
159
|
+
# or
|
|
160
|
+
python main.py
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Web UI mode
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
luckyd-code --web
|
|
167
|
+
# or
|
|
168
|
+
python main.py --web
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Then open `http://localhost:8000` in your browser.
|
|
172
|
+
|
|
173
|
+
### Commands
|
|
174
|
+
|
|
175
|
+
Once in the CLI, use slash commands:
|
|
176
|
+
|
|
177
|
+
| Command | Description |
|
|
178
|
+
|---------|-------------|
|
|
179
|
+
| `/help` | Show available commands |
|
|
180
|
+
| `/model` | Switch model or view current model |
|
|
181
|
+
| `/cost` | Show session cost |
|
|
182
|
+
| `/memory` | View or search memory |
|
|
183
|
+
| `/session` | Save, load, or list sessions |
|
|
184
|
+
| `/export` | Export conversation |
|
|
185
|
+
| `/undo` | Undo last file write/edit |
|
|
186
|
+
| `/orchestrate` | Run multi-agent pipeline |
|
|
187
|
+
| `/analytics` | Run code health analysis |
|
|
188
|
+
| `/clear` | Clear conversation |
|
|
189
|
+
| `/quit` | Exit |
|
|
190
|
+
|
|
191
|
+
### Environment variables
|
|
192
|
+
|
|
193
|
+
Copy `.env.example` to `.env` and set your API key:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
cp .env.example .env
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Then edit `.env`:
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
DEEPSEEK_API_KEY=sk-your-deepseek-key-here
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Built-in Tools
|
|
208
|
+
|
|
209
|
+
LuckyD Code includes 35+ tools for interacting with your codebase:
|
|
210
|
+
|
|
211
|
+
- **File operations**: Read, Write, Edit, Glob, Grep, Delete, Move, Copy
|
|
212
|
+
- **Code analysis**: Lint, TypeCheck, Complexity, Coverage
|
|
213
|
+
- **Search**: Semantic search, keyword search, file search
|
|
214
|
+
- **Shell**: Bash execution, PowerShell, Git operations
|
|
215
|
+
- **Web**: Playwright browser automation, HTTP requests
|
|
216
|
+
- **Knowledge**: Knowledge graph query, memory search
|
|
217
|
+
- **Project**: Project scan, dependency analysis, code smell detection
|
|
218
|
+
- **Utility**: Undo, Export, Session management
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Project Structure
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
luckyd_code/
|
|
226
|
+
├── cli.py # Terminal UI and REPL
|
|
227
|
+
├── cli_commands/ # Slash-command handlers
|
|
228
|
+
├── web_app.py # Web UI server (FastAPI)
|
|
229
|
+
├── web_routes/ # Web UI route handlers
|
|
230
|
+
├── api.py # API streaming client
|
|
231
|
+
├── router.py # Model routing
|
|
232
|
+
├── config.py # Configuration
|
|
233
|
+
├── context.py # Conversation context
|
|
234
|
+
├── cost_tracker.py # Cost tracking
|
|
235
|
+
├── hooks.py # Lifecycle hooks
|
|
236
|
+
├── model_registry.py # Model definitions
|
|
237
|
+
├── memory/ # Persistent memory
|
|
238
|
+
├── brain/ # Knowledge graph & RAG
|
|
239
|
+
├── tools/ # Tool registry (35+ tools)
|
|
240
|
+
├── mcp/ # MCP client
|
|
241
|
+
├── permissions/ # Permission system
|
|
242
|
+
├── skills/ # Review & security
|
|
243
|
+
├── analytics/ # Usage analytics
|
|
244
|
+
├── templates/ # Web UI assets
|
|
245
|
+
└── background/ # Background agents
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Development
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
# Install in editable mode with dev dependencies
|
|
254
|
+
pip install -e ".[dev]"
|
|
255
|
+
|
|
256
|
+
# Run tests
|
|
257
|
+
pytest
|
|
258
|
+
|
|
259
|
+
# With coverage
|
|
260
|
+
pytest --cov=luckyd_code --cov-report=term
|
|
261
|
+
|
|
262
|
+
# Type checking
|
|
263
|
+
mypy luckyd_code
|
|
264
|
+
|
|
265
|
+
# Build distribution
|
|
266
|
+
make build
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Contributing
|
|
272
|
+
|
|
273
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines.
|
|
274
|
+
|
|
275
|
+
1. Fork the repository
|
|
276
|
+
2. Create a feature branch from `main`
|
|
277
|
+
3. Write tests for new functionality
|
|
278
|
+
4. Ensure all existing tests pass
|
|
279
|
+
5. Submit a pull request
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## License
|
|
284
|
+
|
|
285
|
+
MIT License — see [LICENSE](LICENSE) for details.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Security
|
|
290
|
+
|
|
291
|
+
See [SECURITY.md](SECURITY.md) for supported versions and how to report vulnerabilities.
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Changelog
|
|
296
|
+
|
|
297
|
+
See [CHANGELOG.md](CHANGELOG.md) for a history of changes.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
luckyd_code/__init__.py,sha256=B-nEQd8Kz69iTMyE8PeBCQQb8zmGrNdvUY6M71PBbd0,1871
|
|
2
|
+
luckyd_code/__main__.py,sha256=29wc0D-c-lzxpWvwbIeyoPH8EfW2LwOB1Be9i4OjfKg,102
|
|
3
|
+
luckyd_code/_agent_loop.py,sha256=ntcDQE4-lgCmhEG9DQT52wL8JmaAxSH6_JztzG4DCUo,21720
|
|
4
|
+
luckyd_code/_data_dir.py,sha256=BmbTO0W_t-KX0Ug7E0MOuW4lB8NZ9wZ7ZAwHLrllxYM,2232
|
|
5
|
+
luckyd_code/agent.py,sha256=5RVqtwBeZG-nmSl2YwuIujS_ZXfsBOiH-CjIZ2i-48c,1162
|
|
6
|
+
luckyd_code/api.py,sha256=FlfqyimaptY-CBK0lkcnmhpUJR18u6mX8wuMBuj7C6M,16536
|
|
7
|
+
luckyd_code/audit_daemon.py,sha256=JbWgNqN8cKjEsYTHITG1Xgojpw9I6Wnb9TpR8p6F7CM,33619
|
|
8
|
+
luckyd_code/autonomous_fixer.py,sha256=wDp3cVHdtVJZelKwaHr0521oXCJdut1QnMhtUQY1X3U,15235
|
|
9
|
+
luckyd_code/background.py,sha256=2ZPGGmqREuPY8eRYo1ynOywvDNEaI4xPfhRgMMqArm0,5468
|
|
10
|
+
luckyd_code/backup.py,sha256=xmLGOoZzpRI3cD5xMPuUYSRZGtfwXFRM6dHN_PkaXLQ,8168
|
|
11
|
+
luckyd_code/cli.py,sha256=7jFfaA1SmQZvma4VgW9WajVZxqc8IEwqKwqWMpyb8n4,37562
|
|
12
|
+
luckyd_code/cli_entry.py,sha256=HF6J09sOoWvv-653uaz3br4VTlWJZ66fXsdxuYwC0Po,5433
|
|
13
|
+
luckyd_code/cli_utils.py,sha256=EyZosgbjt1hFRNWkRPOZ6FbpVQwM82kJYqSItJ38Ql0,3421
|
|
14
|
+
luckyd_code/config.py,sha256=UWEykbBpN9Ikp1CzQlgNv0PSgdhedebZG8N_oawPGLs,8852
|
|
15
|
+
luckyd_code/context.py,sha256=-wLQmDOBAHoLkHDo8qtGVS1av9IUQhyXiz811K-a9ps,8870
|
|
16
|
+
luckyd_code/cost_tracker.py,sha256=SwM2LKc6bq11OsEfPPS6rpH9rICE0388jWT5NioQYoY,8461
|
|
17
|
+
luckyd_code/error_reporter.py,sha256=u4Gw5yEckybOpPhiRVDJeGrGWqOuXVGxlXzA0-j8yOU,17102
|
|
18
|
+
luckyd_code/exceptions.py,sha256=PT8rQZF8HWiOQtUDb0cFYRG1XYnOxW8zt9Fclg_668Q,1117
|
|
19
|
+
luckyd_code/export.py,sha256=Jm4y13mFL7QzymLTuWdC7V4fA3daTIeq2Wt0emXNmSg,4830
|
|
20
|
+
luckyd_code/feedback_analyzer.py,sha256=1fLa41guebw5BcVLfn5FtItG726p9ctFWOIu2qtjQfQ,9770
|
|
21
|
+
luckyd_code/file_watcher.py,sha256=4jV8X3uejgyE00fWxUG-aPqWRmI9RRwlJFteT8eBJVs,8973
|
|
22
|
+
luckyd_code/hooks.py,sha256=zeQKOv6X_AGFLRoMBi0JhAdNRk59eIKHNXV_YLjIvDE,8293
|
|
23
|
+
luckyd_code/indexer.py,sha256=WoTXLJbp9PmH5Na-_fXzjZb9cqrzwoLjyCHtTNPYWm0,9484
|
|
24
|
+
luckyd_code/init.py,sha256=MEAlISSCtbiS5AiThxg8iWHZuJZ8oeYknYXgsKZhmkE,939
|
|
25
|
+
luckyd_code/keybindings.py,sha256=Z51Pw8i_NNf0tODlCo_gL4ndVEg563WhaikAtYrYZwo,2123
|
|
26
|
+
luckyd_code/log.py,sha256=Twb5cKdlWLzKFS_JWDzI53L-Q-JxGeReYB9WkgF9AbA,1666
|
|
27
|
+
luckyd_code/model_registry.py,sha256=zFm0LeKpbtYMO5Qca3NTZlBxpnowPLlgI9UTTz1Jcrw,4461
|
|
28
|
+
luckyd_code/orchestrator.py,sha256=HVGSwwxh5U39RC-l96UfCYA0Vzb3Zw6jcdvNVWC3KFE,8703
|
|
29
|
+
luckyd_code/planner.py,sha256=MYSuWcOgWLBQmkXEhQJ72pJMbLkTmfYwrHuUjRHLQ5s,12324
|
|
30
|
+
luckyd_code/plugins.py,sha256=4VEOZBLxNxiwCfLBonMP3z-fwQIGzEOV7xiGasup57E,2730
|
|
31
|
+
luckyd_code/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
|
+
luckyd_code/retry.py,sha256=EHMi9dayc3NhrQ-i1qfDmxg8BCv1ugLgwKqrmzrc6JE,2161
|
|
33
|
+
luckyd_code/router.py,sha256=El91u1rn1NcfKs5H3DLm3HVjkRNgxGnMDvr76FdKjKA,15140
|
|
34
|
+
luckyd_code/sandbox.py,sha256=AYxbssqNunKQMVPLYUjCYqZtlaSVdmDCs93hBXkV0Xg,5228
|
|
35
|
+
luckyd_code/self_critique.py,sha256=YxzbhoOVDeazGtRbjrj5GiUVVBBnF8WpSHr1GSbaNrQ,162
|
|
36
|
+
luckyd_code/self_improve.py,sha256=GvdaW8mV6556V8TLq99sBw7Ii9XMgwy4n2Pn7oSoXF8,12073
|
|
37
|
+
luckyd_code/sessions.py,sha256=81IPE0EzIky23lOEzvs5Af6osNbeRceeeESvQ40Pn7k,3582
|
|
38
|
+
luckyd_code/settings.py,sha256=chGcTr_5sxgcSe1SoZUJJ0iLiNqEuiacAQmBxeT8gKI,2165
|
|
39
|
+
luckyd_code/themes.py,sha256=fEJme4SlIk43ccjojmu445fkR3C7BoVXoZRNJuQ49YU,1035
|
|
40
|
+
luckyd_code/tools_bridge.py,sha256=p7PVAIGlb89I9gnPyYZqrJdnk4mcEn5fPoWQmjtPz14,5209
|
|
41
|
+
luckyd_code/undo.py,sha256=HlbuRwbyBESXXT1PI-6YjQVHiGWtBCc1P-GG454SHpE,3390
|
|
42
|
+
luckyd_code/update.py,sha256=ANXKdUYi6n4-26as2ftHSqQ5eCUUE-iqK1PwAopN3aE,1992
|
|
43
|
+
luckyd_code/verify.py,sha256=8YBhmDFs59LZiu2m1AswjxxIj3u4pCSu5tGDoVxOYbQ,14047
|
|
44
|
+
luckyd_code/web_app.py,sha256=mDy_Ypv3BSqDbAksPwkxZVBB0tJEbjqsICgdGkQOe18,5999
|
|
45
|
+
luckyd_code/analytics/__init__.py,sha256=F88oArnOex1os8l3HwuLBqL5RwN6Nz-rM7Y7gfkWQHM,510
|
|
46
|
+
luckyd_code/analytics/reporter.py,sha256=MBQ_4D-zfeaJtPHiAhvRuylEWvaquBD8xom9QA_pAGs,6797
|
|
47
|
+
luckyd_code/analytics/scanner.py,sha256=CRQOYqfpYfRtSgupgJobwTJwmDHpUaDrCzA3z5xmvJk,15075
|
|
48
|
+
luckyd_code/analytics/smells.py,sha256=P5svsjbo4NFRHNDlHU9vovvZN9cbLqldSj7uhcZKxjs,12873
|
|
49
|
+
luckyd_code/analytics/trends.py,sha256=7O-gyO3Dk8nxOoE2GU3pgPEDKuw7NFqtZG8Hj6EHonY,10495
|
|
50
|
+
luckyd_code/brain/__init__.py,sha256=iBxmwXJ_ZBA7sDDRPKWza9ZkK9YP5YldDaj5MpBfOF0,2709
|
|
51
|
+
luckyd_code/brain/assembler.py,sha256=U9aurkm26ExQltt8l7O7tbhA2F9QggfxHqNfiqGWmlg,3168
|
|
52
|
+
luckyd_code/brain/chunker.py,sha256=--pii3pfTpMSud_P5oa6jLCwd-rleo22FwJ90qiTNg8,11884
|
|
53
|
+
luckyd_code/brain/constants.py,sha256=slT0goqohwfeOLf_LWmXF8CLE_I7pmFiMWi6thLNEE8,1766
|
|
54
|
+
luckyd_code/brain/embedder.py,sha256=85_ij8shpSKZqxw8HanrvUevaobl_8c6bzeWfch_dms,5222
|
|
55
|
+
luckyd_code/brain/graph.py,sha256=L4iQWszdf1KHAunKAnvFneeh7UoxE2e5GUz34h3EAjY,11743
|
|
56
|
+
luckyd_code/brain/indexer.py,sha256=-oLJBF_hugbyU38uzsDLcBvv4du3BHDfTyS3oZfOeKQ,10086
|
|
57
|
+
luckyd_code/brain/parser.py,sha256=xLTJ2tJkQD4NQ0JkArfZ60OS5ZM8xw_SczfVySMx-SU,4910
|
|
58
|
+
luckyd_code/brain/retriever.py,sha256=oKuY2xBSssWcBG5e-Tf6JRPmRsjozxUI_8ROKGg7c-w,8107
|
|
59
|
+
luckyd_code/cli_commands/__init__.py,sha256=hc6STRHVU3MaSFVFmWgfROsA8-U9Lm-HqFjchBQgkX4,34
|
|
60
|
+
luckyd_code/cli_commands/audit.py,sha256=on9Fd3vqq3sxv2AFsLaFkqOfQKG_n4tmAm3RmGWHMaU,4094
|
|
61
|
+
luckyd_code/cli_commands/background.py,sha256=ltm_5elpJw-WP74n-pB03JckFLkld7hLPTilBi25LyA,3044
|
|
62
|
+
luckyd_code/cli_commands/brain.py,sha256=geJeXpK3D7RqoJkeLDfGVDqg16m9vWhxV6GcFNFcIrc,3284
|
|
63
|
+
luckyd_code/cli_commands/config.py,sha256=zP1WFtjxfgNDlOl_HxpALybEU78aN1zirBZeBVZ8LUY,2838
|
|
64
|
+
luckyd_code/cli_commands/dispatcher.py,sha256=pKl-z4OkF-GwYYwCTBSt3Htf1aFALQCIm0wiVzgzFG8,31289
|
|
65
|
+
luckyd_code/cli_commands/sessions.py,sha256=raeW6CRhd3FvtV10yNXA2Jri_Qbq-5EJbwooqpxOElY,1318
|
|
66
|
+
luckyd_code/git/__init__.py,sha256=OkkXSmDeNttwQYsDfgpjIc6wtiAWIL33n_u6lXMd0qM,192
|
|
67
|
+
luckyd_code/git/auto_commit.py,sha256=6WCLUMiebJFO-T-7oLG0qHYY0kgDrcM0dEIEwZVl8t0,5042
|
|
68
|
+
luckyd_code/git/tools.py,sha256=9_8AZOtC7JztJwVvkinej_6U1RftHHCzEzdonk80Eh0,2556
|
|
69
|
+
luckyd_code/mcp/__init__.py,sha256=P0S1s_UMBRg3sZELyF_U5KKc2vr6hGDFZ5JFDIKfA-U,151
|
|
70
|
+
luckyd_code/mcp/client.py,sha256=2Bt6heIL7tw3JCmqQ8nFOr2vHwiZ4KGDC1qtKwLmdSE,6928
|
|
71
|
+
luckyd_code/memory/__init__.py,sha256=JUWxyeOJQDvqqcZhUSWR7xrO8LTlj0Zj86iFmuasdvU,346
|
|
72
|
+
luckyd_code/memory/manager.py,sha256=LO7QahygLGoV-i_GVYsud70uy4rl1WPtRNNjVUKxOXk,13313
|
|
73
|
+
luckyd_code/metrics/__init__.py,sha256=PZzlmGn6QHAyn5CsflfO1rsS-8Fr4FA1-CCVpgYKbpo,180
|
|
74
|
+
luckyd_code/permissions/__init__.py,sha256=3LCcI5CFhuWIRTF7g1Ke2AOpnA_2Ovew5j7D4TAsV4s,50
|
|
75
|
+
luckyd_code/permissions/manager.py,sha256=ZwvDBRB9fWB9Qk8DuAqHAy92UGLin45dMYFp5--AYrA,3011
|
|
76
|
+
luckyd_code/skills/__init__.py,sha256=BjMn7aqZQJ6RlT_ZGUiPeSbgWI6EdJQmucklB85VCtc,137
|
|
77
|
+
luckyd_code/skills/review.py,sha256=emgq4ZRi-3vi9Ul7r51lDhD97tos6Bpnq_C0Xgn3DjA,646
|
|
78
|
+
luckyd_code/skills/security.py,sha256=EHHu9XFmygcU4BM4rrRo0LKor2cPbTPcdPPldad5K9Q,482
|
|
79
|
+
luckyd_code/tasks/__init__.py,sha256=3mQrNW09kzV0kIxWKIr6TjZKYPnQQu0wxSdUXGCXmUU,68
|
|
80
|
+
luckyd_code/tasks/manager.py,sha256=Zq5lAx-cd2UdT63vCRNiH_bfVKBEgVO1BmA2QCvAZBw,3022
|
|
81
|
+
luckyd_code/templates/icon-192.png,sha256=w5ly8dInHA0ZOUqeIQxggLTRAeYUwfj1U_D5_cVR3Aw,545
|
|
82
|
+
luckyd_code/templates/icon-512.png,sha256=hPWk5h7uL_lN5um6MxUqQ3zczv0YJQc4Z7mgGL42SLU,1879
|
|
83
|
+
luckyd_code/templates/index.html,sha256=IiS1N_tm6m6ZckSNNpbRFhnbAuDPSxLn9B1wyDSby4c,56633
|
|
84
|
+
luckyd_code/templates/manifest.json,sha256=5f7DpJDMfro6S9Ara4WnmGHmMoOJ1NPPMoMHNahODqg,404
|
|
85
|
+
luckyd_code/templates/sw.js,sha256=mVouoTNHStf2y_BqRy1bXZjnMB1w8blSW337n8HkHxE,743
|
|
86
|
+
luckyd_code/templates/test.html,sha256=L0FV3KYZVHcxlAP7a_0ZDo2MMD1Wg_nJsSfYc51ybvo,59
|
|
87
|
+
luckyd_code/templates/src/app.js,sha256=gu9MaGPkiI-GSMLI6PdKxCfWVkXttny2iT39APMUBxo,20595
|
|
88
|
+
luckyd_code/templates/src/body.html,sha256=5VvS1ifVqTPSnuYld8nsWkGvlxsQYz6q6Evc8g8Tz-g,23528
|
|
89
|
+
luckyd_code/templates/src/cdn.txt,sha256=EpxH2jnBR-CjogOYUoAykqMpFTDQgcP4UThrfhBtVYA,190
|
|
90
|
+
luckyd_code/templates/src/style.css,sha256=iMMEvg9lZDbBZoln3V-lB0cJx9st8BK8_M9lTsgkC0c,11279
|
|
91
|
+
luckyd_code/tools/__init__.py,sha256=OHsnqSuFdYXMVjqC67H5_ElEYccL5QHgec67tWmfCFc,3553
|
|
92
|
+
luckyd_code/tools/agent_tools.py,sha256=mOrqfNZ95G8ImdJ1VZHCv5A_b84v4Hs60aXtZ0st99E,2124
|
|
93
|
+
luckyd_code/tools/bash.py,sha256=j3FI9KVjPZLJ7YUse5o54gTqcyOXPP0lty28k48cHxU,12534
|
|
94
|
+
luckyd_code/tools/brain_tools.py,sha256=3KUJ_XHXEtpLutJXd0Eos5R7Z5MI4nqtFiSR0EBZUFU,5122
|
|
95
|
+
luckyd_code/tools/browser.py,sha256=11uN6VanMM2JJ9iBjocJC2uj-YXAr2aGUhLXiwaH51g,12546
|
|
96
|
+
luckyd_code/tools/datetime_tool.py,sha256=GwLezvuSw9v6-UQznbRsCTuWJZZgHwWocZskc7fOLOo,1062
|
|
97
|
+
luckyd_code/tools/dockerfile_gen.py,sha256=sTh6HLx8n35tfGifwIt2DP-WdfC3rEI4MTfUqZPA8lg,7461
|
|
98
|
+
luckyd_code/tools/file_ops.py,sha256=drIhUqa5dh7CfLdHQ-5wyBh65mTO9D_MJ_AwfXdAEkM,13604
|
|
99
|
+
luckyd_code/tools/game_gen.py,sha256=bHqJHZ2-0hKAyVrQrCwDvIx8NMUV88RIoJF9UjLHy5c,13931
|
|
100
|
+
luckyd_code/tools/git_tools.py,sha256=EcDgZqGBNz5bVLWpbqGrGVmV0tdAfVgQpgKJP5dtdlg,3558
|
|
101
|
+
luckyd_code/tools/git_worktree.py,sha256=7rwU13AXe-t56m6BCQNMVuUT9Le21ZFhlHmoPywO_Ts,2191
|
|
102
|
+
luckyd_code/tools/path_validate.py,sha256=qriGBn5tKAGtfV_ky26Evmk7uSgAH2zIljRtXqUN_iI,1988
|
|
103
|
+
luckyd_code/tools/project_gen.py,sha256=rOMfCB3M5BIbcBQ-WlsAQP5DFnjwo-qmrsvbi04CCOM,7024
|
|
104
|
+
luckyd_code/tools/readme_gen.py,sha256=TeIbHujuTDoILoIu_R8HbtBVs0bDmOzEaBvCs5CfVng,8061
|
|
105
|
+
luckyd_code/tools/registry.py,sha256=NLua9vzfZ4QK1Ek8GNN-C4OKMaOWecbv3jatZb46cZ8,5267
|
|
106
|
+
luckyd_code/tools/shell_detect.py,sha256=TnWLYSQLm_QjIxwF1C5Z56-grDHGOzhYqr929tqofvU,3168
|
|
107
|
+
luckyd_code/tools/web.py,sha256=Ax6iyTvn04ARJqb5w41nw4EwAIFfzEIrwRrhuRf_HqY,3201
|
|
108
|
+
luckyd_code/tools/youtube.py,sha256=tcru64GaDbm4qF_8-Vecivclp61qSbKioYSPO-JHmB0,6762
|
|
109
|
+
luckyd_code/web_routes/__init__.py,sha256=_9cJdsjcrR4aZsT39gDXdNXK08lhgNmEuw3fBmCmq3I,721
|
|
110
|
+
luckyd_code/web_routes/background.py,sha256=QxlYNa7w-eLFzp6D5q5e0raQ1Od8FBpk_EPDTSIAQTw,2420
|
|
111
|
+
luckyd_code/web_routes/brain.py,sha256=kM5I7cowVGnOUytc3HIoHXsf_CvZIEGj2P8pwqDjr6k,3323
|
|
112
|
+
luckyd_code/web_routes/cost.py,sha256=DoyCosb8GYSQLTBv0ODTXeTPVTf7Dunt8uY0w0LDoJY,256
|
|
113
|
+
luckyd_code/web_routes/files.py,sha256=gqs0yQHJOJf3PJpbKbbJUGY_P3G0X3UYtRHz5B35Dkc,5136
|
|
114
|
+
luckyd_code/web_routes/memories.py,sha256=hv6LecGM75bZTat-v27Vie-CZgolapUeuvGZS7BlMSE,3045
|
|
115
|
+
luckyd_code/web_routes/misc.py,sha256=38la5tejKtyHBzXMqAPCZEC2wbKg6mKx5QsZTL4zaug,2092
|
|
116
|
+
luckyd_code/web_routes/project.py,sha256=c9GgRZSAuJFiSsEPmcpd24uZhVM7l6SCPAZCPpTiyVs,1515
|
|
117
|
+
luckyd_code/web_routes/review.py,sha256=_q-f4BiRsuba-v03uf3rhLksNa8ORoaRUAFlh4ashOs,462
|
|
118
|
+
luckyd_code/web_routes/sessions.py,sha256=VdrS13q91x6UVYC4ugRCmcYLuXtFSlBdSaG1uBvsJ2I,1136
|
|
119
|
+
luckyd_code/web_routes/settings.py,sha256=XYb9QfwI1l96p8Piz5E4zx0YvP10k37SzsueHQFHNMs,982
|
|
120
|
+
luckyd_code/web_routes/static.py,sha256=ZiMP0XxB0ifKu6WBsMsdABD38d0SMj_b9Betom2V99w,1982
|
|
121
|
+
luckyd_code/web_routes/update.py,sha256=596InmLi0fKCpF46bnAIZg5LuUMZIGprKQJH203h4-0,418
|
|
122
|
+
luckyd_code/web_routes/ws.py,sha256=8m44b4fFCUKCjrYIykgOPuGlJ914vNhGrf4GGNM7xWo,9955
|
|
123
|
+
luckyd_code-1.2.2.dist-info/METADATA,sha256=G1ZB4FQ0m8l9vKUimzLSNvqk0MErLADdHHwxakgaUsk,9184
|
|
124
|
+
luckyd_code-1.2.2.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
125
|
+
luckyd_code-1.2.2.dist-info/entry_points.txt,sha256=yKIYwVTUMAQkkypS4MVpX9rJqRP3hmQ7214pKLop-n0,92
|
|
126
|
+
luckyd_code-1.2.2.dist-info/licenses/LICENSE,sha256=BCKpWQ4QZD0PD1q2iWThm1JbS6Pk-irbN48eSO-tcfE,1084
|
|
127
|
+
luckyd_code-1.2.2.dist-info/RECORD,,
|