// ==UserScript== // @name Deepseek Chat 实时网页检索对话工具版 // @namespace Monika_host // @version 3.4.5 // @description 支持流式响应、历史记录、多服务API配置、模型选择、参数设置、Agent浏览器操控(参考pi-agent-browser),增强Markdown渲染 // @author Monika_host // @match *://*/* // @grant GM_getValue // @grant GM_setValue // @grant GM_xmlhttpRequest // @grant GM_registerMenuCommand // @grant GM_addStyle // @connect * // @connect cdn.jsdelivr.net // @connect dashscope.aliyuncs.com // @connect api.siliconflow.cn // @license MIT // @resource icon https://img.alicdn.com/imgextra/i2/O1CN01bYc1m81RrcSAyOjMu_!!6000000002165-54-tps-60-60.apng // @resource icon_backup https://cdn.jsdelivr.net/gh/simple-icons/simple-icons/icons/deepseek.svg // @grant GM_getResourceURL // @require https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js // @icon https://deepseek.com/favicon.ico // ==/UserScript== (function() { 'use strict'; // 加载Markdown渲染资源 function loadMarkdownResources() { return new Promise((resolve) => { // 加载KaTeX(数学公式渲染) const katexScript = document.createElement('script'); katexScript.src = 'https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js'; const katexCSS = document.createElement('link'); katexCSS.rel = 'stylesheet'; katexCSS.href = 'https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css'; katexScript.onload = () => { // 加载Highlight.js const hljsScript = document.createElement('script'); hljsScript.src = 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js'; hljsScript.onload = () => { // 加载Mermaid const mermaidScript = document.createElement('script'); mermaidScript.src = 'https://cdn.jsdelivr.net/npm/mermaid@10.9.0/dist/mermaid.min.js'; mermaidScript.onload = () => { // 更新Mermaid配置并添加错误处理 try { if (typeof mermaid !== 'undefined') { mermaid.initialize({ startOnLoad: false, theme: 'dark', securityLevel: 'loose', flowchart: { curve: 'basis', useMaxWidth: false }, sequence: { showSequenceNumbers: true }, gantt: { axisFormat: '%Y-%m-%d' } }); } } catch (e) { console.error('Mermaid初始化错误:', e); } resolve(); }; document.head.appendChild(mermaidScript); }; document.head.appendChild(hljsScript); }; document.head.appendChild(katexScript); document.head.appendChild(katexCSS); }); } // 安全渲染数学公式函数 - 增强版,支持延迟渲染 function renderMathFormula(formula, isBlock = false) { try { if (typeof katex !== 'undefined') { const options = { displayMode: isBlock, throwOnError: false, strict: false, output: 'html' }; return katex.renderToString(formula.trim(), options); } else { // KaTeX尚未加载,返回占位符,稍后重新渲染 const placeholderId = `math-placeholder-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const placeholder = isBlock ? `
$$${formula.trim()}$$
` : `$${formula.trim()}$`; return placeholder; } } catch (error) { console.warn('KaTeX渲染错误:', error); // 如果KaTeX不可用或渲染失败,回退到原始LaTeX显示 return isBlock ? `$$${formula.trim()}$$` : `$${formula.trim()}$`; } } // 重新渲染所有数学公式占位符 function rerenderMathPlaceholders() { if (typeof katex === 'undefined') return; document.querySelectorAll('[data-math-placeholder]').forEach(element => { try { const formula = decodeURIComponent(element.getAttribute('data-formula')); const isBlock = element.getAttribute('data-is-block') === 'true'; const options = { displayMode: isBlock, throwOnError: false, strict: false, output: 'html' }; const rendered = katex.renderToString(formula.trim(), options); // 替换占位符为渲染后的公式 const newElement = document.createElement(isBlock ? 'div' : 'span'); newElement.className = element.className; newElement.innerHTML = rendered; element.parentNode.replaceChild(newElement, element); } catch (error) { console.warn('重新渲染数学公式失败:', error); } }); } // 增强版Markdown渲染函数 function renderMarkdown(content) { let output = content; // 1. 处理数学公式 - 使用KaTeX渲染 output = output .replace(/\$\$(.*?)\$\$/gs, (match, formula) => { const rendered = renderMathFormula(formula, true); return `
${rendered}
`; }) .replace(/\$(.*?)\$/gs, (match, formula) => { const rendered = renderMathFormula(formula, false); return `${rendered}`; }) // 处理 \(...\) 格式的行内公式 .replace(/\\\(([\s\S]*?)\\\)/gs, (match, formula) => { const rendered = renderMathFormula(formula, false); return `${rendered}`; }) // 处理 \[...\] 格式的块级公式 .replace(/\\\[([\s\S]*?)\\\]/gs, (match, formula) => { const rendered = renderMathFormula(formula, true); return `
${rendered}
`; }); // 2. 处理表格 - 增强版 output = output.replace(/(?:\|.*\|(?:\r?\n|\r))+/g, (table) => { const lines = table.trim().split('\n').filter(line => line.trim()); if (lines.length < 2) return table; // 不是有效的表格 // 检查是否有分隔线 const hasSeparator = lines[1].includes('---') || lines[1].includes(':|') || lines[1].includes('|:'); let headers = []; let body = []; if (hasSeparator && lines.length >= 2) { // 有表头和分隔线 headers = lines[0].split('|').slice(1, -1).map(h => h.trim()); body = lines.slice(2); } else { // 没有分隔线,第一行作为表头 headers = lines[0].split('|').slice(1, -1).map(h => h.trim()); body = lines.slice(1); } // 构建HTML表格 let html = ''; // 表头 html += ''; headers.forEach(header => { html += ``; }); html += ''; // 表格体 if (body.length > 0) { html += ''; body.forEach(row => { const cells = row.split('|').slice(1, -1).map(cell => cell.trim()); html += ''; cells.forEach(cell => { html += ``; }); html += ''; }); html += ''; } html += '
${header}
${cell}
'; return html; }); // 3. 处理任务列表 output = output.replace(/^\s*[-*+]\s+\[ \]\s+(.+)$/gm, '
  • $1
  • '); output = output.replace(/^\s*[-*+]\s+\[x\]\s+(.+)$/gm, '
  • $1
  • '); // 将任务列表项包装在ul中 output = output.replace(/(
  • .*<\/li>)+/g, ''); // 4. 处理普通列表 output = output.replace(/^\s*[-*+]\s+(?!\[[ x]\])(.+)$/gm, '
  • $1
  • '); output = output.replace(/^\s*\d+\.\s+(.+)$/gm, '
  • $1
  • '); // 将普通列表项包装在ul或ol中 output = output.replace(/(
  • (?!.*)+/g, (match) => { const items = match.match(/
  • .*?<\/li>/g) || []; if (items.length > 0) { // 检查是否为有序列表 const isOrdered = content.includes('\n1.') || content.includes('\n2.') || content.includes('\n3.'); return isOrdered ? `
      ${match}
    ` : ``; } return match; }); // 5. 处理标题 output = output.replace(/^#\s+(.+)$/gm, '

    $1

    '); output = output.replace(/^##\s+(.+)$/gm, '

    $1

    '); output = output.replace(/^###\s+(.+)$/gm, '

    $1

    '); output = output.replace(/^####\s+(.+)$/gm, '

    $1

    '); output = output.replace(/^#####\s+(.+)$/gm, '
    $1
    '); output = output.replace(/^######\s+(.+)$/gm, '
    $1
    '); // 6. 处理加粗和斜体 output = output.replace(/\*\*\*(.*?)\*\*\*/g, '$1'); output = output.replace(/\*\*(.*?)\*\*/g, '$1'); output = output.replace(/\*(.*?)\*/g, '$1'); // 7. 处理代码块(fenced code blocks,支持 ``` 和 ``) output = output.replace(/```(\w*)\n([\s\S]*?)```/g, (match, lang, code) => { var langClass = lang ? ' class="language-' + lang + '"' : ''; return '
    ' + code.trim() + '
    '; }); output = output.replace(/``(\w*)\n([\s\S]*?)``/g, (match, lang, code) => { var langClass = lang ? ' class="language-' + lang + '"' : ''; return '
    ' + code.trim() + '
    '; }); // 8. 处理内联代码 output = output.replace(/`([^`]+)`/g, '$1'); // 8. 处理链接 output = output.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '$1'); // 9. 处理块引用 output = output.replace(/^>\s+(.+)$/gm, '
    $1
    '); // 10. 处理水平线 output = output.replace(/^---$/gm, '
    '); output = output.replace(/^\*\*\*$/gm, '
    '); output = output.replace(/^___$/gm, '
    '); // 11. 处理换行(两个空格或反斜杠) output = output.replace(/ \n/g, '
    '); output = output.replace(/\\\n/g, '
    '); return output; } // 渲染代码高亮 function renderCodeHighlight(element) { if (typeof hljs !== 'undefined') { element.querySelectorAll('pre code').forEach(block => { try { hljs.highlightElement(block); } catch (e) { console.warn('代码高亮错误:', e); } }); } } // 渲染Mermaid图表 function renderMermaidDiagrams(element) { if (typeof mermaid !== 'undefined') { element.querySelectorAll('.ds-mermaid').forEach(el => { try { if (!el.hasAttribute('data-rendered')) { const code = el.textContent.trim(); if (code) { mermaid.render('mermaid-' + Date.now(), code, (svgCode) => { el.innerHTML = svgCode; }); el.setAttribute('data-rendered', 'true'); } } } catch (e) { console.error('Mermaid渲染错误:', e); el.innerHTML = `
    图表渲染失败: ${e.message}
    `; el.setAttribute('data-rendered', 'error'); } }); } } // 添加CSS样式 GM_addStyle(` /* KaTeX数学公式样式 */ .latex-math-inline { display: inline-block; margin: 0 2px; vertical-align: middle; line-height: 1.2; } .latex-math-block { display: block; text-align: center; margin: 20px 0; padding: 15px; overflow-x: auto; overflow-y: hidden; position: relative; } /* 确保KaTeX公式正确显示 */ .latex-math-inline .katex, .latex-math-block .katex { font-size: 1.05em; } .latex-math-block .katex { font-size: 1.1em; } /* 块级公式容器美化 */ .latex-math-block { background: linear-gradient(145deg, rgba(20, 20, 35, 0.95), rgba(15, 15, 30, 0.95)); border-radius: 8px; border: 1px solid rgba(80, 120, 200, 0.3); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); } .latex-math-block:hover { border-color: rgba(100, 150, 255, 0.5); box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3); transition: all 0.3s ease; } /* 行内公式容器美化 */ .latex-math-inline { padding: 2px 4px; background: rgba(40, 40, 60, 0.1); border-radius: 4px; border: 1px solid rgba(100, 150, 255, 0.2); } .latex-math-inline:hover { background: rgba(50, 50, 80, 0.15); border-color: rgba(120, 180, 255, 0.3); } /* 表格样式增强 */ /* 表格样式增强 - 修复边框半径问题 */ .ds-markdown-table { border-collapse: separate; border-spacing: 0; width: 100%; margin: 15px 0; background: rgba(255, 255, 255, 0.7); border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } .ds-markdown-table th { background: linear-gradient(135deg, rgba(0, 123, 255, 0.6), rgba(0, 86, 179, 0.6)); color: #ffffff; font-weight: bold; padding: 12px 15px; text-align: center; border-bottom: 2px solid rgba(0, 86, 179, 0.8); text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); } .ds-markdown-table th:first-child { border-top-left-radius: 8px; } .ds-markdown-table th:last-child { border-top-right-radius: 8px; } .ds-markdown-table td { padding: 10px 15px; border-bottom: 1px solid rgba(0, 0, 0, 0.1); color: #2c3e50; } .ds-markdown-table tr:nth-child(even) { background: rgba(0, 0, 0, 0.04); } .ds-markdown-table tr:hover { background: rgba(0, 123, 255, 0.15); transition: background 0.3s ease; } .ds-markdown-table tr:last-child td:first-child { border-bottom-left-radius: 8px; } .ds-markdown-table tr:last-child td:last-child { border-bottom-right-radius: 8px; } .ds-markdown-table tr:last-child td { border-bottom: none; } /* 列表样式 */ .ds-task-list { list-style: none; padding-left: 0; margin: 10px 0; } .ds-task-item { margin: 5px 0; padding: 5px 10px; background: rgba(255, 255, 255, 0.05); border-radius: 4px; display: flex; align-items: center; } .ds-task-item input[type="checkbox"] { margin-right: 10px; } .ds-unordered-list, .ds-ordered-list { margin: 10px 0; padding-left: 25px; } .ds-unordered-list li, .ds-ordered-list li { margin: 5px 0; padding: 3px 0; } /* 标题渐变色效果 */ .ds-markdown-h1 { font-size: 2em; margin: 20px 0 15px; background: linear-gradient(90deg, #ff6b6b, #4ecdc4); -webkit-background-clip: text; background-clip: text; color: transparent; padding-bottom: 5px; border-bottom: 2px solid rgba(78, 205, 196, 0.3); } .ds-markdown-h2 { font-size: 1.7em; margin: 18px 0 13px; background: linear-gradient(90deg, #4ecdc4, #1a936f); -webkit-background-clip: text; background-clip: text; color: transparent; padding-bottom: 4px; border-bottom: 1px solid rgba(26, 147, 111, 0.3); } .ds-markdown-h3 { font-size: 1.4em; margin: 16px 0 11px; background: linear-gradient(90deg, #1a936f, #114b5f); -webkit-background-clip: text; background-clip: text; color: transparent; } .ds-markdown-h4 { font-size: 1.2em; margin: 14px 0 9px; background: linear-gradient(90deg, #114b5f, #0d3a4a); -webkit-background-clip: text; background-clip: text; color: transparent; } .ds-markdown-h5 { font-size: 1.1em; margin: 12px 0 7px; background: linear-gradient(90deg, #0d3a4a, #082a35); -webkit-background-clip: text; background-clip: text; color: transparent; } .ds-markdown-h6 { font-size: 1em; margin: 10px 0 5px; background: linear-gradient(90deg, #082a35, #041a1f); -webkit-background-clip: text; background-clip: text; color: transparent; } /* 增强的内联代码样式 */ .inline-code { background: linear-gradient(145deg, #1a1a2e, #16213e); color: #66fcf1; padding: 2px 8px; border-radius: 4px; font-family: 'Fira Code', 'Consolas', 'Monaco', monospace; border: 1px solid rgba(102, 252, 241, 0.3); box-shadow: 0 3px 6px rgba(0,0,0,0.3), inset 0 1px 1px rgba(255,255,255,0.1); display: inline-block; transform: translateY(-1px); transition: all 0.3s ease; font-size: 90%; line-height: 1.4; } .inline-code:hover { transform: translateY(-2px); box-shadow: 0 5px 10px rgba(0,0,0,0.4), inset 0 1px 2px rgba(255,255,255,0.2); color: #45a29e; } /* 代码块样式 */ .ds-message-content pre { background: rgba(10, 10, 20, 0.95) !important; padding: 15px; border-radius: 8px; overflow-x: auto; margin: 15px 0; border: 1px solid rgba(80, 120, 200, 0.4); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.4); position: relative; } .ds-message-content pre > .code-title { display: block; position: absolute; top: -12px; left: 15px; background: linear-gradient(90deg, #0f2027, #203a43, #2c5364); color: #fff; padding: 5px 15px; border-radius: 5px 5px 0 0; font-family: monospace; font-size: 12px; text-transform: uppercase; z-index: 1; box-shadow: 0 4px 6px rgba(0,0,0,0.3); } /* 链接样式 */ .ds-message-content a { color: #4ecdc4; text-decoration: none; border-bottom: 1px dotted rgba(78, 205, 196, 0.5); transition: all 0.3s ease; } .ds-message-content a:hover { color: #ff6b6b; border-bottom: 1px solid #ff6b6b; } /* 块引用样式 */ blockquote { border-left: 4px solid rgba(78, 205, 196, 0.7); padding: 10px 15px; margin: 15px 0; background: rgba(78, 205, 196, 0.1); border-radius: 0 8px 8px 0; color: #e0e0e0; font-style: italic; } /* 水平线样式 */ hr { border: none; height: 2px; background: linear-gradient(90deg, transparent, rgba(78, 205, 196, 0.5), transparent); margin: 20px 0; } /* Mermaid图表样式 */ .ds-mermaid { background: rgba(25, 25, 35, 0.9); padding: 15px; border-radius: 8px; margin: 15px 0; border: 1px solid rgba(100, 200, 255, 0.2); overflow: auto; max-height: 500px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); display: flex; justify-content: center; align-items: center; } .mermaid-error { color: #ff9999; padding: 10px; border: 1px solid #ff9999; border-radius: 4px; background: rgba(255, 153, 153, 0.1); } /* 淡入淡出动画 */ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } /* 模态框淡入动画 */ @keyframes modalFadeIn { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } /* 模态框淡出动画 */ @keyframes modalFadeOut { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(0.95); } } /* 设置界面样式 - 新增 */ .ds-settings-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(200, 200, 200, 0.4); z-index: 2147483647; display: flex; justify-content: center; align-items: center; backdrop-filter: blur(15px) saturate(180%); -webkit-backdrop-filter: blur(15px) saturate(180%); animation: fadeIn 0.5s ease-out forwards; } .ds-settings-overlay.fade-out { animation: fadeOut 0.5s ease-in forwards; } .ds-settings-modal { background: linear-gradient(135deg, rgba(255, 255, 255, 0.4) 0%, rgba(245, 245, 245, 0.4) 100%); border-radius: 12px; width: 90%; max-width: 1200px; max-height: 90vh; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15); border: 1px solid rgba(0, 0, 0, 0.1); backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); animation: modalFadeIn 0.5s ease-out forwards; } .ds-settings-modal.fade-out { animation: modalFadeOut 0.5s ease-in forwards; } .ds-edit-modal { max-width: 600px; } .ds-settings-header { display: flex; justify-content: space-between; align-items: center; padding: 15px 20px; background: linear-gradient(135deg, rgba(240, 240, 240, 0.4) 0%, rgba(230, 230, 230, 0.4) 100%); border-bottom: 1px solid rgba(0, 0, 0, 0.1); backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); } .ds-settings-title { font-size: 18px; font-weight: bold; color: #2c3e50; } .ds-settings-close { cursor: pointer; font-size: 24px; color: #ff6b6b; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: all 0.3s ease; } .ds-settings-close:hover { background: rgba(255, 107, 107, 0.2); transform: rotate(90deg); } .ds-settings-content { flex: 1; overflow-y: auto; padding: 20px; background: linear-gradient(135deg, rgba(255, 255, 255, 0.4) 0%, rgba(250, 250, 250, 0.4) 100%); backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); } .ds-section-title { font-size: 16px; font-weight: bold; color: #4ecdc4; margin-bottom: 15px; padding-bottom: 8px; border-bottom: 2px solid rgba(78, 205, 196, 0.3); } .ds-services-list { display: grid; gap: 12px; margin-bottom: 25px; } .ds-service-card { background: rgba(255, 255, 255, 0.4); border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 15px; transition: all 0.3s ease; backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); } .ds-service-card:hover { background: rgba(255, 255, 255, 0.4); border-color: rgba(0, 0, 0, 0.2); transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); } .ds-service-active { background: rgba(0, 123, 255, 0.15); border-color: rgba(0, 123, 255, 0.8); box-shadow: 0 0 20px rgba(0, 123, 255, 0.3); } .ds-service-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .ds-service-name { font-size: 16px; font-weight: bold; color: #fff; display: flex; align-items: center; gap: 8px; } .ds-service-icon { font-size: 18px; } .ds-current-badge { background: linear-gradient(135deg, #007bff, #0056b3); color: white; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: bold; margin-left: 8px; } .ds-service-actions { display: flex; gap: 6px; } .ds-action-btn { padding: 6px 12px; border: none; border-radius: 5px; cursor: pointer; font-size: 12px; font-weight: bold; transition: all 0.3s ease; display: flex; align-items: center; gap: 4px; } .ds-btn-select { background: linear-gradient(135deg, #00c853, #009624); color: white; } .ds-btn-select:hover { background: linear-gradient(135deg, #009624, #006414); transform: scale(1.05); } .ds-btn-edit { background: linear-gradient(135deg, #ff9800, #f57c00); color: white; } .ds-btn-edit:hover { background: linear-gradient(135deg, #f57c00, #e65100); transform: scale(1.05); } .ds-btn-delete { background: linear-gradient(135deg, #f44336, #c62828); color: white; } .ds-btn-delete:hover { background: linear-gradient(135deg, #c62828, #b71c1c); transform: scale(1.05); } .ds-service-details { margin-top: 10px; padding-top: 10px; border-top: 1px solid rgba(255, 255, 255, 0.1); } .ds-detail-row { display: flex; margin-bottom: 6px; font-size: 13px; } .ds-detail-label { color: #666666; min-width: 80px; margin-right: 10px; } .ds-detail-value { color: #2c3e50; flex: 1; word-break: break-all; } .ds-url-value { font-family: monospace; font-size: 12px; color: #4ecdc4; } .ds-empty-message { text-align: center; color: #666666; padding: 20px; font-style: italic; } /* 表单样式 */ .ds-config-form { background: rgba(250, 250, 250, 0.9); border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 15px; margin-bottom: 20px; } .ds-add-form { border-color: rgba(0, 0, 0, 0.2); background: rgba(245, 245, 245, 0.9); } .ds-form-field { margin-bottom: 15px; } .ds-form-label { display: block; margin-bottom: 5px; color: #2c3e50; font-size: 13px; font-weight: 500; } .ds-form-input, .ds-form-textarea { width: 100%; padding: 10px 12px; background: rgba(255, 255, 255, 0.95); border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 6px; color: #333333; font-size: 14px; transition: all 0.3s ease; box-sizing: border-box; } .ds-form-input:focus, .ds-form-textarea:focus { outline: none; border-color: rgba(0, 0, 0, 0.4); background: rgba(255, 255, 255, 1); box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } .ds-form-input:hover, .ds-form-textarea:hover { background: rgba(255, 255, 255, 0.98); border-color: rgba(0, 0, 0, 0.3); } .ds-form-input::placeholder, .ds-form-textarea::placeholder { color: rgba(0, 0, 0, 0.4); } .ds-form-textarea { min-height: 80px; resize: vertical; font-family: monospace; } .ds-form-buttons { display: flex; gap: 10px; justify-content: flex-end; margin-top: 15px; } /* 获取模型列表按钮样式 */ .ds-btn-fetch { padding: 8px 12px; background: linear-gradient(135deg, #6f42c1, #5a32a3); color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 12px; font-weight: bold; transition: all 0.3s ease; white-space: nowrap; display: flex; align-items: center; gap: 4px; } .ds-btn-fetch:hover { background: linear-gradient(135deg, #5a32a3, #4a268a); transform: translateY(-1px); box-shadow: 0 4px 12px rgba(111, 66, 193, 0.4); } .ds-btn-fetch:active { transform: translateY(0); } .ds-btn-fetch:disabled { background: #6c757d; cursor: not-allowed; transform: none; box-shadow: none; } /* 输入框容器 */ .ds-input-with-button { display: flex; gap: 8px; align-items: stretch; } .ds-input-with-button .ds-form-input { flex: 1; min-width: 0; } /* 响应式调整 */ @media (max-width: 768px) { .ds-input-with-button { flex-direction: column; gap: 6px; } .ds-btn-fetch { width: 100%; justify-content: center; } } /* 按钮样式 */ .ds-btn-primary, .ds-btn-secondary, .ds-btn-success { padding: 10px 20px; border: none; border-radius: 6px; cursor: pointer; font-size: 14px; font-weight: bold; transition: all 0.3s ease; display: inline-flex; align-items: center; gap: 6px; } .ds-btn-primary { background: linear-gradient(135deg, #007bff, #0056b3); color: white; } .ds-btn-primary:hover { background: linear-gradient(135deg, #0056b3, #003d82); transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0, 123, 255, 0.4); } .ds-btn-secondary { background: linear-gradient(135deg, #6c757d, #545b62); color: white; } .ds-btn-secondary:hover { background: linear-gradient(135deg, #545b62, #3d4146); transform: translateY(-2px); box-shadow: 0 5px 15px rgba(108, 117, 125, 0.4); } .ds-btn-success { background: linear-gradient(135deg, #28a745, #1e7e34); color: white; } .ds-btn-success:hover { background: linear-gradient(135deg, #1e7e34, #155724); transform: translateY(-2px); box-shadow: 0 5px 15px rgba(40, 167, 69, 0.4); } /* 模板按钮 */ .ds-template-container { margin-bottom: 15px; } .ds-template-title { color: #888; font-size: 13px; margin-bottom: 8px; } .ds-template-buttons { display: flex; gap: 8px; flex-wrap: wrap; } .ds-template-btn { padding: 6px 12px; background: rgba(220, 220, 220, 0.5); border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 15px; color: #555555; cursor: pointer; font-size: 12px; transition: all 0.3s ease; } .ds-template-btn:hover { background: rgba(200, 200, 200, 0.6); transform: translateY(-1px); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); color: #000000; } /* 当前服务信息 */ .ds-current-info { background: rgba(220, 220, 220, 0.3); border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 8px; padding: 15px; } .ds-current-service { display: flex; flex-direction: column; gap: 8px; } .ds-current-name { font-size: 18px; font-weight: bold; color: #2c3e50; } .ds-current-details { display: flex; flex-wrap: wrap; gap: 12px; font-size: 12px; color: #555555; } .ds-current-details span { background: rgba(255, 255, 255, 0.05); padding: 4px 8px; border-radius: 4px; } /* 设置底部 */ .ds-settings-footer { display: flex; justify-content: space-between; align-items: center; padding: 15px 20px; background: linear-gradient(135deg, rgba(240, 240, 240, 0.4) 0%, rgba(230, 230, 230, 0.4) 100%); border-top: 1px solid rgba(0, 0, 0, 0.1); backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); } .ds-footer-info { display: flex; gap: 15px; font-size: 13px; color: #666666; } .ds-footer-buttons { display: flex; gap: 8px; } /* 响应式设计 */ @media (max-width: 768px) { .ds-settings-modal { width: 95%; max-height: 95vh; } .ds-service-header { flex-direction: column; align-items: flex-start; gap: 10px; } .ds-service-actions { width: 100%; justify-content: flex-start; } .ds-current-details { flex-direction: column; gap: 6px; } .ds-footer-info { flex-direction: column; gap: 5px; } .ds-footer-buttons { flex-wrap: wrap; } .ds-form-buttons { flex-wrap: wrap; } } /* 滚动条美化 */ .ds-settings-content::-webkit-scrollbar { width: 8px; } .ds-settings-content::-webkit-scrollbar-track { background: rgba(255, 255, 255, 0.05); border-radius: 4px; } .ds-settings-content::-webkit-scrollbar-thumb { background: rgba(0, 123, 255, 0.5); border-radius: 4px; } .ds-settings-content::-webkit-scrollbar-thumb:hover { background: rgba(0, 123, 255, 0.7); } /* 简洁人格设置模态框样式 */ .ds-personality-quick-modal { max-width: 600px; max-height: 80vh; } .ds-personality-content { padding: 20px; display: flex; flex-direction: column; gap: 15px; max-height: 65vh; } /* 提示文字 */ .ds-personality-hint { background: linear-gradient(135deg, rgba(78, 205, 196, 0.1) 0%, rgba(78, 205, 196, 0.05) 100%); padding: 12px; border-radius: 8px; border: 1px solid rgba(78, 205, 196, 0.2); font-size: 13px; color: #2c3e50; line-height: 1.5; backdrop-filter: blur(5px) saturate(180%); -webkit-backdrop-filter: blur(5px) saturate(180%); } /* 文本编辑器 */ .ds-personality-textarea { width: 100%; flex: 1; min-height: 200px; padding: 15px; border: 2px solid rgba(0, 0, 0, 0.15); border-radius: 10px; font-size: 14px; font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif; line-height: 1.6; resize: vertical; background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(5px) saturate(180%); -webkit-backdrop-filter: blur(5px) saturate(180%); transition: all 0.3s ease; color: #2c3e50; box-sizing: border-box; } .ds-personality-textarea:focus { outline: none; border-color: #4ecdc4; box-shadow: 0 0 0 4px rgba(78, 205, 196, 0.2); background: rgba(255, 255, 255, 0.98); } .ds-personality-textarea::placeholder { color: #999; font-style: italic; line-height: 1.8; } /* 按钮区域 */ .ds-personality-buttons { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-top: 5px; } .ds-buttons-left { display: flex; gap: 8px; } /* 按钮样式 */ .ds-personality-buttons .ds-btn-secondary, .ds-personality-buttons .ds-btn-primary { padding: 10px 16px; font-size: 14px; border-radius: 8px; border: none; cursor: pointer; transition: all 0.3s ease; font-weight: 500; display: flex; align-items: center; gap: 6px; white-space: nowrap; } .ds-personality-buttons .ds-btn-secondary { background: linear-gradient(135deg, #6c757d, #545b62); color: white; } .ds-personality-buttons .ds-btn-secondary:hover { background: linear-gradient(135deg, #545b62, #3d4146); transform: translateY(-2px); box-shadow: 0 4px 12px rgba(108, 117, 125, 0.3); } .ds-personality-buttons .ds-btn-primary { background: linear-gradient(135deg, #4ecdc4, #3bb5ad); color: white; padding: 12px 20px; font-size: 15px; } .ds-personality-buttons .ds-btn-primary:hover { background: linear-gradient(135deg, #3bb5ad, #2a9d8f); transform: translateY(-2px); box-shadow: 0 4px 12px rgba(78, 205, 196, 0.4); } /* 响应式优化 */ @media (max-width: 768px) { .ds-personality-quick-modal { max-width: 95vw; max-height: 85vh; } .ds-personality-content { padding: 15px; max-height: 70vh; } .ds-personality-textarea { min-height: 180px; max-height: 250px; } .ds-personality-buttons { flex-direction: column; gap: 8px; } .ds-buttons-left { width: 100%; justify-content: stretch; } .ds-buttons-left .ds-btn-secondary { flex: 1; justify-content: center; } .ds-personality-buttons .ds-btn-primary { width: 100%; justify-content: center; } } /* 原有样式保持不变 */ @keyframes fadeInOut { 0% { opacity: 0; } 100% { opacity: 1; } } @keyframes fadeOut { 0% { opacity: 1; transform: translateY(0); } 100% { opacity: 0; transform: translateY(20px); } } .ds-chat-icon img { width: 30px; height: 30px; border-radius: 50%; transition: all 0.3s ease; animation: breath 2s infinite alternate; } .ds-chat-icon:hover img { transform: scale(1.1); filter: drop-shadow(0 0 8px rgba(0, 123, 255, 0.6)); animation: pulse 0.5s infinite alternate; } @keyframes breath { 0% { opacity: 0.9; } 100% { opacity: 1; } } @keyframes pulse { 0% { transform: scale(1); } 100% { transform: scale(1.15); } } .ds-chat-window { position: fixed; bottom: 20px; right: 20px; width: 340px; max-width: 70vw; max-height: 70vh; background: linear-gradient(135deg, rgba(255, 255, 255, 0.4) 0%, rgba(245, 245, 245, 0.4) 100%); border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 15px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15); display: none; flex-direction: column; overflow: hidden; opacity: 0; transform: translateY(20px); z-index: 2147483646; backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); animation: fadeInOut 0.5s ease-in-out forwards; transition: all 1s ease-in-out; } .ds-chat-window.active { display: flex; opacity: 1; transform: translateY(0); } .ds-chat-window.fullscreen { width: 100% !important; max-width: 100vw !important; max-height: 100vh !important; bottom: 0 !important; right: 0 !important; border-radius: 0 !important; animation: fadeInOut 1.2s ease-in-out forwards; } .ds-chat-icon { position: fixed; bottom: 5px; right: 5px; width: 50px; height: 50px; background: linear-gradient(135deg, rgba(0, 123, 255, 0.4), rgba(0, 86, 179, 0.4)); border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 24px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4), 0 0 20px rgba(0, 123, 255, 0.3); transition: all 0.3s ease; z-index: 2147483647; backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); border: 2px solid rgba(255, 255, 255, 0.8); overflow: hidden; animation: pulse 2s infinite; } .ds-chat-icon:hover { transform: scale(1.1) translateY(-2px); box-shadow: 0 8px 25px rgba(0, 123, 255, 0.6), 0 0 30px rgba(0, 123, 255, 0.4); background: linear-gradient(135deg, rgba(0, 123, 255, 0.6), rgba(0, 86, 179, 0.6)); animation: none; } .ds-chat-icon img { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; image-rendering: -webkit-optimize-contrast; -webkit-user-drag: none; user-select: none; } .ds-chat-icon:active { transform: scale(0.95); } /* 图标加载失败时的样式 */ .ds-chat-icon::after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(circle at 30% 30%, rgba(255,255,255,0.3), transparent); border-radius: 50%; pointer-events: none; } /* 图标脉冲动画 */ @keyframes pulse { 0% { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4), 0 0 15px rgba(0, 123, 255, 0.3); } 50% { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4), 0 0 25px rgba(0, 123, 255, 0.5); } 100% { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4), 0 0 15px rgba(0, 123, 255, 0.3); } } .ds-chat-icon:hover { transform: scale(1.05); box-shadow: 0 6px 8px rgba(0, 0, 0, 0.3); background-color: rgba(0, 123, 255, 0.6); } .ds-chat-header { padding: 10px 15px; background: linear-gradient(135deg, rgba(0, 123, 255, 0.4) 0%, rgba(0, 86, 179, 0.4) 100%); color: white; display: flex; justify-content: space-between; align-items: center; border-radius: 15px 15px 0 0; backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); border-bottom: 1px solid rgba(255, 255, 255, 0.2); } .ds-chat-title { font-weight: bold; color: #2372c3; } .ds-chat-close { cursor: pointer; font-size: 18px; color: #ff6666; margin-left: 5px; } .ds-chat-fullscreen { cursor: pointer; font-size: 18px; margin-right: 5px; } /* HTML预览按钮 */ .ds-preview-html { background-color: rgba(0, 123, 255, 0.3); color: white; border: none; padding: 5px 10px; border-radius: 4px; cursor: pointer; margin-top: 5px; font-size: 12px; } .ds-preview-html:hover { background-color: rgba(0, 123, 255, 0.5); } /* HTML预览窗口 */ .ds-html-preview { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 80%; height: 80%; background: white; border-radius: 10px; box-shadow: 0 10px 30px rgba(0,0,0,0.3); z-index: 2147483647; display: flex; flex-direction: column; overflow: hidden; } .ds-preview-header { padding: 10px 15px; background: #f0f0f0; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #ddd; } .ds-preview-iframe { flex: 1; border: none; } .ds-preview-close { cursor: pointer; font-size: 18px; color: #ff6666; } .ds-preview-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 2147483646; } .ds-chat-content { flex: 1; padding: 0px; overflow-y: auto; background: linear-gradient(135deg, rgba(255, 255, 255, 0.4) 0%, rgba(250, 250, 250, 0.4) 100%); border-bottom: 1px solid rgba(0, 0, 0, 0.05); backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); } .ds-chat-message { background-color: rgba(255, 255, 255, 0.4); margin-bottom: 10px; padding: 8px 12px; border-radius: 10px; line-height: 1.5; word-wrap: break-word; color: #333333; font-size: 14px; border: 1px solid rgba(0, 0, 0, 0.05); backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); } .ds-user-message { background: linear-gradient(135deg, rgba(240, 240, 240, 0.4) 0%, rgba(230, 230, 230, 0.4) 100%); color: #2c3e50; margin-left: auto; text-align: right; font-size: 14px; padding: 8px 12px; border: 1px solid rgba(0, 0, 0, 0.1); backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); } .ds-ai-message { background-color: rgba(255, 255, 255, 0.4); margin-right: 10%; font-size: 14px; padding: 8px 12px; line-height: 1.5; color: #2c3e50; border: 1px solid rgba(0, 0, 0, 0.05); backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); } .ds-chat-input-area { padding: 10px; display: flex; flex-direction: column; background: linear-gradient(135deg, rgba(255, 255, 255, 0.4) 0%, rgba(245, 245, 245, 0.4) 100%); border-top: 1px solid rgba(0, 0, 0, 0.05); backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); } .ds-chat-input { width: 100%; padding: 8px 10px; border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 8px; margin-bottom: 8px; outline: none; transition: all 0.3s ease; font-size: 15px; color: #333333; background-color: rgba(255, 255, 255, 0.95); box-sizing: border-box; } .ds-chat-input:hover { border-color: rgba(0, 0, 0, 0.2); background-color: rgba(255, 255, 255, 0.98); box-shadow: 0 0 8px rgba(0, 0, 0, 0.1); } .ds-chat-input:focus { border-color: rgba(0, 0, 0, 0.3); background-color: rgba(255, 255, 255, 1); box-shadow: 0 0 12px rgba(0, 0, 0, 0.15); } .ds-chat-input::placeholder { color: rgba(0, 0, 0, 0.4); } .ds-chat-settings { display: flex; justify-content: space-between; font-size: 12px; color: #666666; align-items: center; padding: 0 5px; gap: 8px; flex-wrap: nowrap; } .ds-chat-settings-btn { cursor: pointer; text-decoration: underline; padding: 2px 5px; border-radius: 3px; transition: all 0.3s ease; color: #555555; } .ds-chat-settings-btn:hover { background-color: rgba(0, 0, 0, 0.05); color: #000000; } /* 服务选择器样式 */ .ds-service-select { padding: 4px 8px; background: rgba(255, 255, 255, 0.95); border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 4px; color: #333333; font-size: 12px; cursor: pointer; transition: all 0.3s ease; max-width: 120px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .ds-service-select:hover { border-color: rgba(0, 0, 0, 0.3); background: rgba(255, 255, 255, 0.98); box-shadow: 0 0 8px rgba(0, 0, 0, 0.1); } .ds-service-select:focus { outline: none; border-color: rgba(0, 0, 0, 0.4); background: rgba(255, 255, 255, 1); box-shadow: 0 0 12px rgba(0, 0, 0, 0.15); } /* 模型选择器样式 */ .ds-model-select { padding: 4px 8px; background: rgba(255, 255, 255, 0.95); border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 4px; color: #333333; font-size: 12px; cursor: pointer; transition: all 0.3s ease; max-width: 180px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .ds-model-select:hover { border-color: rgba(0, 0, 0, 0.3); background: rgba(255, 255, 255, 0.98); box-shadow: 0 0 8px rgba(0, 0, 0, 0.1); } .ds-model-select:focus { outline: none; border-color: rgba(0, 0, 0, 0.4); background: rgba(255, 255, 255, 1); box-shadow: 0 0 12px rgba(0, 0, 0, 0.15); } /* 调整聊天设置区域的布局 */ .ds-chat-settings { display: flex; justify-content: space-between; font-size: 12px; color: #666; align-items: center; padding: 0 5px; gap: 8px; flex-wrap: nowrap; } /* 通知样式 */ .ds-notification { position: fixed; top: 20px; right: 20px; background: linear-gradient(135deg, #00c853, #009624); color: white; padding: 12px 20px; border-radius: 8px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); z-index: 2147483648; font-size: 14px; font-weight: 500; animation: slideInRight 0.3s ease-out; max-width: 300px; } .ds-notification.error { background: linear-gradient(135deg, #f44336, #c62828); } .ds-notification.warning { background: linear-gradient(135deg, #ff9800, #f57c00); } @keyframes slideInRight { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } .ds-thinking { color: #e87be4; font-style: italic; } .ds-error { color: #ff0000; } .ds-reasoning-content { color: #888; font-size: 0.9em; border-left: 2px solid #ddd; padding-left: 10px; margin-bottom: 10px; } .ds-context-toggle { margin-bottom: 8px; display: flex; align-items: center; font-size: 12px; backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); } .ds-context-toggle input { margin-right: 5px; } /* Agent模式激活状态指示器 */ .ds-chat-header.agent-active { background: linear-gradient(135deg, rgba(156, 39, 176, 0.6) 0%, rgba(103, 58, 183, 0.6) 100%) !important; border-bottom: 2px solid rgba(156, 39, 176, 0.8); } .ds-chat-header.agent-active .ds-chat-title::after { content: ' 🤖'; animation: pulse 1.5s infinite; } .ds-agent-status { display: inline-block; font-size: 10px; padding: 2px 6px; border-radius: 8px; background: rgba(156, 39, 176, 0.3); color: #fff; margin-left: 6px; vertical-align: middle; } .ds-context-summary { font-size: 11px; color: #666; margin-top: 5px; font-style: italic; } .ds-chat-message { white-space: pre-wrap; word-break: break-word; visibility: visible !important; display: block !important; opacity: 1 !important; } .ds-ai-message { font-size: 14px; line-height: 1.5; padding: 8px 12px; margin: 0px 0px; background-color: rgba(255, 255, 255, 0.1); border-radius: 8px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); color: #2372c3 !important; } .ds-message-content { font-size: 14px !important; line-height: 1.5 !important; color: #2372c3 !important; display: block !important; visibility: visible !important; opacity: 1 !important; min-height: 1em; background: none !important; background-color: transparent !important; background-image: none !important; text-shadow: none !important; } @keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } } .ds-message-content::after { content: '|'; position: relative; display: inline; color: transparent !important; animation: blink 1s infinite; margin-left: 2px; } .ds-message-content:not(:empty)::after { display: none; } /* Agent Console Panel - Terminal Style */ .ds-console-panel { background: #0d1117; border-top: 1px solid #30363d; border-bottom: 1px solid #30363d; font-family: 'Menlo', 'Consolas', 'Monaco', monospace; font-size: 12px; line-height: 1.5; color: #8b949e; max-height: 0; overflow: hidden; transition: max-height 0.3s ease; position: relative; } .ds-console-panel.active { max-height: 240px; overflow-y: auto; } .ds-console-content { padding: 8px 12px; } .ds-console-line { white-space: pre-wrap; word-break: break-all; padding: 1px 0; display: flex; align-items: baseline; gap: 6px; } .ds-console-prompt { color: #7ee787; user-select: none; flex-shrink: 0; } .ds-console-cmd { color: #ffa657; } .ds-console-result { color: #8b949e; } .ds-console-success { color: #3fb950; } .ds-console-error { color: #f85149; } .ds-console-info { color: #58a6ff; } .ds-console-separator { border: none; border-top: 1px solid #21262d; margin: 4px 0; } .ds-console-header { display: flex; justify-content: space-between; align-items: center; padding: 4px 12px; background: #161b22; border-bottom: 1px solid #30363d; font-size: 11px; color: #8b949e; cursor: pointer; user-select: none; } .ds-console-header:hover { background: #1c2128; } .ds-console-header .ds-console-title { display: flex; align-items: center; gap: 6px; } .ds-console-header .ds-console-clear { cursor: pointer; color: #8b949e; font-size: 14px; padding: 0 4px; } .ds-console-header .ds-console-clear:hover { color: #f85149; } .ds-console-panel::-webkit-scrollbar { width: 6px; } .ds-console-panel::-webkit-scrollbar-track { background: #0d1117; } .ds-console-panel::-webkit-scrollbar-thumb { background: #30363d; border-radius: 3px; } /* Console badge in header */ .ds-console-badge { display: inline-block; font-size: 9px; padding: 1px 5px; border-radius: 6px; background: #238636; color: #fff; margin-left: 4px; vertical-align: middle; } `); // ============================================================ // BrowserAgent — 浏览器控制代理 (参考 pi-agent-browser 设计) // ============================================================ class BrowserAgent { constructor() { this.elements = {}; this.refIndex = 1; this.screenshotCount = 0; } static getToolDescriptions() { var desc = ` ## Browser Agent Tools You are a browser AI agent that controls the browser to accomplish user goals. ### Available Commands (all in [TOOL] prefix) | Command | Description | Example | |---------|-------------|---------| | navigate | Navigate to URL | navigate https://www.google.com | | snapshot -i | List interactive elements with @ref handles | snapshot -i | | click @eN | Click an element | click @e3 | | fill @eN "text" | Clear field and type text | fill @e5 "search query" | | type @eN "text" | Type text without clearing | type @e5 "more text" | | select @eN "value" | Select dropdown option | select @e7 "Option B" | | press | Press a keyboard key | press Enter | | scroll down [px] | Scroll down | scroll down 500 | | scroll up [px] | Scroll up | scroll up 200 | | get text | Get page body text | get text | | get title | Get page title | get title | | get url | Get current URL | get url | | extract @eN | Get element text content | extract @e1 | | screenshot | Take a screenshot (base64 image) | screenshot | | wait | Wait for milliseconds | wait 2000 | | done | Task complete, summarize results | done | ### @ref System snapshot -i returns elements as: @e1