Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions GROK_INTEGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
Grok bot integration for Codespaces Jupyter

Overview
- Adds a minimal Grok API client and an IPython magic to call it from notebooks.

Authentication
- Set the GROK_API_KEY environment variable to your API key, e.g. in Codespaces /devcontainer.json or your shell:

export GROK_API_KEY="sk-..." # Linux/macOS
# PowerShell
$env:GROK_API_KEY = "sk-..."

- Optionally set GROK_API_URL to a custom endpoint if your provider requires it.

Usage in notebooks
- Load the extension once per kernel:

%load_ext grok_bot.magic

- Use line magic:

%grok What is the summary of this dataset?

- Use cell magic for multi-line prompts:

%%grok
Analyze the following:
- Column A distribution
- Suggestions for visualization

Notes
- The client uses the GROK_API_KEY env var by default. The API URL is configurable via GROK_API_URL.
- Error handling prints helpful messages in the notebook; exceptions from the HTTP client are surfaced as text.

Developer notes
- The package lives in grok_bot/ and exposes GrokClient and IPython extension loader.
- Requirements updated to include `requests`.

Security
- Do not commit API keys to the repository. Prefer Codespaces secrets or devcontainer environment variables.
4 changes: 4 additions & 0 deletions grok_bot/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .api import GrokClient
from .magic import load_ipython_extension, unload_ipython_extension

__all__ = ["GrokClient", "load_ipython_extension", "unload_ipython_extension"]
34 changes: 34 additions & 0 deletions grok_bot/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import os
import requests
from typing import Optional


class GrokClient:
"""Minimal Grok API wrapper.

Authentication: set the GROK_API_KEY environment variable (or pass api_key).
Configure endpoint with GROK_API_URL if your provider uses a custom URL.
"""

def __init__(self, api_key: Optional[str] = None, api_url: Optional[str] = None, timeout: int = 30):
self.api_key = api_key or os.getenv("GROK_API_KEY")
self.api_url = api_url or os.getenv("GROK_API_URL") or "https://api.grok.example/v1/complete"
self.timeout = timeout
if not self.api_key:
raise ValueError("GROK_API_KEY environment variable not set. Set it or pass api_key to GrokClient.")

def ask(self, prompt: str, model: str = "grok-1") -> str:
payload = {"model": model, "prompt": prompt}
headers = {"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"}
try:
resp = requests.post(self.api_url, json=payload, headers=headers, timeout=self.timeout)
resp.raise_for_status()
data = resp.json()
# Support a couple common response shapes
if isinstance(data, dict) and "text" in data:
return data["text"]
if isinstance(data, dict) and "choices" in data and data["choices"]:
return data["choices"][0].get("text") or str(data)
return str(data)
except requests.RequestException as e:
raise RuntimeError(f"Grok API request failed: {e}") from e
48 changes: 48 additions & 0 deletions grok_bot/magic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from IPython.core.magic import Magics, magics_class, line_cell_magic
from IPython.display import Markdown, display
from .api import GrokClient
import os


@magics_class
class GrokMagics(Magics):
def __init__(self, shell):
super().__init__(shell)
api_key = os.getenv("GROK_API_KEY")
self.client = None
if api_key:
try:
self.client = GrokClient(api_key=api_key)
except Exception:
self.client = None

@line_cell_magic
def grok(self, line, cell=None):
"""%grok <prompt> or %%grok <multi-line prompt>

Outputs Grok's response as rendered Markdown.
"""
prompt = cell if cell is not None else line
if not prompt:
print("Usage: %grok <prompt> or %%grok <multi-line prompt>")
return
if not self.client:
try:
self.client = GrokClient()
except Exception as e:
print(f"Grok client initialization error: {e}")
return
try:
resp = self.client.ask(prompt)
display(Markdown("**Grok**\n\n" + resp))
except Exception as e:
print(f"Grok request failed: {e}")


def load_ipython_extension(ipython):
ipython.register_magics(GrokMagics)


def unload_ipython_extension(ipython):
# IPython does not provide a stable unregister API for magics; keep this as a noop.
pass
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ pillow>=12.1.1
fonttools>=4.60.0
filelock>=3.20.3
Pygments==2.20.0
requests>=2.30.0