coreinsight-cli 0.1.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Varun Jani
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,115 @@
1
+ Metadata-Version: 2.4
2
+ Name: coreinsight-cli
3
+ Version: 0.1.0
4
+ Summary: Local-first AI performance profiler that mathematically verifies optimizations for Python, C++, and CUDA
5
+ Author: Varun Jani
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Prais3/coreinsight_cli
8
+ Project-URL: Bug Tracker, https://github.com/Prais3/coreinsight_cli/issues
9
+ Keywords: performance,profiling,optimization,llm,cuda,cpp,python,hpc,benchmarking
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Topic :: Software Development :: Debuggers
18
+ Classifier: Topic :: System :: Hardware
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: rich>=13.0
23
+ Requires-Dist: docker>=6.0
24
+ Requires-Dist: tree-sitter==0.21.3
25
+ Requires-Dist: tree-sitter-languages
26
+ Requires-Dist: langchain>=0.2.0
27
+ Requires-Dist: langchain-core>=0.2.0
28
+ Requires-Dist: langchain-ollama>=0.1.0
29
+ Requires-Dist: langchain-google-genai>=1.0.0
30
+ Requires-Dist: langchain-openai>=0.1.0
31
+ Requires-Dist: langchain-anthropic>=0.1.0
32
+ Requires-Dist: pydantic>=2.0
33
+ Requires-Dist: chromadb>=0.5.0
34
+ Requires-Dist: sentence-transformers>=3.0.0
35
+ Requires-Dist: psutil>=5.9
36
+ Dynamic: license-file
37
+
38
+ # CoreInsight CLI
39
+
40
+ CoreInsight is a local-first, hardware-aware AI performance profiler. It shifts performance engineering "left" by parsing your Python, C++, and CUDA code, identifying hardware bottlenecks (like CPU cache thrashing or CUDA warp divergence), and mathematically verifying AI-generated optimizations inside secure Docker sandboxes.
41
+
42
+ ## Prerequisites
43
+
44
+ * **Python 3.9+**
45
+ * **Docker Desktop / Docker Engine** (Must be running for the sandbox verification)
46
+ * **Ollama** (Optional, if using local models) or API keys for cloud models.
47
+
48
+ ## Installation & Usage
49
+
50
+ **Required: Install Docker: https://docs.docker.com/engine/install/**
51
+
52
+ **Optional (Suggested): Setup OpenAI/Anthropic/Google API keys to load their models**
53
+
54
+ **1. Build locally:**
55
+ Clone this repository and install it in editable mode:
56
+ ```bash
57
+ pip install -e .
58
+ ```
59
+
60
+ **2. Configure CoreInsight CLI:**
61
+ Set up your preferred AI provider (Ollama, local vLLM, OpenAI, Anthropic, or Gemini):
62
+ ```bash
63
+ coreinsight configure
64
+ ```
65
+
66
+ **3. Build Global Context (Recommended for multiple files):**
67
+ Index your repository so the AI understands your custom structs, classes, and dependencies across files:
68
+ ```bash
69
+ coreinsight index
70
+ ```
71
+
72
+ **4. Test on a file:**
73
+ Analyze a specific file. The CLI will extract hot loops, process them in parallel, verify optimizations in Docker, and output a live Markdown report.
74
+ ```bash
75
+ coreinsight analyze <file_name>
76
+ ```
77
+
78
+ **5. Project-Wide Hotspot Scanning:**
79
+ Instead of guessing which files are slow, scan your entire repository. CoreInsight will use static AST analysis to rank the most complex, deeply-nested loops in your project.
80
+ ```bash
81
+ coreinsight scan
82
+ ```
83
+
84
+ ## Build the Project
85
+
86
+ Download build:
87
+ ```bash
88
+ pip install build
89
+ ```
90
+
91
+ Run the build command to generate wheel file:
92
+ ```bash
93
+ python -m build --wheel
94
+ ```
95
+
96
+ To build project elsewhere using wheel file:
97
+ ```bash
98
+ pip install dist/coreinsight_cli-*.whl
99
+ ```
100
+
101
+ To build project using source code:
102
+ ```bash
103
+ pip install -e .
104
+ ```
105
+
106
+ ### Architecture Notes
107
+ CoreInsight runs 100% locally. Code is only transmitted to the AI provider you configure. If you use Ollama or a local server, your proprietary code never leaves your machine.
108
+
109
+ ## Current/Future Features In Progess:
110
+
111
+ - Improve AST parsing
112
+ - Extract and integrate hardware information for the LLM
113
+ - Improve CLI interface
114
+ - Parallel execution
115
+ - Improve RAG
@@ -0,0 +1,78 @@
1
+ # CoreInsight CLI
2
+
3
+ CoreInsight is a local-first, hardware-aware AI performance profiler. It shifts performance engineering "left" by parsing your Python, C++, and CUDA code, identifying hardware bottlenecks (like CPU cache thrashing or CUDA warp divergence), and mathematically verifying AI-generated optimizations inside secure Docker sandboxes.
4
+
5
+ ## Prerequisites
6
+
7
+ * **Python 3.9+**
8
+ * **Docker Desktop / Docker Engine** (Must be running for the sandbox verification)
9
+ * **Ollama** (Optional, if using local models) or API keys for cloud models.
10
+
11
+ ## Installation & Usage
12
+
13
+ **Required: Install Docker: https://docs.docker.com/engine/install/**
14
+
15
+ **Optional (Suggested): Setup OpenAI/Anthropic/Google API keys to load their models**
16
+
17
+ **1. Build locally:**
18
+ Clone this repository and install it in editable mode:
19
+ ```bash
20
+ pip install -e .
21
+ ```
22
+
23
+ **2. Configure CoreInsight CLI:**
24
+ Set up your preferred AI provider (Ollama, local vLLM, OpenAI, Anthropic, or Gemini):
25
+ ```bash
26
+ coreinsight configure
27
+ ```
28
+
29
+ **3. Build Global Context (Recommended for multiple files):**
30
+ Index your repository so the AI understands your custom structs, classes, and dependencies across files:
31
+ ```bash
32
+ coreinsight index
33
+ ```
34
+
35
+ **4. Test on a file:**
36
+ Analyze a specific file. The CLI will extract hot loops, process them in parallel, verify optimizations in Docker, and output a live Markdown report.
37
+ ```bash
38
+ coreinsight analyze <file_name>
39
+ ```
40
+
41
+ **5. Project-Wide Hotspot Scanning:**
42
+ Instead of guessing which files are slow, scan your entire repository. CoreInsight will use static AST analysis to rank the most complex, deeply-nested loops in your project.
43
+ ```bash
44
+ coreinsight scan
45
+ ```
46
+
47
+ ## Build the Project
48
+
49
+ Download build:
50
+ ```bash
51
+ pip install build
52
+ ```
53
+
54
+ Run the build command to generate wheel file:
55
+ ```bash
56
+ python -m build --wheel
57
+ ```
58
+
59
+ To build project elsewhere using wheel file:
60
+ ```bash
61
+ pip install dist/coreinsight_cli-*.whl
62
+ ```
63
+
64
+ To build project using source code:
65
+ ```bash
66
+ pip install -e .
67
+ ```
68
+
69
+ ### Architecture Notes
70
+ CoreInsight runs 100% locally. Code is only transmitted to the AI provider you configure. If you use Ollama or a local server, your proprietary code never leaves your machine.
71
+
72
+ ## Current/Future Features In Progess:
73
+
74
+ - Improve AST parsing
75
+ - Extract and integrate hardware information for the LLM
76
+ - Improve CLI interface
77
+ - Parallel execution
78
+ - Improve RAG
@@ -0,0 +1,2 @@
1
+ FROM gcc:latest
2
+ WORKDIR /workspace
@@ -0,0 +1,3 @@
1
+ FROM python:3.11-slim
2
+ RUN pip install --no-cache-dir numpy pandas scipy matplotlib
3
+ WORKDIR /workspace
File without changes
@@ -0,0 +1,374 @@
1
+ import re
2
+ import logging
3
+ from typing import Optional, List
4
+ from pydantic import BaseModel, Field
5
+
6
+ from langchain_core.output_parsers import JsonOutputParser
7
+ from langchain_core.prompts import PromptTemplate
8
+ from langchain_core.exceptions import OutputParserException
9
+
10
+ from langchain_ollama import ChatOllama
11
+ from langchain_google_genai import ChatGoogleGenerativeAI
12
+ from langchain_openai import ChatOpenAI
13
+ from langchain_anthropic import ChatAnthropic
14
+
15
+ from coreinsight.prompts import SYSTEM_PROMPT, ANALYSIS_TEMPLATE
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class Bottleneck(BaseModel):
21
+ line: int = Field(description="The approximate line number of the issue in the original code")
22
+ severity: str = Field(description="Critical, High, Medium, Low")
23
+ message: str = Field(description="Specific hardware or algorithmic bottleneck at this line")
24
+ suggestion: str = Field(description="How to fix this specific line")
25
+
26
+
27
+ class AuditResult(BaseModel):
28
+ severity: str = Field(description="Overall severity: Critical, High, Medium, Low")
29
+ issue: str = Field(description="Brief overall description of the bottleneck")
30
+ reasoning: str = Field(description="Step-by-step hardware-level reasoning for the proposed changes")
31
+ suggestion: str = Field(description="Overall specific fix strategy")
32
+ bottlenecks: List[Bottleneck] = Field(description="List of specific line-level bottlenecks", default_factory=list)
33
+ optimized_code: Optional[str] = Field(description="The entirely rewritten optimized code, ready to drop in", default=None)
34
+
35
+
36
+ _HARNESS_TEMPLATE = """
37
+ You are a strict QA engineer writing a standalone asymptotic scaling benchmark script in {language}.
38
+
39
+ ORIGINAL FUNCTION (Name: {func_name}):
40
+ {original}
41
+
42
+ OPTIMIZED FUNCTION:
43
+ {optimized}
44
+
45
+ GLOBAL DEPENDENCIES (Helper functions/structs required to run the code):
46
+ {context}
47
+
48
+ Write the complete executable script (e.g., `int main()` or `if __name__ == "__main__":`) that:
49
+ 1. Includes necessary imports/headers.
50
+ 2. Includes ALL required helper functions or structs from GLOBAL DEPENDENCIES so the script is fully standalone.
51
+ 3. Defines BOTH the original and optimized functions exactly as provided above.
52
+ 4. Tests multiple data sizes (e.g., N=10, 100, 1000, 5000).
53
+ 5. Target Hardware: {hardware_target}. The largest N MUST cross cache boundaries but MUST NOT exceed 20% of available RAM to prevent OOM crashes.
54
+ 6. Initializes realistic dummy data for each size N.
55
+ 7. Times execution of original vs optimized using high-resolution timers.
56
+
57
+ CRITICAL TIMING:
58
+ - Python: use `time.perf_counter()`. C++: use `std::chrono::high_resolution_clock`.
59
+ - Clamp: `orig_time = max(end - start, 1e-9)` to prevent zero-division.
60
+ - Speedup: `speedup = orig_time / opt_time`.
61
+
62
+ ISOLATION RULES (CRITICAL):
63
+ - This runs in an empty Docker container. NO local files exist.
64
+ - DO NOT use local imports. Define everything inline.
65
+ - DO NOT rename the original function — call it exactly `{func_name}`.
66
+
67
+ OUTPUT FORMAT (CRITICAL):
68
+ Print ONLY this exact CSV to stdout, no other text:
69
+ N,Original_Time,Optimized_Time,Speedup
70
+ 10,0.002,0.001,2.00
71
+
72
+ [PYTHON ONLY]: Also import matplotlib, plot results, and save as `benchmark_plot.png`.
73
+
74
+ FORMATTING RULE: Wrap your ENTIRE script in a single markdown code block. No text before or after.
75
+ """
76
+
77
+ _FIX_TEMPLATE = """
78
+ You are an expert {language} developer. Your previous benchmark script FAILED in an isolated sandbox.
79
+
80
+ ORIGINAL FUNCTION (Name: {func_name}):
81
+ {original}
82
+
83
+ GLOBAL DEPENDENCIES:
84
+ {context}
85
+
86
+ YOUR FAILED SCRIPT:
87
+ {bad_harness}
88
+
89
+ EXECUTION ERROR LOGS:
90
+ {error_logs}
91
+
92
+ ISOLATION CONSTRAINTS (CRITICAL):
93
+ - Empty Docker container. No local files. NO local imports.
94
+ - Define `{func_name}` and all GLOBAL DEPENDENCIES inline.
95
+
96
+ FIX INSTRUCTIONS:
97
+ 1. Diagnose the failure from the error logs above.
98
+ 2. Fix imports, NameErrors, type mismatches, infinite loops, or OOM issues.
99
+ 3. Maintain the CSV stdout format exactly: N,Original_Time,Optimized_Time,Speedup
100
+ 4. Use high-resolution timers and clamp with `max(t, 1e-9)`.
101
+ 5. [PYTHON ONLY]: Save benchmark plot as `benchmark_plot.png`.
102
+
103
+ FORMATTING RULE: Wrap your ENTIRE fixed script in a single markdown code block. No text before or after.
104
+ """
105
+
106
+ _TEST_CASES_TEMPLATE = """
107
+ You are a QA engineer writing correctness test cases for a function.
108
+
109
+ FUNCTION NAME: {func_name}
110
+ LANGUAGE: {language}
111
+
112
+ FUNCTION SIGNATURE AND BODY:
113
+ {original}
114
+
115
+ GLOBAL DEPENDENCIES (helper functions / structs this function relies on):
116
+ {context}
117
+
118
+ Your task: generate {num_cases} diverse test cases that call `{func_name}` with different
119
+ arguments. The cases must cover:
120
+ - Small inputs (N ~ 10)
121
+ - Medium inputs (N ~ 100-500)
122
+ - Edge cases: empty collections, single-element, all-zeros, negative values (where applicable)
123
+ - Boundary conditions specific to this function's logic
124
+
125
+ OUTPUT FORMAT — respond with ONLY a valid JSON array, nothing else. No markdown fences,
126
+ no explanation. Each element must be a JSON object with exactly two keys:
127
+ "args" : a JSON array of positional arguments (use only JSON-serialisable types:
128
+ numbers, strings, booleans, arrays, objects — NO numpy, NO bytes)
129
+ "kwargs": a JSON object of keyword arguments (may be empty {{}})
130
+
131
+ Example (do NOT copy this — generate cases specific to {func_name}):
132
+ [
133
+ {{"args": [[1, 2, 3]], "kwargs": {{}}}},
134
+ {{"args": [[]], "kwargs": {{}}}},
135
+ {{"args": [[9, -1, 4, 0, 7]], "kwargs": {{"reverse": true}}}}
136
+ ]
137
+
138
+ CONSTRAINTS:
139
+ - All values must be plain JSON types — no numpy arrays, no custom objects.
140
+ - If the function operates on a matrix, represent it as a list-of-lists.
141
+ - If the function takes a size integer N, generate concrete data of that size inline.
142
+ - Do NOT include function calls or expressions — only literal values.
143
+ - Produce exactly {num_cases} test cases.
144
+ """
145
+
146
+
147
+ class AnalyzerAgent:
148
+ def __init__(self, provider="ollama", model_name="llama3.2", api_keys=None):
149
+ self.parser = JsonOutputParser(pydantic_object=AuditResult)
150
+ self.provider = provider
151
+ api_keys = api_keys or {}
152
+
153
+ if provider == "openai":
154
+ if not api_keys.get("openai"):
155
+ raise ValueError("OpenAI API Key required.")
156
+ self.base_llm = ChatOpenAI(
157
+ model=model_name,
158
+ api_key=api_keys["openai"],
159
+ temperature=0.1,
160
+ model_kwargs={"response_format": {"type": "json_object"}},
161
+ )
162
+ self.json_llm = self.base_llm
163
+
164
+ elif provider == "local_server":
165
+ base_url = api_keys.get("local_url", "http://localhost:1234/v1")
166
+ self.base_llm = ChatOpenAI(
167
+ model=model_name,
168
+ api_key="not-needed",
169
+ base_url=base_url,
170
+ temperature=0.1,
171
+ model_kwargs={"response_format": {"type": "json_object"}},
172
+ )
173
+ self.json_llm = self.base_llm
174
+
175
+ elif provider == "anthropic":
176
+ if not api_keys.get("anthropic"):
177
+ raise ValueError("Anthropic API Key required.")
178
+ self.base_llm = ChatAnthropic(
179
+ model=model_name,
180
+ api_key=api_keys["anthropic"],
181
+ temperature=0.1,
182
+ )
183
+ # Anthropic doesn't support response_format; JSON is enforced via prompt only
184
+ self.json_llm = self.base_llm
185
+
186
+ elif provider == "google":
187
+ if not api_keys.get("google"):
188
+ raise ValueError("Google Gemini API Key required.")
189
+ self.base_llm = ChatGoogleGenerativeAI(
190
+ model=model_name,
191
+ google_api_key=api_keys["google"],
192
+ temperature=0.1,
193
+ convert_system_message_to_human=True,
194
+ )
195
+ self.json_llm = self.base_llm
196
+
197
+ else: # Ollama default
198
+ self.base_llm = ChatOllama(
199
+ model=model_name,
200
+ temperature=0.1,
201
+ num_predict=4096,
202
+ num_ctx=8192,
203
+ )
204
+ self.json_llm = self.base_llm.bind(format="json")
205
+
206
+ self.prompt = PromptTemplate(
207
+ template=ANALYSIS_TEMPLATE + "\n\n{format_instructions}",
208
+ input_variables=["language", "code_content", "context", "hardware_target"],
209
+ partial_variables={
210
+ "system_prompt": SYSTEM_PROMPT,
211
+ "format_instructions": self.parser.get_format_instructions(),
212
+ },
213
+ )
214
+ self.chain = self.prompt | self.json_llm | self.parser
215
+
216
+ def analyze(self, code: str, language: str, context: str = "", hardware_target: str = "Generic CPU"):
217
+ try:
218
+ return self.chain.invoke({
219
+ "language": language,
220
+ "code_content": code,
221
+ "context": context,
222
+ "hardware_target": hardware_target,
223
+ })
224
+ except OutputParserException:
225
+ return {
226
+ "severity": "Error",
227
+ "issue": "AI Output Parsing Failed",
228
+ "reasoning": "The model failed to return valid JSON.",
229
+ "suggestion": "Try running the analysis again or use a larger parameter model.",
230
+ "bottlenecks": [],
231
+ "optimized_code": None,
232
+ }
233
+ except Exception as e:
234
+ return {
235
+ "severity": "Error",
236
+ "issue": str(e),
237
+ "reasoning": "System error during analysis pipeline.",
238
+ "suggestion": "Check LLM API keys and connectivity.",
239
+ "bottlenecks": [],
240
+ "optimized_code": None,
241
+ }
242
+
243
+ def _extract_executable_code(self, response_text: str) -> str:
244
+ """Extract the first/longest fenced code block from model output."""
245
+ blocks = re.findall(r"```[a-zA-Z+#]*\s*\n(.*?)```", response_text, re.DOTALL)
246
+ if blocks:
247
+ return max(blocks, key=len).strip()
248
+
249
+ # Fallback: strip fence markers line by line to avoid corrupting code
250
+ lines = response_text.strip().split("\n")
251
+ lines = [l for l in lines if not re.match(r"^```", l)]
252
+ while lines and lines[0].lower().startswith(("here is", "sure", "certainly", "output:")) \
253
+ and not lines[0].strip().startswith(("#", "//")):
254
+ lines.pop(0)
255
+ return "\n".join(lines).strip()
256
+
257
+ def _invoke_code_chain(self, template: str, variables: dict, language: str) -> str:
258
+ """Shared invocation + extraction logic for harness and fix chains."""
259
+ chain = PromptTemplate.from_template(template) | self.base_llm
260
+ result = chain.invoke(variables)
261
+ raw = result.content if hasattr(result, "content") else str(result)
262
+ # Handle Anthropic returning a list of content blocks
263
+ if isinstance(raw, list):
264
+ raw = "\n".join(
265
+ item["text"] if isinstance(item, dict) and "text" in item else str(item)
266
+ for item in raw
267
+ )
268
+ return self._extract_executable_code(raw)
269
+
270
+ def generate_harness(
271
+ self,
272
+ func_name: str,
273
+ original_code: str,
274
+ optimized_code: str,
275
+ language: str,
276
+ context: str = "",
277
+ hardware_target: str = "Generic CPU",
278
+ ) -> str:
279
+ try:
280
+ return self._invoke_code_chain(
281
+ _HARNESS_TEMPLATE,
282
+ {
283
+ "language": language,
284
+ "func_name": func_name,
285
+ "original": original_code,
286
+ "optimized": optimized_code,
287
+ "context": context,
288
+ "hardware_target": hardware_target,
289
+ },
290
+ language,
291
+ )
292
+ except Exception as e:
293
+ is_python = language.lower() == "python"
294
+ opener = "#" if is_python else "//"
295
+ entry = 'if __name__ == "__main__":' if is_python else "int main() {"
296
+ stub = " pass" if is_python else " return 1;\n}"
297
+ return f"{opener} Failed to generate harness: {e}\n{entry}\n{stub}"
298
+
299
+ def fix_harness(
300
+ self,
301
+ func_name: str,
302
+ original_code: str,
303
+ bad_harness: str,
304
+ error_logs: str,
305
+ language: str,
306
+ context: str = "",
307
+ ) -> str:
308
+ try:
309
+ return self._invoke_code_chain(
310
+ _FIX_TEMPLATE,
311
+ {
312
+ "language": language,
313
+ "func_name": func_name,
314
+ "original": original_code,
315
+ "bad_harness": bad_harness,
316
+ "error_logs": error_logs,
317
+ "context": context,
318
+ },
319
+ language,
320
+ )
321
+ except Exception as e:
322
+ is_python = language.lower() == "python"
323
+ opener = "#" if is_python else "//"
324
+ return f"{opener} Failed to fix harness: {e}"
325
+
326
+ def generate_test_cases(
327
+ self,
328
+ func_name: str,
329
+ original_code: str,
330
+ language: str,
331
+ context: str = "",
332
+ num_cases: int = 8,
333
+ ) -> list:
334
+ """
335
+ Ask the LLM to generate diverse, JSON-serialisable test cases for
336
+ `func_name` so the sandbox can run correctness verification.
337
+
338
+ Returns a list of {"args": [...], "kwargs": {...}} dicts, or an
339
+ empty list if generation or parsing fails (sandbox skips gracefully).
340
+ """
341
+ import json
342
+
343
+ chain = PromptTemplate.from_template(_TEST_CASES_TEMPLATE) | self.base_llm
344
+ try:
345
+ result = chain.invoke({
346
+ "func_name": func_name,
347
+ "language": language,
348
+ "original": original_code,
349
+ "context": context or "None",
350
+ "num_cases": num_cases,
351
+ })
352
+ raw = result.content if hasattr(result, "content") else str(result)
353
+ if isinstance(raw, list):
354
+ raw = "\n".join(
355
+ item["text"] if isinstance(item, dict) and "text" in item else str(item)
356
+ for item in raw
357
+ )
358
+
359
+ # Strip markdown fences if the model wrapped anyway
360
+ raw = re.sub(r"```[a-zA-Z]*\s*", "", raw).strip()
361
+
362
+ cases = json.loads(raw)
363
+
364
+ # Validate structure — drop malformed entries silently
365
+ return [
366
+ case for case in cases
367
+ if isinstance(case, dict)
368
+ and isinstance(case.get("args"), list)
369
+ and isinstance(case.get("kwargs"), dict)
370
+ ]
371
+
372
+ except Exception as e:
373
+ logger.warning(f"generate_test_cases failed for '{func_name}': {e}")
374
+ return []
@@ -0,0 +1,51 @@
1
+ import json
2
+ from pathlib import Path
3
+ from rich.console import Console
4
+ from rich.prompt import Prompt, Confirm
5
+
6
+ console = Console()
7
+ CONFIG_FILE = Path.home() / ".coreinsight" / "config.json"
8
+
9
+ def load_config():
10
+ if not CONFIG_FILE.exists():
11
+ return {"provider": "ollama", "model_name": "llama3.2", "api_keys": {}}
12
+ with open(CONFIG_FILE, "r") as f:
13
+ return json.load(f)
14
+
15
+ def save_config(config_data):
16
+ CONFIG_FILE.parent.mkdir(parents=True, exist_ok=True)
17
+ with open(CONFIG_FILE, "w") as f:
18
+ json.dump(config_data, f, indent=4)
19
+
20
+ def run_configure():
21
+ """Interactive CLI to set up models and API keys."""
22
+ console.print("[bold cyan]⚙️ CoreInsight Configuration[/bold cyan]")
23
+
24
+ config = load_config()
25
+
26
+ provider = Prompt.ask(
27
+ "Which AI provider do you want to use?",
28
+ choices=["ollama", "local_server", "openai", "anthropic", "google"],
29
+ default=config.get("provider", "ollama")
30
+ )
31
+
32
+ config["provider"] = provider
33
+
34
+ if provider == "ollama":
35
+ config["model_name"] = Prompt.ask("Ollama model name", default=config.get("model_name", "llama3.2"))
36
+ elif provider == "local_server":
37
+ config["model_name"] = Prompt.ask("Local model name (optional)", default=config.get("model_name", "local-model"))
38
+ config["api_keys"]["local_url"] = Prompt.ask("Local Server Base URL", default="http://localhost:1234/v1")
39
+ elif provider == "openai":
40
+ config["model_name"] = Prompt.ask("OpenAI model name", default="gpt-4o")
41
+ config["api_keys"]["openai"] = Prompt.ask("OpenAI API Key (hidden)", password=True)
42
+ elif provider == "anthropic":
43
+ config["model_name"] = Prompt.ask("Claude model name", default="claude-3-5-sonnet-latest")
44
+ config["api_keys"]["anthropic"] = Prompt.ask("Anthropic API Key (hidden)", password=True)
45
+ elif provider == "google":
46
+ config["model_name"] = Prompt.ask("Gemini model name", default="gemini-1.5-pro")
47
+ config["api_keys"]["google"] = Prompt.ask("Google Gemini API Key (hidden)", password=True)
48
+
49
+ save_config(config)
50
+ console.print("\n[bold green]✅ Configuration saved successfully![/bold green]")
51
+ console.print(f"CoreInsight is now using [bold]{provider}[/bold] ({config['model_name']}).")