9.7 KiB
title, project, created, source, description, tags
| title | project | created | source | description | tags | |||||
|---|---|---|---|---|---|---|---|---|---|---|
| Modul-System für aICentral — Entwurf | ai-control | 2026-07-22T16:26:08Z | ai-control | Modul-System für aICentral: Deskriptoren, Registry, Enablement, Migration in 5 Schritten, Plugin-Ausblick |
|
Modul-System für aICentral — Entwurf
Stand 2026-07-22. Grundlage: panel-wiring.ts, commands-view.ts, mcp.rs, terminal.rs, app.rs, domain/project.rs (Stand 513e1a7).
1. Ziel und Abgrenzung
Alle Panel-Funktionen werden zu- und abwählbare Module; die anstehenden Features (ToDo-Liste, Commit-Dialog, Archiv-Ausbau, Authoring-Ansicht) entstehen direkt als Module. Ein System für fremde Plugins (zur Laufzeit geladener Code) wird jetzt nicht gebaut — der Entwurf legt aber die Schnittstellen so, dass es später ohne Umbau andockt (Abschnitt 9).
2. Bestandsaufnahme — was schon Modulform hat
Die vier Panel-Ansichten folgen bereits einem einheitlichen Muster, es ist nur nicht als Schnittstelle benannt:
| Baustein | draft | commands | search | wiki |
|---|---|---|---|---|
| Pufferdatei (Env an MCP) | AI_CONTROL_PANEL | …_COMMANDS | …_SEARCH | …_WIKI |
| Watcher-Event | panel-update | commands-update | search-update | wiki-update |
| View-Interface | set/flush | set/empty | set/empty | set/empty |
| Read-Command | panel_read | commands_read | search_read | wiki_read |
| MCP-Tools | write_panel | write/show_commands | search_archive | show_archive, archive_panel |
Der Datenfluss ist überall gleich: MCP-Server oder Command schreibt die
Pufferdatei → Datei-Watcher im Terminal-Prozess emittiert <x>-update →
View rendert. Es gibt auch schon ein abwählbares Modul: archiveHome: null
blendet Wiki-/Suche-Tab und Archiv-Werkzeuge aus (panel-wiring.ts:45).
Das Modul-System verallgemeinert genau diese zwei Präzedenzfälle.
3. Modulbegriff
Ein Modul ist ein benannter Funktionsblock mit bis zu vier Beiträgen:
- Panel-Tab mit View (Kachel- oder Dokumentansicht)
- MCP-Tools (Angebot an claude)
- Pufferdatei + Watcher-Event (der Transportweg dazwischen)
- optional Fenster/Dialoge (z. B. Commit-Dialog)
Geplanter Zuschnitt:
| Modul | Tab | MCP-Tools | abwählbar |
|---|---|---|---|
draft (Entwurf) |
ja | write_panel | nein — Kern |
commands |
ja | write_commands, show_commands | ja |
archive |
Wiki + Suche | archive_panel, show_archive, search_archive | ja (heute: archiveHome) |
todo (neu) |
ja | write_todos, show_todos | ja |
commit (neu) |
nein, eigener Dialog | — | ja |
authoring (später) |
ja | … | ja |
draft bleibt Kern: Titel, Editier-Modus, flush und das Archivieren hängen
daran; ohne Entwurf ist das Panel leer. Alles andere ist abschaltbar.
4. Backend: Deskriptoren und eine Durchsetzungsstelle
Neu domain/modules.rs:
pub(crate) struct ModuleDesc {
pub id: &'static str, // "commands", "todo", ...
pub default_enabled: bool,
/// Modul setzt ein konfiguriertes archiveHome voraus.
pub requires_archive: bool,
pub mcp_tools: &'static [&'static str],
/// Pufferdatei-Name im Projekt-Runtime-Ordner, None = kein Puffer.
pub buffer: Option<&'static str>,
}
pub(crate) const MODULES: &[ModuleDesc] = &[ /* draft, commands, archive, todo, … */ ];
/// Die eine Quelle für „was ist in diesem Projekt an?“.
pub(crate) fn enabled_modules_in(paths: &Paths, project: &str)
-> Result<Vec<&'static str>, String>
enabled_modules_in = MODULES, gefiltert durch Projekt-Config und
requires_archive (Archiv-Module fallen ohne archiveHome automatisch weg —
das ersetzt die heutige Sonderbehandlung, statt eine zweite daneben zu
stellen). Genau drei Aufrufer:
- Tauri-Command
enabled_modules(project)— das Frontend fragt einmal beim Verdrahten. - mcp.rs
tools/list— die Tool-Liste wird ausMODULES[…].mcp_toolsder aktiven Module gebaut (Projekt kommt wie heute überAI_CONTROL_PROJECT). claude sieht Tools abgeschalteter Module gar nicht erst. - mcp.rs
tools/call— Guard vor dem Dispatch: Tool eines inaktiven Moduls → Fehler „Modul X ist in diesem Projekt abgeschaltet". Nötig, weil eine laufende claude-Session die Tool-Liste vom Start behält.
Verallgemeinert wird außerdem:
- terminal.rs: die vier
spawn_file_watcher-Zeilen werden eine Schleife über die aktiven Module mit Puffer; Event-Name per Konvention<id>-update, Env-NameAI_CONTROL_<ID>. - Read-Commands:
panel_read/commands_read/search_read/wiki_readverschmelzen zumodule_read(project, module)(alle vier sind „Pufferdatei als String").panel_setbleibt eigenständig, es ist der einzige Rückkanal.
Statisch bleiben: generate_handler! (Commands aller Module sind kompiliert
registriert; Abwahl wirkt auf Sichtbarkeit und Tools, nicht auf die
IPC-Registrierung), die Capability-Manifeste pro Fenster und die CSP. Die
Modul-Abwahl ist Konfiguration, keine Sicherheitsgrenze — dieselbe Linie
wie bei den Pools (Konfiguration trennen, nicht Zugriff).
5. Frontend: Registry statt Verdrahtung von Hand
Neu src/modules/ mit einem Deskriptor pro Modul:
export interface PanelModule {
id: string;
tabLabelKey: string; // i18n-Key
order: number; // Tab-Reihenfolge
init(container: HTMLElement, ctx: ModuleCtx): ModuleView;
/// Kopfzeilen-Werkzeuge des Moduls (z. B. Archivieren-Button).
headerTools?(ctx: ModuleCtx): HTMLElement[];
}
export interface ModuleView { set(text: string): void; empty(): boolean; }
export interface ModuleCtx {
project: string;
toast(msg: string): void;
openDoc(path: string): void; // Dokument in den Entwurfs-Tab laden
openWiki(name: string): void;
}
panel-wiring.ts wird generisch: enabled_modules abfragen, pro Modul
Tab + Container erzeugen, module_read laden, <id>-update abonnieren,
initPanelMode über die Modulliste statt über vier feste Felder. Die
PanelMode-Union und die archiveHome-Ausblendelogik entfallen. Die
HTML-Dateien verlieren die fest verdrahteten Tab-/Container-Elemente;
beide Panel-Markups (angedockt/abgelöst) entstehen aus derselben Registry.
Kachel-Renderer als gemeinsamer Baustein: commands-view.ts wird in
einen deklarativen Tile-Renderer zerlegt (Titel/Text/Note, Zeitmarke,
Aktionen kopieren/löschen/öffnen, optionales Badge). Commands, ToDo
(Due-Date-Ampel = Badge) und Suchtreffer rendern darüber — die
ToDo-Ansicht „analog commandlist" ist dann im Wesentlichen ein
Puffer-Format plus Badge-Logik. Das Sanitizing (stripInvisibles, kein
innerHTML) liegt damit an einer Stelle.
6. Konfiguration
Projekt-Config (.ai-control/config.json) bekommt:
{ "modules": { "commands": false, "todo": true } }
Nur Abweichungen vom Default werden gespeichert; fehlender Key = alle
Defaults (bestehende Configs bleiben unverändert gültig, kein
Migrationsschritt). archiveHome bleibt eigenständiges Feld — es ist
Pfad-Konfiguration, das Archiv-Modul hängt über requires_archive daran.
Ein Eintrag "archive": false schaltet das Modul trotz gesetztem
archiveHome ab.
Settings-UI: im Projekt-Dialog eine Checkbox-Gruppe „Module" aus MODULES generiert; Archiv-Zeile kombiniert Checkbox + Pfadwahl (heutige Archiv-Einstellung wandert dorthin). Änderungen wirken beim nächsten Panel-Aufbau; eine laufende claude-Session behält ihre Tool-Liste, der tools/call-Guard fängt das ab.
7. Migration in Schritten
domain/modules.rs+enabled_modules+ tools/list/call aus MODULES speisen — reine Umformung, Verhalten identisch.- Frontend-Registry: die vier Bestands-Views als Deskriptoren,
panel-wiring generisch, archiveHome-Sonderlogik durch
requires_archiveersetzen. Bestehende vitest-Tests laufen gegen die Deskriptoren weiter. - Kachel-Renderer aus commands-view extrahieren, Suche darauf umstellen.
- Settings-UI mit Modul-Checkboxen +
modules-Feld in der Config. - Erstes neues Modul: ToDo — validiert den Schnitt komplett (Deskriptor, Puffer, zwei MCP-Tools, Tile-Renderer mit Badge), ohne eine Zeile Sonderverdrahtung.
Schritte 1–3 sind Refactoring ohne Funktionsänderung und einzeln committbar; ab Schritt 4 wird das System sichtbar.
8. Auswirkung auf die geplanten Features
- ToDo: Modul nach Schema F (Schritt 5), Aufwand fast nur Puffer-Format und Badge.
- Commit-Dialog: Modul ohne Tab — Beitrag ist ein Fenster samt Capability-Datei; die Abwahl blendet den Einstieg (Menü/Button) aus. Zeigt, dass der Modulbegriff nicht am Panel klebt.
- Archiv-Ausbau: Seitennavigation, Metadaten, Ordnerverwaltung wachsen im Archiv-Modul, dessen Grenze (requires_archive, drei MCP-Tools, zwei Tabs) dann schon gezogen ist.
- Authoring-Ansicht: bekommt mit der Registry eine definierte Andockstelle statt weiterer Handverdrahtung in zwei HTML-Dateien.
9. Ausblick fremde Plugins — drei Stufen, Empfehlung Stufe 2
- Kompilierte Module (dieser Entwurf): Code im Repo, Registry statisch.
- Prozess-Plugins: ein externes Programm liefert einen Deskriptor (JSON-Manifest: id, Label, Tile-Schema, MCP-Tool-Definitionen) und schreibt Pufferdateien im Tile-Format; die App rendert deklarativ und reicht Tool-Calls per stdio durch — dasselbe Muster, mit dem claude heute schon angebunden ist. Kein Fremdcode im Webview, Isolation = Prozessgrenze, CSP und ACL bleiben unangetastet.
- Geladener UI-Code (JS/WASM im Webview): verworfen — hebelt CSP
(
style-src 'self'ohne unsafe-inline) und das App-ACL-Manifest aus und schafft genau die Angriffsfläche, die die Sicherheitsrunden geschlossen haben.
Der Entwurf hält Stufe 2 offen, ohne sie zu bauen: Deskriptor, Tile-Format und Puffer/Event-Konvention sind bereits die Plugin-API — später kommt nur ein Loader dazu, der Deskriptoren aus Manifesten statt aus dem Repo bezieht.