From 106d5128ccadb7fb9e1a136bd21a64d0e1f1f560 Mon Sep 17 00:00:00 2001 From: ittuann Date: Wed, 19 Apr 2023 22:46:11 +0800 Subject: [PATCH] Add restrictions on the sending button & partially translated document --- .github/workflows/FOSSA.yml | 8 ++-- README.md | 28 +++++++++----- README.zh-CN.md | 75 +++++++++++++++++++++++++++++++++++++ main.js | 38 ++++++++++++------- main.ts | 49 ++++++++++++++---------- 5 files changed, 153 insertions(+), 45 deletions(-) create mode 100644 README.zh-CN.md diff --git a/.github/workflows/FOSSA.yml b/.github/workflows/FOSSA.yml index 00a05ed..19a9bae 100644 --- a/.github/workflows/FOSSA.yml +++ b/.github/workflows/FOSSA.yml @@ -1,12 +1,14 @@ -name: FOSSA Analysis +name: FOSSA on: push: branches: - master + release: + types: [created] jobs: - fossa: + analysis: runs-on: ubuntu-latest environment: staging @@ -18,6 +20,6 @@ jobs: uses: actions/checkout@v3 - name: Run FOSSA Scan - uses: fossas/fossa-action@main + uses: fossas/fossa-action@v1.3.1 with: api-key: ${{ secrets.FOSSA_API }} diff --git a/README.md b/README.md index 7d32dbb..a2e469f 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,16 @@ [code-scanning-image]: https://img.shields.io/github/actions/workflow/status/ittuann/obsidian-gpt-liteinquirer-plugin/CodeQL.yml?branch=master&label=Code%20Scanning&logo=github&style=for-the-badge [code-scanning-url]: https://github.com/ittuann/obsidian-gpt-liteinquirer-plugin [tag-image]: https://img.shields.io/github/v/release/ittuann/obsidian-gpt-liteinquirer-plugin?branch=master&label=Release%20tag&logo=github&style=for-the-badge -[tag-url]: https://github.com/ittuann/obsidian-gpt-liteinquirer-plugin/releases +[tag-url]: https://github.com/ittuann/obsidian-gpt-liteinquirer-plugin/releases/latest +
+Language: +:gb: English · +:cn: 简体中文 +
+ With this GPT-LiteInquirer Plugin, you can quickly and senselessly generate ideas, draft content, or get assistance from the ChatGPT AI, all without leaving Obsidian, without interrupt your creative flow. The Lightweight ChatGPT Plugin is a fast, easy-to-use, and non-intrusive AI assistant plugin, which senselessly integrates OpenAI's ChatGPT API directly into Obsidian. @@ -23,15 +29,19 @@ If you enjoy this plugin or would like to show your support, please consider giv **Install and view this plugin automatically within Obsidian: [Click here](https://obsidian.md/plugins?id=gpt-liteinquirer)** -**Download manually: [Click here](https://github.com/ittuann/obsidian-gpt-liteinquirer-plugin/releases/latest)** +**Download manually: [Click here](https://github.com/ittuann/obsidian-gpt-liteinquirer-plugin/releases/latest)**. You only need to manually download `main.js`, `styles.css` and `manifest.json` and put them in the `.obsidian\plugins\gpt-liteinquirer` folder. -## Features +## ✨ Features - **Seamless integration with Obsidian:** + - Enjoy the convenience of accessing lightweight ChatGPT directly within Obsidian. - You no longer have to worry about being interrupted in your creative process by leaving Obsidian to switch between software. + - **User-friendly interface:** + - Interact with the ChatGPT API through an intuitive and straightforward lightweight design interface. + - **Diverse ways to use:** - You can quickly input the current document as a knowledge base into ChatGPT, and ask any questions about any content. @@ -40,9 +50,9 @@ If you enjoy this plugin or would like to show your support, please consider giv - **Flexible response handling:** - Copy the AI-generated response to the clipboard. Alternatively, insert it directly at the cursor position in your current document, or at the end of the document. -## Configuration +## 🧩 Configuration -You need to first set your own OpenAI API key in the Plugin Settings , so that the plugin can work properly. +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 `GPT-LiteInquirer` in the Installed Plugins. @@ -50,7 +60,7 @@ You need to first set your own OpenAI API key in the Plugin Settings , so that t To download Obsidian: [Click here](https://www.obsidian.md/) -## Usage +## 📝 Usage You can open the Lightweight ChatGPT Plugin interface in three ways: @@ -58,7 +68,7 @@ You can open the Lightweight ChatGPT Plugin interface in three ways: - By the Obsidian command `Open Lightweight Window`. - By manually set a keyboard shortcut for the command, such as `CTRL + K`. -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. +When opening 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. @@ -66,8 +76,8 @@ Tips: You can also send content directly using the `CTRL + ENTER` shortcut. TODO List: -- [*] Add configuration default Prompt -- [*] Add support for self-built API +- [x] Add configuration default Prompt +- [x] Add support for self-built API - [ ] Add support for GPT-4 - [ ] Add support for Azure API diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 0000000..f45df89 --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,75 @@ +# Obsidian 的 GPT-LiteInquirer 插件 + +
+ +[![CI][ci-image]][ci-url] +[![Code Scanning][code-scanning-image]][code-scanning-url] +[![TAG][tag-image]][tag-url] + +[ci-image]: https://img.shields.io/github/actions/workflow/status/ittuann/obsidian-gpt-liteinquirer-plugin/CI.yml?branch=master&label=Build%20Status&logo=github&style=for-the-badge +[ci-url]: https://github.com/ittuann/obsidian-gpt-liteinquirer-plugin +[code-scanning-image]: https://img.shields.io/github/actions/workflow/status/ittuann/obsidian-gpt-liteinquirer-plugin/CodeQL.yml?branch=master&label=Code%20Scanning&logo=github&style=for-the-badge +[code-scanning-url]: https://github.com/ittuann/obsidian-gpt-liteinquirer-plugin +[tag-image]: https://img.shields.io/github/v/release/ittuann/obsidian-gpt-liteinquirer-plugin?branch=master&label=Release%20tag&logo=github&style=for-the-badge +[tag-url]: https://github.com/ittuann/obsidian-gpt-liteinquirer-plugin/releases/latest + +
+ +
+Language: +:gb: English · +:cn: 简体中文 +
+ +通过 GPT-LiteInquirer 插件,您可以在 Obsidian 中快速、无障碍地生成想法、起草内容或获得 ChatGPT AI 的帮助,而不会中断您的创意流程。 + +这个轻量级 ChatGPT 插件是一个快速、易于使用和不会干扰的 AI 助手插件,可以直接将 OpenAI 的 ChatGPT API 无缝集成到 Obsidian 中。 + +如果您喜欢这个插件或想要支持它,请考虑在 GitHub 上免费给它点个星~ + +**在 Obsidian 中自动安装和查看此插件**:[点击这里](https://obsidian.md/plugins?id=gpt-liteinquirer)\*\* + +**手动安装:[点击这里](https://github.com/ittuann/obsidian-gpt-liteinquirer-plugin/releases/latest)**。您只需要手动下载 `main.js`、`styles.css` 和 `manifest.json`,然后将它们放在 `.obsidian\plugins\gpt-liteinquirer` 文件夹中即可。 + +## ✨ 特性 + +- **与 Obsidian 无缝集成:** + + - 方便地在 Obsidian 中直接访问轻量级 ChatGPT。 + - 您无需离开 Obsidian 来切换软件,也不必担心创意过程被中断。 + +- **用户友好的界面:** + + - 通过直观和简单的轻量级设计界面与 ChatGPT API 进行交互。 + +- **多种使用方式:** + + - 您可以快速将当前文档作为知识库输入到 ChatGPT 中,并询问任何关于任何内容的问题。 + - 您还可以直接与 ChatGPT 开始对话,快速起草和丰富您的内容,生成新的想法,或使用 ChatGPT 人工智能来做任何您想做的事情。 + +- **灵活的响应处理:** + - 将 AI 生成的响应复制到剪贴板。或者直接在当前文档的光标位置或文档末尾插入它。 + +## 🧩 配置 + +您需要先在插件设置中设置自己的 OpenAI API 密钥,以便插件可以正常工作。 + +1. 在官方网站上生成 OpenAI API 密钥。[点击这里](https://beta.openai.com/account/api-keys) +2. 在 Obsidian 中,转到`设置`,在左侧菜单中单击`社区插件`,然后启用已经安装好的`GPT-LiteInquirer`插件。 +3. 单击齿轮图标进入插件设置。然后在“OpenAI API Key”字段中输入您的 API 密钥,然后完成! 🎉 + +下载 Obsidian:[点击这里](https://www.obsidian.md/) + +## 📝 使用 + +您可以通过以下三种方式打开 Lightweight ChatGPT 插件界面: + +- 点击左侧的 Obsidian 侧边栏 +- 使用 Obsidian 命令 `Open Lightweight Window` +- 手动设置一个命令的键盘快捷键,如 `CTRL + K` + +在打开 GPT Lite Inquirer 窗口时,您在当前 Markdown 文档中选择的内容将自动复制到文本框中。因此,您可以使用这段文本来提问或执行其他操作,或直接写下您想说的任何内容。 + +提示:您也可以使用 `CTRL + ENTER` 快捷键直接发送内容。 + +GPT-LiteInquirer 插件旨在成为提高您创造力和生产力的小工具。今天就在 Obsidian 中体验无缝的 AI 增强写作和内容生成能力吧! diff --git a/main.js b/main.js index f2645e8..e2bed8d 100644 --- a/main.js +++ b/main.js @@ -108,6 +108,7 @@ var LightweightChatGPTPlugin = class extends import_obsidian.Plugin { var LightweightChatGPTWindow = class extends import_obsidian.Modal { constructor(app, plugin) { super(app); + this.isSendingRequest = false; this.plugin = plugin; } onOpen() { @@ -173,8 +174,8 @@ ${this.plugin.settings.defaultPrompt} el.style.backgroundColor = "green"; el.style.color = "white"; }); - const responseDivider = contentEl.createEl("hr"); - responseDivider.style.display = "none"; + const responseDividerLine = contentEl.createEl("hr"); + responseDividerLine.style.display = "none"; this.outputContainer = contentEl.createEl("div"); this.outputContainer.classList.add("output-container"); const buttonsContainer = contentEl.createEl("div"); @@ -196,23 +197,39 @@ ${this.plugin.settings.defaultPrompt} new import_obsidian.Notice(`Use the default value of ${this.plugin.settings.maxTokens.toString()} for max Tokens`); this.maxTokensInput.value = this.plugin.settings.maxTokens.toString(); } + if (!this.plugin.settings.apiKey) { + new import_obsidian.Notice("Please enter your API key in the plugin settings."); + return; + } if (!this.inputTextArea.value) { new import_obsidian.Notice("Please Enter text"); return; } + if (this.isSendingRequest) { + return; + } + this.isSendingRequest = true; sendButton.textContent = "Sending ..."; sendButton.textContent = "Waiting for API full response ..."; - copyToClipboardButton.style.display = "none"; - addToPostButton.style.display = "none"; - responseDivider.style.display = "none"; try { + new import_obsidian.Notice("Sending..."); this.responseAPIText = await this.sendRequestToChatGPT(); + if (!this.responseAPIText) { + this.outputContainer.empty(); + responseDividerLine.style.display = "none"; + copyToClipboardButton.style.display = "none"; + addToPostButton.style.display = "none"; + } + this.outputContainer.createEl("p", { text: this.responseAPIText }); sendButton.textContent = "Send"; + responseDividerLine.style.display = "block"; copyToClipboardButton.style.display = "block"; addToPostButton.style.display = "block"; - responseDivider.style.display = "block"; } catch (error) { sendButton.textContent = "Send"; + console.error("Error during API request:", error); + } finally { + this.isSendingRequest = false; } }); copyToClipboardButton.addEventListener("click", () => { @@ -223,12 +240,6 @@ ${this.plugin.settings.defaultPrompt} }); } async sendRequestToChatGPT() { - if (!this.plugin.settings.apiKey) { - new import_obsidian.Notice("Please enter your API key in the plugin settings."); - return; - } - this.outputContainer.empty(); - new import_obsidian.Notice("Sending..."); const maxTokens = parseInt(this.maxTokensInput.value); try { const response = await (0, import_obsidian.request)({ @@ -242,6 +253,7 @@ ${this.plugin.settings.defaultPrompt} model: this.plugin.settings.chatGPTModel, max_tokens: maxTokens, temperature: this.plugin.settings.temperature, + stream: false, messages: [ { role: "user", content: this.inputTextArea.value } ] @@ -250,8 +262,6 @@ ${this.plugin.settings.defaultPrompt} 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)); diff --git a/main.ts b/main.ts index 095c343..e77046e 100644 --- a/main.ts +++ b/main.ts @@ -137,6 +137,7 @@ class LightweightChatGPTWindow extends Modal { private maxTokensInput: HTMLInputElement; private responseAPIText: string; + private isSendingRequest = false; constructor(app: App, plugin: LightweightChatGPTPlugin) { super(app); @@ -215,8 +216,8 @@ class LightweightChatGPTWindow extends Modal { el.style.color = 'white'; }); - const responseDivider = contentEl.createEl('hr'); - responseDivider.style.display = 'none'; + const responseDividerLine = contentEl.createEl('hr'); + responseDividerLine.style.display = 'none'; // Output Container this.outputContainer = contentEl.createEl('div'); @@ -245,26 +246,46 @@ class LightweightChatGPTWindow extends Modal { this.maxTokensInput.value = this.plugin.settings.maxTokens.toString(); } + if (!this.plugin.settings.apiKey) { + new Notice('Please enter your API key in the plugin settings.'); + return; + } + if (!this.inputTextArea.value) { new Notice('Please Enter text'); return; } + if (this.isSendingRequest) { + // new Notice('Please wait until receive API response'); + return; + } + + this.isSendingRequest = true; sendButton.textContent = 'Sending ...'; sendButton.textContent = 'Waiting for API full response ...'; - copyToClipboardButton.style.display = 'none'; - addToPostButton.style.display = 'none'; - responseDivider.style.display = 'none'; try { + new Notice('Sending...'); this.responseAPIText = await this.sendRequestToChatGPT(); + + if (!this.responseAPIText) { + this.outputContainer.empty(); + responseDividerLine.style.display = 'none'; + copyToClipboardButton.style.display = 'none'; + addToPostButton.style.display = 'none'; + } + this.outputContainer.createEl('p', { text: this.responseAPIText }); + sendButton.textContent = 'Send'; + responseDividerLine.style.display = 'block'; copyToClipboardButton.style.display = 'block'; addToPostButton.style.display = 'block'; - responseDivider.style.display = 'block'; } catch (error) { sendButton.textContent = 'Send'; - // new Notice('Error during API request: ' + error.message); + console.error('Error during API request:', error); + } finally { + this.isSendingRequest = false; } }); @@ -278,15 +299,8 @@ class LightweightChatGPTWindow extends Modal { } async sendRequestToChatGPT() { - if (!this.plugin.settings.apiKey) { - new Notice('Please enter your API key in the plugin settings.'); - return; - } - this.outputContainer.empty(); - - new Notice('Sending...'); - const maxTokens = parseInt(this.maxTokensInput.value); + try { const response = await request({ url: this.plugin.settings.apiUrl + this.plugin.settings.apiUrlPath, @@ -299,6 +313,7 @@ class LightweightChatGPTWindow extends Modal { model: this.plugin.settings.chatGPTModel, max_tokens: maxTokens, temperature: this.plugin.settings.temperature, + stream: false, messages: [ { role: 'user', content: this.inputTextArea.value } ] @@ -308,10 +323,6 @@ class LightweightChatGPTWindow extends Modal { 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));