added functionality to gui to create your own patterns
This commit is contained in:
parent
3121730102
commit
7eb5f953d7
@ -1,45 +0,0 @@
|
|||||||
const { OpenAI } = require("openai");
|
|
||||||
require("dotenv").config({
|
|
||||||
path: require("os").homedir() + "/.config/fabric/.env",
|
|
||||||
});
|
|
||||||
|
|
||||||
let openaiClient = null;
|
|
||||||
|
|
||||||
// Function to initialize and get the OpenAI client
|
|
||||||
function getOpenAIClient() {
|
|
||||||
if (!process.env.OPENAI_API_KEY) {
|
|
||||||
throw new Error(
|
|
||||||
"The OPENAI_API_KEY environment variable is missing or empty."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function queryOpenAI(system, user, callback) {
|
|
||||||
const openai = getOpenAIClient(); // Ensure the client is initialized here
|
|
||||||
const messages = [
|
|
||||||
{ role: "system", content: system },
|
|
||||||
{ role: "user", content: user },
|
|
||||||
];
|
|
||||||
try {
|
|
||||||
const stream = await openai.chat.completions.create({
|
|
||||||
model: "gpt-4-1106-preview", // Adjust the model as necessary.
|
|
||||||
messages: messages,
|
|
||||||
temperature: 0.0,
|
|
||||||
top_p: 1,
|
|
||||||
frequency_penalty: 0.1,
|
|
||||||
presence_penalty: 0.1,
|
|
||||||
stream: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
for await (const chunk of stream) {
|
|
||||||
const message = chunk.choices[0]?.delta?.content || "";
|
|
||||||
callback(message); // Process each chunk of data
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error querying OpenAI:", error);
|
|
||||||
callback("Error querying OpenAI. Please try again.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { queryOpenAI };
|
|
@ -36,6 +36,9 @@
|
|||||||
>
|
>
|
||||||
Update Patterns
|
Update Patterns
|
||||||
</button>
|
</button>
|
||||||
|
<button id="createPattern" class="btn btn-outline-success my-2 my-sm-0">
|
||||||
|
Create Pattern
|
||||||
|
</button>
|
||||||
<div class="collapse navbar-collapse" id="navbarCollapse"></div>
|
<div class="collapse navbar-collapse" id="navbarCollapse"></div>
|
||||||
<div class="m1-auto">
|
<div class="m1-auto">
|
||||||
<a class="navbar-brand" id="themeChanger" href="#">Dark</a>
|
<a class="navbar-brand" id="themeChanger" href="#">Dark</a>
|
||||||
@ -53,6 +56,24 @@
|
|||||||
></textarea>
|
></textarea>
|
||||||
<button class="btn btn-primary" id="submit">Submit</button>
|
<button class="btn btn-primary" id="submit">Submit</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="patternCreator" class="container hidden">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="patternName"
|
||||||
|
placeholder="Enter Pattern Name"
|
||||||
|
class="form-control"
|
||||||
|
/>
|
||||||
|
<textarea
|
||||||
|
rows="5"
|
||||||
|
class="form-control"
|
||||||
|
id="patternBody"
|
||||||
|
placeholder="Create your pattern"
|
||||||
|
></textarea>
|
||||||
|
<button class="btn btn-primary" id="submitPattern">Submit</button>
|
||||||
|
<div id="patternCreatedMessage" class="hidden">
|
||||||
|
Pattern created successfully!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="configSection" class="container hidden">
|
<div id="configSection" class="container hidden">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
const { app, BrowserWindow, ipcMain, dialog } = require("electron");
|
const { app, BrowserWindow, ipcMain, dialog } = require("electron");
|
||||||
const fs = require("fs");
|
const fs = require("fs").promises;
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const os = require("os");
|
const os = require("os");
|
||||||
const OpenAI = require("openai");
|
const OpenAI = require("openai");
|
||||||
const Ollama = require("ollama");
|
const Ollama = require("ollama");
|
||||||
const Anthropic = require("@anthropic-ai/sdk");
|
const Anthropic = require("@anthropic-ai/sdk");
|
||||||
|
const axios = require("axios");
|
||||||
|
const fsExtra = require("fs-extra");
|
||||||
|
const fsConstants = require("fs").constants;
|
||||||
|
|
||||||
let fetch, allModels;
|
let fetch, allModels;
|
||||||
|
|
||||||
@ -17,26 +20,22 @@ let win;
|
|||||||
let openai;
|
let openai;
|
||||||
let ollama;
|
let ollama;
|
||||||
|
|
||||||
function ensureFabricFoldersExist() {
|
async function ensureFabricFoldersExist() {
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
const fabricPath = path.join(os.homedir(), ".config", "fabric");
|
const fabricPath = path.join(os.homedir(), ".config", "fabric");
|
||||||
const patternsPath = path.join(fabricPath, "patterns");
|
const patternsPath = path.join(fabricPath, "patterns");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!fs.existsSync(fabricPath)) {
|
await fs
|
||||||
fs.mkdirSync(fabricPath, { recursive: true });
|
.access(fabricPath, fsConstants.F_OK)
|
||||||
}
|
.catch(() => fs.mkdir(fabricPath, { recursive: true }));
|
||||||
|
await fs
|
||||||
if (!fs.existsSync(patternsPath)) {
|
.access(patternsPath, fsConstants.F_OK)
|
||||||
fs.mkdirSync(patternsPath, { recursive: true });
|
.catch(() => fs.mkdir(patternsPath, { recursive: true }));
|
||||||
await downloadAndUpdatePatterns(patternsPath);
|
// Optionally download and update patterns after ensuring the directories exist
|
||||||
}
|
|
||||||
resolve(); // Resolve the promise once everything is set up
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error ensuring fabric folders exist:", error);
|
console.error("Error ensuring fabric folders exist:", error);
|
||||||
reject(error); // Reject the promise if an error occurs
|
throw error; // Make sure to re-throw the error to handle it further up the call stack if necessary
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadAndUpdatePatterns() {
|
async function downloadAndUpdatePatterns() {
|
||||||
@ -105,51 +104,77 @@ async function downloadAndUpdatePatterns() {
|
|||||||
}
|
}
|
||||||
function getPatternFolders() {
|
function getPatternFolders() {
|
||||||
const patternsPath = path.join(os.homedir(), ".config", "fabric", "patterns");
|
const patternsPath = path.join(os.homedir(), ".config", "fabric", "patterns");
|
||||||
return fs
|
return new Promise((resolve, reject) => {
|
||||||
.readdirSync(patternsPath, { withFileTypes: true })
|
fs.readdir(patternsPath, { withFileTypes: true }, (error, dirents) => {
|
||||||
|
if (error) {
|
||||||
|
console.error("Failed to read pattern folders:", error);
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
const folders = dirents
|
||||||
.filter((dirent) => dirent.isDirectory())
|
.filter((dirent) => dirent.isDirectory())
|
||||||
.map((dirent) => dirent.name);
|
.map((dirent) => dirent.name);
|
||||||
|
resolve(folders);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkApiKeyExists() {
|
async function checkApiKeyExists() {
|
||||||
const configPath = path.join(os.homedir(), ".config", "fabric", ".env");
|
const configPath = path.join(os.homedir(), ".config", "fabric", ".env");
|
||||||
return fs.existsSync(configPath);
|
try {
|
||||||
|
await fs.access(configPath, fsConstants.F_OK);
|
||||||
|
return true; // The file exists
|
||||||
|
} catch (e) {
|
||||||
|
return false; // The file does not exist
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadApiKeys() {
|
async function loadApiKeys() {
|
||||||
const configPath = path.join(os.homedir(), ".config", "fabric", ".env");
|
const configPath = path.join(os.homedir(), ".config", "fabric", ".env");
|
||||||
let keys = { openAIKey: null, claudeKey: null };
|
let keys = { openAIKey: null, claudeKey: null };
|
||||||
|
|
||||||
if (fs.existsSync(configPath)) {
|
try {
|
||||||
const envContents = fs.readFileSync(configPath, { encoding: "utf8" });
|
// Use fs.promises.readFile and await its result
|
||||||
|
const envContents = await fs.readFile(configPath, { encoding: "utf8" });
|
||||||
const openAIMatch = envContents.match(/^OPENAI_API_KEY=(.*)$/m);
|
const openAIMatch = envContents.match(/^OPENAI_API_KEY=(.*)$/m);
|
||||||
const claudeMatch = envContents.match(/^CLAUDE_API_KEY=(.*)$/m);
|
const claudeMatch = envContents.match(/^CLAUDE_API_KEY=(.*)$/m);
|
||||||
|
|
||||||
if (openAIMatch && openAIMatch[1]) {
|
if (openAIMatch && openAIMatch[1]) {
|
||||||
keys.openAIKey = openAIMatch[1];
|
keys.openAIKey = openAIMatch[1];
|
||||||
openai = new OpenAI({ apiKey: keys.openAIKey });
|
// Initialize your OpenAI client here if necessary
|
||||||
}
|
}
|
||||||
if (claudeMatch && claudeMatch[1]) {
|
if (claudeMatch && claudeMatch[1]) {
|
||||||
keys.claudeKey = claudeMatch[1];
|
keys.claudeKey = claudeMatch[1];
|
||||||
claude = new Anthropic({ apiKey: keys.claudeKey });
|
// Initialize your Claude client here if necessary
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Handle the case where the .env file doesn't exist or can't be read
|
||||||
|
console.error("Could not load API keys:", error);
|
||||||
}
|
}
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveApiKeys(openAIKey, claudeKey) {
|
async function saveApiKeys(openAIKey, claudeKey) {
|
||||||
const configPath = path.join(os.homedir(), ".config", "fabric");
|
const configPath = path.join(os.homedir(), ".config", "fabric");
|
||||||
const envFilePath = path.join(configPath, ".env");
|
const envFilePath = path.join(configPath, ".env");
|
||||||
|
|
||||||
if (!fs.existsSync(configPath)) {
|
try {
|
||||||
fs.mkdirSync(configPath, { recursive: true });
|
await fs.access(configPath);
|
||||||
|
} catch {
|
||||||
|
await fs.mkdir(configPath, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
let envContent = "";
|
let envContent = "";
|
||||||
|
|
||||||
// Read the existing .env file if it exists
|
// Read the existing .env file if it exists
|
||||||
if (fs.existsSync(envFilePath)) {
|
try {
|
||||||
envContent = fs.readFileSync(envFilePath, "utf8");
|
envContent = await fs.readFile(envFilePath, "utf8");
|
||||||
|
} catch (err) {
|
||||||
|
if (err.code !== "ENOENT") {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
// If the file doesn't exist, create an empty .env file
|
||||||
|
await fs.writeFile(envFilePath, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the specific API key
|
// Update the specific API key
|
||||||
@ -164,9 +189,9 @@ function saveApiKeys(openAIKey, claudeKey) {
|
|||||||
claude = new Anthropic({ apiKey: claudeKey });
|
claude = new Anthropic({ apiKey: claudeKey });
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(envFilePath, envContent.trim());
|
await fs.writeFile(envFilePath, envContent.trim());
|
||||||
loadApiKeys();
|
await loadApiKeys();
|
||||||
win.webContents.send("reload-app");
|
win.webContents.send("api-keys-saved");
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateOrAddKey(envContent, keyName, keyValue) {
|
function updateOrAddKey(envContent, keyName, keyValue) {
|
||||||
@ -195,7 +220,7 @@ async function getModels() {
|
|||||||
ollamaModels: [],
|
ollamaModels: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
let keys = loadApiKeys(); // Assuming loadApiKeys() is updated to return both keys
|
let keys = await loadApiKeys(); // Assuming loadApiKeys() is updated to return both keys
|
||||||
|
|
||||||
if (keys.claudeKey) {
|
if (keys.claudeKey) {
|
||||||
// Assuming claudeModels do not require an asynchronous call to be fetched
|
// Assuming claudeModels do not require an asynchronous call to be fetched
|
||||||
@ -245,7 +270,7 @@ async function getModels() {
|
|||||||
return allModels; // Return the aggregated results
|
return allModels; // Return the aggregated results
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPatternContent(patternName) {
|
async function getPatternContent(patternName) {
|
||||||
const patternPath = path.join(
|
const patternPath = path.join(
|
||||||
os.homedir(),
|
os.homedir(),
|
||||||
".config",
|
".config",
|
||||||
@ -255,7 +280,8 @@ function getPatternContent(patternName) {
|
|||||||
"system.md"
|
"system.md"
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
return fs.readFileSync(patternPath, "utf8");
|
const content = await fs.readFile(patternPath, "utf8");
|
||||||
|
return content;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error reading pattern file:", error);
|
console.error("Error reading pattern file:", error);
|
||||||
return "";
|
return "";
|
||||||
@ -332,6 +358,33 @@ async function claudeMessage(system, user, model, event) {
|
|||||||
event.reply("model-response-end", responseMessage);
|
event.reply("model-response-end", responseMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function createPatternFolder(patternName, patternBody) {
|
||||||
|
try {
|
||||||
|
const patternsPath = path.join(
|
||||||
|
os.homedir(),
|
||||||
|
".config",
|
||||||
|
"fabric",
|
||||||
|
"patterns"
|
||||||
|
);
|
||||||
|
const patternFolderPath = path.join(patternsPath, patternName);
|
||||||
|
|
||||||
|
// Create the pattern folder using the promise-based API
|
||||||
|
await fs.mkdir(patternFolderPath, { recursive: true });
|
||||||
|
|
||||||
|
// Create the system.md file inside the pattern folder
|
||||||
|
const filePath = path.join(patternFolderPath, "system.md");
|
||||||
|
await fs.writeFile(filePath, patternBody);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Pattern folder '${patternName}' created successfully with system.md inside.`
|
||||||
|
);
|
||||||
|
return `Pattern folder '${patternName}' created successfully with system.md inside.`;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Failed to create the pattern folder: ${err.message}`);
|
||||||
|
throw err; // Ensure the error is thrown so it can be caught by the caller
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function createWindow() {
|
function createWindow() {
|
||||||
win = new BrowserWindow({
|
win = new BrowserWindow({
|
||||||
width: 800,
|
width: 800,
|
||||||
@ -377,10 +430,21 @@ ipcMain.on("start-query", async (event, system, user, model) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.handle("create-pattern", async (event, patternName, patternContent) => {
|
||||||
|
try {
|
||||||
|
const result = await createPatternFolder(patternName, patternContent);
|
||||||
|
return { status: "success", message: result }; // Use a response object for more detailed responses
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating pattern:", error);
|
||||||
|
return { status: "error", message: error.message }; // Return an error object
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Example of using ipcMain.handle for asynchronous operations
|
// Example of using ipcMain.handle for asynchronous operations
|
||||||
ipcMain.handle("get-patterns", async (event) => {
|
ipcMain.handle("get-patterns", async (event) => {
|
||||||
try {
|
try {
|
||||||
return getPatternFolders();
|
const patterns = await getPatternFolders();
|
||||||
|
return patterns;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to get patterns:", error);
|
console.error("Failed to get patterns:", error);
|
||||||
return [];
|
return [];
|
||||||
@ -394,7 +458,8 @@ ipcMain.on("update-patterns", () => {
|
|||||||
|
|
||||||
ipcMain.handle("get-pattern-content", async (event, patternName) => {
|
ipcMain.handle("get-pattern-content", async (event, patternName) => {
|
||||||
try {
|
try {
|
||||||
return getPatternContent(patternName);
|
const content = await getPatternContent(patternName);
|
||||||
|
return content;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to get pattern content:", error);
|
console.error("Failed to get pattern content:", error);
|
||||||
return "";
|
return "";
|
||||||
@ -403,7 +468,7 @@ ipcMain.handle("get-pattern-content", async (event, patternName) => {
|
|||||||
|
|
||||||
ipcMain.handle("save-api-keys", async (event, { openAIKey, claudeKey }) => {
|
ipcMain.handle("save-api-keys", async (event, { openAIKey, claudeKey }) => {
|
||||||
try {
|
try {
|
||||||
saveApiKeys(openAIKey, claudeKey);
|
await saveApiKeys(openAIKey, claudeKey);
|
||||||
return "API Keys saved successfully.";
|
return "API Keys saved successfully.";
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error saving API keys:", error);
|
console.error("Error saving API keys:", error);
|
||||||
@ -423,22 +488,13 @@ ipcMain.handle("get-models", async (event) => {
|
|||||||
|
|
||||||
app.whenReady().then(async () => {
|
app.whenReady().then(async () => {
|
||||||
try {
|
try {
|
||||||
const keys = loadApiKeys();
|
const keys = await loadApiKeys();
|
||||||
if (!keys.openAIKey && !keys.claudeKey) {
|
|
||||||
promptUserForApiKey();
|
|
||||||
} else {
|
|
||||||
createWindow();
|
|
||||||
}
|
|
||||||
await ensureFabricFoldersExist(); // Ensure fabric folders exist
|
await ensureFabricFoldersExist(); // Ensure fabric folders exist
|
||||||
createWindow(); // Create the application window
|
await getModels(); // Fetch models after loading API keys
|
||||||
|
createWindow(); // Keep this line
|
||||||
// After window creation, check if the API key exists
|
|
||||||
if (!checkApiKeyExists()) {
|
|
||||||
console.log("API key is missing. Prompting user to input API key.");
|
|
||||||
win.webContents.send("request-api-key");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to initialize fabric folders:", error);
|
await ensureFabricFoldersExist(); // Ensure fabric folders exist
|
||||||
|
createWindow(); // Keep this line
|
||||||
// Handle initialization failure (e.g., close the app or show an error message)
|
// Handle initialization failure (e.g., close the app or show an error message)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,10 @@ document.addEventListener("DOMContentLoaded", async function () {
|
|||||||
const openaiApiKeyInput = document.getElementById("apiKeyInput");
|
const openaiApiKeyInput = document.getElementById("apiKeyInput");
|
||||||
const claudeApiKeyInput = document.getElementById("claudeApiKeyInput");
|
const claudeApiKeyInput = document.getElementById("claudeApiKeyInput");
|
||||||
const updatePatternsButton = document.getElementById("updatePatternsButton");
|
const updatePatternsButton = document.getElementById("updatePatternsButton");
|
||||||
|
const updatePatternButton = document.getElementById("createPattern");
|
||||||
|
const patternCreator = document.getElementById("patternCreator");
|
||||||
|
const submitPatternButton = document.getElementById("submitPattern");
|
||||||
|
const myForm = document.getElementById("my-form");
|
||||||
const copyButton = document.createElement("button");
|
const copyButton = document.createElement("button");
|
||||||
|
|
||||||
window.electronAPI.on("patterns-ready", () => {
|
window.electronAPI.on("patterns-ready", () => {
|
||||||
@ -70,6 +74,35 @@ document.addEventListener("DOMContentLoaded", async function () {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function submitPattern(patternName, patternText) {
|
||||||
|
try {
|
||||||
|
const response = await window.electronAPI.invoke(
|
||||||
|
"create-pattern",
|
||||||
|
patternName,
|
||||||
|
patternText
|
||||||
|
);
|
||||||
|
if (response.status === "success") {
|
||||||
|
console.log(response.message);
|
||||||
|
// Show success message
|
||||||
|
const patternCreatedMessage = document.getElementById(
|
||||||
|
"patternCreatedMessage"
|
||||||
|
);
|
||||||
|
patternCreatedMessage.classList.remove("hidden");
|
||||||
|
setTimeout(() => {
|
||||||
|
patternCreatedMessage.classList.add("hidden");
|
||||||
|
}, 3000); // Hide the message after 3 seconds
|
||||||
|
|
||||||
|
// Update pattern list
|
||||||
|
loadPatterns();
|
||||||
|
} else {
|
||||||
|
console.error(response.message);
|
||||||
|
// Handle failure (e.g., showing an error message to the user)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("IPC error:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function copyToClipboard() {
|
function copyToClipboard() {
|
||||||
const containerClone = responseContainer.cloneNode(true);
|
const containerClone = responseContainer.cloneNode(true);
|
||||||
const copyButtonClone = containerClone.querySelector("#copyButton");
|
const copyButtonClone = containerClone.querySelector("#copyButton");
|
||||||
@ -135,13 +168,12 @@ document.addEventListener("DOMContentLoaded", async function () {
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to load models:", error);
|
console.error("Failed to load models:", error);
|
||||||
|
alert(
|
||||||
|
"Failed to load models. Please check the console for more details."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePatternsButton.addEventListener("click", () => {
|
|
||||||
window.electronAPI.send("update-patterns");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Load patterns and models on startup
|
// Load patterns and models on startup
|
||||||
loadPatterns();
|
loadPatterns();
|
||||||
loadModels();
|
loadModels();
|
||||||
@ -168,13 +200,18 @@ document.addEventListener("DOMContentLoaded", async function () {
|
|||||||
submitQuery(message);
|
submitQuery(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
window.electronAPI.on;
|
window.electronAPI.on("api-keys-saved", async () => {
|
||||||
"reload-app",
|
try {
|
||||||
() => {
|
await loadModels();
|
||||||
// Reload the app
|
alert("API Keys saved successfully.");
|
||||||
loadModels();
|
configSection.classList.add("hidden");
|
||||||
location.reload();
|
openaiApiKeyInput.value = "";
|
||||||
};
|
claudeApiKeyInput.value = "";
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to reload models:", error);
|
||||||
|
alert("Failed to reload models.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Submit button click handler
|
// Submit button click handler
|
||||||
submitButton.addEventListener("click", async () => {
|
submitButton.addEventListener("click", async () => {
|
||||||
@ -182,6 +219,14 @@ document.addEventListener("DOMContentLoaded", async function () {
|
|||||||
submitQuery(userInputValue);
|
submitQuery(userInputValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
submitPatternButton.addEventListener("click", async () => {
|
||||||
|
const patternName = document.getElementById("patternName").value;
|
||||||
|
const patternText = document.getElementById("patternBody").value;
|
||||||
|
document.getElementById("patternName").value = "";
|
||||||
|
document.getElementById("patternBody").value = "";
|
||||||
|
submitPattern(patternName, patternText);
|
||||||
|
});
|
||||||
|
|
||||||
// Theme changer click handler
|
// Theme changer click handler
|
||||||
themeChanger.addEventListener("click", function (e) {
|
themeChanger.addEventListener("click", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -190,6 +235,14 @@ document.addEventListener("DOMContentLoaded", async function () {
|
|||||||
themeChanger.innerText === "Dark" ? "Light" : "Dark";
|
themeChanger.innerText === "Dark" ? "Light" : "Dark";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updatePatternButton.addEventListener("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
patternCreator.classList.toggle("hidden");
|
||||||
|
myForm.classList.toggle("hidden");
|
||||||
|
|
||||||
|
// window.electronAPI.send("create-pattern");
|
||||||
|
});
|
||||||
|
|
||||||
// Config button click handler - toggles the config section visibility
|
// Config button click handler - toggles the config section visibility
|
||||||
configButton.addEventListener("click", function (e) {
|
configButton.addEventListener("click", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -202,14 +255,6 @@ document.addEventListener("DOMContentLoaded", async function () {
|
|||||||
const claudeKey = claudeApiKeyInput.value;
|
const claudeKey = claudeApiKeyInput.value;
|
||||||
window.electronAPI
|
window.electronAPI
|
||||||
.invoke("save-api-keys", { openAIKey, claudeKey })
|
.invoke("save-api-keys", { openAIKey, claudeKey })
|
||||||
.then(() => {
|
|
||||||
alert("API Keys saved successfully.");
|
|
||||||
configSection.classList.add("hidden");
|
|
||||||
openaiApiKeyInput.value = "";
|
|
||||||
claudeApiKeyInput.value = "";
|
|
||||||
// Reload the models
|
|
||||||
loadModels();
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error("Error saving API keys:", err);
|
console.error("Error saving API keys:", err);
|
||||||
alert("Failed to save API Keys.");
|
alert("Failed to save API Keys.");
|
||||||
|
@ -158,3 +158,27 @@ body.light-theme .navbar-toggler-icon {
|
|||||||
#copyButton:focus {
|
#copyButton:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
#patternCreatedMessage {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #4caf50;
|
||||||
|
color: white;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-theme #patternCreator {
|
||||||
|
background: #f0f0f0;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-theme #patternCreator input,
|
||||||
|
.light-theme #patternCreator textarea {
|
||||||
|
background-color: #fff;
|
||||||
|
color: #333;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
#patternCreator textarea {
|
||||||
|
background-color: #424242;
|
||||||
|
color: #e0e0e0;
|
||||||
|
border: 1px solid #555;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user