crystalwindow 4.2__py3-none-any.whl → 4.4__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.
crystalwindow/ai.py CHANGED
@@ -1,19 +1,18 @@
1
1
  # ==========================================================
2
- # CrystalAI v0.6Unified Engine
2
+ # CrystalAI v0.8Hybrid Engine (Groq + Symbolic Fallback)
3
3
  # ----------------------------------------------------------
4
4
  # Combines:
5
- # - v0.4: auto-fix, AST parser, docs index, diff tools
6
- # - v0.5: personality, library ingestion, safe key check
7
- # - Groq fallback, local fallback, file analysis
5
+ # - Groq API for general knowledge (Primary)
6
+ # - Pure Python Symbolic Engine for Code Analysis (Fallback)
7
+ # - Memory, File Reading, AST Parsing, and Diff Utilities
8
8
  # ==========================================================
9
9
 
10
10
  import os
11
11
  import ast
12
12
  import difflib
13
- from typing import Optional, Dict, Any
14
- import requests
15
- import groq
16
-
13
+ import requests # Re-added for API communication
14
+ from typing import Optional, Dict, Any, List
15
+ # Removed groq import, using requests for simplicity
17
16
 
18
17
  # ==========================================================
19
18
  # Response Wrapper
@@ -34,10 +33,11 @@ class AI:
34
33
  DEFAULT_MODEL = "llama-3.1-8b"
35
34
  DEFAULT_PERSONALITY = (
36
35
  "You are CrystalWindow AI. You help users with Python code, "
37
- "debugging, errors, docs, and file analysis. "
38
- "Be friendly, technical, clear, and precise."
36
+ "debugging, errors, docs, and file analysis. You are currently running in "
37
+ "Hybrid Mode. Be friendly, technical, clear, and precise."
39
38
  )
40
- PLACEHOLDER_KEY = "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"
39
+ # Placeholder Key for testing or when user key is invalid
40
+ PLACEHOLDER_KEY = "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"
41
41
 
42
42
  # ------------------------------------------------------
43
43
  def __init__(self, key=None, model=None):
@@ -47,10 +47,10 @@ class AI:
47
47
  self.key = self.PLACEHOLDER_KEY
48
48
  else:
49
49
  self.key = key
50
-
50
+
51
51
  # --- MODEL VALIDATION ---
52
52
  if not model or not isinstance(model, str) or len(model) < 3:
53
- print("[CrystalAI] Unknown model → using default.")
53
+ print(f"[CrystalAI] Unknown model → using default: {self.DEFAULT_MODEL}.")
54
54
  self.model = self.DEFAULT_MODEL
55
55
  else:
56
56
  self.model = model
@@ -58,22 +58,25 @@ class AI:
58
58
  # Persona
59
59
  self.personality = self.DEFAULT_PERSONALITY
60
60
 
61
+ # Pure AI knowledge (used in symbolic fallback)
62
+ self.knowledge_graph: Dict[str, Any] = self._build_knowledge_graph()
63
+
61
64
  # Library knowledge (loaded .py files)
62
65
  self.library_context = ""
63
66
 
64
- # v0.4 memory system (optional)
65
- self.memory = []
67
+ # Memory system
68
+ self.memory: List[Dict[str, str]] = []
66
69
  self.use_memory = True
67
70
 
68
- # v0.4 toggle for forcing local engine
69
- self.force_local = False
71
+ # Force local toggle (currently not used as logic is based on Groq success)
72
+ self.force_local = False
70
73
 
71
74
  # ==========================================================
72
75
  # PERSONALITY
73
76
  # ==========================================================
74
77
  def set_personality(self, txt):
75
78
  if not isinstance(txt, str) or len(txt.strip()) < 10:
76
- print("Oops! thats not how to use it—reverting to default.")
79
+ print("Oops! that's not how to use it—reverting to default.")
77
80
  self.personality = self.DEFAULT_PERSONALITY
78
81
  return
79
82
 
@@ -103,7 +106,7 @@ class AI:
103
106
  path = os.path.join(root, f)
104
107
  with open(path, "r", encoding="utf8") as fp:
105
108
  out.append(f"# FILE: {path}\n" + fp.read() + "\n\n")
106
- except:
109
+ except Exception:
107
110
  pass
108
111
 
109
112
  self.library_context = "\n".join(out)
@@ -119,8 +122,8 @@ class AI:
119
122
  try:
120
123
  with open(path, "r", encoding="utf8") as f:
121
124
  return f.read()
122
- except:
123
- return "[CrystalAI] couldnt read file."
125
+ except Exception:
126
+ return "[CrystalAI] couldn't read file."
124
127
 
125
128
  # ==========================================================
126
129
  # PROMPT BUILDER (Unified)
@@ -151,74 +154,98 @@ class AI:
151
154
  self.memory.pop(0)
152
155
 
153
156
  # ==========================================================
154
- # LOCAL FALLBACK AI (modern, useful, not dumb)
157
+ # PURE AI KNOWLEDGE BASE (Symbolic Core)
158
+ # ==========================================================
159
+ def _build_knowledge_graph(self) -> Dict[str, Any]:
160
+ """
161
+ Defines the internal knowledge the symbolic AI can reason with.
162
+ """
163
+ return {
164
+ "python": {
165
+ "desc": "A high-level, interpreted programming language.",
166
+ "keywords": ["language", "interpreted", "high-level"],
167
+ "syntax": {
168
+ "if_statement": "if condition: ... else: ...",
169
+ "loop": "for item in iterable: ..."
170
+ }
171
+ },
172
+ "ast": {
173
+ "desc": "Abstract Syntax Tree. Used for parsing code structure.",
174
+ "keywords": ["parsing", "code", "structure", "tree"]
175
+ },
176
+ "fix_code": {
177
+ "rule": "look for SyntaxError, especially missing colons or mismatched brackets",
178
+ "keywords": ["fix", "error", "bug", "syntax"]
179
+ }
180
+ }
181
+
182
+ # ==========================================================
183
+ # PURE AI 'THINKING' ENGINE (Symbolic Fallback)
155
184
  # ==========================================================
156
- def _local_ai(self, prompt, file_data):
185
+ def _symbolic_engine(self, prompt: str, file_data: Optional[str]) -> str:
157
186
  """
158
- Improved fallback mode:
159
- - If file provided → real AST analysis
160
- - If general question → helpful offline response
161
- - No more random jokes or irrelevant "forgot a colon"
187
+ Fallback logic: Simulates 'thinking' using only internal rules and AST.
162
188
  """
189
+ output = ["[Local/SymbolicEngine] Processing request..."]
190
+ lower_prompt = prompt.lower()
163
191
 
164
- # --- If file provided, try real Python AST parsing ---
192
+ # --- Stage 1: File Analysis (Real Python AST) ---
165
193
  if file_data and not file_data.startswith("[CrystalAI]"):
194
+ output.append("\n[Stage 1: Code Parsing]")
166
195
  try:
167
196
  ast.parse(file_data)
168
- return (
169
- "[LocalAI] I was able to parse the file successfully.\n"
170
- "There are no syntax errors.\n"
171
- "Ask me to explain, summarize, refactor, or improve something."
172
- )
197
+ output.append("✅ **No Syntax Errors Detected** (via AST).")
198
+ output.append("The code is structurally sound. Ask for refactoring or explanation.")
199
+ return "\n".join(output)
173
200
  except SyntaxError as se:
201
+ fix_rule = self.knowledge_graph["fix_code"]["rule"]
174
202
  lineno = se.lineno or 0
175
- offset = se.offset or 0
176
203
  msg = (
177
- f"[LocalAI] SyntaxError detected:\n"
204
+ f" **SyntaxError Detected** (via AST):\n"
178
205
  f"• Message: {se.msg}\n"
179
206
  f"• Line: {lineno}\n"
180
- f"• Column: {offset}\n\n"
207
+ f"• Rule suggestion: {fix_rule}"
181
208
  )
182
- snippet = self._snippet(file_data, lineno)
183
- return msg + snippet
184
-
185
- # --- General offline fallback (safe + useful) ---
186
- lower = prompt.lower()
187
-
188
- # Code-related queries
189
- if "fix" in lower or "error" in lower or "bug" in lower:
190
- return (
191
- "[LocalAI] I can't reach Groq right now,\n"
192
- "but here's what I can do offline:\n"
193
- "• Check for syntax problems if you provide a file\n"
194
- " Suggest common Python mistakes\n\n"
195
- "Tip: try again once Groq is reachable for full debugging."
196
- )
197
-
198
- # Regular questions (time, math, writing, etc.)
199
- if any(x in lower for x in ["time", "story", "game", "explain", "python"]):
200
- return (
201
- "[LocalAI] I'm offline, but I can still give general help:\n"
202
- "- Ask me Python questions\n"
203
- "- Ask for concepts, writing tips, structure examples\n"
204
- "- Provide a file and I can analyze it with AST\n"
205
- )
209
+ output.append(msg)
210
+ output.append(self._snippet(file_data, lineno))
211
+ return "\n".join(output)
212
+
213
+ # --- Stage 2: Knowledge Graph Lookup (Rule-Based Reasoning) ---
214
+ output.append("\n[Stage 2: Symbolic Lookup]")
215
+
216
+ found_concept = False
217
+ for key, knowledge in self.knowledge_graph.items():
218
+ if key in lower_prompt or any(k in lower_prompt for k in knowledge.get("keywords", [])):
219
+ if key == "fix_code": continue
220
+
221
+ output.append(f"🧠 Found Concept: **{key.upper()}**")
222
+ output.append(f"Description: {knowledge.get('desc', 'No detailed description.')}")
223
+
224
+ if 'syntax' in knowledge:
225
+ output.append("Related Syntax:")
226
+ for syn, code in knowledge['syntax'].items():
227
+ output.append(f" - {syn.replace('_', ' ')}: `{code}`")
228
+
229
+ found_concept = True
230
+ break
231
+
232
+ if not found_concept:
233
+ output.append("❓ Concept Unknown: I am currently offline and limited to my internal knowledge base (Python, AST, Fix Code).")
234
+ output.append("Please provide a file for AST analysis or try again later for a full Groq response.")
235
+
236
+ return "\n".join(output)
206
237
 
207
- # Catch-all fallback
208
- return (
209
- "[LocalAI] Offline mode enabled.\n"
210
- "I can still analyze Python code and help with general knowledge.\n"
211
- "Once online, Groq will give full intelligent responses."
212
- )
213
238
 
214
239
  # ==========================================================
215
- # ASK (Groq → fallback)
240
+ # ASK (Groq → Symbolic Fallback)
216
241
  # ==========================================================
217
242
  def ask(self, text, file=None):
218
243
  file_data = self._read_file(file)
219
244
  prompt = self._build_prompt(text, file_data)
245
+
246
+ resp = None
220
247
 
221
- # Try to call Groq normally
248
+ # --- Attempt 1: Call External API (Groq) ---
222
249
  try:
223
250
  url = "https://api.groq.com/openai/v1/chat/completions"
224
251
  headers = {
@@ -227,7 +254,7 @@ class AI:
227
254
  }
228
255
 
229
256
  payload = {
230
- "model": "llama-3.3-70b-versatile",
257
+ "model": self.model,
231
258
  "messages": [
232
259
  {"role": "system", "content": self.personality},
233
260
  {"role": "user", "content": prompt}
@@ -235,18 +262,23 @@ class AI:
235
262
  "temperature": 0.3
236
263
  }
237
264
 
238
- import requests
239
- r = requests.post(url, json=payload, headers=headers, timeout=8)
265
+ r = requests.post(url, json=payload, headers=headers, timeout=10)
240
266
  data = r.json()
241
267
 
242
268
  if "error" in data:
243
- raise RuntimeError(data["error"])
269
+ # If the API returns an error (e.g., bad key), we force the fallback
270
+ raise RuntimeError(f"API Error: {data['error'].get('message', 'Unknown API Error')}")
244
271
 
245
272
  resp = data["choices"][0]["message"]["content"]
246
273
 
247
- except Exception:
248
- # Groq unreachable fallback
249
- resp = self._local_ai(prompt, file_data)
274
+ except Exception as e:
275
+ # This block handles API connection failures (timeout) or API-side errors (bad key)
276
+ print(f"[CrystalAI] Groq connection failed or returned error: {e.__class__.__name__}")
277
+ print("[CrystalAI] Falling back to self-contained Symbolic Engine...")
278
+
279
+ # --- Attempt 2: Fallback to Symbolic Engine ---
280
+ resp = self._symbolic_engine(prompt, file_data)
281
+
250
282
 
251
283
  self._save_memory(text, resp)
252
284
  return CrystalAIResponse(resp)
@@ -284,7 +316,7 @@ class AI:
284
316
  msg = getattr(syntax_error, "msg", "")
285
317
  lineno = syntax_error.lineno or 0
286
318
 
287
- # missing colon
319
+ # missing colon fix
288
320
  if "expected" in msg and ":" in msg:
289
321
  if 1 <= lineno <= len(lines):
290
322
  line = lines[lineno - 1].rstrip()
@@ -295,7 +327,7 @@ class AI:
295
327
  try:
296
328
  ast.parse(candidate)
297
329
  return candidate, notes
298
- except:
330
+ except Exception:
299
331
  pass
300
332
 
301
333
  # fallback
@@ -326,9 +358,9 @@ class AI:
326
358
  out = []
327
359
  for i in range(start, end):
328
360
  mark = "->" if (i + 1) == lineno else " "
329
- out.append(f"{mark} {i+1:4}: {lines[i]}")
361
+ out.append(f"{mark} {i+1:<4}: {lines[i]}")
330
362
  return "\n".join(out)
331
363
 
332
364
  # ==========================================================
333
- # END OF ENGINE
334
- # ==========================================================
365
+ # END OF HYBRID ENGINE
366
+ # ==========================================================
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crystalwindow
3
- Version: 4.2
3
+ Version: 4.4
4
4
  Summary: A Tkinter powered window + GUI toolkit made by Crystal (MEEEEEE)! Easier apps, smoother UI and all-in-one helpers!
5
5
  Home-page: https://pypi.org/project/crystalwindow/
6
6
  Author: CrystalBallyHereXD
@@ -1,6 +1,6 @@
1
1
  crystalwindow/FileHelper.py,sha256=aUnnRG7UwvzJt-idjWjmpwy3RM6nqLlC3-7Bae6Yb94,5471
2
2
  crystalwindow/__init__.py,sha256=a2kdMZ29QZ4kSQ3M8jLvCR6g3OUQxNhdaT3ycxoames,2264
3
- crystalwindow/ai.py,sha256=jQ-O3h0HvDlmopWSZSTP0oEwnxZzrDCTCPNjjslB0IE,12504
3
+ crystalwindow/ai.py,sha256=4CN3_Fi5zERxyqoHcUyXPvm4MVWaicA7JGK0lRb-ybQ,14661
4
4
  crystalwindow/animation.py,sha256=zHjrdBXQeyNaLAuaGPldJueX05OZ5j31YR8NizmR0uQ,427
5
5
  crystalwindow/assets.py,sha256=2Cj0zdhMWo3mWjdr9KU5n-9_8iKj_fJ9uShMFA-27HU,5193
6
6
  crystalwindow/camera.py,sha256=tbn4X-jxMIszAUg3Iu-89gJN5nij0mjPMEzGotcLbJI,712
@@ -33,8 +33,8 @@ crystalwindow/gametests/guitesting.py,sha256=SrOssY5peCQEV6TQ1AiOWtjb9phVGdRzW-Q
33
33
  crystalwindow/gametests/sandbox.py,sha256=Oo2tU2N0y3BPVa6T5vs_h9N6islhQrjSrr_78XLut5I,1007
34
34
  crystalwindow/gametests/squaremove.py,sha256=poP2Zjl2oc2HVvIAgIK34H2jVj6otL4jEdvAOR6L9sI,572
35
35
  crystalwindow/gametests/windowtesting.py,sha256=_9X6wnV1-_X_PtNS-0zu-k209NtFIwAc4vpxLPp7V2o,97
36
- crystalwindow-4.2.dist-info/licenses/LICENSE,sha256=Gt5cJRchdNt0guxyQMHKsATN5PM5mjuDhdO6Gzs9qQc,1096
37
- crystalwindow-4.2.dist-info/METADATA,sha256=_R-c3vsY6VjcDO_LozKHcvZWXHFU0vD80ArnEw-biRg,7338
38
- crystalwindow-4.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
39
- crystalwindow-4.2.dist-info/top_level.txt,sha256=PeQSld4b19XWT-zvbYkvE2Xg8sakIMbDzSzSdOSRN8o,14
40
- crystalwindow-4.2.dist-info/RECORD,,
36
+ crystalwindow-4.4.dist-info/licenses/LICENSE,sha256=Gt5cJRchdNt0guxyQMHKsATN5PM5mjuDhdO6Gzs9qQc,1096
37
+ crystalwindow-4.4.dist-info/METADATA,sha256=8j8_X2PPPAo6OmZELS5-KpjARhkwJcnYcC4r2qur-7M,7338
38
+ crystalwindow-4.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
39
+ crystalwindow-4.4.dist-info/top_level.txt,sha256=PeQSld4b19XWT-zvbYkvE2Xg8sakIMbDzSzSdOSRN8o,14
40
+ crystalwindow-4.4.dist-info/RECORD,,