{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a3a1f945",
   "metadata": {},
   "source": [
    "# Prompt-to-cell generation\n",
    "\n",
    "`%%there ai` turns a plain-language request into a new `%%there` Python cell.\n",
    "The generated cell is inserted in the notebook below the prompt cell. Review or\n",
    "edit it, then run it on the connected PythonHere device.\n",
    "\n",
    "The AI command is provided by the underlying `herethere` library. PythonHere\n",
    "adds Android/Kivy prompt sections on top of it. For the generic library\n",
    "behavior, see the `herethere` docs:\n",
    "https://herethere.me/library/there_ai.html"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "72ed57ac",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-07T10:31:23.101781Z",
     "iopub.status.busy": "2026-06-07T10:31:23.101403Z",
     "iopub.status.idle": "2026-06-07T10:31:26.348136Z",
     "shell.execute_reply": "2026-06-07T10:31:26.347523Z"
    }
   },
   "outputs": [],
   "source": [
    "%load_ext pythonhere\n",
    "%connect-there"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d50dc25b",
   "metadata": {},
   "source": [
    "## Configure an AI provider\n",
    "\n",
    "`%%there ai` uses an OpenAI-compatible chat API. Put provider settings in\n",
    "`there_ai.env` next to the notebook:\n",
    "\n",
    "```text\n",
    "THERE_AI_MODEL=<model-name>\n",
    "THERE_AI_API_KEY=sk-...\n",
    "THERE_AI_BASE_URL=https://api.openai.com/v1\n",
    "THERE_AI_TEMPERATURE=0.2\n",
    "THERE_AI_TIMEOUT=300\n",
    "```\n",
    "\n",
    "Only `THERE_AI_MODEL` is required for local providers that do not need an API\n",
    "key. Hosted providers usually need `THERE_AI_API_KEY`.\n",
    "\n",
    "`THERE_AI_BASE_URL` defaults to `https://api.openai.com/v1`.\n",
    "`THERE_AI_TEMPERATURE` defaults to `0.2`.\n",
    "`THERE_AI_TIMEOUT` defaults to `300` seconds.\n",
    "\n",
    "Internally, `%%there ai` sends a POST request to\n",
    "`${THERE_AI_BASE_URL}/chat/completions` with `model`, `messages`, and\n",
    "`temperature`, and uses `Authorization: Bearer ${THERE_AI_API_KEY}` when an API\n",
    "key is configured. See the\n",
    "[OpenAI-compatible adapter](https://github.com/b3b/herethere/blob/master/herethere/there/ai/llm.py)\n",
    "for the current implementation.\n",
    "\n",
    "Environment variables with the same names override values from `there_ai.env`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "69ae14e5",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-07T10:31:26.350951Z",
     "iopub.status.busy": "2026-06-07T10:31:26.350736Z",
     "iopub.status.idle": "2026-06-07T10:31:26.353705Z",
     "shell.execute_reply": "2026-06-07T10:31:26.353331Z"
    },
    "tags": [
     "remove-output"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "env: THERE_AI_TIMEOUT=120\n"
     ]
    }
   ],
   "source": [
    "%env THERE_AI_TIMEOUT=120"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a881ac5a",
   "metadata": {},
   "source": [
    "Use a different settings file for the current notebook session:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "b84e025f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-07T10:31:26.355353Z",
     "iopub.status.busy": "2026-06-07T10:31:26.355186Z",
     "iopub.status.idle": "2026-06-07T10:31:26.357542Z",
     "shell.execute_reply": "2026-06-07T10:31:26.357067Z"
    }
   },
   "outputs": [],
   "source": [
    "from herethere.there.ai import set_ai_config_path\n",
    "\n",
    "set_ai_config_path(\"there_ai.local.env\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7768e9d2",
   "metadata": {},
   "source": [
    "Example local-provider settings:\n",
    "\n",
    "```text\n",
    "THERE_AI_MODEL=qwen2.5-coder\n",
    "THERE_AI_BASE_URL=http://localhost:11434/v1\n",
    "THERE_AI_TEMPERATURE=0.1\n",
    "THERE_AI_TIMEOUT=300\n",
    "```\n",
    "\n",
    "## First generated cell\n",
    "\n",
    "Write the request in the cell body:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "cdb3dcd1",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-07T10:31:26.359998Z",
     "iopub.status.busy": "2026-06-07T10:31:26.359785Z",
     "iopub.status.idle": "2026-06-07T10:31:26.365101Z",
     "shell.execute_reply": "2026-06-07T10:31:26.364731Z"
    },
    "tags": [
     "remove-output"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "herethere AI generation is not configured. Set THERE_AI_MODEL. For hosted providers, also set THERE_AI_API_KEY. Optionally set THERE_AI_BASE_URL.\n"
     ]
    }
   ],
   "source": [
    "%%there ai\n",
    "Inspect the live PythonHere runtime.\n",
    "Print Python version, Kivy platform, current working directory, screen size,\n",
    "and whether globals named app and root are available.\n",
    "Store the structured result in pythonhere_ai_runtime_report."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2f35e0b6",
   "metadata": {},
   "source": [
    "The generated cell will be inserted locally as a `%%there` cell. Read it before\n",
    "running it on the connected device.\n",
    "\n",
    "It may look like this:\n",
    "\n",
    "```python\n",
    "%%there\n",
    "# Generated locally by %%there ai. Review before running.\n",
    "import os\n",
    "import platform\n",
    "import sys\n",
    "\n",
    "from kivy import platform as kivy_platform\n",
    "from kivy.core.window import Window\n",
    "\n",
    "pythonhere_ai_runtime_report = {\n",
    "    \"python\": sys.version,\n",
    "    \"platform\": platform.platform(),\n",
    "    \"kivy_platform\": kivy_platform,\n",
    "    \"cwd\": os.getcwd(),\n",
    "    \"window_size\": tuple(Window.size),\n",
    "    \"has_app\": \"app\" in globals(),\n",
    "    \"has_root\": \"root\" in globals(),\n",
    "    \"root_class\": root.__class__.__name__ if \"root\" in globals() else None,\n",
    "}\n",
    "\n",
    "for key, value in pythonhere_ai_runtime_report.items():\n",
    "    print(f\"{key}: {value}\")\n",
    "```\n",
    "\n",
    "## PythonHere prompt context\n",
    "\n",
    "When you load `%load_ext pythonhere`, PythonHere registers prompt sections for\n",
    "Kivy, Android, Pyjnius, permissions, packages, media, and Plyer. Normal\n",
    "`%%there ai` requests use that context automatically.\n",
    "\n",
    "For tasks that need extra context, add a prompt section for one request:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "b215ca44",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-07T10:31:26.366653Z",
     "iopub.status.busy": "2026-06-07T10:31:26.366492Z",
     "iopub.status.idle": "2026-06-07T10:31:26.369568Z",
     "shell.execute_reply": "2026-06-07T10:31:26.369178Z"
    },
    "tags": [
     "remove-output"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "herethere AI generation is not configured. Set THERE_AI_MODEL. For hosted providers, also set THERE_AI_API_KEY. Optionally set THERE_AI_BASE_URL.\n"
     ]
    }
   ],
   "source": [
    "%%there ai --prompts able\n",
    "Build a BLE scanner prototype that lists discovered devices with name, address,\n",
    "RSSI, and last-seen time."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c3abe622",
   "metadata": {},
   "source": [
    "For the full prompt list, source links, custom prompt registration, and prompt\n",
    "composition rules, see [Prompt sections](prompts.md).\n",
    "\n",
    "## Fix a previous cell\n",
    "\n",
    "`%%there ai --fix` generates a replacement `%%there` cell. The AI request uses\n",
    "the active system prompt stack plus the built-in `fix` prompt section. Its user\n",
    "message includes the last executed Python `%%there` magic line, that cell body,\n",
    "and the text you write in the `--fix` cell. It does not automatically include\n",
    "previous output, traceback text, screenshots, remote variables, or live device\n",
    "state. Paste the important error message or requested change into the `--fix`\n",
    "cell body. The old cell is not changed.\n",
    "\n",
    "Run a broken cell:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "efaaf261",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-07T10:31:26.371098Z",
     "iopub.status.busy": "2026-06-07T10:31:26.370915Z",
     "iopub.status.idle": "2026-06-07T10:31:26.708487Z",
     "shell.execute_reply": "2026-06-07T10:31:26.707606Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  File \"<string>\", line 3\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "    root.add_widget(Button(text=\"Click me))\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                ^\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "SyntaxError: unterminated string literal (detected at line 3)\n"
     ]
    }
   ],
   "source": [
    "%%there\n",
    "root.clear_widgets()\n",
    "root.add_widget(Button(text=\"Click me))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d489b9d5",
   "metadata": {},
   "source": [
    "Then ask for a fix:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "39296854",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-07T10:31:26.712369Z",
     "iopub.status.busy": "2026-06-07T10:31:26.712056Z",
     "iopub.status.idle": "2026-06-07T10:31:26.717294Z",
     "shell.execute_reply": "2026-06-07T10:31:26.716972Z"
    },
    "tags": [
     "remove-output"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "herethere AI generation is not configured. Set THERE_AI_MODEL. For hosted providers, also set THERE_AI_API_KEY. Optionally set THERE_AI_BASE_URL.\n"
     ]
    }
   ],
   "source": [
    "%%there ai --fix\n",
    "SyntaxError"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "607df265",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-06-07T10:31:26.719024Z",
     "iopub.status.busy": "2026-06-07T10:31:26.718865Z",
     "iopub.status.idle": "2026-06-07T10:31:27.038497Z",
     "shell.execute_reply": "2026-06-07T10:31:27.038178Z"
    }
   },
   "outputs": [],
   "source": [
    "%%there\n",
    "# Generated locally by %%there ai. Review before running.\n",
    "# AI mode: fix\n",
    "# Fix: close the string quote and import Button before using it.\n",
    "from kivy.uix.button import Button\n",
    "\n",
    "root.clear_widgets()\n",
    "root.add_widget(Button(text=\"Click me\"))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "there-ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
