diff --git a/README.md b/README.md index bb6bce8..3c8e39d 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,8 @@ If you enjoy this plugin or would like to show your support, please consider giv You need to first set your own OpenAI API key in the Plugin Settings , so that the plugin can work properly. 1. Generate an OpenAI API key on the official website. [Click here](https://beta.openai.com/account/api-keys) -2. In Obsidian, go to `Settings`, click `Community Plugins` in the left menu , and enable `Lightweight ChatGPT Plugin` in the Installed Plugins. -3. Click the gear icon to enter the plugin settings. Then enter your API key in the `OpenAI API Key` field. +2. In Obsidian, go to `Settings`, click `Community Plugins` in the left menu , and enable `GPT-LiteInquirer` in the Installed Plugins. +3. Click the gear icon to enter the plugin settings. Then enter your API key in the `OpenAI API Key` field and then you're done! 🎉 To download Obsidian: [Click here](https://www.obsidian.md/) @@ -43,23 +43,23 @@ To download Obsidian: [Click here](https://www.obsidian.md/) You can open the Lightweight ChatGPT Plugin interface in three ways: - By clicking on the Obsidian ribbon on the left. +- By the Obsidian command `Open Lightweight Window`. +- By manually set a keyboard shortcut for the command, such as `CTRL + K`. -- By the keyboard shortcuts `ALT + C`. -- By the Obsidian command `Open Lightweight ChatGPT Plugin Window`. - -In the Lightweight ChatGPT Plugin Window, the content you selected in the current Markdown document will be copied to the text box automatically. So you can use this text to ask questions or perform other operations, or directly write down anything you want to say. +In the GPT Lite Inquirer Window, the content you selected in the current Markdown document will be copied to the text box automatically. So you can use this text to ask questions or perform other operations, or directly write down anything you want to say. Tips: You can also send content directly using the `CTRL + ENTER` shortcut. --- -- TODO List: +TODO List: - - Add support for Azure API +- [ ] Add configuration default Prompt +- [ ] Add support for Azure API - - Add support for GPT-4 +- [ ] Add support for GPT-4 -Lightweight ChatGPT Plugin for Obsidian wants to be a nice companion to boost your creativity and productivity. Experience the seamless AI-enhanced writing and content generation capabilities within Obsidian today! +GPT-LiteInquirer Plugin for Obsidian wants to be a nice companion to boost your creativity and productivity. Experience the seamless AI-enhanced writing and content generation capabilities within Obsidian today! diff --git a/main.js b/main.js index 08e2544..cf9e0eb 100644 --- a/main.js +++ b/main.js @@ -49,21 +49,21 @@ var LightweightChatGPTPlugin = class extends import_obsidian.Plugin { } }); this.addCommand({ - id: "lightweight-chatgpt-window-hotkey", - name: "Open Lightweight ChatGPT Plugin Window", + id: "open-lightweight-window", + name: "Open Lightweight Window", callback: () => { try { new LightweightChatGPTWindow(this.app, this.settings.apiKey, this.settings.temperature, this.settings.maxTokens, this.settings.insertionMode).open(); } catch (error) { console.error("Error opening Lightweight ChatGPT Plugin Window:", error); } - }, - hotkeys: [ - { - modifiers: ["Alt"], - key: "c" - } - ] + } + // hotkeys: [ + // { + // modifiers: ['CTRL'], + // key: 'k', + // }, + // ] }); try { this.addSettingTab(new LightweightChatGPTSettingTab(this.app, this)); @@ -113,11 +113,11 @@ var LightweightChatGPTWindow = class extends import_obsidian.Modal { } onOpen() { const { contentEl } = this; - contentEl.createEl("h2", { text: "Lightweight ChatGPT Plugin Window" }); + contentEl.createEl("h2", { text: "GPT Lite Inquirer Window" }); const activeView = this.app.workspace.getActiveViewOfType(import_obsidian.MarkdownView); const selectedText = activeView ? activeView.editor.getSelection() : ""; this.inputTextArea = contentEl.createEl("textarea"); - this.inputTextArea.style.width = "100%"; + this.inputTextArea.classList.add("gpt-input-textarea"); this.inputTextArea.rows = 4; this.inputTextArea.placeholder = "Enter your text here ..."; this.inputTextArea.value = selectedText ? `${selectedText} @@ -138,14 +138,10 @@ var LightweightChatGPTWindow = class extends import_obsidian.Modal { const maxTokensLabelContainer = maxTokensContainer.createEl("div"); maxTokensLabelContainer.createEl("label", { text: "Max tokens:" }); const maxTokensDescription = maxTokensLabelContainer.createEl("p", { text: "Max OpenAI ChatGpt Tokens" }); - maxTokensDescription.style.fontSize = "0.8rem"; - maxTokensDescription.style.marginTop = "0.25rem"; - maxTokensDescription.style.marginRight = "0.5rem"; + maxTokensDescription.classList.add("max-tokens-description"); this.maxTokensInput = maxTokensContainer.createEl("input", { type: "number" }); this.maxTokensInput.placeholder = "Enter max Tokens number"; - this.maxTokensInput.style.width = "40%"; - this.maxTokensInput.style.height = "calc(1.5em + 1.25em)"; - this.maxTokensInput.style.textAlign = "right"; + this.maxTokensInput.classList.add("max-tokens-input"); this.maxTokensInput.min = "1"; this.maxTokensInput.max = "2048"; this.maxTokensInput.value = this.maxTokens.toString(); @@ -169,8 +165,7 @@ var LightweightChatGPTWindow = class extends import_obsidian.Modal { const responseDivider = contentEl.createEl("hr"); responseDivider.style.display = "none"; this.outputContainer = contentEl.createEl("div"); - this.outputContainer.style.whiteSpace = "pre-wrap"; - this.outputContainer.style.userSelect = "text"; + this.outputContainer.classList.add("output-container"); const buttonsContainer = contentEl.createEl("div"); buttonsContainer.style.display = "flex"; buttonsContainer.style.marginTop = "1rem"; @@ -226,7 +221,8 @@ var LightweightChatGPTWindow = class extends import_obsidian.Modal { const apiUrl = "https://api.openai.com/v1/chat/completions"; const maxTokens = parseInt(this.maxTokensInput.value); try { - const response = await fetch(apiUrl, { + const response = await (0, import_obsidian.request)({ + url: apiUrl, method: "POST", headers: { "Content-Type": "application/json", @@ -241,18 +237,22 @@ var LightweightChatGPTWindow = class extends import_obsidian.Modal { ] }) }); - if (response.ok) { - const result = await response.json(); + const result = JSON.parse(response); + if (result.choices && result.choices.length > 0) { const gptResponse = result.choices[0].message.content; this.outputContainer.empty(); this.outputContainer.createEl("p", { text: gptResponse }); return gptResponse; + } else if (result.error) { + throw new Error(JSON.stringify(result.error)); } else { - throw new Error(`API request failed with status: ${response.status}`); + throw new Error("Unexpected API response format"); } } catch (error) { console.error("Error during API request:", error); - new import_obsidian.Notice("Error during API request: " + error.message); + new import_obsidian.Notice( + "Error during API request: " + error.message + ); } } insertAtCursor(textArea, text) { @@ -363,8 +363,6 @@ var LightweightChatGPTSettingTab = class extends import_obsidian.PluginSettingTa cls: "polite-message" }); politeMessage.textContent = "If you enjoy this plugin or would like to show your support, please consider giving it a free star on GitHub~ Your appreciation means a lot to me!"; - politeMessage.style.marginBottom = "1rem"; - politeMessage.style.fontStyle = "italic"; const githubLink = containerEl.createEl("div", { cls: "github-link-container" }); @@ -379,6 +377,10 @@ var LightweightChatGPTSettingTab = class extends import_obsidian.PluginSettingTa }); const style = document.createElement("style"); style.innerHTML = ` + .polite-message { + margin-bottom: 1rem; + font-style: italic; + } .github-link-container { margin-top: 2rem; text-align: center; diff --git a/main.ts b/main.ts index a159b14..d4b2cd0 100644 --- a/main.ts +++ b/main.ts @@ -1,4 +1,13 @@ -import { App, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian'; +import { + App, + MarkdownView, + Modal, + Notice, + Plugin, + PluginSettingTab, + Setting, + request +} from 'obsidian'; @@ -39,24 +48,23 @@ export default class LightweightChatGPTPlugin extends Plugin { }); this.addCommand({ - id: 'lightweight-chatgpt-window-hotkey', - name: 'Open Lightweight ChatGPT Plugin Window', + id: 'open-lightweight-window', + name: 'Open Lightweight Window', callback: () => { try { new LightweightChatGPTWindow(this.app, this.settings.apiKey, this.settings.temperature, this.settings.maxTokens, this.settings.insertionMode).open(); } catch (error) { console.error('Error opening Lightweight ChatGPT Plugin Window:', error); } - }, - hotkeys: [ - { - modifiers: ['Alt'], - key: 'c', - }, - ], + } + // hotkeys: [ + // { + // modifiers: ['CTRL'], + // key: 'k', + // }, + // ] }); - // Add a settings tab for user configuration try { this.addSettingTab(new LightweightChatGPTSettingTab(this.app, this)); } catch (error) { @@ -86,7 +94,7 @@ export default class LightweightChatGPTPlugin extends Plugin { } // Perform additional things with the ribbon - this.ribbonIconEl.addClass('lightweight-chatgpt-ribbon-class'); + // this.ribbonIconEl.addClass('gpt-liteinquirer-ribbon-class'); } removeSidebarIcon() { @@ -135,13 +143,13 @@ class LightweightChatGPTWindow extends Modal { onOpen() { const { contentEl } = this; - contentEl.createEl('h2', { text: 'Lightweight ChatGPT Plugin Window' }); + contentEl.createEl('h2', { text: 'GPT Lite Inquirer Window' }); const activeView = this.app.workspace.getActiveViewOfType(MarkdownView); const selectedText = activeView ? activeView.editor.getSelection() : ''; this.inputTextArea = contentEl.createEl('textarea'); - this.inputTextArea.style.width = '100%'; + this.inputTextArea.classList.add('gpt-input-textarea') this.inputTextArea.rows = 4; this.inputTextArea.placeholder = 'Enter your text here ...'; this.inputTextArea.value = selectedText ? `${selectedText}\n====\n` : ''; @@ -160,21 +168,16 @@ class LightweightChatGPTWindow extends Modal { // Max Tokens const maxTokensContainer = contentEl.createEl('div'); - // maxTokensContainer.style.marginRight = '0.5rem'; maxTokensContainer.className = "max-tokens-container"; const maxTokensLabelContainer = maxTokensContainer.createEl('div'); maxTokensLabelContainer.createEl('label', { text: 'Max tokens:' }); const maxTokensDescription = maxTokensLabelContainer.createEl('p', { text: 'Max OpenAI ChatGpt Tokens' }); - maxTokensDescription.style.fontSize = '0.8rem'; - maxTokensDescription.style.marginTop = '0.25rem'; - maxTokensDescription.style.marginRight = '0.5rem'; + maxTokensDescription.classList.add('max-tokens-description'); this.maxTokensInput = maxTokensContainer.createEl('input', { type: 'number' }); this.maxTokensInput.placeholder = 'Enter max Tokens number'; - this.maxTokensInput.style.width = '40%'; - this.maxTokensInput.style.height = 'calc(1.5em + 1.25em)'; // sum of label and description line heights - this.maxTokensInput.style.textAlign = 'right'; + this.maxTokensInput.classList.add('max-tokens-input'); this.maxTokensInput.min = "1"; this.maxTokensInput.max = "2048"; this.maxTokensInput.value = this.maxTokens.toString(); @@ -205,8 +208,7 @@ class LightweightChatGPTWindow extends Modal { // Output Container this.outputContainer = contentEl.createEl('div'); - this.outputContainer.style.whiteSpace = 'pre-wrap'; - this.outputContainer.style.userSelect = 'text'; + this.outputContainer.classList.add('output-container'); // Add Other Button const buttonsContainer = contentEl.createEl('div'); @@ -274,7 +276,8 @@ class LightweightChatGPTWindow extends Modal { const apiUrl = 'https://api.openai.com/v1/chat/completions'; const maxTokens = parseInt(this.maxTokensInput.value); try { - const response = await fetch(apiUrl, { + const response = await request({ + url: apiUrl, method: 'POST', headers: { 'Content-Type': 'application/json', @@ -290,21 +293,25 @@ class LightweightChatGPTWindow extends Modal { }) }); - if (response.ok) { - const result = await response.json(); + const result = JSON.parse(response); + if (result.choices && result.choices.length > 0) { const gptResponse = result.choices[0].message.content; - + // Display the response in the output container this.outputContainer.empty(); this.outputContainer.createEl('p', { text: gptResponse }); return gptResponse; + } else if (result.error) { + throw new Error(JSON.stringify(result.error)); } else { - throw new Error(`API request failed with status: ${response.status}`); + throw new Error('Unexpected API response format'); } } catch (error) { // Handle errors console.error('Error during API request:', error); - new Notice('Error during API request: ' + error.message); + new Notice( + 'Error during API request: ' + error.message + ); } } @@ -469,8 +476,6 @@ class LightweightChatGPTSettingTab extends PluginSettingTab { }); politeMessage.textContent = 'If you enjoy this plugin or would like to show your support, please consider giving it a free star on GitHub~ Your appreciation means a lot to me!'; // politeMessage.style.textAlign = 'center'; - politeMessage.style.marginBottom = '1rem'; - politeMessage.style.fontStyle = 'italic'; const githubLink = containerEl.createEl('div', { cls: 'github-link-container', @@ -495,6 +500,10 @@ class LightweightChatGPTSettingTab extends PluginSettingTab { }); const style = document.createElement('style'); style.innerHTML = ` + .polite-message { + margin-bottom: 1rem; + font-style: italic; + } .github-link-container { margin-top: 2rem; text-align: center; diff --git a/manifest.json b/manifest.json index 3ead8cc..ac784c4 100644 --- a/manifest.json +++ b/manifest.json @@ -6,6 +6,6 @@ "description": "Experience OpenAI ChatGPT assistance directly within Obsidian, drafting content without interrupting your creative flow.", "author": "ittuann", "authorUrl": "https://github.com/ittuann", - "fundingUrl": "https://github.com/ittuann/obsidian-gpt-liteinquirer-plugin", + "fundingUrl": "", "isDesktopOnly": false } diff --git a/styles.css b/styles.css index e24ee78..18a1b60 100644 --- a/styles.css +++ b/styles.css @@ -1,6 +1,40 @@ +/* Input Textarea */ +.gpt-input-textarea { + width: 100%; +} + +/* Max Tokens */ +.max-tokens-container, +.max-tokens-input { + margin-right: 1rem; +} + .max-tokens-container { display: flex; justify-content: space-between; align-items: center; - margin-top: 1rem; -} \ No newline at end of file +} + +.max-tokens-description { + font-size: 0.8rem; + margin-top: 0.25rem; + margin-right: 0.5rem; +} + +.max-tokens-input { + width: 40%; + height: calc(1.5em + 1.25em); + text-align: right; +} + +/* Output Container */ +.output-container { + white-space: pre-wrap; + user-select: text; +} + +/* Buttons */ +.buttons-container { + display: flex; + margin-top: 1rem; +}