Entwurfs-Panel mit MCP-Tool write_panel
- Andockbares Panel im Terminal-Fenster: Markdown-Rendering, Copy-Button, normale Selektion; in eigenes Fenster ablösbar und wieder andockbar (Splitter, panel-detached/panel-attached). - MCP-stdio-Server (app --mcp-panel) mit Tool write_panel; schreibt in die Datei aus AI_CONTROL_PANEL, Watcher zieht sie ins Panel. - Provisionierung je Pool: Server-Registrierung in .claude.json (alwaysLoad), Freigabe mcp__text-panel__write_panel in settings.json, Panel-Skill; bei App-Start (alle Pools) und Pool-Anlage. Alte tee-Freigaben werden entfernt. - Capability deckt panel-*-Fenster ab.
This commit is contained in:
@@ -9,6 +9,8 @@ import "@fontsource/jetbrains-mono/600.css";
|
||||
import "@fontsource/jetbrains-mono/700.css";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { initPanelView } from "./panel-view";
|
||||
|
||||
// Debug-Instrumentierung: Fehler auf der Seite anzeigen und ins Dev-Log spiegeln.
|
||||
function showError(msg: string) {
|
||||
@@ -529,3 +531,73 @@ window.addEventListener("resize", () => fit.fit());
|
||||
|
||||
await invoke("term_start", { project, rows: term.rows, cols: term.cols });
|
||||
term.focus();
|
||||
|
||||
// --- Andockbares Entwurfs-Panel -------------------------------------------
|
||||
// Der Skill schreibt Entwürfe in eine Datei; terminal.rs meldet neuen Inhalt
|
||||
// per `panel-update`. Das Panel blendet sich dann ein — außer es ist gerade in
|
||||
// ein eigenes Fenster abgelöst (`panel-detached`).
|
||||
const panel = document.getElementById("panel")!;
|
||||
const splitter = document.getElementById("splitter")!;
|
||||
const panelContent = document.getElementById("panel-content")!;
|
||||
|
||||
// Panelfarben ans Theme koppeln.
|
||||
panel.style.background = picked.header;
|
||||
panel.style.color = theme.foreground;
|
||||
splitter.style.background = picked.border;
|
||||
(panel.querySelector(".panel-head") as HTMLElement).style.borderBottomColor =
|
||||
picked.border;
|
||||
|
||||
const view = initPanelView({
|
||||
content: panelContent,
|
||||
copyBtn: document.getElementById("panel-copy")!,
|
||||
modeBtn: document.getElementById("panel-mode")!,
|
||||
});
|
||||
|
||||
let detached = false;
|
||||
let hasContent = false;
|
||||
|
||||
function showPanel() {
|
||||
panel.hidden = false;
|
||||
splitter.hidden = false;
|
||||
fit.fit();
|
||||
}
|
||||
function hidePanel() {
|
||||
panel.hidden = true;
|
||||
splitter.hidden = true;
|
||||
fit.fit();
|
||||
}
|
||||
|
||||
await listen<string>("panel-update", (e) => {
|
||||
view.set(e.payload);
|
||||
hasContent = true;
|
||||
if (!detached) showPanel();
|
||||
});
|
||||
await listen("panel-detached", () => {
|
||||
detached = true;
|
||||
hidePanel();
|
||||
});
|
||||
await listen("panel-attached", () => {
|
||||
detached = false;
|
||||
if (hasContent) showPanel();
|
||||
});
|
||||
|
||||
document
|
||||
.getElementById("panel-detach")!
|
||||
.addEventListener("click", () => invoke("open_panel_window", { project }));
|
||||
document.getElementById("panel-hide")!.addEventListener("click", hidePanel);
|
||||
|
||||
// Splitter: Panelbreite ziehen.
|
||||
splitter.addEventListener("mousedown", (e) => {
|
||||
e.preventDefault();
|
||||
const move = (ev: MouseEvent) => {
|
||||
const w = Math.max(240, Math.min(window.innerWidth - 200, window.innerWidth - ev.clientX));
|
||||
panel.style.width = `${w}px`;
|
||||
fit.fit();
|
||||
};
|
||||
const up = () => {
|
||||
window.removeEventListener("mousemove", move);
|
||||
window.removeEventListener("mouseup", up);
|
||||
};
|
||||
window.addEventListener("mousemove", move);
|
||||
window.addEventListener("mouseup", up);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user