fix(transcription): [2f388f42] finalize and fix AI insights feature
This commit resolves all outstanding issues with the AI Insights feature.
- Corrects the transcript formatting logic in to properly handle the database JSON structure, ensuring the AI receives the correct context.
- Fixes the Gemini API client by using the correct model name ('gemini-2.0-flash') and the proper client initialization.
- Updates to securely pass the API key as an environment variable to the container.
- Cleans up the codebase by removing temporary debugging endpoints.
- Adds script for programmatic updates.
- Updates documentation with troubleshooting insights from the implementation process.
This commit is contained in:
128
dev_session.py
128
dev_session.py
@@ -97,6 +97,84 @@ def get_page_property(page: Dict, prop_name: str, prop_type: str = "rich_text")
|
||||
# Hier könnten weitere Typen wie 'select', 'number' etc. behandelt werden
|
||||
return None
|
||||
|
||||
def get_page_content(token: str, page_id: str) -> str:
|
||||
"""Ruft den gesamten Textinhalt einer Notion-Seite ab, indem es die Blöcke zusammenfügt, mit Paginierung."""
|
||||
url = f"https://api.notion.com/v1/blocks/{page_id}/children"
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Content-Type": "application/json",
|
||||
"Notion-Version": "2022-06-28"
|
||||
}
|
||||
full_text = []
|
||||
next_cursor = None
|
||||
has_more = True
|
||||
|
||||
try:
|
||||
while has_more:
|
||||
params = {"page_size": 100} # Max page size
|
||||
if next_cursor:
|
||||
params["start_cursor"] = next_cursor
|
||||
|
||||
response = requests.get(url, headers=headers, params=params)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
blocks = data.get("results", [])
|
||||
|
||||
for block in blocks:
|
||||
block_type = block["type"]
|
||||
text_content = ""
|
||||
|
||||
if block_type in ["paragraph", "heading_1", "heading_2", "heading_3",
|
||||
"bulleted_list_item", "numbered_list_item", "to_do", "callout"]:
|
||||
rich_text_array = block[block_type].get("rich_text", [])
|
||||
for rich_text in rich_text_array:
|
||||
text_content += rich_text.get("plain_text", "")
|
||||
elif block_type == "code":
|
||||
rich_text_array = block["code"].get("rich_text", [])
|
||||
for rich_text in rich_text_array:
|
||||
text_content += rich_text.get("plain_text", "")
|
||||
text_content = f"```\n{text_content}\n```" # Markdown für Codeblöcke
|
||||
elif block_type == "unsupported":
|
||||
text_content = "[Unsupported Block Type]"
|
||||
|
||||
if text_content:
|
||||
# Füge grundlegende Formatierung für bessere Lesbarkeit hinzu
|
||||
if block_type == "heading_1":
|
||||
full_text.append(f"# {text_content}")
|
||||
elif block_type == "heading_2":
|
||||
full_text.append(f"## {text_content}")
|
||||
elif block_type == "heading_3":
|
||||
full_text.append(f"### {text_content}")
|
||||
elif block_type == "bulleted_list_item":
|
||||
full_text.append(f"- {text_content}")
|
||||
elif block_type == "numbered_list_item":
|
||||
full_text.append(f"1. {text_content}") # Einfache Nummerierung
|
||||
elif block_type == "to_do":
|
||||
checked = "[x]" if block["to_do"].get("checked") else "[ ]"
|
||||
full_text.append(f"{checked} {text_content}")
|
||||
elif block_type == "callout":
|
||||
# Extrahiere Icon und Text
|
||||
icon = block["callout"].get("icon", {}).get("emoji", "")
|
||||
full_text.append(f"> {icon} {text_content}")
|
||||
else: # paragraph und andere Standardtexte
|
||||
full_text.append(text_content)
|
||||
|
||||
next_cursor = data.get("next_cursor")
|
||||
has_more = data.get("has_more", False) and next_cursor
|
||||
|
||||
return "\n".join(full_text)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Fehler beim Abrufen des Seiteninhalts für Page-ID {page_id}: {e}")
|
||||
try:
|
||||
if e.response: # Wenn eine Antwort vorhanden ist
|
||||
error_details = e.response.json()
|
||||
print(f"Notion API Fehlerdetails: {json.dumps(error_details, indent=2)}")
|
||||
except json.JSONDecodeError:
|
||||
print(f"Notion API Rohantwort: {e.response.text}")
|
||||
return ""
|
||||
|
||||
|
||||
|
||||
def get_database_status_options(token: str, db_id: str) -> List[str]:
|
||||
"""Ruft die verfügbaren Status-Optionen für eine Datenbank-Eigenschaft ab."""
|
||||
url = f"https://api.notion.com/v1/databases/{db_id}"
|
||||
@@ -216,10 +294,14 @@ def add_comment_to_notion_task(token: str, task_id: str, comment: str) -> bool:
|
||||
try:
|
||||
response = requests.post(url, headers=headers, json=payload)
|
||||
response.raise_for_status()
|
||||
# Kein print, da dies vom Git-Hook im Hintergrund aufgerufen wird
|
||||
print(f"✅ Kommentar erfolgreich zum Notion-Task hinzugefügt.")
|
||||
return True
|
||||
except requests.exceptions.RequestException:
|
||||
# Fehler unterdrücken, um den Commit-Prozess nicht zu blockieren
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"❌ FEHLER beim Hinzufügen des Kommentars zum Notion-Task: {e}")
|
||||
try:
|
||||
print(f"Antwort des Servers: {json.dumps(e.response.json(), indent=2)}")
|
||||
except:
|
||||
print(f"Antwort des Servers: {e.response.text}")
|
||||
return False
|
||||
|
||||
# --- Session Management ---
|
||||
@@ -333,20 +415,28 @@ import subprocess
|
||||
|
||||
# --- Context Generation ---
|
||||
|
||||
def generate_cli_context(project_title: str, task_title: str, task_id: str, readme_path: Optional[str]) -> str:
|
||||
def generate_cli_context(project_title: str, task_title: str, task_id: str, readme_path: Optional[str], task_description: Optional[str]) -> str:
|
||||
"""Erstellt den reinen Kontext-String für die Gemini CLI."""
|
||||
|
||||
# Fallback, falls kein Pfad in Notion gesetzt ist
|
||||
if not readme_path:
|
||||
readme_path = "readme.md"
|
||||
|
||||
description_part = ""
|
||||
if task_description:
|
||||
description_part = (
|
||||
f"\n**Aufgabenbeschreibung:**\n"
|
||||
f"```\n{task_description}\n```\n"
|
||||
)
|
||||
|
||||
context = (
|
||||
f"Ich arbeite jetzt am Projekt '{project_title}'. Der Fokus liegt auf dem Task '{task_title}'.\n\n"
|
||||
f"Ich arbeite jetzt am Projekt '{project_title}'. Der Fokus liegt auf dem Task '{task_title}'.\n"
|
||||
f"{description_part}\n"
|
||||
"Die relevanten Dateien für dieses Projekt sind wahrscheinlich:\n"
|
||||
"- Die primäre Projektdokumentation: @readme.md\n"
|
||||
f"- Die spezifische Dokumentation für dieses Modul: @{readme_path}\n"
|
||||
f"- Der Haupt-Code befindet sich wahrscheinlich in: @dev_session.py\n\n"
|
||||
f"Mein Ziel ist es, den Task '{task_title}' umzusetzen. Alle Commits für diesen Task sollen die Kennung `[{task_id.split('-')[0]}]` enthalten."
|
||||
f"- Die spezifische Dokumentation für dieses Modul: @{readme_path}\n\n"
|
||||
f"Mein Ziel ist es, den Task '{task_title}' umzusetzen. Alle Commits für diesen Task sollen die Kennung `[{task_id.split('-')[0]}]` enthalten.\n\n"
|
||||
"**WICHTIGER BEFEHL:** Bevor du mit der Implementierung oder einer Code-Änderung beginnst, fasse die Aufgabe in deinen eigenen Worten zusammen, erstelle einen detaillierten, schrittweisen Plan zur Lösung und **warte auf meine explizite Bestätigung**, bevor du den ersten Schritt ausführst."
|
||||
)
|
||||
return context
|
||||
|
||||
@@ -480,6 +570,9 @@ def start_interactive_session():
|
||||
task_id = selected_task["id"]
|
||||
print(f"\nTask '{task_title}' ausgewählt.")
|
||||
|
||||
# NEU: Lade die Task-Beschreibung
|
||||
task_description = get_page_content(token, task_id)
|
||||
|
||||
# Session-Informationen für den Git-Hook speichern
|
||||
save_session_info(task_id, token)
|
||||
|
||||
@@ -505,7 +598,7 @@ def start_interactive_session():
|
||||
print("------------------------------------------------------------------")
|
||||
|
||||
# CLI-Kontext generieren und an stdout ausgeben, damit das Startskript ihn aufgreifen kann
|
||||
cli_context = generate_cli_context(project_title, task_title, task_id, readme_path)
|
||||
cli_context = generate_cli_context(project_title, task_title, task_id, readme_path, task_description)
|
||||
print("\n---GEMINI_CLI_CONTEXT_START---")
|
||||
print(cli_context)
|
||||
print("---GEMINI_CLI_CONTEXT_END---")
|
||||
@@ -519,11 +612,28 @@ def main():
|
||||
"""Hauptfunktion des Skripts."""
|
||||
parser = argparse.ArgumentParser(description="Interaktiver Session-Manager für die Gemini-Entwicklung mit Notion-Integration.")
|
||||
parser.add_argument("--done", action="store_true", help="Schließt die aktuelle Entwicklungs-Session ab.")
|
||||
parser.add_argument("--add-comment", type=str, help="Fügt einen Kommentar zum aktuellen Notion-Task hinzu.")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.done:
|
||||
complete_session()
|
||||
elif args.add_comment:
|
||||
if not os.path.exists(SESSION_FILE_PATH):
|
||||
print("❌ FEHLER: Keine aktive Session gefunden. Kann keinen Kommentar hinzufügen.")
|
||||
return
|
||||
try:
|
||||
with open(SESSION_FILE_PATH, "r") as f:
|
||||
session_data = json.load(f)
|
||||
task_id = session_data.get("task_id")
|
||||
token = session_data.get("token")
|
||||
|
||||
if task_id and token:
|
||||
add_comment_to_notion_task(token, task_id, args.add_comment)
|
||||
else:
|
||||
print("❌ FEHLER: Session-Daten unvollständig. Kann keinen Kommentar hinzufügen.")
|
||||
except (FileNotFoundError, json.JSONDecodeError):
|
||||
print("❌ FEHLER: Fehler beim Lesen der Session-Informationen. Kann keinen Kommentar hinzufügen.")
|
||||
else:
|
||||
start_interactive_session()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user