Greasy Fork

Greasy Fork is available in English.

一个优化你使用AI时候的prompt智能体。

prompt-agent

当前为 2025-06-24 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         一个优化你使用AI时候的prompt智能体。
// @namespace    prompt-agent
// @version      0.0.2
// @description  prompt-agent
// @author       LLinkedList771
// @run-at       document-end
// @match        https://chat.deepseek.com/*
// @homepageURL  https://github.com/linkedlist771/prompt-agent
// @supportURL   https://github.com/linkedlist771/prompt-agent/issues
// @license      MIT
// ==/UserScript==



(function() {
  'use strict';

  // 配置变量
  let isEnabled = false;
  let apiKey = localStorage.getItem('ai-script-apikey') || '';
  let isProcessing = false;

  // 创建浮动UI
  function createFloatingUI() {
      const container = document.createElement('div');
      container.id = 'ai-floating-ui';
      container.style.cssText = `
          position: fixed;
          top: 20px;
          right: 20px;
          width: 280px;
          background: #ffffff;
          border: 1px solid #ddd;
          border-radius: 8px;
          box-shadow: 0 4px 12px rgba(0,0,0,0.15);
          z-index: 10000;
          font-family: Arial, sans-serif;
          font-size: 14px;
      `;

      container.innerHTML = `
          <div style="background: #f5f5f5; padding: 12px; border-radius: 8px 8px 0 0; border-bottom: 1px solid #ddd;">
              <div style="display: flex; justify-content: space-between; align-items: center;">
                  <span style="font-weight: bold; color: #333;">Prompt Agent</span>
                  <button id="ai-minimize" style="background: none; border: none; font-size: 16px; cursor: pointer;">−</button>
              </div>
          </div>
          <div id="ai-content" style="padding: 15px;">
              <div style="margin-bottom: 15px;">
                  <label style="display: block; margin-bottom: 5px; color: #555;">API Key:</label>
                  <input type="password" id="ai-apikey" placeholder="Bearer token..."
                         style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box;"
                         value="${apiKey}">
              </div>
              <div style="margin-bottom: 15px;">
                  <label style="display: flex; align-items: center; color: #555;">
                      <input type="checkbox" id="ai-enable" ${isEnabled ? 'checked' : ''}
                             style="margin-right: 8px;">
                      启用AI响应
                  </label>
              </div>
              <div style="margin-bottom: 10px;">
                  <button id="ai-test" style="width: 100%; padding: 8px; background: #007cba; color: white; border: none; border-radius: 4px; cursor: pointer;">
                      测试连接
                  </button>
              </div>
              <div style="margin-bottom: 10px;">
                  <button id="ai-manual-send" style="width: 100%; padding: 8px; background: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer;">
                      手动发送
                  </button>
              </div>
              <div id="ai-status" style="font-size: 12px; color: #666; text-align: center;"></div>
          </div>
      `;

      document.body.appendChild(container);

      // 事件监听
      document.getElementById('ai-minimize').addEventListener('click', toggleMinimize);
      document.getElementById('ai-enable').addEventListener('change', toggleEnable);
      document.getElementById('ai-apikey').addEventListener('input', saveApiKey);
      document.getElementById('ai-test').addEventListener('click', testConnection);
      document.getElementById('ai-manual-send').addEventListener('click', manualSend);

      // 监听Ctrl+Enter组合键
      document.addEventListener('keydown', handleKeyDown);
  }

  function toggleMinimize() {
      const content = document.getElementById('ai-content');
      const button = document.getElementById('ai-minimize');
      if (content.style.display === 'none') {
          content.style.display = 'block';
          button.textContent = '−';
      } else {
          content.style.display = 'none';
          button.textContent = '+';
      }
  }

  function toggleEnable(e) {
      isEnabled = e.target.checked;
      updateStatus(isEnabled ? '已启用 - 按Ctrl+Enter发送' : '已禁用');
  }

  function saveApiKey(e) {
      apiKey = e.target.value;
      localStorage.setItem('ai-script-apikey', apiKey);
  }

  function updateStatus(message, isError = false) {
      const status = document.getElementById('ai-status');
      if (status) {
          status.textContent = message;
          status.style.color = isError ? '#d32f2f' : '#666';
      }
  }

  function handleKeyDown(e) {
      if (e.ctrlKey && e.key === 'Enter' && isEnabled && !isProcessing) {
          const textarea = document.querySelector('textarea:focus');
          if (textarea && textarea.value.trim()) {
              e.preventDefault();
              sendRequest(textarea);
          }
      }
  }

  async function testConnection() {
      if (!apiKey.trim()) {
          updateStatus('请先输入API Key', true);
          return;
      }

      updateStatus('测试连接中...');

      try {
          const response = await fetch("https://promptagent.qqyunsd.com/api/v1/chat/completions", {
              method: 'POST',
              headers: {
                  "authorization": `Bearer ${apiKey}`,
                  "User-Agent": "Apifox/1.0.0 (https://apifox.com)",
                  "Content-Type": "application/json"
              },
              body: JSON.stringify({
                  "model": "mock-gpt-model",
                  "messages": [
                      { "role": "user", "content": "test" }
                  ],
                  "max_tokens": 10,
                  "temperature": 0.1,
                  "stream": false
              })
          });

          if (response.ok) {
              updateStatus('连接成功!');
          } else {
              updateStatus(`连接失败: ${response.status}`, true);
          }
      } catch (error) {
          updateStatus(`连接错误: ${error.message}`, true);
      }
  }

  function manualSend() {
      if (isProcessing) {
          updateStatus('正在处理中,请稍后...', true);
          return;
      }

      // 查找当前页面中聚焦的textarea或者最后一个textarea
      let textarea = document.querySelector('textarea:focus');
      
      if (!textarea) {
          // 如果没有聚焦的textarea,尝试找到页面上的textarea
          const textareas = document.querySelectorAll('textarea');
          if (textareas.length > 0) {
              textarea = textareas[textareas.length - 1]; // 选择最后一个textarea
          }
      }

      if (!textarea) {
          updateStatus('未找到输入框', true);
          return;
      }

      if (!textarea.value.trim()) {
          updateStatus('请先输入内容', true);
          return;
      }

      sendRequest(textarea);
  }

  async function sendRequest(textarea) {
      if (!apiKey.trim()) {
          updateStatus('请先输入API Key', true);
          return;
      }

      isProcessing = true;
      updateStatus('处理中...');

      const userInput = textarea.value.trim();

      // 清空textarea
      textarea.value = '';

      const myHeaders = new Headers();
      myHeaders.append("authorization", `Bearer ${apiKey}`);
      myHeaders.append("User-Agent", "Apifox/1.0.0 (https://apifox.com)");
      myHeaders.append("Content-Type", "application/json");

      const raw = JSON.stringify({
          "model": "mock-gpt-model",
          "messages": [
              { "role": "user", "content": userInput }
          ],
          "max_tokens": 512,
          "temperature": 0.1,
          "stream": true
      });

      const requestOptions = {
          method: 'POST',
          headers: myHeaders,
          body: raw,
          redirect: 'follow'
      };

      try {
          const response = await fetch("http://localhost:3648/api/v1/chat/completions", requestOptions);

          if (!response.ok) {
              throw new Error(`HTTP ${response.status}: ${response.statusText}`);
          }

          const reader = response.body.getReader();
          const decoder = new TextDecoder();

          updateStatus('接收响应中...');

          while (true) {
              const { done, value } = await reader.read();

              if (done) {
                  break;
              }

              const chunk = decoder.decode(value, { stream: true });
              const lines = chunk.split('\n');

              for (const line of lines) {
                  if (line.startsWith('data: ')) {
                      const jsonStr = line.substring(6).trim();
                      if (jsonStr === '[DONE]') {
                          continue;
                      }

                      try {
                          const data = JSON.parse(jsonStr);
                          if (data.choices && data.choices[0] && data.choices[0].delta && data.choices[0].delta.content) {
                              const content = data.choices[0].delta.content;

                              // 逐字添加到textarea
                              for (const char of content) {
                                  textarea.value += char;
                                  // 模拟打字效果
                                  await new Promise(resolve => setTimeout(resolve, 20));

                                  // 滚动到底部
                                  textarea.scrollTop = textarea.scrollHeight;
                              }
                          }
                      } catch (parseError) {
                          console.log('JSON解析错误:', parseError, jsonStr);
                      }
                  }
              }
          }

          updateStatus('完成!');

      } catch (error) {
          updateStatus(`错误: ${error.message}`, true);
          console.error('请求错误:', error);
      } finally {
          isProcessing = false;
      }
  }

  // 初始化
  function init() {
      // 等待页面加载完成
      if (document.readyState === 'loading') {
          document.addEventListener('DOMContentLoaded', createFloatingUI);
      } else {
          createFloatingUI();
      }

      updateStatus('就绪 - 在textarea中输入后按Ctrl+Enter');
  }

  init();
})();