Chat Eksporter
This commit is contained in:
6
.ai_logs/chat-2026-04-10.md
Normal file
6
.ai_logs/chat-2026-04-10.md
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
---
|
||||
### [4/10/2026, 3:25:48 PM]
|
||||
|
||||
3
|
||||
7
.vscode/settings.json
vendored
Normal file
7
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"chat.tools.terminal.autoApprove": {
|
||||
"npm install": true,
|
||||
"vsce": true,
|
||||
"command": true
|
||||
}
|
||||
}
|
||||
15
.vscode/tasks.json
vendored
Normal file
15
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "AI Chat Logger: Generuj VSIX",
|
||||
"type": "shell",
|
||||
"command": "./build.sh",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
7
.vscodeignore
Normal file
7
.vscodeignore
Normal file
@@ -0,0 +1,7 @@
|
||||
.vscode/**
|
||||
.ai_logs/**
|
||||
build.sh
|
||||
node_modules/**
|
||||
*.vsix
|
||||
.git/**
|
||||
.gitignore
|
||||
20
README.md
Normal file
20
README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# AI Chat Logger
|
||||
|
||||
Minimalistyczny plugin zapisujący historię czatu Copilot Chat do plików Markdown.
|
||||
|
||||
## Instalacja
|
||||
|
||||
1. Skopiuj folder `ai-chat-logger` do dowolnego katalogu.
|
||||
2. W VS Code uruchom:
|
||||
- `F1 → Developer: Install Extension from Location`
|
||||
3. Wskaż folder pluginu.
|
||||
|
||||
## Konfiguracja
|
||||
|
||||
W `settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"aiChatLogger.outputDir": ".ai_logs"
|
||||
}
|
||||
# ai-chat-logger
|
||||
BIN
ai-chat-logger-1.0.3.vsix
Normal file
BIN
ai-chat-logger-1.0.3.vsix
Normal file
Binary file not shown.
12
build.sh
Executable file
12
build.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
# Skrypt do budowania rozszerzenia .vsix
|
||||
|
||||
# Sprawdź czy vsce jest zainstalowane
|
||||
if ! command -v vsce &> /dev/null
|
||||
then
|
||||
echo "vsce nie jest zainstalowane. Instalowanie globalnie..."
|
||||
npm install -g @vscode/vsce
|
||||
fi
|
||||
|
||||
echo "Budowanie rozszerzenia..."
|
||||
vsce package --no-git-tag-version --allow-missing-repository --skip-license --allow-star-activation
|
||||
155
extension.js
Normal file
155
extension.js
Normal file
@@ -0,0 +1,155 @@
|
||||
const vscode = require("vscode");
|
||||
const path = require("path");
|
||||
|
||||
function activate(context) {
|
||||
const config = vscode.workspace.getConfiguration("aiChatLogger");
|
||||
const outputDir = config.get("outputDir") || ".ai_logs";
|
||||
const logFormat = config.get("format") || "markdown";
|
||||
|
||||
const workspaceFolder = vscode.workspace.workspaceFolders
|
||||
? vscode.workspace.workspaceFolders[0]
|
||||
: null;
|
||||
|
||||
if (!workspaceFolder) {
|
||||
console.log("AI Chat Logger: brak workspace — plugin nie działa.");
|
||||
return;
|
||||
}
|
||||
|
||||
const workspaceRoot = workspaceFolder.uri;
|
||||
const fullOutputDir = vscode.Uri.joinPath(workspaceRoot, outputDir);
|
||||
|
||||
// Inicjalizacja folderu logów
|
||||
vscode.workspace.fs.createDirectory(fullOutputDir);
|
||||
|
||||
// Rejestracja komendy ręcznego zapisu
|
||||
let disposable = vscode.commands.registerCommand('ai-chat-logger.saveChat', async () => {
|
||||
// Log all document schemes to debug
|
||||
const allDocs = vscode.workspace.textDocuments;
|
||||
const schemes = [...new Set(allDocs.map(d => d.uri.scheme))];
|
||||
console.log("All open documents:", allDocs.map(d => `${d.uri.scheme}:${d.uri.path}`));
|
||||
|
||||
// 1. Proba pobrania tekstu ze schowka (najskuteczniejsza metoda dla nowoczesnego Copilota)
|
||||
try {
|
||||
// Próbujemy skopiować całą treść czatu do schowka
|
||||
await vscode.commands.executeCommand('workbench.action.chat.copyAll');
|
||||
const clipboardText = await vscode.env.clipboard.readText();
|
||||
|
||||
if (clipboardText && clipboardText.trim()) {
|
||||
await saveToFile(clipboardText, "clipboard-chat");
|
||||
vscode.window.showInformationMessage("Czat zapisany pomyślnie na podstawie zawartości okna.");
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("Metoda copyAll nie powiodła się, próbuję metodę dokumentową...");
|
||||
}
|
||||
|
||||
// 2. Metoda dokumentowa dla starszych wersji lub specyficznych widoków
|
||||
const chatDocs = vscode.workspace.textDocuments.filter(doc =>
|
||||
doc.uri.scheme === "vscode-chat" ||
|
||||
doc.uri.scheme === "vscode-chat-result" ||
|
||||
doc.uri.scheme === "chat-session-history" ||
|
||||
doc.uri.scheme === "comment" ||
|
||||
doc.uri.scheme === "vscode-chat-editor" ||
|
||||
doc.uri.scheme === "chat-editing-text-model" ||
|
||||
doc.uri.scheme === "chat-editing-snapshot-text-model");
|
||||
|
||||
if (chatDocs.length === 0) {
|
||||
vscode.window.showErrorMessage(`Nie znaleziono otwartej sesji czatu AI w pamięci ani w schowku. (Dostępne schematy: ${schemes.join(", ")})`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Jeśli jest więcej niż jeden czat, spróbujmy wybrać najnowszy lub połączyć
|
||||
let chosenDoc = chatDocs[0];
|
||||
if (chatDocs.length > 1) {
|
||||
const items = chatDocs.map(d => ({ label: `Czat: ${d.uri.path} (${d.uri.scheme})`, doc: d }));
|
||||
const selection = await vscode.window.showQuickPick(items, { placeHolder: "Wybierz sesję czatu do zapisu" });
|
||||
if (!selection) return;
|
||||
chosenDoc = selection.doc;
|
||||
}
|
||||
|
||||
const content = chosenDoc.getText();
|
||||
|
||||
if (!content.trim()) {
|
||||
vscode.window.showWarningMessage("Czat jest pusty.");
|
||||
return;
|
||||
}
|
||||
|
||||
await saveToFile(content, "manual-chat");
|
||||
});
|
||||
|
||||
context.subscriptions.push(disposable);
|
||||
|
||||
// Rejestracja zdarzenia zmiany dokumentu dla automatycznego logowania
|
||||
const documentChangeDisposable = vscode.workspace.onDidChangeTextDocument(async event => {
|
||||
const doc = event.document;
|
||||
|
||||
// Lista obsługiwanych schematów chatu
|
||||
const chatSchemes = ["vscode-chat", "vscode-chat-result", "chat-session-history", "chat-editing-text-model"];
|
||||
if (!chatSchemes.includes(doc.uri.scheme)) return;
|
||||
|
||||
// Optymalizacja: zapisujemy tylko nowe zmiany (contentChanges)
|
||||
if (event.contentChanges.length === 0) return;
|
||||
|
||||
const date = new Date().toISOString().slice(0, 10);
|
||||
const extension = logFormat === "markdown" ? "md" : "txt";
|
||||
const fileName = `chat-${date}.${extension}`;
|
||||
const fileUri = vscode.Uri.joinPath(fullOutputDir, fileName);
|
||||
|
||||
let newText = event.contentChanges
|
||||
.map(change => change.text)
|
||||
.join("");
|
||||
|
||||
if (!newText.trim()) return;
|
||||
|
||||
const timestamp = new Date().toLocaleString();
|
||||
let entryText = "";
|
||||
|
||||
if (logFormat === "markdown") {
|
||||
entryText = `\n\n---\n### [${timestamp}]\n\n${newText}\n`;
|
||||
} else {
|
||||
entryText = `\n\n---\n[${timestamp}]\n\n${newText}\n`;
|
||||
}
|
||||
|
||||
const entry = Buffer.from(entryText);
|
||||
|
||||
try {
|
||||
let existingContent = Buffer.from("");
|
||||
try {
|
||||
existingContent = await vscode.workspace.fs.readFile(fileUri);
|
||||
} catch (e) {
|
||||
// Plik może nie istnieć, to normalne przy pierwszym wpisie dnia
|
||||
}
|
||||
|
||||
const combinedContent = Buffer.concat([existingContent, entry]);
|
||||
await vscode.workspace.fs.writeFile(fileUri, combinedContent);
|
||||
} catch (err) {
|
||||
console.error("AI Chat Logger error:", err);
|
||||
}
|
||||
});
|
||||
|
||||
context.subscriptions.push(documentChangeDisposable);
|
||||
|
||||
// Pomocnicza funkcja do zapisu (manualnego)
|
||||
async function saveToFile(content, prefix) {
|
||||
const date = new Date().toISOString().slice(0, 10);
|
||||
const time = new Date().toTimeString().slice(0, 8).replace(/:/g, "-");
|
||||
const extension = logFormat === "markdown" ? "md" : "txt";
|
||||
const fileName = `${prefix}-${date}-${time}.${extension}`;
|
||||
const fileUri = vscode.Uri.joinPath(fullOutputDir, fileName);
|
||||
|
||||
const entry = Buffer.from(content);
|
||||
|
||||
try {
|
||||
await vscode.workspace.fs.writeFile(fileUri, entry);
|
||||
vscode.window.showInformationMessage(`Czat zapisany w: ${outputDir}/${fileName}`);
|
||||
} catch (err) {
|
||||
vscode.window.showErrorMessage(`Błąd zapisu: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("AI Chat Logger aktywny.");
|
||||
}
|
||||
|
||||
function deactivate() {}
|
||||
|
||||
module.exports = { activate, deactivate };
|
||||
38
package.json
Normal file
38
package.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "ai-chat-logger",
|
||||
"displayName": "AI Chat Logger",
|
||||
"description": "Automatyczne zapisywanie historii czatu Copilot Chat do pliku.",
|
||||
"version": "1.0.3",
|
||||
"publisher": "local",
|
||||
"engines": {
|
||||
"vscode": "^1.80.0"
|
||||
},
|
||||
"activationEvents": [],
|
||||
"main": "./extension.js",
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "ai-chat-logger.saveChat",
|
||||
"title": "AI Chat Logger: Zapisz Chat"
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"type": "object",
|
||||
"title": "AI Chat Logger",
|
||||
"properties": {
|
||||
"aiChatLogger.outputDir": {
|
||||
"type": "string",
|
||||
"default": ".ai_logs",
|
||||
"description": "Folder, w którym będą zapisywane logi czatu."
|
||||
},
|
||||
"aiChatLogger.format": {
|
||||
"type": "string",
|
||||
"enum": ["markdown", "plaintext"],
|
||||
"default": "markdown",
|
||||
"description": "Format zapisu logów czatu."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"categories": ["Other"]
|
||||
}
|
||||
Reference in New Issue
Block a user