Skip to content

Releases: n-sig/ContextCruncher

ContextCruncher v2.6.2

Choose a tag to compare

@n-sig n-sig released this 26 Aug 20:23

ContextCruncher v2.6.2

Changed

  • Komplett überarbeitete Oberfläche — „Rot/Schwarz modernisiert". Alle Fenster der App und das Browser-AddOn-Popup wurden visuell überarbeitet: runde Ecken, weiche Hover- und Klick-Zustände, eine klare Schriftgrößen-Hierarchie in Segoe UI Variable (Rückfall auf Segoe UI) und ein durchgehendes 4/8-px-Abstandsraster. Die Identität bleibt: Schwarz und Marken-Rot. Es ändert sich nichts an der Funktionsweise — keine neuen Einstellungen, keine geänderten Tastenkürzel, kein Light Mode.
    • Varianten-Picker & Stack-Suche (Ctrl+Shift+L): Jeder Eintrag ist jetzt eine abgerundete Karte statt einer flachen Zeile. Der ausgewählte Eintrag wird dunkelrot getönt mit rotem Rand und einem roten Balken an der linken Kante — die frühere knallrote Vollfläche machte den Text schwer lesbar.
    • Token-Heatmap (Ctrl+Shift+H): Legenden-Chips und Kontextfenster-Balken sind abgerundet. Die Ampelfarben (Grün/Gelb/Rot) bleiben bewusst erhalten — sie zeigen Daten, nicht die Marke. Behoben: Das Heatmap-Fenster stürzte in einer Zwischenversion beim Öffnen ab.
    • Hotkey-Spickzettel: Tastenkürzel erscheinen als abgerundete Tastenkappen.
    • Einstellungen: Alle Schaltflächen sind abgerundet mit sauberer Hierarchie — ein rotes „Speichern", der Rest zurückhaltend. Die Akkordeon-Abschnitte haben statt des harten roten Kastens einen dezenten grauen Rahmen, einen weißen Titel mit rotem Pfeil und heben sich beim Überfahren hervor.
    • Erststart-Dialog: Neue Tastenkappen und ein abgerundeter „Los geht's"-Knopf. Behoben: Der Knopf wurde beim Anklicken türkis — ein Rest aus einer alten Farbpalette.
    • Hinweis-Einblendungen (Toasts): Statt eines nackten grauen Kastens jetzt eine Karte mit feiner Umrandung und rotem Akzentstreifen. Position (unten links) und Stapelverhalten sind unverändert.
    • Snip-Editor: Das aktive Werkzeug war zuvor system-blau und passte nicht zur App. Es ist jetzt rot getönt — deutlich unterscheidbar vom roten „Fertig"-Knopf. Farbfelder sind abgerundet und zeigen die Auswahl mit einem hellen Ring.
    • Browser-AddOn-Popup: Nutzt jetzt exakt dieselben Farb-, Abstands- und Rundungswerte wie die Desktop-App, damit beide als ein Produkt wirken.

Fixed

  • KI-Crunch scheiterte an System-Proxies (prompt_optimizer.py) — stand im System ein Proxy mit einem von httpx nicht unterstützten Schema (z. B. socks4://), warf jeder AI-Crunch-Aufruf vor dem eigentlichen Request einen Fehler („Unknown scheme for proxy URL", 62× im Log). Der neue _post()-Wrapper erkennt genau diesen Fall, warnt einmalig und sendet den Request stattdessen direkt (trust_env=False). Funktionierende Proxies (http/https/socks5) bleiben unberührt. Regression: tests/test_prompt_optimizer.py::TestProxyFallback.
  • Stack: IndexError bei veraltetem Varianten-Index (stack.py) — der active_index eines Eintrags überlebt Rundreisen (pinned.json-Restore, Varianten-Neuaufbau während eines laufenden KI-Callbacks). War er außerhalb des Bereichs, crashte jede Leseproperty mit „list index out of range" (15× im Log, u. a. beim Maustasten-Crunch). Der Index wird jetzt beim Konstruieren (__post_init__) und beim Lesen geclampt, statt zu crashen. Regression: tests/test_stack.py::TestActiveIndexClamping.
  • Zwei Instanzen konnten gleichzeitig laufen (main.py) — der Singleton-Guard las den Win32-LastError über einen zweiten ctypes-Aufruf (kernel32.GetLastError()) ab; Python-seitige Aktivität zwischen den beiden Aufrufen kann diesen Wert überschreiben, das ERROR_ALREADY_EXISTS-Signal ging verloren und eine zweite Instanz startete durch (in freier Wildbahn beobachtet). Jetzt wird ctypes.WinDLL(use_last_error=True) + ctypes.get_last_error() verwendet — der dokumentierte, immunisierte Weg. Regression: tests/test_singleton_mutex.py.
  • Bild-Snip konnte die Zwischenablage verlieren bzw. blockieren (clipboard.py) — OpenClipboard() scheiterte einmalig, sobald gerade ein anderer Prozess die Zwischenablage offen hielt; und ohne try/finally blieb sie bei einem Schreibfehler offen und blockierte Copy/Paste aller anderen Apps bis zum Prozessende. Jetzt: begrenzter Retry (~100 ms) + garantiertes Schließen. Regression: tests/test_clipboard_set_image.py.
  • Eingebaute Crunch-Profile verloren ihre Integritätsregeln (prompt_optimizer.py, ai_crunch.js) — die 2.6.1-Prompt-Erneuerung hatte in Ausgewogen und Maximal die Verankerungen „Preserve ALL facts…" und „NEVER translate" fallen lassen (und dem Maximal-Profil seinen erkennbaren Namen); damit war auch der Faktenschutz-Umschalter wirkungslos positionierbar. Beide Regeln sind zurück, Desktop und AddOn wieder synchron. Regression: tests/test_crunch_profiles.py, browser_extension/tests/profiles.test.js.
  • Rate-Limit-/Überlast-Fehler erklären jetzt den nächsten Schritt (prompt_optimizer.py) — statt nur „rate limit reached" (91× im Log) sagen 429-Toasts jetzt „Wait ~1 min, then try again", und 5xx/529 nennt Überlastung + kurzen Retry-Hinweis.
  • Testsuite war seit v2.6.1 rot (12 Failures) — die Prompt-Erneuerung hatte die eingefrorenen Profil-Verträge nicht aktualisiert. Die Tests beschreiben jetzt bewusst den v2.6.1-Vertrag: Custom-Prompts laufen pur (nichts wird angehängt, weder Schutzblock noch Fakt-Politik — Owner-Entscheidung), Built-ins tragen die Integritätsregeln, der Faktenschutz-Umschalter wirkt auf alle Built-ins. Neu: tests/test_no_hardcoded_keys.py scannt Source + AddOn bei jedem Lauf auf hartcodierte API-Keys.

ContextCruncher v2.6.1

Choose a tag to compare

@n-sig n-sig released this 03 Aug 20:42

ContextCruncher v2.6.1

Added

  • Gemini Support & Opus-Level Prompts: Die Text-Komprimierung wurde massiv durch neue, token-effiziente System-Prompts ("Claude Opus"-Level) und die Integration von Google Gemini als Provider (Standard: gemini-3.5-flash) verbessert.
  • Quick Templates: Schnellauswahl für häufige Custom Prompts ("Blog Summary", "Tech Stack", "Simple Explain") in den Einstellungen hinzugefügt.
  • Die angehängten Sicherheits-Regeln für das Custom Profil wurden auf Wunsch entfernt, sodass wirklich nur der pure Nutzer-Prompt ausgeführt wird.

ContextCruncher v2.6.0

Choose a tag to compare

@n-sig n-sig released this 25 Jul 22:54

ContextCruncher v2.6.0

Added

  • Faktenschutz-Schalter — echte Zusammenfassungen sind jetzt möglich (prompt_optimizer.py, ai_crunch.js, settings.py, popup/) — gemeldet: Bei faktendichten Texten lieferte das Modell keine ganzheitliche Zusammenfassung, sondern kopierte die ersten Fakten-Sätze wörtlich, bis das Ausgabe-Limit erreicht war, und ignorierte den Rest (oft über die Hälfte). Ursache bestätigt: Alle drei eingebauten Profile schrieben „Preserve ALL: facts, numbers, names, dates…" vor (Stichpunkte sogar „Numbers are never rounded or dropped"), und der Hinweis für Fließtext sagte zusätzlich „preserving all facts". Unter endlichem Ausgabe-Budget ist das eine unerfüllbare Anweisung — das Modell füllt das Budget vorne auf und bricht ab.
    • Der eigentliche Konstruktionsfehler: „nichts erfinden" (Wahrhaftigkeit) und „nichts weglassen" (Vollständigkeit) steckten in einer Regel. Beides ist jetzt getrennt: Erfinden und Verfälschen bleiben immer verboten, das Weglassen ist schaltbar.
    • Neuer Schalter „Faktenschutz" (Standard: an, also unverändertes Verhalten) in den Einstellungen und im AddOn direkt unter der Profilauswahl. Aus = echte Zusammenfassung: Unwichtiges darf entfallen.
    • Der Aufhebungs-Block wird ganz zuletzt angehängt und überschreibt damit die „Preserve ALL"-Regeln der Profile — sonst würden sich zwei Anweisungen im selben Prompt widersprechen. Er enthält außerdem eine ausdrückliche Abdeckungs-Regel („verteile das Budget bis zum LETZTEN Abschnitt, kürze lieber überall als hinten wegzulassen"), denn die Erlaubnis wegzulassen allein behebt das Vorne-Auffüllen nicht.
    • Der Fließtext-Hinweis folgt jetzt derselben Einstellung, statt gegen sie zu arbeiten.
  • Crunch-Profile statt „Aggressiv"-Häkchen (prompt_optimizer.py, settings.py, ai_crunch.js, popup/) — wie die KI verdichten soll, ist jetzt eine echte Auswahl statt eines versteckten Schalters: Ausgewogen (jedes Detail bleibt), Maximal (so kurz wie möglich), Stichpunkte (strukturierte Übersicht) und Eigenes (frei formulierte Vorgabe). Im AddOn steht die Auswahl direkt unter „AI Crunch Page Content" statt in den Einstellungen; im Desktop in der KI-Sektion mit Textfeld für die eigene Vorgabe. In allen 5 Sprachen lokalisiert.
    • Eine eigene Vorgabe kann die Schutzregeln nicht aushebeln: an jeden selbst geschriebenen Prompt wird ein fester, nicht editierbarer Block angehängt (Platzhalter ⟨CODE_BLOCK_N⟩ wörtlich übernehmen, nichts erfinden, Sprache nicht übersetzen, Code/Befehle unverändert). Ohne ihn würde der Code-Auslagerungs-Mechanismus stillschweigend kaputtgehen. Der Block steht hinter dem Nutzertext und überschreibt ihn deshalb.
    • Bestehende Installationen ändern ihr Verhalten nicht: solange kein Profil gewählt wurde, entscheidet weiterhin das alte aggressive-Flag.
  • „Speichern"-Knopf im AddOn neben „Test Connection" (popup/) — die Einstellungen speicherten zwar bei jeder Änderung, aber ohne jede Rückmeldung. „Test Connection" speichert jetzt außerdem vor dem Test, damit nicht gegen die vorherigen Zugangsdaten getestet wird.

Fixed

  • Ein Kopiervorgang landete mehrfach im Stack (clipboard.py, main.py) — einmal kopieren, kurz darauf crunchen, und derselbe Text stand mehrfach im Verlauf: einmal als Original und noch einmal separat als „Original", das in Wahrheit das komprimierte Ergebnis war. Ursache: die App schreibt jedes Ergebnis in die Zwischenablage (Crunch, OCR, Variantenwechsel), und der Zwischenablage-Beobachter hielt das für eine neue Nutzer-Kopie. In CLAUDE.md war ein Zähler _ignore_next_changes beschrieben, der genau das verhindern sollte — den gab es im Code nicht. Jetzt merkt sich set_clipboard (als Prüfsumme, nie im Klartext) was die App selbst geschrieben hat, und der Beobachter verwirft dieses Echo genau einmal — eine echte erneute Kopie desselben Textes landet weiterhin im Verlauf.

  • Die KI-Variante war im Tray unsichtbar (tray.py, main.py) — das Untermenü zeigte fest verdrahtet nur die ersten beiden Varianten (Original/Kompakt), weshalb ein KI-Ergebnis „gar nicht drin" war und man in die Stack-Suche wechseln musste. Jetzt werden alle Varianten aufgelistet, jeweils mit Symbol und Ersparnis, und die Zeile trägt ein Abzeichen (🔢/🤖), das ohne Aufklappen zeigt, was der Eintrag enthält. Angepinnte Einträge werden identisch dargestellt. Die Bezeichnungen (Original / Komprimiert / KI) sind jetzt überall dieselben und übersetzt.

  • AddOn: Ergebnis ging beim Wegklicken verloren (background.js, popup/popup.js) — klickte man während der Kompression irgendwo hin, schloss sich das Popup und das fertige Ergebnis war weg; der Durchlauf musste bezahlt wiederholt werden. Die Kompression lief immer schon im Hintergrund — nur ihr Ergebnis hing am Popup. Der Auftrag lebt jetzt im Service Worker (inkl. storage.session als Rückfallebene, falls der Worker zwischendurch beendet wird): Beim erneuten Öffnen zeigt das Popup das fertige Ergebnis an oder hängt sich an den noch laufenden Durchlauf. Der Fortschrittstext sagt jetzt ausdrücklich, dass man das Popup schließen darf.

  • Maustasten fielen aus, sobald „PrtScn ersetzen" mitgespeichert wurde (mouse_hotkeys.py (neu), hotkeys.py) — wer gleichzeitig eine Tastenkombination änderte und den PrtScn-Haken setzte und dann speicherte, bei dem lösten die Maus-Seitentasten anschließend nicht mehr aus; nur eine Taste zu ändern ging weiterhin. Ursache: die E14-Umstellung hatte die Tastatur vom Low-Level-Hook auf RegisterHotKey geholt, die Maustasten aber auf pynputs mouse.Listener gelassen — und der ist selbst ein WH_MOUSE_LL-Hook. Damit blieb für sie genau die Fehlerklasse bestehen, die für die Tastatur beseitigt wurde: das Installieren des E5-PrtScn-Hooks legt andere Hooks im Prozess lahm. Nur der Pfad „Bindung geändert und PrtScn geändert" führt den vollständigen Neuaufbau aus, der den Maus-Listener startet und unmittelbar danach den PrtScn-Hook (neu) installiert — deshalb war der Fehler an genau diese Kombination gekoppelt.

    • Fix: die Maustasten laufen jetzt über den neuen MouseHotkeyRegistrarhook-frei per GetAsyncKeyState-Flankenerkennung (kein Hook, kein Fenster, keine Nachrichtenschleife), also gibt es nichts mehr, was ausgehungert oder von Windows verdrängt werden könnte. Ausgelöst wird nur auf dem Übergang losgelassen→gedrückt (entspricht MOD_NOREPEAT bei der Tastatur), und nichts wird geschluckt — genau wie bei RegisterHotKey. Damit bleibt ein einziger Low-Level-Hook im Prozess übrig (PrtScn, und nur wenn das Feature an ist); ein Test friert diese Invariante ein.
    • Maustasten zählen jetzt auch im Hotkey-Selbsttest mit (gleicher Ergebnis-Kontrakt pro Bindung wie bei der Tastatur).
  • Programm blieb nach „Beenden" gelegentlich als Prozess zurück (main.py) — das Tray-Symbol verschwand, der Prozess lief im Task-Manager weiter. Alle eigenen Threads sind Daemon-Threads, blockieren den Shutdown also nicht; der Hänger steckt in Pythons Finalisierung (Tcl/Tk abbauen, während dessen mainloop auf einem anderen Thread läuft, plus die C-Schichten von WinRT/pystray/pynput) — daher auch das „nicht immer". Statt jeder Bibliothek beim Aufräumen hinterherzulaufen, verlässt sich das Beenden nicht mehr auf die Finalisierung: alle dauerhaften Daten sind vorher synchron geschrieben (Konfiguration, DPAPI-verschlüsselte Pins, PrtScn-Registry-Rückgabe), Logging wird geleert, dann endet der Prozess sofort. Zusätzlich wird beim Beenden zuerst ein Wächter scharf gestellt, damit auch ein Hänger in einem der Aufräumschritte den Prozess nicht mehr stehen lassen kann.

Added

  • Mausrad-Klick als Hotkey belegbar (mouse_hotkeys.py, settings.py, config.py) — neben den beiden Daumentasten ist jetzt auch die mittlere Maustaste (<mouse_middle>) belegbar. Links- und Rechtsklick sowie das Scrollen bleiben bewusst gesperrt: es wird nichts geschluckt, eine Bindung dort würde also bei fast jeder Interaktion auslösen. Der Rekorder warnt beim Mausrad-Klick wie bei einer bloßen Buchstabentaste (er scrollt automatisch bzw. öffnet Links in neuen Tabs) — die Belegung bleibt erlaubt.

ContextCruncher v2.5.0

Choose a tag to compare

@n-sig n-sig released this 25 Jul 16:08

ContextCruncher v2.5.0

Changed (UX — Tray & Einstellungen aufgeräumt)

  • Tray radikal verschlankt (tray.py) — das Kontextmenü zeigt jetzt nur noch die eigentlichen Aktionen (Bild-Snip, Fenster erfassen, Region-OCR, Vollbild-OCR [neu im Tray], Crunch, Stack-Suche), die zwei Verlaufs-Untermenüs 🖼 Letzte Snips ▶ und 📋 Letzte Scans ▶ sowie ⏸ Pause / Einstellungen / Beenden — statt der bisher ~22 Zeilen. Die früher direkt in die Wurzel geschriebenen letzten Scans + Pins + „Aktuelles anheften" + „Stack leeren" (der größte Platzfresser) liegen jetzt komplett im neuen 📋 Letzte Scans ▶-Untermenü. Reihenfolge, Gruppierung und Trennlinien kommen aus der reinen, kopflos testbaren build_tray_rows(). Alle Umschalter, Diagnose-Einträge und der Profil-Wechsler sind aus dem Tray in die Einstellungen gewandert; ⏸ Pause bleibt als einziger Schnellschalter.
  • „KI-Crunch" heißt jetzt überall „Crunch" (config.py, i18n.py, main.py) — die sichtbare Bezeichnung der ai_compact-Aktion (Tray, Cheat-Sheet, Einstellungen, Erstlauf-Dialog) ist in allen 5 Sprachen „Crunch". Reine Anzeige — der Aktions-Schlüssel und die Konfiguration bleiben unverändert.
  • Einstellungen als einklappbare Abschnitte (Accordion) (settings.py) — die Sektionen (Workspace-Profil, Tastenkürzel, Allgemein, KI-Kompression, Browser-AddOn) sind jetzt per ▸/▾-Kopf ein-/ausklappbar im App-Look (Rot/Schwarz); Workspace + Tastenkürzel offen, der Rest zu. Modulfilter (welche Abschnitte je aktivem Modul da sind) und Auf/Zu sind zwei getrennte Achsen. Neuer Abschnitt ℹ Über / Wartung unten bündelt „Nach Updates suchen", „Hotkey-Selbsttest" und „Cheat-Sheet" (dieselben Aktionen wie früher im Tray) plus die Versionszeile.

Added (UX)

  • Auto-Komprimierung als Einstellungs-Schalter (settings.py, main.py) — der bisherige Tray-Umschalter „Auto-crunch on scan" ist jetzt eine Checkbox in den Einstellungen (Cruncher-Modul); sie schreibt denselben auto_crunch-Schlüssel und löst dieselbe Wirkung aus wie zuvor der Tray-Eintrag.

Fixed (Hotkey-Zuverlässigkeit)

  • Bei aktivem PrtScn ließen sich keine Hotkeys mehr neu belegen (settings.py, main.py, hotkeys.py) — mit eingeschaltetem „PrtScn ersetzen" nahm der Hotkey-Recorder keine Taste mehr auf. Per app.log schrittweise diagnostiziert: der Recorder startet, empfängt aber kein einziges Tastenereignis — und zwar auch dann noch, wenn der PrtScn-Low-Level-Hook 10 Sekunden zuvor entfernt wurde. Ursache ist also nicht die laufende Hook-Konkurrenz, sondern dass das Installieren/Entfernen eines Low-Level-Hooks im Prozess pynputs eigene Tastatur-Erfassung dauerhaft lahmlegt. Fix: der Recorder benutzt keinen globalen Tastatur-Hook mehr, sondern erfasst Tasten über Tk-Fensterereignisse (<KeyPress>/<KeyRelease> auf dem Einstellungen-Fenster) — das läuft über die normale Fokus-Eingabe ohne Hook und ist damit immun. Maustasten (X1/X2) bleiben beim separaten pynput-Maus-Hook (unbetroffen). Der PrtScn-Hook wird weiterhin nur pausiert, solange die Einstellungen offen sind, damit die Druck-Taste als Kombi aufgenommen statt geschluckt wird. Zwei frühere Fixe (ganzen Manager pausieren; nur PrtScn-Hook pausieren) waren auf der falschen Ebene und wurden ersetzt. Tests: tests/test_printscreen_recorder.py, tests/test_hotkey_rebuild_guard.py.
  • „PrtScn ersetzen" anhaken + Speichern legte die anderen Hotkeys lahm (main.py) — der Einstellungen-Speichern-Pfad baute den kompletten Hotkey-Manager neu auf, sobald sich der PrtScn-Auslöser änderte (auch beim reinen An-/Abhaken der Checkbox), und registrierte dadurch alle Tastatur-Hotkeys über den RegisterHotKey-Registrar neu — genau das Teardown, das die Hotkey-Zustellung stört (das Tray-Umschalten vermied das schon über refresh_printscreen, der Speichern-Pfad nicht). Jetzt erkennt _rebuild_hotkey_manager eine reine PrtScn-Änderung (Bindungen unverändert, nur der PrtScn-Trigger anders) und konfiguriert ausschließlich den Low-Level-PrtScn-Hook auf dem laufenden Manager neu — die Tastatur-/Maus-Listener bleiben unangetastet. Regression: tests/test_hotkey_rebuild_guard.py.
  • Globale Hotkeys: Wurzelursache behoben — Umstieg von pynput auf Win32 RegisterHotKey (win_hotkeys.py (neu), hotkey_codes.py (neu), hotkeys.py, config.py, main.py) — die Hotkeys waren unzuverlässig (Owner: „mal ja, mal nein"; andere Nutzer: „geht gar nicht"; „das ganze Tool spinnt"), und drei frühere Einzelfixe (Recorder-Steuerzeichen, Maus-Listener-Leck, Rebuild-Guard) hatten es nicht gelöst. Empirisch belegte Wurzelursache — architektonisch, kein vierter Bug: pynput.keyboard.GlobalHotKeys(map) parst jede Kombi im Konstruktor, also brachte eine unparsebare Kombi (eine hand-editierte, eine Steuerzeichen-Bindung aus der Zeit vor dem Recorder-Fix, ein layoutfremdes Token) den gesamten Listener zum Absturz → kein Hotkey lief; und der Boot-start() war ungefangen, also flog die Exception aus main() vor tray.start() → die App erschien nie („bei anderen geht gar nichts"). Zusätzlich ist GlobalHotKeys ein WH_KEYBOARD_LL-Hook; mehrere gleichzeitig (mit dem E5-PrtScn-Hook, während einer Aufnahme drei) laden zur stillen LowLevelHooksTimeout-Verdrängung ein — die intermittierende Owner-Störung.
    • Fix: normale Tastatur-Kombis laufen jetzt über Win32HotkeyRegistrar (Win32 RegisterHotKey auf eigenem GetMessageW-Pump-Thread, nach dem Muster von printscreen_hook.py; _windll() unter sys.platform-Guard → importiert auf Linux-CI). RegisterHotKey ist pro Bindung: jede Kombi registriert per eigenem Aufruf, eine kaputte/belegte reißt die anderen nie mit; kein LL-Hook (beendet die Verdrängungs-Klasse); layoutstabil über VK (feste NAMED_VK-Tabelle für Sondertasten, Einzelzeichen über das layout-abhängige VkKeyScanW); und es meldet Erfolg/Fehler pro Bindung (Codes ok/unparsable/already_in_use/error) — beim Start als N/M aktiv geloggt und über einen Tray-Eintrag ⌨ Hotkey-Selbsttest sichtbar (E10-loghygienisch: nur Aktionsnamen/Kombis/Codes, keine Inhalte).
    • Maustasten (<mouse_x1/x2>) bleiben beim pynput-Maus-Listener und PrtScn beim E5-LL-Hook — RegisterHotKey kann beides nicht — es bleibt also genau ein LL-Hook, und nur wenn das PrtScn-Feature an ist.
    • Bestehende kaputte Configs werden geheilt (zwei Ebenen): das reine sanitize_hotkeys_dict leert unparsebare/Steuerzeichen-Bindungen als einmaligen Schema-v3-Migrationsschritt (migrate_hotkey_schema: v<2 hebt unangetastete Bindungen an, v<3 säubert; idempotent, Roh-Datei-Versionsprüfung), und der Registrar überspringt eine weiterhin unparsebare Kombi eigenständig mit Log-Zeile.
    • Dokumentierte Grenzen (keine Bugs): RegisterHotKey umgeht nicht die Rechte-Isolation (UIPI) — ein nicht-elevierter Prozess (LL-Hook oder RegisterHotKey) erhält keine Eingaben, solange ein als Administrator laufendes Fenster im Vordergrund ist; der No-Admin-Standard bleibt, „als Admin starten" ist nur eine dokumentierte Option — und unterdrückt die Taste nicht (für normale Kombis gewollt).

Added

  • Beliebige Taste belegbar (settings.py, hotkey_codes.py) — der Recorder akzeptiert jetzt jede einzelne Taste (auch bare Buchstaben/Ziffern/F1–F12). Bei einer riskanten bloßen Taste (wird global abgefangen und ist bei laufender App nicht mehr normal tippbar) warnt der Recorder sofort (Toast + orange Beschriftung), die Belegung bleibt aber erlaubt. In allen 5 Sprachen lokalisiert.
  • Konfigurierbare Tray-Aktion (tray.py, settings.py, config.py, i18n.py) — die fixe Linksklick-Aktion des Tray-Symbols (bisher fest „OCR") ist jetzt über tray_default_action einstellbar (Auswahlfeld in den Einstellungen; fällt auf die erste verfügbare aktive Aktion zurück, Standard scan). In allen 5 Sprachen lokalisiert.

ContextCruncher v2.4.0

Choose a tag to compare

@n-sig n-sig released this 23 Jul 22:52

ContextCruncher v2.4.0

Added

  • Freie Anbieterwahl: konfigurierbare OpenAI-Basis-URL (prompt_optimizer.py, settings.py, i18n.py, browser_extension/ai_crunch.js, popup/) — der OpenAI-Pfad hatte https://api.openai.com/v1 fest im Code, wodurch jeder OpenAI-kompatible Anbieter unerreichbar war — inklusive aller mit Gratis-Kontingent (Groq, OpenRouter, Gemini-Kompatibilitäts-Endpunkt, Cerebras, Mistral, eigenes Gateway). Da weder OpenAI noch Anthropic eine kostenlose API-Stufe haben, gab es damit keinen kostenlosen Weg, die KI-Funktionen überhaupt auszuprobieren. Die Basis-URL ist jetzt über openai_base_url (llm_keys.json) bzw. ein Settings-Feld einstellbar; leer = offizielles OpenAI, also unverändertes Verhalten für bestehende Installationen. Gilt für Kompression, Optimierung und den „Verbindung testen"-Knopf, im Desktop und im Browser-AddOn.
    • Die E10-Egress-Garantie bleibt scharf: die Basis-URL ist das zweite nicht-hartkodierte Anfrageziel, deshalb läuft sie durch denselben SSRF-Klasse-Schutz wie der Ollama-Endpunkt. Der Schutz wurde nach _validate_base_url() herausgezogen und von validate_ollama_endpoint() (Verhalten unverändert) und dem neuen validate_openai_base_url() geteilt; _call_openai validiert zusätzlich selbst, damit ein direkter Aufruf den Schutz nicht umgehen kann. tests/test_egress_guard.py erzwingt das jetzt für beide Ziele. Die JS-Seite portiert dieselbe Prüfung (validateBaseUrl) — file:/ftp:/javascript:/data: und Müll fallen auf den Standard zurück.
    • Das AddOn-Feld erscheint bewusst nur beim OpenAI-Anbieter (Anthropics API-Form ist anders — ein Feld dort wäre irreführend). Lokalisiert in allen 5 Sprachen. Abgedeckt durch tests/test_openai_base_url.py (14) und browser_extension/tests/base_url.test.js (7).
  • INSTALL.txt liegt jetzt der browser_extension.zip bei (release.py) — die öffentliche README versprach eine Lade-Anleitung „in der ZIP", die es nicht gab. Browser können eine ZIP nicht direkt laden; ohne Anleitung hat ein nicht-technischer Empfänger keine Chance. Die Datei erklärt Entpacken, den Chrome/Edge-Weg (Entwicklermodus → entpackte Erweiterung laden), den Firefox-Sonderweg und den Tipp, den Ordner neben die .exe zu legen — UTF-8 mit BOM, damit Windows-Notepad die Umlaute korrekt zeigt. Ein Test pinnt die Datei samt Kerninhalten, damit die README-Zusage nicht wieder still falsch wird.

Fixed

  • Öffentliche README: falsche AddOn-Aussage korrigiert (docs/release/README-public.md) — die Behauptung, eine Anleitung liege der ZIP bei, stimmte nicht. Ersetzt durch eine echte Schritt-für-Schritt-Anleitung inkl. der Warnung, dass Browser keine ZIP laden können, und dem Ordner-Layout neben der .exe.