supermegaexplosion 0.3.1__tar.gz → 0.4.0__tar.gz

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 (21) hide show
  1. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/PKG-INFO +18 -8
  2. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/README.md +15 -6
  3. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/libbs/__init__.py +2 -1
  4. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/libbs/ai_helper.py +93 -80
  5. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/libbs/catalog.py +2 -1
  6. supermegaexplosion-0.4.0/libbs/so_helper.py +62 -0
  7. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/pyproject.toml +2 -2
  8. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/supermegaexplosion.egg-info/PKG-INFO +18 -8
  9. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/supermegaexplosion.egg-info/SOURCES.txt +1 -0
  10. supermegaexplosion-0.4.0/supermegaexplosion.egg-info/requires.txt +4 -0
  11. supermegaexplosion-0.3.1/supermegaexplosion.egg-info/requires.txt +0 -3
  12. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/libbs/arrays.py +0 -0
  13. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/libbs/ds.py +0 -0
  14. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/libbs/input_utils.py +0 -0
  15. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/libbs/math_utils.py +0 -0
  16. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/libbs/strings.py +0 -0
  17. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/libbs/tools/__init__.py +0 -0
  18. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/libbs/tools/add_func.py +0 -0
  19. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/setup.cfg +0 -0
  20. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/supermegaexplosion.egg-info/dependency_links.txt +0 -0
  21. {supermegaexplosion-0.3.1 → supermegaexplosion-0.4.0}/supermegaexplosion.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: supermegaexplosion
3
- Version: 0.3.1
3
+ Version: 0.4.0
4
4
  Summary: DSA utility library — input helpers, algorithms, data structures, and AI assistant
5
5
  Author-email: "Hadoopnb.ai" <hadoopnb@example.com>
6
6
  License-Expression: MIT
@@ -8,11 +8,12 @@ Classifier: Programming Language :: Python :: 3
8
8
  Requires-Python: >=3.8
9
9
  Description-Content-Type: text/markdown
10
10
  Provides-Extra: ai
11
- Requires-Dist: google-genai; extra == "ai"
11
+ Requires-Dist: groq; extra == "ai"
12
+ Requires-Dist: azure-ai-inference; extra == "ai"
12
13
 
13
14
  # supermegaexplosion
14
15
 
15
- DSA utility library — interactive input helpers, string/math/array algorithms, data structures, and an AI assistant powered by Google Gemini.
16
+ DSA utility library — interactive input helpers, string/math/array algorithms, data structures, and an AI assistant powered by Groq (primary), GitHub Models, and Stack Overflow.
16
17
 
17
18
  ```python
18
19
  from libbs import *
@@ -24,26 +25,35 @@ sieve(100) # primes up to 100
24
25
  max_subarray_sum([-2,1,-3,4,-1,2,1,-5,4]) # 6
25
26
  ListNode.from_list([1,2,3,4,5])
26
27
 
27
- # AI assistant (requires API key + dependency)
28
+ # AI assistant — works out of the box (free embedded Groq key)
28
29
  respond_help("How to reverse a linked list?")
30
+
31
+ # Direct Stack Overflow search — also works out of the box
32
+ stack_overflow("python reverse linked list")
29
33
  ```
30
34
 
31
35
  ## Install
32
36
 
33
37
  ```bash
34
38
  pip install supermegaexplosion # core (zero deps)
35
- pip install supermegaexplosion[ai] # with AI assistant (google-genai)
39
+ pip install supermegaexplosion[ai] # with Groq + GitHub Models
36
40
  ```
37
41
 
38
42
  ## AI Setup
39
43
 
40
- Get a free API key from https://aistudio.google.com/ and set it:
44
+ `respond_help` works immediately with the embedded Groq key. For better quota, set your own:
45
+
46
+ ```bash
47
+ set GROQ_API_KEY=gsk_your_key_here
48
+ ```
49
+
50
+ Optional — GitHub Models fallback:
41
51
 
42
52
  ```bash
43
- set GEMINI_API_KEY=your_api_key_here
53
+ set GITHUB_TOKEN=ghp_your_token_here
44
54
  ```
45
55
 
46
- Then use `respond_help("your question")` free tier gives 60 requests/min, 1500/day.
56
+ Provider chain: Groq (fastest) -> GitHub Models -> Stack Overflow -> built-in DSA answers.
47
57
 
48
58
  ## Adding New Functions
49
59
 
@@ -1,6 +1,6 @@
1
1
  # supermegaexplosion
2
2
 
3
- DSA utility library — interactive input helpers, string/math/array algorithms, data structures, and an AI assistant powered by Google Gemini.
3
+ DSA utility library — interactive input helpers, string/math/array algorithms, data structures, and an AI assistant powered by Groq (primary), GitHub Models, and Stack Overflow.
4
4
 
5
5
  ```python
6
6
  from libbs import *
@@ -12,26 +12,35 @@ sieve(100) # primes up to 100
12
12
  max_subarray_sum([-2,1,-3,4,-1,2,1,-5,4]) # 6
13
13
  ListNode.from_list([1,2,3,4,5])
14
14
 
15
- # AI assistant (requires API key + dependency)
15
+ # AI assistant — works out of the box (free embedded Groq key)
16
16
  respond_help("How to reverse a linked list?")
17
+
18
+ # Direct Stack Overflow search — also works out of the box
19
+ stack_overflow("python reverse linked list")
17
20
  ```
18
21
 
19
22
  ## Install
20
23
 
21
24
  ```bash
22
25
  pip install supermegaexplosion # core (zero deps)
23
- pip install supermegaexplosion[ai] # with AI assistant (google-genai)
26
+ pip install supermegaexplosion[ai] # with Groq + GitHub Models
24
27
  ```
25
28
 
26
29
  ## AI Setup
27
30
 
28
- Get a free API key from https://aistudio.google.com/ and set it:
31
+ `respond_help` works immediately with the embedded Groq key. For better quota, set your own:
32
+
33
+ ```bash
34
+ set GROQ_API_KEY=gsk_your_key_here
35
+ ```
36
+
37
+ Optional — GitHub Models fallback:
29
38
 
30
39
  ```bash
31
- set GEMINI_API_KEY=your_api_key_here
40
+ set GITHUB_TOKEN=ghp_your_token_here
32
41
  ```
33
42
 
34
- Then use `respond_help("your question")` free tier gives 60 requests/min, 1500/day.
43
+ Provider chain: Groq (fastest) -> GitHub Models -> Stack Overflow -> built-in DSA answers.
35
44
 
36
45
  ## Adding New Functions
37
46
 
@@ -4,6 +4,7 @@ from libbs.math_utils import *
4
4
  from libbs.arrays import *
5
5
  from libbs.ds import *
6
6
  from libbs.ai_helper import respond_help
7
+ from libbs.so_helper import stack_overflow
7
8
  from libbs.catalog import show_commands, show_command
8
9
 
9
- __version__ = "0.3.1"
10
+ __version__ = "0.4.0"
@@ -1,19 +1,17 @@
1
- import os
2
- import json
3
1
  import base64
2
+ import json
3
+ import os
4
4
  import re
5
- import time
6
5
  import threading
6
+ import time
7
7
 
8
8
  _CONFIG_DIR = os.path.expanduser("~/.config/supermegaexplosion")
9
9
  _CONFIG_FILE = os.path.join(_CONFIG_DIR, "config.json")
10
10
 
11
- _EMBEDDED_KEY = base64.b64decode(
12
- "QVEuQWI4Uk42SVhxTFVmcEpqVlhaTjY3S3lkRFUtNFoxWHZKWXFWMnBPMGMzZHZoSTRISXc="
11
+ _EMBEDDED_GROQ_KEY = base64.b64decode(
12
+ "Z3NrX3A5cWdDQlp3OFFSWDBQdkhtdXphV0dkeWIzRllTd1lJT29Kd25YSnBlRHVod2ZIWHgyQng="
13
13
  ).decode()
14
14
 
15
- _MODELS = ["gemini-2.0-flash-lite", "gemini-2.0-flash"]
16
-
17
15
  _lock = threading.Lock()
18
16
  _request_times = []
19
17
 
@@ -151,8 +149,21 @@ def _save_config(data):
151
149
  json.dump(data, f)
152
150
 
153
151
 
154
- def _get_key(api_key):
155
- return api_key or os.environ.get("GEMINI_API_KEY") or _load_config().get("api_key")
152
+ def _get_groq_key(api_key=None):
153
+ if api_key:
154
+ return api_key
155
+ env = os.environ.get("GROQ_API_KEY")
156
+ if env:
157
+ return env
158
+ cfg = _load_config()
159
+ return cfg.get("groq_key") or _EMBEDDED_GROQ_KEY
160
+
161
+
162
+ def _get_github_token():
163
+ token = os.environ.get("GITHUB_TOKEN")
164
+ if token:
165
+ return token
166
+ return _load_config().get("github_token")
156
167
 
157
168
 
158
169
  def _rate_limit_wait():
@@ -199,6 +210,52 @@ def _find_fallback(query):
199
210
  return None
200
211
 
201
212
 
213
+ def _groq_answer(query, api_key=None):
214
+ from groq import Groq
215
+ key = _get_groq_key(api_key)
216
+ client = Groq(api_key=key)
217
+ response = client.chat.completions.create(
218
+ model="llama-3.1-8b-instant",
219
+ messages=[
220
+ {"role": "system", "content": "You are a DSA and Python coding assistant. Answer concisely with code examples."},
221
+ {"role": "user", "content": query},
222
+ ],
223
+ max_tokens=512,
224
+ temperature=0.3,
225
+ )
226
+ return response.choices[0].message.content
227
+
228
+
229
+ def _github_answer(query):
230
+ token = _get_github_token()
231
+ if not token:
232
+ raise RuntimeError("GITHUB_TOKEN not set")
233
+ from azure.ai.inference import ChatCompletionsClient
234
+ from azure.core.credentials import AzureKeyCredential
235
+ client = ChatCompletionsClient(
236
+ endpoint="https://models.inference.ai.azure.com",
237
+ credential=AzureKeyCredential(token),
238
+ )
239
+ response = client.complete(
240
+ messages=[
241
+ {"role": "system", "content": "You are a DSA and Python coding assistant. Answer concisely with code examples."},
242
+ {"role": "user", "content": query},
243
+ ],
244
+ model="gpt-4o-mini",
245
+ max_tokens=512,
246
+ temperature=0.3,
247
+ )
248
+ return response.choices[0].message.content
249
+
250
+
251
+ def _so_answer(query):
252
+ from libbs.so_helper import stack_overflow
253
+ result = stack_overflow(query)
254
+ if not result or result.startswith("No results") or "error" in result.lower():
255
+ raise RuntimeError(result or "No answer from Stack Overflow")
256
+ return result
257
+
258
+
202
259
  def respond_help(query=None, api_key=None):
203
260
  interactive = query is None
204
261
  if interactive:
@@ -208,81 +265,37 @@ def respond_help(query=None, api_key=None):
208
265
 
209
266
  fallback = _find_fallback(query)
210
267
 
211
- try:
212
- from google import genai
213
- except ImportError:
214
- print(
215
- "Missing dependency. Install with:\n"
216
- " pip install supermegaexplosion[ai]"
217
- )
218
- if fallback:
219
- print("\n Here's a built-in answer:\n")
220
- print(fallback)
221
- return
222
-
223
- key = _get_key(api_key)
224
-
225
- if not key:
226
- print(
227
- "No API key found. Using a shared demo key (rate-limited).\n"
228
- "Set your own free key at https://aistudio.google.com/ for better quota.\n"
229
- )
230
- key = _EMBEDDED_KEY
231
- _save_config({"api_key": ""})
232
-
233
- if key == _EMBEDDED_KEY and not _load_config().get("api_key"):
234
- if interactive:
235
- try:
236
- ans = input("Enter your Gemini API key (or press Enter to use the demo key): ").strip()
237
- if ans:
238
- key = ans
239
- _save_config({"api_key": ans})
240
- except (EOFError, OSError):
241
- pass
242
-
243
- wait = _rate_limit_wait()
244
- if wait > 0:
245
- _countdown(wait, "Cooling down")
246
-
247
- client = genai.Client(api_key=key)
248
- last_error = None
249
-
250
- for attempt in range(4):
251
- for model_name in _MODELS:
268
+ providers = [
269
+ ("Groq", lambda: _groq_answer(query, api_key)),
270
+ ("GitHub Models", lambda: _github_answer(query)),
271
+ ("Stack Overflow", lambda: _so_answer(query)),
272
+ ]
273
+
274
+ for name, func in providers:
275
+ for attempt in range(3):
276
+ wait = _rate_limit_wait()
277
+ if wait > 0:
278
+ _countdown(wait, "Cooling down")
279
+
252
280
  try:
253
- resp = client.models.generate_content(
254
- model=model_name,
255
- contents=(
256
- "You are a DSA and Python coding assistant. "
257
- "Answer concisely with code examples.\n\n"
258
- f"Question: {query}"
259
- ),
260
- config={"max_output_tokens": 512, "temperature": 0.3},
261
- )
262
- print(resp.text)
263
- return
281
+ result = func()
282
+ if result:
283
+ print(result)
284
+ return
285
+ except ImportError:
286
+ break
264
287
  except Exception as e:
265
- last_error = e
266
- msg = str(e)
267
-
268
- if "limit: 0" in msg or "PERMISSION_DENIED" in msg:
269
- continue
270
-
271
- if "429" in msg or "RESOURCE_EXHAUSTED" in msg:
272
- delay = _extract_retry_delay(msg)
273
- if delay:
274
- _countdown(min(delay, 30), "Quota hit")
275
- elif attempt < 3:
276
- _countdown(5 * (attempt + 1), f"Retry {attempt + 1}/3")
277
- else:
278
- break
288
+ error = str(e)
289
+ if not error:
290
+ break
291
+ err_lower = error.lower()
292
+ if attempt < 2 and ("429" in error or "quota" in err_lower or "limit" in err_lower or "rate" in err_lower):
293
+ delay = _extract_retry_delay(error)
294
+ _countdown(delay or 5 * (attempt + 1), f"Retry {name} {attempt+1}/2")
295
+ else:
279
296
  break
280
297
 
281
298
  if fallback:
282
- print("\n [!] AI unavailable. Here's a built-in answer:\n")
283
299
  print(fallback)
284
300
  else:
285
- print(
286
- "\n [X] AI quota exhausted. Set your own key or try again later:\n"
287
- " set GEMINI_API_KEY=your_key"
288
- )
301
+ print("No answer found. Try: stack_overflow('your question here')")
@@ -55,7 +55,8 @@ COMMANDS = {
55
55
  "has_path_sum": "Check if root-to-leaf path sums to target.",
56
56
  },
57
57
  "AI Assistant": {
58
- "respond_help": "Ask a coding/DSA question via Google Gemini (free, needs GEMINI_API_KEY env var).",
58
+ "respond_help": "Ask a coding/DSA question via Groq (AI, free) with automatic fallback to GitHub Models, Stack Overflow, and built-in answers.",
59
+ "stack_overflow": "Search Stack Overflow directly. Returns top-voted answers with code. No API key needed (embedded key provided).",
59
60
  },
60
61
  }
61
62
 
@@ -0,0 +1,62 @@
1
+ import base64
2
+ import html
3
+ import json
4
+ import os
5
+ import re
6
+ import urllib.parse
7
+ import urllib.request
8
+ import urllib.error
9
+
10
+ _EMBEDDED_SO_KEY = base64.b64decode("cmxfUWFuS1lNMkhWVzRRZVZGTHRqWE4xaGlOdg==").decode()
11
+
12
+
13
+ def _resolve_key(api_key=None):
14
+ if api_key:
15
+ return api_key
16
+ env = os.environ.get("STACK_OVERFLOW_KEY")
17
+ if env:
18
+ return env
19
+ return _EMBEDDED_SO_KEY
20
+
21
+
22
+ def stack_overflow(query, api_key=None):
23
+ key = _resolve_key(api_key)
24
+ params = {
25
+ "order": "desc",
26
+ "sort": "votes",
27
+ "q": query,
28
+ "key": key,
29
+ "site": "stackoverflow",
30
+ "pagesize": 2,
31
+ "filter": "withbody",
32
+ }
33
+ url = "https://api.stackexchange.com/2.3/search/advanced?" + urllib.parse.urlencode(params)
34
+
35
+ try:
36
+ with urllib.request.urlopen(url, timeout=15) as resp:
37
+ data = json.loads(resp.read().decode())
38
+ except Exception as e:
39
+ return f"Stack Overflow API error: {e}"
40
+
41
+ if "items" not in data or not data["items"]:
42
+ return "No results found on Stack Overflow."
43
+
44
+ result_parts = []
45
+ for item in data["items"][:2]:
46
+ title = item.get("title", "Untitled")
47
+ score = item.get("score", 0)
48
+ body = item.get("body", "")
49
+
50
+ codes = re.findall(r"<pre><code>(.*?)</code></pre>", body, re.DOTALL)
51
+ text = html.unescape(re.sub(r"<[^>]+>", "", body))[:300].strip()
52
+
53
+ result_parts.append(f"[{score} votes] {title}")
54
+ result_parts.append(f" {text}\n")
55
+ for code in codes[:2]:
56
+ cleaned = html.unescape(code.strip())
57
+ result_parts.append(f" ---")
58
+ for line in cleaned.split("\n"):
59
+ result_parts.append(f" {line}")
60
+ result_parts.append("")
61
+
62
+ return "\n".join(result_parts).strip()
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "supermegaexplosion"
7
- version = "0.3.1"
7
+ version = "0.4.0"
8
8
  description = "DSA utility library — input helpers, algorithms, data structures, and AI assistant"
9
9
  readme = "README.md"
10
10
  authors = [{ name = "Hadoopnb.ai", email = "hadoopnb@example.com" }]
@@ -15,4 +15,4 @@ classifiers = [
15
15
  requires-python = ">=3.8"
16
16
 
17
17
  [project.optional-dependencies]
18
- ai = ["google-genai"]
18
+ ai = ["groq", "azure-ai-inference"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: supermegaexplosion
3
- Version: 0.3.1
3
+ Version: 0.4.0
4
4
  Summary: DSA utility library — input helpers, algorithms, data structures, and AI assistant
5
5
  Author-email: "Hadoopnb.ai" <hadoopnb@example.com>
6
6
  License-Expression: MIT
@@ -8,11 +8,12 @@ Classifier: Programming Language :: Python :: 3
8
8
  Requires-Python: >=3.8
9
9
  Description-Content-Type: text/markdown
10
10
  Provides-Extra: ai
11
- Requires-Dist: google-genai; extra == "ai"
11
+ Requires-Dist: groq; extra == "ai"
12
+ Requires-Dist: azure-ai-inference; extra == "ai"
12
13
 
13
14
  # supermegaexplosion
14
15
 
15
- DSA utility library — interactive input helpers, string/math/array algorithms, data structures, and an AI assistant powered by Google Gemini.
16
+ DSA utility library — interactive input helpers, string/math/array algorithms, data structures, and an AI assistant powered by Groq (primary), GitHub Models, and Stack Overflow.
16
17
 
17
18
  ```python
18
19
  from libbs import *
@@ -24,26 +25,35 @@ sieve(100) # primes up to 100
24
25
  max_subarray_sum([-2,1,-3,4,-1,2,1,-5,4]) # 6
25
26
  ListNode.from_list([1,2,3,4,5])
26
27
 
27
- # AI assistant (requires API key + dependency)
28
+ # AI assistant — works out of the box (free embedded Groq key)
28
29
  respond_help("How to reverse a linked list?")
30
+
31
+ # Direct Stack Overflow search — also works out of the box
32
+ stack_overflow("python reverse linked list")
29
33
  ```
30
34
 
31
35
  ## Install
32
36
 
33
37
  ```bash
34
38
  pip install supermegaexplosion # core (zero deps)
35
- pip install supermegaexplosion[ai] # with AI assistant (google-genai)
39
+ pip install supermegaexplosion[ai] # with Groq + GitHub Models
36
40
  ```
37
41
 
38
42
  ## AI Setup
39
43
 
40
- Get a free API key from https://aistudio.google.com/ and set it:
44
+ `respond_help` works immediately with the embedded Groq key. For better quota, set your own:
45
+
46
+ ```bash
47
+ set GROQ_API_KEY=gsk_your_key_here
48
+ ```
49
+
50
+ Optional — GitHub Models fallback:
41
51
 
42
52
  ```bash
43
- set GEMINI_API_KEY=your_api_key_here
53
+ set GITHUB_TOKEN=ghp_your_token_here
44
54
  ```
45
55
 
46
- Then use `respond_help("your question")` free tier gives 60 requests/min, 1500/day.
56
+ Provider chain: Groq (fastest) -> GitHub Models -> Stack Overflow -> built-in DSA answers.
47
57
 
48
58
  ## Adding New Functions
49
59
 
@@ -7,6 +7,7 @@ libbs/catalog.py
7
7
  libbs/ds.py
8
8
  libbs/input_utils.py
9
9
  libbs/math_utils.py
10
+ libbs/so_helper.py
10
11
  libbs/strings.py
11
12
  libbs/tools/__init__.py
12
13
  libbs/tools/add_func.py
@@ -0,0 +1,4 @@
1
+
2
+ [ai]
3
+ groq
4
+ azure-ai-inference
@@ -1,3 +0,0 @@
1
-
2
- [ai]
3
- google-genai