// ==UserScript==
// @name 一个优化你使用AI时候的prompt智能体。
// @namespace prompt-agent
// @version 0.0.1
// @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
// @downloadURL none
// ==/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 = `
`;
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);
// 监听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);
}
}
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();
})();