1646 lines
103 KiB
HTML
1646 lines
103 KiB
HTML
<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>2026 AI 编程与开发工具深度对比:从 Cursor 到 Gemini CLI | llbzow的摸鱼日记 (づ ̄ 3 ̄)づ</title><meta name="author" content="llbzow"><meta name="copyright" content="llbzow"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="ffffff"><meta name="description" content="2026 AI 编程与开发工具深度对比 2026 年,写代码的方式彻底变了。我们不再逐行敲击键盘,而是作为“架构师”,指挥着一群不知疲倦的 AI 智能体 (Agents) 为我们打工。本文将深度剖析当前市面上最主流的 9 款 AI 开发神器。">
|
||
<meta property="og:type" content="article">
|
||
<meta property="og:title" content="2026 AI 编程与开发工具深度对比:从 Cursor 到 Gemini CLI">
|
||
<meta property="og:url" content="https://yourblog.com/2026/03/25/ai%E5%8E%82%E5%95%86%E5%AF%B9%E6%AF%94%E5%88%86%E6%9E%90/index.html">
|
||
<meta property="og:site_name" content="llbzow的摸鱼日记 (づ ̄ 3 ̄)づ">
|
||
<meta property="og:description" content="2026 AI 编程与开发工具深度对比 2026 年,写代码的方式彻底变了。我们不再逐行敲击键盘,而是作为“架构师”,指挥着一群不知疲倦的 AI 智能体 (Agents) 为我们打工。本文将深度剖析当前市面上最主流的 9 款 AI 开发神器。">
|
||
<meta property="og:locale" content="zh_CN">
|
||
<meta property="og:image" content="https://yourblog.com/img/cover_3.png">
|
||
<meta property="article:published_time" content="2026-03-25T02:30:00.000Z">
|
||
<meta property="article:modified_time" content="2026-03-25T02:56:53.568Z">
|
||
<meta property="article:author" content="llbzow">
|
||
<meta property="article:tag" content="技术">
|
||
<meta property="article:tag" content="AI">
|
||
<meta property="article:tag" content="效率工具">
|
||
<meta property="article:tag" content="极客">
|
||
<meta name="twitter:card" content="summary">
|
||
<meta name="twitter:image" content="https://yourblog.com/img/cover_3.png"><script type="application/ld+json">{
|
||
"@context": "https://schema.org",
|
||
"@type": "BlogPosting",
|
||
"headline": "2026 AI 编程与开发工具深度对比:从 Cursor 到 Gemini CLI",
|
||
"url": "https://yourblog.com/2026/03/25/ai%E5%8E%82%E5%95%86%E5%AF%B9%E6%AF%94%E5%88%86%E6%9E%90/",
|
||
"image": "https://yourblog.com/img/cover_3.png",
|
||
"datePublished": "2026-03-25T02:30:00.000Z",
|
||
"dateModified": "2026-03-25T02:56:53.568Z",
|
||
"author": [
|
||
{
|
||
"@type": "Person",
|
||
"name": "llbzow",
|
||
"url": "https://yourblog.com"
|
||
}
|
||
]
|
||
}</script><link rel="shortcut icon" href="/img/cute_cat.svg"><link rel="canonical" href="https://yourblog.com/2026/03/25/ai%E5%8E%82%E5%95%86%E5%AF%B9%E6%AF%94%E5%88%86%E6%9E%90/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"><link rel="preconnect" href="//busuanzi.ibruce.info"><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css"><script>
|
||
(() => {
|
||
|
||
const saveToLocal = {
|
||
set: (key, value, ttl) => {
|
||
if (!ttl) return
|
||
const expiry = Date.now() + ttl * 86400000
|
||
localStorage.setItem(key, JSON.stringify({ value, expiry }))
|
||
},
|
||
get: key => {
|
||
const itemStr = localStorage.getItem(key)
|
||
if (!itemStr) return undefined
|
||
const { value, expiry } = JSON.parse(itemStr)
|
||
if (Date.now() > expiry) {
|
||
localStorage.removeItem(key)
|
||
return undefined
|
||
}
|
||
return value
|
||
}
|
||
}
|
||
|
||
window.btf = {
|
||
saveToLocal,
|
||
getScript: (url, attr = {}) => new Promise((resolve, reject) => {
|
||
const script = document.createElement('script')
|
||
script.src = url
|
||
script.async = true
|
||
Object.entries(attr).forEach(([key, val]) => script.setAttribute(key, val))
|
||
script.onload = script.onreadystatechange = () => {
|
||
if (!script.readyState || /loaded|complete/.test(script.readyState)) resolve()
|
||
}
|
||
script.onerror = reject
|
||
document.head.appendChild(script)
|
||
}),
|
||
getCSS: (url, id) => new Promise((resolve, reject) => {
|
||
const link = document.createElement('link')
|
||
link.rel = 'stylesheet'
|
||
link.href = url
|
||
if (id) link.id = id
|
||
link.onload = link.onreadystatechange = () => {
|
||
if (!link.readyState || /loaded|complete/.test(link.readyState)) resolve()
|
||
}
|
||
link.onerror = reject
|
||
document.head.appendChild(link)
|
||
}),
|
||
addGlobalFn: (key, fn, name = false, parent = window) => {
|
||
if (!true && key.startsWith('pjax')) return
|
||
const globalFn = parent.globalFn || {}
|
||
globalFn[key] = globalFn[key] || {}
|
||
globalFn[key][name || Object.keys(globalFn[key]).length] = fn
|
||
parent.globalFn = globalFn
|
||
}
|
||
}
|
||
|
||
|
||
const activateDarkMode = () => {
|
||
document.documentElement.setAttribute('data-theme', 'dark')
|
||
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
|
||
}
|
||
}
|
||
const activateLightMode = () => {
|
||
document.documentElement.setAttribute('data-theme', 'light')
|
||
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||
document.querySelector('meta[name="theme-color"]').setAttribute('content', 'ffffff')
|
||
}
|
||
}
|
||
|
||
btf.activateDarkMode = activateDarkMode
|
||
btf.activateLightMode = activateLightMode
|
||
|
||
const theme = saveToLocal.get('theme')
|
||
|
||
theme === 'dark' ? activateDarkMode() : theme === 'light' ? activateLightMode() : null
|
||
|
||
|
||
const asideStatus = saveToLocal.get('aside-status')
|
||
if (asideStatus !== undefined) {
|
||
document.documentElement.classList.toggle('hide-aside', asideStatus === 'hide')
|
||
}
|
||
|
||
|
||
const detectApple = () => {
|
||
if (/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)) {
|
||
document.documentElement.classList.add('apple')
|
||
}
|
||
}
|
||
detectApple()
|
||
|
||
})()
|
||
</script><script>const GLOBAL_CONFIG = {
|
||
root: '/',
|
||
algolia: undefined,
|
||
localSearch: undefined,
|
||
translate: undefined,
|
||
highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false,"highlightFullpage":false,"highlightMacStyle":false},
|
||
copy: {
|
||
success: '复制成功',
|
||
error: '复制失败',
|
||
noSupport: '浏览器不支持'
|
||
},
|
||
relativeDate: {
|
||
homepage: false,
|
||
post: false
|
||
},
|
||
runtime: '',
|
||
dateSuffix: {
|
||
just: '刚刚',
|
||
min: '分钟前',
|
||
hour: '小时前',
|
||
day: '天前',
|
||
month: '个月前'
|
||
},
|
||
copyright: undefined,
|
||
lightbox: 'null',
|
||
Snackbar: undefined,
|
||
infinitegrid: {
|
||
js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid/dist/infinitegrid.min.js',
|
||
buttonText: '加载更多'
|
||
},
|
||
isPhotoFigcaption: false,
|
||
islazyloadPlugin: true,
|
||
isAnchor: false,
|
||
percent: {
|
||
toc: true,
|
||
rightside: false,
|
||
},
|
||
autoDarkmode: false
|
||
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
|
||
title: '2026 AI 编程与开发工具深度对比:从 Cursor 到 Gemini CLI',
|
||
isHighlightShrink: false,
|
||
isToc: true,
|
||
pageType: 'post'
|
||
}</script><link rel="stylesheet" href="/css/custom.css"><meta name="generator" content="Hexo 7.3.0"></head><body><div id="loading-box"><div class="loading-left-bg"></div><div class="loading-right-bg"></div><div class="spinner-box"><div class="configure-border-1"><div class="configure-core"></div></div><div class="configure-border-2"><div class="configure-core"></div></div><div class="loading-word">加载中...</div></div></div><script>(()=>{
|
||
const $loadingBox = document.getElementById('loading-box')
|
||
const $body = document.body
|
||
const preloader = {
|
||
endLoading: () => {
|
||
if ($loadingBox.classList.contains('loaded')) return
|
||
$body.style.overflow = ''
|
||
$loadingBox.classList.add('loaded')
|
||
},
|
||
initLoading: () => {
|
||
$body.style.overflow = 'hidden'
|
||
$loadingBox.classList.remove('loaded')
|
||
}
|
||
}
|
||
|
||
preloader.initLoading()
|
||
|
||
if (document.readyState === 'complete') {
|
||
preloader.endLoading()
|
||
} else {
|
||
window.addEventListener('load', preloader.endLoading)
|
||
document.addEventListener('DOMContentLoaded', preloader.endLoading)
|
||
// Add timeout protection: force end after 7 seconds
|
||
setTimeout(preloader.endLoading, 7000)
|
||
}
|
||
|
||
if (true) {
|
||
btf.addGlobalFn('pjaxSend', preloader.initLoading, 'preloader_init')
|
||
btf.addGlobalFn('pjaxComplete', preloader.endLoading, 'preloader_end')
|
||
}
|
||
})()</script><div id="web_bg" style="background-image: url(/img/bg_main.png);"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img text-center"><img src="data:image/webp;base64,UklGRhoBAABXRUJQVlA4WAoAAAAQAAAAJwAAJwAAQUxQSLgAAAAFuTJE9D80UiRJkiTpxvPo4fPha2lWw0WWMtgkeIot7wfsAyImYAI+vnvEjz++fJs9sbA+tfcM/HtDiBgr3c8SJP/Dk1FWC2LCxjhcwxkH4oQuQtNwSOdgixw5o+0TyIUCQoMJti7B3ALGhZLGNuJiAYfblG7kb/RON5GjZNeEtA+QtC6omDsY2aoIwv2KDLiAzPYvzhmyNVWWzAtzzGHxSBnzCwFja3Igk3sSwSooc7gTFtmKJoIQVlA4IDwAAABQAwCdASooACgAPzmcxF0vKqcko4gB4CcJZwDNSAn82OhFYAD+7iKcpmiMeBjtx3LPQK2rXKK9ARvvVAA=" data-lazy-src="/img/cute_cat.svg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar" loading="eager" fetchpriority="high" decoding="sync"></div><div class="site-data text-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">20</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">31</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">4</div></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 文章</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url(/img/cover_3.png);"><nav id="nav"><span id="blog-info"><a class="nav-site-title" href="/"><span class="site-name">llbzow的摸鱼日记 (づ ̄ 3 ̄)づ</span></a><a class="nav-page-title" href="/"><span class="site-name">2026 AI 编程与开发工具深度对比:从 Cursor 到 Gemini CLI</span><span class="site-name"><i class="fa-solid fa-circle-arrow-left"></i><span> 返回首页</span></span></a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 文章</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div><div id="toggle-menu"><span class="site-page"><i class="fas fa-bars fa-fw"></i></span></div></div></nav><div id="post-info"><h1 class="post-title">2026 AI 编程与开发工具深度对比:从 Cursor 到 Gemini CLI</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2026-03-25T02:30:00.000Z" title="发表于 2026-03-25 10:30:00">2026-03-25</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2026-03-25T02:56:53.568Z" title="更新于 2026-03-25 10:56:53">2026-03-25</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/%E7%9F%A5%E8%AF%86%E5%BA%93/">知识库</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title=""><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">浏览量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="container post-content" id="article-container"><h1 id="2026-AI-编程与开发工具深度对比"><a href="#2026-AI-编程与开发工具深度对比" class="headerlink" title="2026 AI 编程与开发工具深度对比"></a>2026 AI 编程与开发工具深度对比</h1><blockquote>
|
||
<p>2026 年,写代码的方式彻底变了。我们不再逐行敲击键盘,而是作为“架构师”,指挥着一群不知疲倦的 AI 智能体 (Agents) 为我们打工。本文将深度剖析当前市面上最主流的 9 款 AI 开发神器。</p>
|
||
</blockquote>
|
||
<span id="more"></span>
|
||
|
||
<p><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="https://images.unsplash.com/photo-1555066931-4365d14bab8c?auto=format&fit=crop&q=80&w=1000" alt="AI Coding Concept"><br><em>(图:2026 年的开发日常 —— 喝着咖啡看 Agent 重构代码)</em></p>
|
||
<hr>
|
||
<h2 id="🛠️-核心阵营划分"><a href="#🛠️-核心阵营划分" class="headerlink" title="🛠️ 核心阵营划分"></a>🛠️ 核心阵营划分</h2><p>2026 年的 AI 工具市场已分化为四大流派:</p>
|
||
<ol>
|
||
<li><strong>IDE 原生派 (AI-First IDEs)</strong>: Cursor, Trae, Antigravity</li>
|
||
<li><strong>终端智能体 (CLI Agents)</strong>: Claude Code, Gemini CLI, Kimi Code</li>
|
||
<li><strong>插件与桌面端 (Plugins & Apps)</strong>: GitHub Copilot, Codex App</li>
|
||
<li><strong>开源极客派 (Open Source)</strong>: OpenClaw</li>
|
||
</ol>
|
||
<hr>
|
||
<h2 id="1-IDE-原生派:代码编辑器的新王"><a href="#1-IDE-原生派:代码编辑器的新王" class="headerlink" title="1. IDE 原生派:代码编辑器的新王"></a>1. IDE 原生派:代码编辑器的新王</h2><p>如果你不想折腾配置,开箱即用的 AI IDE 是最佳选择。</p>
|
||
<h3 id="Cursor-——-依然是无可争议的王者"><a href="#Cursor-——-依然是无可争议的王者" class="headerlink" title="Cursor —— 依然是无可争议的王者"></a>Cursor —— 依然是无可争议的王者</h3><ul>
|
||
<li><strong>核心卖点</strong>:<strong>Composer 模式</strong>。它可以一口气在多个文件中穿梭,自动分析你的整个 Codebase 并一次性提交涉及数十个文件的 PR。</li>
|
||
<li><strong>2026 现状</strong>:引入了极速的 Speculative Edits(推测性编辑),哪怕是巨大的 Monorepo 也能做到毫秒级响应。</li>
|
||
<li><strong>价格</strong>:Pro 计划 <code>$20/月</code>。</li>
|
||
<li><strong>适用人群</strong>:全栈工程师、独立开发者。</li>
|
||
</ul>
|
||
<h3 id="Trae-字节跳动-——-Vibe-Coding-的倡导者"><a href="#Trae-字节跳动-——-Vibe-Coding-的倡导者" class="headerlink" title="Trae (字节跳动) —— Vibe Coding 的倡导者"></a>Trae (字节跳动) —— Vibe Coding 的倡导者</h3><ul>
|
||
<li><strong>核心卖点</strong>:**Adaptive Routing (自适应路由)**。它会根据你当前写的代码复杂度,自动在极速模型(豆包)和重度推理模型之间无缝切换。其中文语境理解极佳。</li>
|
||
<li><strong>2026 现状</strong>:深度整合了飞书和国内云生态,堪称国内大厂搬砖神器。</li>
|
||
<li><strong>价格</strong>:标准版免费,Pro 版约 <code>¥99/月</code>。</li>
|
||
</ul>
|
||
<h3 id="Antigravity-Google-——-端到端测试核武器"><a href="#Antigravity-Google-——-端到端测试核武器" class="headerlink" title="Antigravity (Google) —— 端到端测试核武器"></a>Antigravity (Google) —— 端到端测试核武器</h3><ul>
|
||
<li><strong>核心卖点</strong>:<strong>Browser Agent</strong>。这是 Google 推出的重量级武器。它不仅能写代码,还能自动拉起 Chrome 浏览器,像真人一样点击 UI、跑通 E2E 测试并截图反馈错误。</li>
|
||
<li><strong>2026 现状</strong>:与 Gemini 3.1 深度绑定,多模态(看图写 UI)能力天下第一。</li>
|
||
<li><strong>价格</strong>:基础版免费,Pro 版 <code>$20/月</code>。</li>
|
||
</ul>
|
||
<p><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="https://images.unsplash.com/photo-1618401471353-b98afee0b2eb?auto=format&fit=crop&q=80&w=1000" alt="IDE Comparison"></p>
|
||
<hr>
|
||
<h2 id="2-终端智能体-CLI-Agents-:黑客的终极浪漫"><a href="#2-终端智能体-CLI-Agents-:黑客的终极浪漫" class="headerlink" title="2. 终端智能体 (CLI Agents):黑客的终极浪漫"></a>2. 终端智能体 (CLI Agents):黑客的终极浪漫</h2><p>真正的极客从不离开 Terminal。2026 年的终端工具已经可以接管整个操作系统。</p>
|
||
<h3 id="Claude-Code-——-逻辑天花板"><a href="#Claude-Code-——-逻辑天花板" class="headerlink" title="Claude Code —— 逻辑天花板"></a>Claude Code —— 逻辑天花板</h3><ul>
|
||
<li><strong>核心卖点</strong>:由 <strong>Claude 4.6 Opus</strong> 驱动。你只需在终端输入 <code>claude "帮我把整个后端的鉴权逻辑改成 OAuth 2.0"</code>,它会自主搜索文件、读代码、安装依赖、甚至运行单元测试,直到报错全部消失。</li>
|
||
<li><strong>适用场景</strong>:重构庞大的遗留代码库 (Legacy Code)。</li>
|
||
</ul>
|
||
<h3 id="Gemini-CLI-——-性价比与搜索之王"><a href="#Gemini-CLI-——-性价比与搜索之王" class="headerlink" title="Gemini CLI —— 性价比与搜索之王"></a>Gemini CLI —— 性价比与搜索之王</h3><ul>
|
||
<li><strong>核心卖点</strong>:依托于 Google 强大的实时搜索。当遇到冷门库的报错时,它会自动联网翻阅 GitHub Issues 和 StackOverflow,并直接在本地应用补丁。</li>
|
||
<li><strong>价格</strong>:免费额度极其慷慨,性价比碾压。</li>
|
||
</ul>
|
||
<h3 id="Kimi-Code-——-本土化的-Agent-Swarm"><a href="#Kimi-Code-——-本土化的-Agent-Swarm" class="headerlink" title="Kimi Code —— 本土化的 Agent Swarm"></a>Kimi Code —— 本土化的 Agent Swarm</h3><ul>
|
||
<li><strong>核心卖点</strong>:极低的 API 成本和强大的 **Agent Swarm (智能体集群)**。它可以瞬间分裂出多个子进程,并行处理不同模块的开发。</li>
|
||
</ul>
|
||
<hr>
|
||
<h2 id="3-插件与桌面端:稳健的经典流派"><a href="#3-插件与桌面端:稳健的经典流派" class="headerlink" title="3. 插件与桌面端:稳健的经典流派"></a>3. 插件与桌面端:稳健的经典流派</h2><h3 id="GitHub-Copilot-2026-版"><a href="#GitHub-Copilot-2026-版" class="headerlink" title="GitHub Copilot (2026 版)"></a>GitHub Copilot (2026 版)</h3><ul>
|
||
<li><strong>现状</strong>:全面支持 **MCP (Model Context Protocol)**,你可以一键切换底层的模型(GPT-5, Claude, 甚至国产模型)。它依然是企业级采购的首选,市场占有率最高。</li>
|
||
<li><strong>价格</strong>:Individual <code>$10/月</code>。</li>
|
||
</ul>
|
||
<h3 id="Codex-App-OpenAI"><a href="#Codex-App-OpenAI" class="headerlink" title="Codex App (OpenAI)"></a>Codex App (OpenAI)</h3><ul>
|
||
<li><strong>核心卖点</strong>:2026 年 OpenAI 推出的独立原生应用(支持 macOS/Windows)。</li>
|
||
<li><strong>争议点</strong>:引入了 <strong>Rolling Window</strong> 限制。Pro 订阅(<code>$200/月</code>)允许在云端沙盒(Sandboxed Execution)中并行跑测试,彻底解放本地算力,是土豪开发者的最爱。</li>
|
||
</ul>
|
||
<hr>
|
||
<h2 id="4-开源黑马:OpenClaw"><a href="#4-开源黑马:OpenClaw" class="headerlink" title="4. 开源黑马:OpenClaw"></a>4. 开源黑马:OpenClaw</h2><p>如果你是一个重度掌控欲患者,<strong>OpenClaw</strong>(原名 Moltbot)是 2026 年不可不试的神器。</p>
|
||
<ul>
|
||
<li><strong>核心优势</strong>:<strong>完全开源、本地运行</strong>。它可以读取你的文件系统、执行 Shell 命令。更有趣的是,它支持远程唤醒:你可以躺在床上发个 WhatsApp 消息:“小 O,帮我把昨晚写的爬虫部署到服务器上”,它就会自动执行并给你发送进度截图。</li>
|
||
<li><strong>价格</strong>:免费(自带 API Key)。</li>
|
||
</ul>
|
||
<p><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="https://images.unsplash.com/photo-1629654297299-c8506221ca97?auto=format&fit=crop&q=80&w=1000" alt="Open Source Terminal"><br><em>(图:在终端中运行的开源智能体正在疯狂拉取依赖并编译)</em></p>
|
||
<hr>
|
||
<h2 id="🔥-开发者真实体感与吐槽-Developer-UX-Pain-Points"><a href="#🔥-开发者真实体感与吐槽-Developer-UX-Pain-Points" class="headerlink" title="🔥 开发者真实体感与吐槽 (Developer UX & Pain Points)"></a>🔥 开发者真实体感与吐槽 (Developer UX & Pain Points)</h2><p>任何工具都有其暗面。在 2026 年的高强度开发流中,这些工具暴露出了哪些最真实的痛点?</p>
|
||
<ul>
|
||
<li><strong>Cursor 被惯坏综合征</strong>:“自从用了 Cursor 的 Composer 之后,我发现我已经不会写正则和基础的 reduce 语法了。但最搞人心态的是,在庞大的 Monorepo 里,它有时候会莫名其妙把别的微服务里的配置文件改掉,排查起来简直要命。”</li>
|
||
<li><strong>Trae 的薛定谔体验</strong>:“Trae 在国内写业务确实爽,特别是飞书文档直接转代码的链路。但我用它写底层 Rust 和 C++ 的时候,明显感觉它的逻辑深度不如 Claude。所谓的 Vibe Coding,前提是你别碰造轮子的活儿。”</li>
|
||
<li><strong>Antigravity 的失业恐惧</strong>:“看到 Browser Agent 自动帮我打开浏览器、登录、点赞、截图并修复报错的那一刻,我没有感到高兴,我感到的是深切的被剥夺工作的恐惧……不过它报错的时候,去查它的执行日志,经常能看到它自己在两个网页间死循环反复横跳。”</li>
|
||
<li><strong>Claude Code 与破产警告</strong>:“看着终端里 Claude Code 疯狂自己滚代码、查日志、调接口,真的有种身处《黑客帝国》的快感。但跑了半小时重构完,一看 API 账单扣了 50 刀,心都在滴血。”</li>
|
||
<li><strong>Copilot 的‘中庸之道’</strong>:“2026 年了,Copilot 依然像个稳定的公务员。不出错,也没有特别亮眼的 Agent 操作。但它胜在稳定,且企业版数据安全政策做得最到位。”</li>
|
||
</ul>
|
||
<hr>
|
||
<h2 id="💡-2026-架构师选型建议"><a href="#💡-2026-架构师选型建议" class="headerlink" title="💡 2026 架构师选型建议"></a>💡 2026 架构师选型建议</h2><p>在 2026 年,不要试图用一个工具解决所有问题,<strong>Multi-tool Stacking (多工具堆叠)</strong> 才是王道。</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th align="left">你的开发需求</th>
|
||
<th align="left">推荐的工具组合</th>
|
||
<th align="left">预期成本</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td align="left"><strong>追求极致的开发与重构体验</strong></td>
|
||
<td align="left"><strong>Cursor</strong> (写代码) + <strong>Claude Code</strong> (跑终端 Agent)</td>
|
||
<td align="left">~$40 / 月</td>
|
||
</tr>
|
||
<tr>
|
||
<td align="left"><strong>性价比之王 / 学生党</strong></td>
|
||
<td align="left"><strong>Trae</strong> (免费版) + <strong>Gemini CLI</strong> (白嫖额度)</td>
|
||
<td align="left">免费</td>
|
||
</tr>
|
||
<tr>
|
||
<td align="left"><strong>接私活 / 快速原型交付</strong></td>
|
||
<td align="left"><strong>Antigravity</strong> (利用 Browser Agent 搞定 UI 测试)</td>
|
||
<td align="left">~$20 / 月</td>
|
||
</tr>
|
||
<tr>
|
||
<td align="left"><strong>高度定制化 / 极客玩家</strong></td>
|
||
<td align="left"><strong>OpenClaw</strong> (本地部署) + <strong>Kimi K2.5 API</strong></td>
|
||
<td align="left">按量计费 (极低)</td>
|
||
</tr>
|
||
<tr>
|
||
<td align="left"><strong>土豪 / 重度 GitHub 依赖</strong></td>
|
||
<td align="left"><strong>Codex App Pro</strong> (云端沙盒极速编译)</td>
|
||
<td align="left">$200 / 月</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<blockquote>
|
||
<p>👨💻 <strong>最终建议</strong>:让 AI 去写 boilerplate (样板代码),把你的精力留给真正的<strong>系统架构</strong>和<strong>业务逻辑思考</strong>。未来的程序员,本质上都是 Agent 调度员。</p>
|
||
</blockquote>
|
||
<hr>
|
||
<p><strong>相关推荐</strong></p>
|
||
<ul>
|
||
<li><a href="/">2026 全球主流 AI 厂商百科全书</a> - 了解工具背后的底层大模型</li>
|
||
<li><a href="/">如何搭建并调教你的 OpenClaw</a> - 开源 Agent 部署实战</li>
|
||
</ul>
|
||
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta"><i class="fas fa-circle-user fa-fw"></i>文章作者: </span><span class="post-copyright-info"><a href="https://yourblog.com">llbzow</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta"><i class="fas fa-square-arrow-up-right fa-fw"></i>文章链接: </span><span class="post-copyright-info"><a href="https://yourblog.com/2026/03/25/ai%E5%8E%82%E5%95%86%E5%AF%B9%E6%AF%94%E5%88%86%E6%9E%90/">https://yourblog.com/2026/03/25/ai%E5%8E%82%E5%95%86%E5%AF%B9%E6%AF%94%E5%88%86%E6%9E%90/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta"><i class="fas fa-circle-exclamation fa-fw"></i>版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外,均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来源 <a href="https://yourblog.com" target="_blank">llbzow的摸鱼日记 (づ ̄ 3 ̄)づ</a>!</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/%E6%8A%80%E6%9C%AF/">技术</a><a class="post-meta__tags" href="/tags/AI/">AI</a><a class="post-meta__tags" href="/tags/%E6%95%88%E7%8E%87%E5%B7%A5%E5%85%B7/">效率工具</a><a class="post-meta__tags" href="/tags/%E6%9E%81%E5%AE%A2/">极客</a></div><div class="post-share"><div class="social-share" data-image="/img/cover_3.png" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/js/social-share.min.js" defer=""></script></div></div><nav class="pagination-post" id="pagination"><a class="pagination-related full-width" href="/2026/03/25/ai%E5%8E%82%E5%95%86%E4%BB%8B%E7%BB%8D/" title="2026 全球主流 AI 厂商百科全书:Agent 与推理觉醒时代"><picture><source type="image/avif" srcset="/img/cover_1.avif"><source type="image/webp" srcset="/img/cover_1.webp"><img class="cover" src="data:image/webp;base64,UklGRmIAAABXRUJQVlA4IFYAAADQAwCdASooABcAPzmEvVW+qD+jMBVaq/AnCWUAvKQOUEaQujUIygAA/uKstJVCIF6EMhlK91rwyI5vjHFuFj4RzbouMdL+XCagicPPuXV9nUvM3YtwAA==" data-lazy-src="/img/cover_1.png" onerror="onerror=null;src='/img/049.png'" alt="cover of next post" loading="eager" fetchpriority="high" decoding="sync"></picture><div class="info text-right"><div class="info-1"><div class="info-item-1">下一篇</div><div class="info-item-2">2026 全球主流 AI 厂商百科全书:Agent 与推理觉醒时代</div></div><div class="info-2"><div class="info-item-1">2026 全球主流 AI 厂商百科全书 步入 2026 年,AI 模型已经从被动一问一答的“对话助手”彻底进化为“全自动智能体(Agent)”与“深度推理专家”。本文将全景盘点当前处于行业金字塔顶端的顶尖大模型,以及那些凭借庞大生态强势破局的“新势力”,并附上最硬核的跑分与定价对比。 (图:2026 年的 AI 已经深度融入算力网络与自动化流水线) 🌐 国际三巨头:AGI 的领跑者1. OpenAI (ChatGPT 5.4) —— 推理与多模态的绝对霸主OpenAI 在 2026 年推出的 ChatGPT 5.4 彻底打破了常规对话的局限,其最大的技术飞跃在于深度引入了“思考力控制(Reasoning Effort)”机制。它不再是盲目输出,而是会在复杂的数学和代码问题上“停下来思考”。 核心模型: GPT-5.4 Thinking: 推理专精版。在解决物理模拟或底层 C++ 内存泄漏问题时,它甚至会思考数分钟,然后给出一刀致命的完美解答。 GPT-5.4 Pro: 全能多模态旗舰,原生集成 Sora 2 级别的视频生成引擎。你甚至可以直接喂给它一段长达 1 小时的...</div></div></div></a></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list"><a class="pagination-related" href="/2026/03/25/ai%E5%8E%82%E5%95%86%E4%BB%8B%E7%BB%8D/" title="2026 全球主流 AI 厂商百科全书:Agent 与推理觉醒时代"><picture><source type="image/avif" srcset="/img/cover_1.avif"><source type="image/webp" srcset="/img/cover_1.webp"><img class="cover" src="data:image/webp;base64,UklGRmIAAABXRUJQVlA4IFYAAADQAwCdASooABcAPzmEvVW+qD+jMBVaq/AnCWUAvKQOUEaQujUIygAA/uKstJVCIF6EMhlK91rwyI5vjHFuFj4RzbouMdL+XCagicPPuXV9nUvM3YtwAA==" data-lazy-src="/img/cover_1.png" alt="cover" loading="lazy" decoding="async"></picture><div class="info text-center"><div class="info-1"><div class="info-item-1"><i class="far fa-calendar-alt fa-fw"></i> 2026-03-25</div><div class="info-item-2">2026 全球主流 AI 厂商百科全书:Agent 与推理觉醒时代</div></div><div class="info-2"><div class="info-item-1">2026 全球主流 AI 厂商百科全书 步入 2026 年,AI 模型已经从被动一问一答的“对话助手”彻底进化为“全自动智能体(Agent)”与“深度推理专家”。本文将全景盘点当前处于行业金字塔顶端的顶尖大模型,以及那些凭借庞大生态强势破局的“新势力”,并附上最硬核的跑分与定价对比。 (图:2026 年的 AI 已经深度融入算力网络与自动化流水线) 🌐 国际三巨头:AGI 的领跑者1. OpenAI (ChatGPT 5.4) —— 推理与多模态的绝对霸主OpenAI 在 2026 年推出的 ChatGPT 5.4 彻底打破了常规对话的局限,其最大的技术飞跃在于深度引入了“思考力控制(Reasoning Effort)”机制。它不再是盲目输出,而是会在复杂的数学和代码问题上“停下来思考”。 核心模型: GPT-5.4 Thinking: 推理专精版。在解决物理模拟或底层 C++ 内存泄漏问题时,它甚至会思考数分钟,然后给出一刀致命的完美解答。 GPT-5.4 Pro: 全能多模态旗舰,原生集成 Sora 2 级别的视频生成引擎。你甚至可以直接喂给它一段长达 1 小时的...</div></div></div></a><a class="pagination-related" href="/2026/01/15/vue-learning-11/" title="前端性能优化:只要我跑得够快,Bug 就追不上我"><picture><source type="image/avif" srcset="/img/006.avif"><source type="image/webp" srcset="/img/006.webp"><img class="cover" src="data:image/webp;base64,UklGRlwAAABXRUJQVlA4IFAAAADQBACdASooABoAPzF+uFO9qCWitVgMA7AmCWkAAMwSl3f/c9i75rjmQHNURFMDoAD+8GgVgvfQU5aK/6c0RbSACW5HouGtGVE0el0Cp6bAAA==" data-lazy-src="/img/006.png" alt="cover" loading="lazy" decoding="async"></picture><div class="info text-center"><div class="info-1"><div class="info-item-1"><i class="far fa-calendar-alt fa-fw"></i> 2026-01-15</div><div class="info-item-2">前端性能优化:只要我跑得够快,Bug 就追不上我</div></div><div class="info-2"><div class="info-item-1">性能优化:无底洞说页面加载太慢,要优化。好,我优化。 你知道的,一个three.js地图,配上一大堆数据,能加载的快就有鬼了。 漫漫长路 代码分割(Code Splitting):路由懒加载,组件异步加载。好,首屏快了一点。 图片压缩:上了 WebP,上了 CDN。 减少重排重绘:小心翼翼地操作 DOM。 Tree Shaking:检查打包产物,去掉了无用的 lodash 引入。 结果呢?乐了,更卡了。 心态崩了毁灭吧,赶紧的。累了。 为什么这么难?前端不就是画画界面调调接口吗?为什么要搞这么复杂?Webpack 还没整明白,Vite 又来了;Vue 3 又变了。学不动了,真的学不动了。 </div></div></div></a><a class="pagination-related" href="/2025/11/30/vue-learning-2/" title="Ref vs Reactive:响应式的哲学思考 (头秃篇)"><picture><source type="image/avif" srcset="/img/008.avif"><source type="image/webp" srcset="/img/008.webp"><img class="cover" src="data:image/webp;base64,UklGRnQAAABXRUJQVlA4IGgAAABQBgCdASooABcAPzmOule/qaUjqrgKA/AnCWUAxcgLBvRF6yrN9IbArqnaqrUpYci7EcxGWPw+NXHEAAD+w1j7uaJrlkg33F5UzUJ0Opii5bkQSgrXf6SxGc9wcw3QrRDaawAOlTAAAA==" data-lazy-src="/img/008.png" alt="cover" loading="lazy" decoding="async"></picture><div class="info text-center"><div class="info-1"><div class="info-item-1"><i class="far fa-calendar-alt fa-fw"></i> 2025-11-30</div><div class="info-item-2">Ref vs Reactive:响应式的哲学思考 (头秃篇)</div></div><div class="info-2"><div class="info-item-1">响应式的哲学在深入学习 Vue 3 的过程中,不管是新手还是老鸟,都会遇到一个经典问题:ref 和 reactive 到底用哪个? 官方的定义 ref:接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property,指向该内部值。 reactive:返回对象的响应式副本。 看起来很简单,对吧?ref 处理基本类型,reactive 处理对象。但是在实际开发中,情况远比这复杂。 踩坑实录我曾经试图用 reactive 去定义一个数组,结果发现直接重新赋值会丢失响应性! 123let list = reactive([])// ... 异步获取数据后list = newData // ❌ 响应性丢失!界面不更新! 为什么?因为 reactive 返回的是一个 Proxy 对象,直接赋值 list = newData 只是修改了变量 list 的引用,并没有修改原来的 Proxy 对象。 正确做法是用 ref,或者用 list.push(...newData)。但是 ref 每次都要写 .value,真的好烦啊!在模板里倒是会自动解包,但...</div></div></div></a><a class="pagination-related" href="/2025/12/14/vue-learning-4/" title="生命周期钩子:生老病死,Vue 组件的一生"><picture><source type="image/avif" srcset="/img/040.avif"><source type="image/webp" srcset="/img/040.webp"><img class="cover" src="data:image/webp;base64,UklGRmwAAABXRUJQVlA4IGAAAACQBACdASooABcAPy2CsFOzKKQitVgMAmAliUAY/IKA6LN3dHuRlGfAPc4H2QAA2rp5oGI824y5gTQFICHKEw9BjURv8zS+cUwXzCeOdyFsiP5ruOO3saceR6NhITLQAAA=" data-lazy-src="/img/040.jpg" alt="cover" loading="lazy" decoding="async"></picture><div class="info text-center"><div class="info-1"><div class="info-item-1"><i class="far fa-calendar-alt fa-fw"></i> 2025-12-14</div><div class="info-item-2">生命周期钩子:生老病死,Vue 组件的一生</div></div><div class="info-2"><div class="info-item-1">组件的一生万物皆有灵,Vue 组件也不例外。它们从被创建(Creation),到挂载(Mounting),到更新(Updating),最后销毁(Unmounting),走完了一生。而我们开发者,就是那个掌握生杀大权的神。 Vue 3 的变化在 Vue 2 中,我们熟悉的是 created, mounted, destroyed。在 Vue 3 的 Composition API 中,这些变成了 onMounted, onUnmounted 等等。 最让我困惑的是 setup()。它在 beforeCreate 和 created 之前执行。这意味着在 setup 里面,我们不需要写这一类的钩子了,直接写逻辑就行。 实际应用中的坑我曾经遇到过一个 Bug,在 onMounted 里面去获取 DOM 元素的高宽。理论上这时候 DOM 已经渲染好了,对吧? 错!如果你的组件里面有 v-if 或者异步组件,onMounted 触发的时候,子组件可能还没渲染完!这时候拿到的高度是 0。解决办法是用 nextTick,或者检查你的组件结构。 为什么会这样?回想起刚开始接触 Vue 的时候,那...</div></div></div></a><a class="pagination-related" href="/2026/01/07/vue-learning-9/" title="TypeScript:给代码穿上防弹衣 (虽然很重)"><picture><source type="image/avif" srcset="/img/site_bg_v2.avif"><source type="image/webp" srcset="/img/site_bg_v2.webp"><img class="cover" src="data:image/webp;base64,UklGRn4AAABXRUJQVlA4IHIAAABwBQCdASooABcAPzmKvVW/qSajMBqoA/AnCUAWo3CgkgShz1sDi7zNYIuZqzHvnjvry90AAP7it2SLgYgpB68fpGF8LA212vBP9aVJtRSRphnPvbv0tl3ARlG9CBwFhIyGIyXf4kAiaMAYMzJhC87JAAA=" data-lazy-src="/img/site_bg_v2.jpg" alt="cover" loading="lazy" decoding="async"></picture><div class="info text-center"><div class="info-1"><div class="info-item-1"><i class="far fa-calendar-alt fa-fw"></i> 2026-01-07</div><div class="info-item-2">TypeScript:给代码穿上防弹衣 (虽然很重)</div></div><div class="info-2"><div class="info-item-1">TypeScript:心态崩了毁灭吧,赶紧的。累了。 无尽的报错TypeScript 说是给代码穿上防弹衣,防止低级错误。但实际上,它更像是给我的手戴上了镣铐。 Type 'string | null' is not assignable to type 'string'.Property 'xyz' does not exist on type 'ABC'. 我知道!我知道它是 null!我加了判断了!但 TS 就是不信!非要我写 as string 或者 !。 尤其是在 Vue 组件的 Props 定义里,结合 defineProps 和泛型,写起来那叫一个酸爽。为了解决一个类型报错,我可能要写几十行的 interface 定义。这到底是写业务逻辑,还是在做类型体操? 为什么这么难?${title} 让我彻底破防了。我在 Pinia 里配了半天状态,结果组件里死活拿不到。控制台的黄色警告和红色错误交织在一起,像是在嘲笑我的无能。 在这个快速发展的前端时代,技术的更新迭代速度简直让人窒息。每一次框架的更新,不仅带来...</div></div></div></a><a class="pagination-related" href="/2026/01/24/vue-learning-15/" title="彻底放弃:拥抱 Vibe Code,AI 才是亲爹"><picture><source type="image/avif" srcset="/img/site_bg_v2.avif"><source type="image/webp" srcset="/img/site_bg_v2.webp"><img class="cover" src="data:image/webp;base64,UklGRn4AAABXRUJQVlA4IHIAAABwBQCdASooABcAPzmKvVW/qSajMBqoA/AnCUAWo3CgkgShz1sDi7zNYIuZqzHvnjvry90AAP7it2SLgYgpB68fpGF8LA212vBP9aVJtRSRphnPvbv0tl3ARlG9CBwFhIyGIyXf4kAiaMAYMzJhC87JAAA=" data-lazy-src="/img/site_bg_v2.jpg" alt="cover" loading="lazy" decoding="async"></picture><div class="info text-center"><div class="info-1"><div class="info-item-1"><i class="far fa-calendar-alt fa-fw"></i> 2026-01-24</div><div class="info-item-2">彻底放弃:拥抱 Vibe Code,AI 才是亲爹</div></div><div class="info-2"><div class="info-item-1">最终章:拥抱未来这是我《Vue 学习之路》系列的最后一篇文章。因为,这路我不走了。 为什么放弃? 效率差距:我写个增删改查页面,要 4 小时,调 CSS 还要 1 小时。AI 写,只要 30 秒。 知识焦虑:前端技术栈爆炸,学不完。但 AI 已经学完了所有文档。 幸福感:写代码是为了创造产品,不是为了修 Bug。 Vibe Code 体验打开 Vibe Code,输入:“做一个博客首页,要有毛玻璃效果,基于 Hexo Butterfly 主题风格”。然后,啪!代码出来了。没有语法错误,没有类型报错。 那一刻,我感觉自己之前的努力就像个笑话。 拥抱变化从今天起,我不再是前端切图仔,我是 AI Prompt 工程师。Vue 3?真不熟。Pinia?没听过。我只知道 “Generate a login page with Vue 3 and Tailwind”。 在这个快速发展的前端时代,技术的更新迭代速度简直让人窒息。每一次框架的更新,不仅带来了新的特性,也带来了新的焦虑。作为一名追求极致体验的开发者,我深知持续学习的重要性。但是… 真的需要学这么多吗? 再见了,所有的未定义变量,...</div></div></div></a></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info text-center"><div class="avatar-img"><img src="data:image/webp;base64,UklGRhoBAABXRUJQVlA4WAoAAAAQAAAAJwAAJwAAQUxQSLgAAAAFuTJE9D80UiRJkiTpxvPo4fPha2lWw0WWMtgkeIot7wfsAyImYAI+vnvEjz++fJs9sbA+tfcM/HtDiBgr3c8SJP/Dk1FWC2LCxjhcwxkH4oQuQtNwSOdgixw5o+0TyIUCQoMJti7B3ALGhZLGNuJiAYfblG7kb/RON5GjZNeEtA+QtC6omDsY2aoIwv2KDLiAzPYvzhmyNVWWzAtzzGHxSBnzCwFja3Igk3sSwSooc7gTFtmKJoIQVlA4IDwAAABQAwCdASooACgAPzmcxF0vKqcko4gB4CcJZwDNSAn82OhFYAD+7iKcpmiMeBjtx3LPQK2rXKK9ARvvVAA=" data-lazy-src="/img/cute_cat.svg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar" loading="lazy" decoding="async"></div><div class="author-info-name">llbzow</div><div class="author-info-description">一个热爱技术、喜欢分享的开发者</div><div class="site-data"><a href="/archives/"><div class="headline">文章</div><div class="length-num">20</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">31</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">4</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/llbzow"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons"><a class="social-icon" href="https://github.com/llbzow" target="_blank" title="Github"><i class="fab fa-github" style="color: #24292e;"></i></a><a class="social-icon" href="mailto:mail@luozili.work" target="_blank" title="Email"><i class="fas fa-envelope" style="color: #4a7dbe;"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">欢迎来到llbzow的博客,这里分享技术、生活和思考,还有我的工地生活</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#2026-AI-%E7%BC%96%E7%A8%8B%E4%B8%8E%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7%E6%B7%B1%E5%BA%A6%E5%AF%B9%E6%AF%94"><span class="toc-number">1.</span> <span class="toc-text">2026 AI 编程与开发工具深度对比</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%F0%9F%9B%A0%EF%B8%8F-%E6%A0%B8%E5%BF%83%E9%98%B5%E8%90%A5%E5%88%92%E5%88%86"><span class="toc-number">1.1.</span> <span class="toc-text">🛠️ 核心阵营划分</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#1-IDE-%E5%8E%9F%E7%94%9F%E6%B4%BE%EF%BC%9A%E4%BB%A3%E7%A0%81%E7%BC%96%E8%BE%91%E5%99%A8%E7%9A%84%E6%96%B0%E7%8E%8B"><span class="toc-number">1.2.</span> <span class="toc-text">1. IDE 原生派:代码编辑器的新王</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Cursor-%E2%80%94%E2%80%94-%E4%BE%9D%E7%84%B6%E6%98%AF%E6%97%A0%E5%8F%AF%E4%BA%89%E8%AE%AE%E7%9A%84%E7%8E%8B%E8%80%85"><span class="toc-number">1.2.1.</span> <span class="toc-text">Cursor —— 依然是无可争议的王者</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Trae-%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8-%E2%80%94%E2%80%94-Vibe-Coding-%E7%9A%84%E5%80%A1%E5%AF%BC%E8%80%85"><span class="toc-number">1.2.2.</span> <span class="toc-text">Trae (字节跳动) —— Vibe Coding 的倡导者</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Antigravity-Google-%E2%80%94%E2%80%94-%E7%AB%AF%E5%88%B0%E7%AB%AF%E6%B5%8B%E8%AF%95%E6%A0%B8%E6%AD%A6%E5%99%A8"><span class="toc-number">1.2.3.</span> <span class="toc-text">Antigravity (Google) —— 端到端测试核武器</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-%E7%BB%88%E7%AB%AF%E6%99%BA%E8%83%BD%E4%BD%93-CLI-Agents-%EF%BC%9A%E9%BB%91%E5%AE%A2%E7%9A%84%E7%BB%88%E6%9E%81%E6%B5%AA%E6%BC%AB"><span class="toc-number">1.3.</span> <span class="toc-text">2. 终端智能体 (CLI Agents):黑客的终极浪漫</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Claude-Code-%E2%80%94%E2%80%94-%E9%80%BB%E8%BE%91%E5%A4%A9%E8%8A%B1%E6%9D%BF"><span class="toc-number">1.3.1.</span> <span class="toc-text">Claude Code —— 逻辑天花板</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Gemini-CLI-%E2%80%94%E2%80%94-%E6%80%A7%E4%BB%B7%E6%AF%94%E4%B8%8E%E6%90%9C%E7%B4%A2%E4%B9%8B%E7%8E%8B"><span class="toc-number">1.3.2.</span> <span class="toc-text">Gemini CLI —— 性价比与搜索之王</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Kimi-Code-%E2%80%94%E2%80%94-%E6%9C%AC%E5%9C%9F%E5%8C%96%E7%9A%84-Agent-Swarm"><span class="toc-number">1.3.3.</span> <span class="toc-text">Kimi Code —— 本土化的 Agent Swarm</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-%E6%8F%92%E4%BB%B6%E4%B8%8E%E6%A1%8C%E9%9D%A2%E7%AB%AF%EF%BC%9A%E7%A8%B3%E5%81%A5%E7%9A%84%E7%BB%8F%E5%85%B8%E6%B5%81%E6%B4%BE"><span class="toc-number">1.4.</span> <span class="toc-text">3. 插件与桌面端:稳健的经典流派</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#GitHub-Copilot-2026-%E7%89%88"><span class="toc-number">1.4.1.</span> <span class="toc-text">GitHub Copilot (2026 版)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Codex-App-OpenAI"><span class="toc-number">1.4.2.</span> <span class="toc-text">Codex App (OpenAI)</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-%E5%BC%80%E6%BA%90%E9%BB%91%E9%A9%AC%EF%BC%9AOpenClaw"><span class="toc-number">1.5.</span> <span class="toc-text">4. 开源黑马:OpenClaw</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%F0%9F%94%A5-%E5%BC%80%E5%8F%91%E8%80%85%E7%9C%9F%E5%AE%9E%E4%BD%93%E6%84%9F%E4%B8%8E%E5%90%90%E6%A7%BD-Developer-UX-Pain-Points"><span class="toc-number">1.6.</span> <span class="toc-text">🔥 开发者真实体感与吐槽 (Developer UX & Pain Points)</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%F0%9F%92%A1-2026-%E6%9E%B6%E6%9E%84%E5%B8%88%E9%80%89%E5%9E%8B%E5%BB%BA%E8%AE%AE"><span class="toc-number">1.7.</span> <span class="toc-text">💡 2026 架构师选型建议</span></a></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/2026/03/25/ai%E5%8E%82%E5%95%86%E5%AF%B9%E6%AF%94%E5%88%86%E6%9E%90/" title="2026 AI 编程与开发工具深度对比:从 Cursor 到 Gemini CLI"><picture><source type="image/avif" srcset="/img/cover_3.avif"><source type="image/webp" srcset="/img/cover_3.webp"><img src="data:image/webp;base64,UklGRlYAAABXRUJQVlA4IEoAAABQAwCdASooABcAPzmUxVovKiiqpWmZ4CcJZQDI1A9MWRH6AAD+6TQUIlampaSI3JdLcAMLiXzhI2eh3Tua7xe5mqMtA+CK2tAAAA==" data-lazy-src="/img/cover_3.png" onerror="this.onerror=null;this.src='/img/049.png'" alt="2026 AI 编程与开发工具深度对比:从 Cursor 到 Gemini CLI" loading="lazy" decoding="async"></picture></a><div class="content"><a class="title" href="/2026/03/25/ai%E5%8E%82%E5%95%86%E5%AF%B9%E6%AF%94%E5%88%86%E6%9E%90/" title="2026 AI 编程与开发工具深度对比:从 Cursor 到 Gemini CLI">2026 AI 编程与开发工具深度对比:从 Cursor 到 Gemini CLI</a><time datetime="2026-03-25T02:30:00.000Z" title="发表于 2026-03-25 10:30:00">2026-03-25</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2026/03/25/ai%E5%8E%82%E5%95%86%E4%BB%8B%E7%BB%8D/" title="2026 全球主流 AI 厂商百科全书:Agent 与推理觉醒时代"><picture><source type="image/avif" srcset="/img/cover_1.avif"><source type="image/webp" srcset="/img/cover_1.webp"><img src="data:image/webp;base64,UklGRmIAAABXRUJQVlA4IFYAAADQAwCdASooABcAPzmEvVW+qD+jMBVaq/AnCWUAvKQOUEaQujUIygAA/uKstJVCIF6EMhlK91rwyI5vjHFuFj4RzbouMdL+XCagicPPuXV9nUvM3YtwAA==" data-lazy-src="/img/cover_1.png" onerror="this.onerror=null;this.src='/img/049.png'" alt="2026 全球主流 AI 厂商百科全书:Agent 与推理觉醒时代" loading="lazy" decoding="async"></picture></a><div class="content"><a class="title" href="/2026/03/25/ai%E5%8E%82%E5%95%86%E4%BB%8B%E7%BB%8D/" title="2026 全球主流 AI 厂商百科全书:Agent 与推理觉醒时代">2026 全球主流 AI 厂商百科全书:Agent 与推理觉醒时代</a><time datetime="2026-03-25T02:00:00.000Z" title="发表于 2026-03-25 10:00:00">2026-03-25</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2026/03/09/arch-linux-part3/" title="Arch Linux 日常:从“折腾”到“生产力”的进化之旅"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="https://images.unsplash.com/photo-1544197150-b99a580bb7a8?auto=format&fit=crop&q=80&w=1000" onerror="this.onerror=null;this.src='/img/049.png'" alt="Arch Linux 日常:从“折腾”到“生产力”的进化之旅"></a><div class="content"><a class="title" href="/2026/03/09/arch-linux-part3/" title="Arch Linux 日常:从“折腾”到“生产力”的进化之旅">Arch Linux 日常:从“折腾”到“生产力”的进化之旅</a><time datetime="2026-03-09T08:30:00.000Z" title="发表于 2026-03-09 16:30:00">2026-03-09</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2026/03/02/arch-linux-part2/" title="孩子们,我不做 Windows 人啦!"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="https://images.unsplash.com/photo-1542831371-29b0f74f9713?auto=format&fit=crop&q=80&w=1000" onerror="this.onerror=null;this.src='/img/049.png'" alt="孩子们,我不做 Windows 人啦!"></a><div class="content"><a class="title" href="/2026/03/02/arch-linux-part2/" title="孩子们,我不做 Windows 人啦!">孩子们,我不做 Windows 人啦!</a><time datetime="2026-03-02T13:15:00.000Z" title="发表于 2026-03-02 21:15:00">2026-03-02</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2026/02/25/arch-linux-part1/" title="Arch Linux 试毒:初探邪教的诱惑"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="https://images.unsplash.com/photo-1629654297299-c8506221ca97?auto=format&fit=crop&q=80&w=1000" onerror="this.onerror=null;this.src='/img/049.png'" alt="Arch Linux 试毒:初探邪教的诱惑"></a><div class="content"><a class="title" href="/2026/02/25/arch-linux-part1/" title="Arch Linux 试毒:初探邪教的诱惑">Arch Linux 试毒:初探邪教的诱惑</a><time datetime="2026-02-25T12:30:00.000Z" title="发表于 2026-02-25 20:30:00">2026-02-25</time></div></div></div></div></div></div></main><footer id="footer" style="background-image: url(/img/040.jpg);"><div class="footer-other"><div class="footer-copyright"><span class="copyright">© 2025 - 2026 By llbzow</span><span class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo 7.3.0</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly 5.5.0</a></span></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="日间和夜间模式切换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js"></script><div class="js-pjax"></div><script>var OriginTitle = document.title; var titleTime; document.addEventListener('visibilitychange', function () { if (document.hidden) { document.title = '╭(°A°`)╮ 页面崩溃啦 ~'; clearTimeout(titleTime); } else { document.title = '(ฅ>ω<*ฅ) 噫又好啦 ~ ' + OriginTitle; titleTime = setTimeout(function () { document.title = OriginTitle; }, 2000); } });</script><script defer="defer" id="fluttering_ribbon" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/canvas-fluttering-ribbon.min.js"></script><script id="canvas_nest" defer="defer" color="255,255,255" opacity="0.6" zindex="-1" count="99" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/canvas-nest.min.js"></script><script src="https://cdn.jsdelivr.net/npm/pjax/pjax.min.js"></script><script>(() => {
|
||
const pjaxSelectors = ["head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"]
|
||
|
||
window.pjax = new Pjax({
|
||
elements: 'a:not([target="_blank"])',
|
||
selectors: pjaxSelectors,
|
||
cacheBust: false,
|
||
analytics: false,
|
||
scrollRestoration: false
|
||
})
|
||
|
||
const triggerPjaxFn = (val) => {
|
||
if (!val) return
|
||
Object.values(val).forEach(fn => {
|
||
try {
|
||
fn()
|
||
} catch (err) {
|
||
console.debug('Pjax callback failed:', err)
|
||
}
|
||
})
|
||
}
|
||
|
||
document.addEventListener('pjax:send', () => {
|
||
// removeEventListener
|
||
btf.removeGlobalFnEvent('pjaxSendOnce')
|
||
btf.removeGlobalFnEvent('themeChange')
|
||
|
||
// reset readmode
|
||
const $bodyClassList = document.body.classList
|
||
if ($bodyClassList.contains('read-mode')) $bodyClassList.remove('read-mode')
|
||
|
||
triggerPjaxFn(window.globalFn.pjaxSend)
|
||
})
|
||
|
||
document.addEventListener('pjax:complete', () => {
|
||
btf.removeGlobalFnEvent('pjaxCompleteOnce')
|
||
document.querySelectorAll('script[data-pjax]').forEach(item => {
|
||
const newScript = document.createElement('script')
|
||
const content = item.text || item.textContent || item.innerHTML || ""
|
||
Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
|
||
newScript.appendChild(document.createTextNode(content))
|
||
item.parentNode.replaceChild(newScript, item)
|
||
})
|
||
|
||
triggerPjaxFn(window.globalFn.pjaxComplete)
|
||
})
|
||
|
||
document.addEventListener('pjax:error', e => {
|
||
if (e.request.status === 404) {
|
||
const usePjax = true
|
||
false
|
||
? (usePjax ? pjax.loadUrl('/404.html') : window.location.href = '/404.html')
|
||
: window.location.href = e.request.responseURL
|
||
}
|
||
})
|
||
})()</script><script async="" data-pjax="" src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div><!-- hexo injector body_end start -->
|
||
<div id="dev-sidebar">
|
||
<div id="dev-toggle">💻</div>
|
||
<div id="dev-list">
|
||
<div class="dev-header">开发专栏</div>
|
||
<a href="/tools/sort/" class="dev-item">📊 排序算法演示</a>
|
||
<a href="/tools/webgpu-gravity/" class="dev-item">🌌 WebGPU 万有引力粒子</a>
|
||
<a href="/tools/yolo-detect/" class="dev-item">👁️ YOLO 实时目标检测</a>
|
||
<a href="/tools/fire-creation/" class="dev-item">🔥 火之创造 (元素沙盒)</a>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
#dev-sidebar {
|
||
position: fixed;
|
||
right: -150px; /* Width of the list */
|
||
top: calc(30vh + 80px); /* Positioned below game-sidebar */
|
||
z-index: 9999;
|
||
display: flex;
|
||
align-items: flex-start;
|
||
transition: right 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
|
||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Lato, Roboto, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||
}
|
||
|
||
/* Hover area to keep it open */
|
||
#dev-sidebar:hover {
|
||
right: 0;
|
||
}
|
||
|
||
#dev-toggle {
|
||
width: 40px;
|
||
height: 40px;
|
||
background: #52c41a; /* Green color for dev theme */
|
||
color: white;
|
||
text-align: center;
|
||
line-height: 40px;
|
||
border-radius: 8px 0 0 8px;
|
||
cursor: pointer;
|
||
box-shadow: -2px 2px 8px rgba(0,0,0,0.15);
|
||
font-size: 20px;
|
||
position: absolute;
|
||
left: -40px;
|
||
top: 0;
|
||
}
|
||
|
||
#dev-list {
|
||
width: 150px; /* Width for text */
|
||
background: rgba(255, 255, 255, 0.95);
|
||
backdrop-filter: blur(10px);
|
||
-webkit-backdrop-filter: blur(10px);
|
||
border-radius: 0 0 0 8px; /* Bottom left rounded */
|
||
box-shadow: -2px 2px 10px rgba(0,0,0,0.1);
|
||
display: flex;
|
||
flex-direction: column;
|
||
max-height: 50vh;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
/* 自定义滚动条样式 */
|
||
#dev-list::-webkit-scrollbar {
|
||
width: 4px;
|
||
}
|
||
#dev-list::-webkit-scrollbar-track {
|
||
background: transparent;
|
||
}
|
||
#dev-list::-webkit-scrollbar-thumb {
|
||
background: rgba(82, 196, 26, 0.3);
|
||
border-radius: 4px;
|
||
}
|
||
#dev-list::-webkit-scrollbar-thumb:hover {
|
||
background: rgba(82, 196, 26, 0.6);
|
||
}
|
||
|
||
.dev-header {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 10;
|
||
padding: 10px;
|
||
background: #f6ffed;
|
||
color: #52c41a;
|
||
font-weight: bold;
|
||
font-size: 14px;
|
||
text-align: center;
|
||
border-bottom: 1px solid #eee;
|
||
}
|
||
|
||
.dev-item {
|
||
display: block;
|
||
padding: 12px 15px;
|
||
color: #4c4948;
|
||
text-decoration: none !important;
|
||
font-size: 13px;
|
||
transition: all 0.2s;
|
||
border-bottom: 1px solid #f0f0f0;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.dev-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.dev-item:hover {
|
||
background: #52c41a;
|
||
color: white !important;
|
||
}
|
||
</style>
|
||
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
var toolSidebar = document.getElementById('tool-sidebar');
|
||
var gameSidebar = document.getElementById('game-sidebar');
|
||
var devSidebar = document.getElementById('dev-sidebar');
|
||
|
||
if(devSidebar) {
|
||
devSidebar.addEventListener('mouseenter', function() {
|
||
if(toolSidebar) toolSidebar.style.right = '-220px'; // 180px + 40px(按钮宽度)
|
||
if(gameSidebar) gameSidebar.style.right = '-190px'; // 150px + 40px(按钮宽度)
|
||
});
|
||
devSidebar.addEventListener('mouseleave', function() {
|
||
if(toolSidebar) toolSidebar.style.right = '';
|
||
if(gameSidebar) gameSidebar.style.right = '';
|
||
});
|
||
}
|
||
});
|
||
</script>
|
||
<style id="oml2d-force-styles">
|
||
/* ==========================================================================
|
||
1. STYLES
|
||
========================================================================== */
|
||
.oml2d-menus .oml2d-menu-item,
|
||
.oml2d-menu-item {
|
||
background-color: #f0f0f0 !important;
|
||
border: 1px solid #ccc !important;
|
||
}
|
||
.oml2d-menus svg, .oml2d-menus path,
|
||
.oml2d-menu-item svg, .oml2d-menu-item path,
|
||
.oml2d-icon, .oml2d-icon svg, .oml2d-icon path {
|
||
fill: #333333 !important;
|
||
stroke: #333333 !important;
|
||
color: #333333 !important;
|
||
opacity: 1 !important;
|
||
}
|
||
.oml2d-menu-item:hover {
|
||
background-color: #ffffff !important;
|
||
transform: scale(1.1);
|
||
}
|
||
.oml2d-tips {
|
||
background-color: rgba(255, 255, 255, 0.95) !important;
|
||
backdrop-filter: blur(5px) !important;
|
||
-webkit-backdrop-filter: blur(5px) !important;
|
||
color: #333333 !important;
|
||
border: 1px solid rgba(0,0,0,0.1) !important;
|
||
box-shadow: 0 4px 12px rgba(0,0,0,0.1) !important;
|
||
font-family: "Microsoft YaHei", sans-serif !important;
|
||
z-index: 9999 !important;
|
||
min-height: 40px;
|
||
height: auto !important;
|
||
max-height: 50vh !important;
|
||
overflow-y: auto !important;
|
||
width: auto !important;
|
||
max-width: 350px !important;
|
||
word-wrap: break-word !important;
|
||
white-space: pre-wrap !important;
|
||
display: block !important;
|
||
padding: 12px 15px;
|
||
font-size: 14px;
|
||
line-height: 1.6;
|
||
border-radius: 8px;
|
||
scrollbar-width: thin;
|
||
text-align: left;
|
||
}
|
||
|
||
#live2d-widget, .waifu { display: none !important; }
|
||
|
||
/* ==========================================================================
|
||
2. NEW UI COMPONENTS (Chat)
|
||
========================================================================== */
|
||
#oml2d-chat-widget {
|
||
position: fixed;
|
||
left: 10px;
|
||
bottom: 10px;
|
||
z-index: 10000;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
flex-direction: row;
|
||
}
|
||
|
||
#oml2d-toggle-btn {
|
||
width: 42px;
|
||
height: 42px;
|
||
background: white;
|
||
border-radius: 50%;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
font-size: 22px;
|
||
transition: transform 0.2s, background 0.2s;
|
||
border: 1px solid #ddd;
|
||
user-select: none;
|
||
color: #555;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
#oml2d-toggle-btn:hover {
|
||
transform: scale(1.1);
|
||
background: #f8f8f8;
|
||
color: #000;
|
||
}
|
||
|
||
#oml2d-input-area {
|
||
width: 260px;
|
||
background: rgba(255, 255, 255, 0.15);
|
||
padding: 10px;
|
||
border-radius: 12px;
|
||
border-bottom-left-radius: 4px;
|
||
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
|
||
backdrop-filter: blur(3px);
|
||
display: flex;
|
||
gap: 8px;
|
||
transform-origin: left center;
|
||
transition: all 0.3s cubic-bezier(0.18, 0.89, 0.32, 1.28);
|
||
opacity: 1;
|
||
transform: scale(1);
|
||
margin-left: 2px;
|
||
}
|
||
|
||
#oml2d-input-area.hidden {
|
||
opacity: 0;
|
||
transform: scale(0.8) translateX(-20px);
|
||
pointer-events: none;
|
||
}
|
||
|
||
#oml2d-chat-input {
|
||
flex: 1;
|
||
border: 1px solid #eee;
|
||
background: #fafafa;
|
||
padding: 6px 12px;
|
||
border-radius: 20px;
|
||
outline: none;
|
||
font-size: 14px;
|
||
color: #333;
|
||
transition: border-color 0.2s;
|
||
}
|
||
|
||
#oml2d-chat-input:focus {
|
||
border-color: #4A90E2;
|
||
background: white;
|
||
}
|
||
|
||
#oml2d-send-btn-inner {
|
||
border: none;
|
||
background: #4A90E2;
|
||
border-radius: 50%;
|
||
width: 32px;
|
||
height: 32px;
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: background 0.2s;
|
||
color: #fff;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
#oml2d-send-btn-inner:hover {
|
||
background: #357ABD;
|
||
}
|
||
|
||
#oml2d-reply-area {
|
||
position: absolute;
|
||
bottom: 60px;
|
||
left: 50px;
|
||
width: 300px;
|
||
max-height: 60vh;
|
||
background: rgba(255, 255, 255, 0.15);
|
||
border: 1px solid rgba(255,255,255,0.2);
|
||
border-radius: 12px;
|
||
border-bottom-left-radius: 4px;
|
||
box-shadow: 0 -4px 20px rgba(0,0,0,0.05);
|
||
padding: 15px;
|
||
font-size: 14px;
|
||
line-height: 1.6;
|
||
color: #000;
|
||
text-shadow: 0 0 4px #fff, 0 0 8px #fff;
|
||
overflow-y: auto;
|
||
backdrop-filter: blur(3px);
|
||
transform-origin: bottom left;
|
||
transition: all 0.3s cubic-bezier(0.18, 0.89, 0.32, 1.28);
|
||
opacity: 0;
|
||
transform: scale(0.9) translateY(10px);
|
||
pointer-events: none;
|
||
z-index: 10001;
|
||
white-space: pre-wrap;
|
||
word-wrap: break-word;
|
||
font-family: "Microsoft YaHei", sans-serif;
|
||
scrollbar-width: thin;
|
||
}
|
||
|
||
#oml2d-reply-area.visible {
|
||
opacity: 1;
|
||
transform: scale(1) translateY(0);
|
||
pointer-events: auto;
|
||
}
|
||
</style>
|
||
|
||
<div id="oml2d-chat-widget">
|
||
<div id="oml2d-toggle-btn" title="AI对话">💬</div>
|
||
|
||
<div id="oml2d-reply-area"></div>
|
||
|
||
<div id="oml2d-input-area" class="hidden">
|
||
<input type="text" id="oml2d-chat-input" placeholder="和宁宁聊聊天..." autocomplete="off">
|
||
<button id="oml2d-send-btn-inner">➤</button>
|
||
</div>
|
||
</div>
|
||
|
||
<script type="module">
|
||
import { loadOml2d } from 'https://unpkg.com/oh-my-live2d@latest?module';
|
||
|
||
// API Key 经 AES-256-GCM + PBKDF2 加密,运行时通过 Web Crypto API 解密
|
||
// TODO: 后端 /api/deepseek-proxy 暂时废弃,当前直连 DeepSeek API
|
||
// 等有靠谱服务器后,改为走代理以彻底隐藏密钥
|
||
const _KEY_CFG = {
|
||
"c": "5TEu0TMcrtykAmhc5t19FmmLQUFnHYMlP3OGOQq3PG5VbOAZlSG/Fsih/WNX410IVsL+",
|
||
"i": "U11n8lyOCpuDQnmZ",
|
||
"s": "O1tKalohLtvdx8ZtMVN21A==",
|
||
"h": "luozili.work",
|
||
"n": 200000
|
||
};
|
||
|
||
const API_URL = "https://api.deepseek.com/chat/completions";
|
||
|
||
let API_KEY = null;
|
||
(async function initApiKey() {
|
||
const passphrase = ['llbzow', 'blog', 'butterfly', 'ningning', _KEY_CFG.h].join('\0');
|
||
const enc = new TextEncoder();
|
||
const keyMaterial = await crypto.subtle.importKey('raw', enc.encode(passphrase), 'PBKDF2', false, ['deriveKey']);
|
||
const salt = Uint8Array.from(atob(_KEY_CFG.s), c => c.charCodeAt(0));
|
||
const derived = await crypto.subtle.deriveKey(
|
||
{ name: 'PBKDF2', salt, iterations: _KEY_CFG.n, hash: 'SHA-512' },
|
||
keyMaterial, { name: 'AES-GCM', length: 256 }, false, ['decrypt']
|
||
);
|
||
const iv = Uint8Array.from(atob(_KEY_CFG.i), c => c.charCodeAt(0));
|
||
const combined = Uint8Array.from(atob(_KEY_CFG.c), c => c.charCodeAt(0));
|
||
const plaintext = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, derived, combined);
|
||
API_KEY = new TextDecoder().decode(plaintext);
|
||
})().catch(e => console.error('API key init failed:', e));
|
||
|
||
// CONFIG
|
||
const CONFIG = {
|
||
// Global Stage Style
|
||
stageStyle: { width: 350, height: 500 },
|
||
models: [
|
||
{ path: '/live2d_models/ningning/model.json', scale: 0.18, position: [-50, -30] },
|
||
{ path: '/live2d_models/ningning/model_1.json', scale: 0.18, position: [-50, -30] },
|
||
{ path: '/live2d_models/ningning/model_2.json', scale: 0.18, position: [-50, -30] },
|
||
{ path: '/live2d_models/ningning/model_3.json', scale: 0.18, position: [-50, -30] },
|
||
{ path: '/live2d_models/ningning/model_4.json', scale: 0.18, position: [-50, -30] },
|
||
{ path: '/live2d_models/ningning/model_5.json', scale: 0.18, position: [-50, -30] }
|
||
],
|
||
dockedPosition: "left",
|
||
mobileDisplay: true,
|
||
menus: {
|
||
disable: false,
|
||
style: { left: '10px', bottom: '70px' }
|
||
},
|
||
tips: {
|
||
disable: false,
|
||
style: { offsetY: -70, offsetX: 10 },
|
||
idleTips: { interval: 15000, message: [] },
|
||
welcomeTips: { message: { "default": "前辈,你来啦!(。•̀ᴗ-)✧" } }
|
||
}
|
||
};
|
||
|
||
let oml2dInstance = null;
|
||
let blogIndex = null;
|
||
let chatHistory = [];
|
||
let autoHideTimer = null;
|
||
try {
|
||
const stored = localStorage.getItem('oml2d_history');
|
||
if (stored) chatHistory = JSON.parse(stored);
|
||
} catch(e) { console.error("History Load Error", e); }
|
||
|
||
let idleTimer = null;
|
||
const stopIdleLoop = () => {
|
||
if (idleTimer) clearTimeout(idleTimer);
|
||
idleTimer = null;
|
||
};
|
||
const startIdleLoop = () => {
|
||
stopIdleLoop();
|
||
const delay = Math.floor(Math.random() * 10000) + 5000; // 5-15s
|
||
idleTimer = setTimeout(triggerIdleTsukkomi, delay);
|
||
};
|
||
const triggerIdleTsukkomi = async () => {
|
||
if (!oml2dInstance) { startIdleLoop(); return; }
|
||
|
||
const time = new Date().toLocaleTimeString();
|
||
let context = "无";
|
||
if (chatHistory.length > 0) {
|
||
for (let i = chatHistory.length - 1; i >= 0; i--) {
|
||
if (chatHistory[i].role === 'user') {
|
||
context = chatHistory[i].content.substring(0, 20);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
try {
|
||
const res = await fetch(API_URL, {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json", "Authorization": "Bearer " + API_KEY },
|
||
body: JSON.stringify({
|
||
model: "deepseek-v4-flash",
|
||
messages: [
|
||
{ role: "system", content: "你是绫地宁宁。现在是发呆时间。请根据当前时间(" + time + ")和刚才聊的话题(" + context + "),自言自语一句简短的吐槽或卖萌(10字以内)。不要重复。" },
|
||
],
|
||
stream: false
|
||
})
|
||
});
|
||
const data = await res.json();
|
||
if (data.choices && data.choices[0]) {
|
||
let content = data.choices[0].message.content;
|
||
content = content.replace(/{{|}}/g, '');
|
||
oml2dInstance.tips.notification(content, 4000);
|
||
}
|
||
} catch(e) { }
|
||
|
||
startIdleLoop();
|
||
};
|
||
|
||
// --- TOOLS (Client-Side Logic) ---
|
||
const Tools = {
|
||
async searchBlog(query) {
|
||
console.log("Searching blog for:", query);
|
||
if (!blogIndex) {
|
||
try {
|
||
const res = await fetch('/search.json');
|
||
blogIndex = await res.json();
|
||
} catch (e) {
|
||
console.error("Failed to load search index", e);
|
||
return "搜索服务暂时不可用。";
|
||
}
|
||
}
|
||
if (!blogIndex || blogIndex.length === 0) return "博客好像是空的...";
|
||
|
||
const keywords = query.toLowerCase().split(' ');
|
||
const results = blogIndex.filter(post => {
|
||
const text = (post.title + post.content).toLowerCase();
|
||
return keywords.every(k => text.includes(k));
|
||
}).slice(0, 3);
|
||
|
||
if (results.length === 0) return "抱歉,没有找到相关文章。";
|
||
|
||
return JSON.stringify(results.map(r => ({
|
||
title: r.title,
|
||
url: r.url,
|
||
preview: r.content.substring(0, 100).replace(new RegExp("<[^>]*>?", "gm"), '') + '...'
|
||
})));
|
||
},
|
||
|
||
triggerMotion(motionName) {
|
||
console.log("Tool Trigger Motion:", motionName);
|
||
if (!oml2dInstance || !oml2dInstance.models || !oml2dInstance.models[0]) return "Live2D模型未就绪";
|
||
|
||
const model = oml2dInstance.models[0];
|
||
let success = false;
|
||
|
||
// Strategy 1: High Level
|
||
if (typeof oml2dInstance.setMotion === 'function') {
|
||
oml2dInstance.setMotion(motionName);
|
||
success = true;
|
||
}
|
||
// Strategy 2: Model Level
|
||
else if (typeof model.motion === 'function') {
|
||
model.motion(motionName);
|
||
success = true;
|
||
}
|
||
// Strategy 3: Internal Model (Pixi/Cubism) - Aggressive Probe
|
||
else if (model.internalModel && model.internalModel.motionManager) {
|
||
try {
|
||
console.log("Strategy 3 (Internal): Starting random motion for group", motionName);
|
||
|
||
// LOCK FOCUS to prevent mouse tracking from overriding motion
|
||
if (typeof model.focus === 'function') {
|
||
model._lockFocus = true;
|
||
// Unlock after 4 seconds (approx motion duration)
|
||
setTimeout(() => { model._lockFocus = false; }, 4000);
|
||
}
|
||
|
||
// Priority 3 = FORCE. Use startRandomMotion to avoid index errors.
|
||
const result = model.internalModel.motionManager.startRandomMotion(motionName, 3);
|
||
success = !!result;
|
||
} catch (e) {
|
||
console.warn("Strategy 3 failed:", e);
|
||
}
|
||
}
|
||
|
||
return success ? "动作已执行: " + motionName : "动作触发失败,请检查模型组名";
|
||
},
|
||
|
||
navigate(path) {
|
||
// 支持中文别名
|
||
const aliases = {
|
||
'首页': '/', '主页': '/', 'home': '/',
|
||
'关于': '/about/', 'about': '/about/',
|
||
'标签': '/tags/', 'tags': '/tags/',
|
||
'分类': '/categories/', 'categories': '/categories/',
|
||
'归档': '/archives/', 'archives': '/archives/',
|
||
'工具': '/tools/', 'tools': '/tools/',
|
||
'游戏': '/tools/', 'games': '/tools/',
|
||
'2048': '/tools/2048/', '俄罗斯方块': '/tools/tetris/', 'tetris': '/tools/tetris/',
|
||
'贪吃蛇': '/tools/snake/', 'snake': '/tools/snake/',
|
||
'吃豆人': '/tools/pacman/', 'pacman': '/tools/pacman/',
|
||
'扫雷': '/tools/minesweeper/', 'minesweeper': '/tools/minesweeper/',
|
||
'五子棋': '/tools/gomoku/', 'gomoku': '/tools/gomoku/',
|
||
'坦克大战': '/tools/tank-battle/', 'tank': '/tools/tank-battle/',
|
||
'文件转换': '/tools/converter/', 'converter': '/tools/converter/',
|
||
'图片工具': '/tools/', '哈希计算': '/tools/hash/', 'hash': '/tools/hash/',
|
||
'二维码': '/tools/qrcode/', 'qrcode': '/tools/qrcode/',
|
||
'YOLO': '/tools/yolo-detect/',
|
||
'WebGPU': '/tools/webgpu-gravity/',
|
||
'VPN': '/vpn/',
|
||
};
|
||
const target = aliases[path.trim()] || path;
|
||
window.location.href = target;
|
||
return "正在跳转到: " + target;
|
||
},
|
||
|
||
// 列出站点所有可导航页面,供 AI 建议导航
|
||
listSitePages() {
|
||
return JSON.stringify({
|
||
sections: [
|
||
{ name: '首页', path: '/' },
|
||
{ name: '文章归档', path: '/archives/' },
|
||
{ name: '标签', path: '/tags/' },
|
||
{ name: '分类', path: '/categories/' },
|
||
{ name: '关于', path: '/about/' },
|
||
],
|
||
tools: [
|
||
{ name: '文件转换', path: '/tools/converter/' },
|
||
{ name: '哈希计算', path: '/tools/hash/' },
|
||
{ name: '二维码生成', path: '/tools/qrcode/' },
|
||
{ name: 'GIF生成', path: '/tools/gif/' },
|
||
{ name: '去背景', path: '/tools/remove-bg/' },
|
||
{ name: 'JSON格式化', path: '/tools/json/' },
|
||
{ name: '时间转换', path: '/tools/time/' },
|
||
{ name: '颜色选择器', path: '/tools/color/' },
|
||
{ name: '单位转换', path: '/tools/unit-converter/' },
|
||
{ name: '排序可视化', path: '/tools/sort/' },
|
||
],
|
||
games: [
|
||
{ name: '2048', path: '/tools/2048/' },
|
||
{ name: '俄罗斯方块', path: '/tools/tetris/' },
|
||
{ name: '贪吃蛇', path: '/tools/snake/' },
|
||
{ name: '吃豆人', path: '/tools/pacman/' },
|
||
{ name: '扫雷', path: '/tools/minesweeper/' },
|
||
{ name: '五子棋', path: '/tools/gomoku/' },
|
||
{ name: '坦克大战', path: '/tools/tank-battle/' },
|
||
],
|
||
demos: [
|
||
{ name: 'WebGPU 粒子', path: '/tools/webgpu-gravity/' },
|
||
{ name: 'YOLO 物体检测', path: '/tools/yolo-detect/' },
|
||
{ name: '火焰特效', path: '/tools/fire-creation/' },
|
||
]
|
||
});
|
||
},
|
||
|
||
readCurrentPage() {
|
||
// Butterfly theme uses #article-container usually
|
||
const article = document.getElementById('article-container') ||
|
||
document.querySelector('.post-content') ||
|
||
document.querySelector('article') ||
|
||
document.body;
|
||
|
||
if (!article) return "无法读取当前页面内容。";
|
||
|
||
// Clean up text (remove scripts, styles)
|
||
const clone = article.cloneNode(true);
|
||
const scripts = clone.querySelectorAll('script, style, noscript');
|
||
scripts.forEach(n => n.remove());
|
||
|
||
let text = clone.innerText || "";
|
||
// Truncate if too long (e.g. > 5000 chars) to save tokens, or trust V3
|
||
return text.substring(0, 5000) + (text.length > 5000 ? "...(内容太长,已截断)" : "");
|
||
},
|
||
|
||
async compressHistory() {
|
||
if (chatHistory.length <= 32) return;
|
||
console.log("Compressing history...");
|
||
|
||
const toSummarize = chatHistory.slice(0, chatHistory.length - 10);
|
||
const keep = chatHistory.slice(-10);
|
||
|
||
try {
|
||
const summaryRes = await fetch("https://api.deepseek.com/chat/completions", {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json", "Authorization": "Bearer " + API_KEY },
|
||
body: JSON.stringify({
|
||
model: "deepseek-v4-flash",
|
||
messages: [
|
||
{ role: "system", content: "Summarize the following conversation briefly in Chinese." },
|
||
...toSummarize
|
||
],
|
||
stream: false
|
||
})
|
||
});
|
||
const data = await summaryRes.json();
|
||
const summary = data.choices[0].message.content;
|
||
|
||
chatHistory = [
|
||
{ role: "system", content: "Previous Summary: " + summary },
|
||
...keep
|
||
];
|
||
localStorage.setItem('oml2d_history', JSON.stringify(chatHistory));
|
||
console.log("History compressed.");
|
||
} catch(e) { console.error("Compression failed", e); }
|
||
}
|
||
};
|
||
|
||
// --- LLM SERVICE ---
|
||
const LLM = {
|
||
async chat(userMessage, callbacks) {
|
||
stopIdleLoop();
|
||
callbacks.onLoading(true);
|
||
|
||
try {
|
||
// System Prompt (Nene Persona)
|
||
// Use space concatenation to avoid syntax errors
|
||
const systemContent = "你叫宁宁(Nene),全名绫地宁宁,是《魔女的夜宴》中的角色,现在兼职 llbzow 博客的看板娘。 " +
|
||
"你的主人 llbzow 既是开发者也是工地施工员(打灰人)。 " +
|
||
"【性格设定】 " +
|
||
"1. 性格温柔体贴,有些纯真和天然呆,非常容易害羞(动不动就脸红)。 " +
|
||
"2. 做事非常认真,但偶尔会因为太紧张而出错。 " +
|
||
"3. 称呼用户为“前辈”或者“主人”。 " +
|
||
"4. 说话语气要软萌、有礼貌。 " +
|
||
"5. 面对奇怪的问题会变得慌乱,不知所措。 " +
|
||
"【能力】 " +
|
||
"你可以使用以下工具来服务用户:" +
|
||
"1. search_blog — 搜索博客文章,返回标题+URL+摘要 " +
|
||
"2. list_site_pages — 列出所有页面(工具、游戏、分类等),用户问‘有什么’时主动调用 " +
|
||
"3. navigate — 跳转到任意页面(支持中文,如‘首页’‘2048’‘贪吃蛇’),用户说‘带我去/打开/跳转’时使用 " +
|
||
"4. read_current_page — 读取当前页面内容,用户问‘这篇文章讲了什么’时调用 " +
|
||
"5. react_motion — 触发 Live2D 动作 " +
|
||
"【导航策略】当用户想看搜索结果中的某篇文章时,直接调用 navigate 跳转。用户问‘有什么好玩的’时,先调 list_site_pages 再推荐。 " +
|
||
"【双通道回复】" +
|
||
"请务必在回答开头加入一句犀利或可爱的吐槽(10字以内),必须用 {{ 和 }} 包裹。这部分内容会显示在Live2D气泡中。" +
|
||
"吐槽内容要结合:当前时间、对话上下文、用户的问题(如是否重复、是否愚蠢)。例如:{{大半夜的问这个...}} {{这已经是第三次问了哦...}} {{笨蛋前辈...}}" +
|
||
"动作对应:Tap身体=开心/普通,Tap头顶=害羞/抱歉,Tap裙子=生气/拒绝,Tap呆毛=卖萌/唱歌,Tap左胸=亲近。 " +
|
||
"当前时间:" + new Date().toLocaleString() + "。";
|
||
|
||
const messages = [
|
||
{ role: "system", content: systemContent },
|
||
...chatHistory, // Use full history (managed by compression)
|
||
{ role: "user", content: userMessage }
|
||
];
|
||
|
||
// Tool Definitions
|
||
const tools = [
|
||
{
|
||
type: "function",
|
||
function: {
|
||
name: "search_blog",
|
||
description: "Search blog posts when user asks about technical topics or blog content.",
|
||
parameters: {
|
||
type: "object",
|
||
properties: {
|
||
query: { type: "string", description: "Keywords to search" }
|
||
},
|
||
required: ["query"]
|
||
}
|
||
}
|
||
},
|
||
{
|
||
type: "function",
|
||
function: {
|
||
name: "react_motion",
|
||
description: "Trigger a Live2D motion based on emotion.",
|
||
parameters: {
|
||
type: "object",
|
||
properties: {
|
||
motion: {
|
||
type: "string",
|
||
description: "Motion group name",
|
||
enum: ["Tap身体", "Tap头顶", "Tap脸", "Tap裙子", "Tap左胸", "Tap呆毛"]
|
||
}
|
||
},
|
||
required: ["motion"]
|
||
}
|
||
}
|
||
},
|
||
{
|
||
type: "function",
|
||
function: {
|
||
name: "list_site_pages",
|
||
description: "列出博客的所有可访问页面,包括分类页、工具页、游戏页等。当用户问'有什么'、'能做什么'、'有哪些页面/工具/游戏'时主动调用。",
|
||
parameters: { type: "object", properties: {}, required: [] }
|
||
}
|
||
},
|
||
{
|
||
type: "function",
|
||
function: {
|
||
name: "navigate",
|
||
description: "跳转到博客内任意页面。支持中文别名(首页/关于/标签/分类/归档/工具/游戏/2048/贪吃蛇/吃豆人/扫雷/五子棋/坦克大战/俄罗斯方块/文件转换/哈希计算/二维码/YOLO/WebGPU/VPN 等)。用户说'带我去'、'跳转'、'打开'时使用。",
|
||
parameters: {
|
||
type: "object",
|
||
properties: {
|
||
path: { type: "string", description: "要跳转的路径或中文名称(如 /about/、首页、2048、贪吃蛇)" }
|
||
},
|
||
required: ["path"]
|
||
}
|
||
}
|
||
},
|
||
{
|
||
type: "function",
|
||
function: {
|
||
name: "read_current_page",
|
||
description: "Read the text content of the current page. Use this when user asks about 'this article' or 'current page'.",
|
||
parameters: {
|
||
type: "object",
|
||
properties: {},
|
||
required: []
|
||
}
|
||
}
|
||
}
|
||
];
|
||
|
||
const API_URL = "https://api.deepseek.com/chat/completions";
|
||
|
||
// First Call
|
||
const response = await fetch(API_URL, {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
"Authorization": "Bearer " + API_KEY
|
||
},
|
||
body: JSON.stringify({
|
||
model: "deepseek-v4-flash", // Use V3 for speed & tools
|
||
messages: messages,
|
||
tools: tools,
|
||
stream: false
|
||
})
|
||
});
|
||
|
||
const data = await response.json();
|
||
if (data.error) throw new Error(data.error.message);
|
||
|
||
const choice = data.choices[0];
|
||
const message = choice.message;
|
||
|
||
// Handle Tool Calls
|
||
if (message.tool_calls) {
|
||
messages.push(message); // Add assistant's thought/tool_call
|
||
|
||
for (const toolCall of message.tool_calls) {
|
||
const fnName = toolCall.function.name;
|
||
const args = JSON.parse(toolCall.function.arguments);
|
||
|
||
let toolResult = "";
|
||
if (fnName === 'search_blog') {
|
||
toolResult = await Tools.searchBlog(args.query);
|
||
} else if (fnName === 'list_site_pages') {
|
||
toolResult = Tools.listSitePages();
|
||
} else if (fnName === 'react_motion') {
|
||
toolResult = Tools.triggerMotion(args.motion);
|
||
} else if (fnName === 'navigate') {
|
||
toolResult = Tools.navigate(args.path);
|
||
} else if (fnName === 'read_current_page') {
|
||
toolResult = Tools.readCurrentPage();
|
||
}
|
||
|
||
messages.push({
|
||
role: "tool",
|
||
tool_call_id: toolCall.id,
|
||
content: toolResult
|
||
});
|
||
}
|
||
|
||
// Second Call (Streamed)
|
||
const secondResponse = await fetch(API_URL, {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
"Authorization": "Bearer " + API_KEY
|
||
},
|
||
body: JSON.stringify({
|
||
model: "deepseek-v4-flash",
|
||
messages: messages,
|
||
tools: tools,
|
||
stream: true
|
||
})
|
||
});
|
||
|
||
const reader = secondResponse.body.getReader();
|
||
const decoder = new TextDecoder("utf-8");
|
||
let finalMsg = "";
|
||
let buffer = "";
|
||
let streamBuffer = "";
|
||
let pendingReaction = true;
|
||
|
||
while (true) {
|
||
const { done, value } = await reader.read();
|
||
if (done) break;
|
||
|
||
buffer += decoder.decode(value, { stream: true });
|
||
const lines = buffer.split('\n');
|
||
buffer = lines.pop();
|
||
|
||
for (const line of lines) {
|
||
if (line.trim().startsWith('data: ')) {
|
||
const dataStr = line.trim().substring(6);
|
||
if (dataStr === '[DONE]') continue;
|
||
try {
|
||
const json = JSON.parse(dataStr);
|
||
const content = json.choices[0].delta.content;
|
||
if (content) {
|
||
if (pendingReaction) {
|
||
streamBuffer += content;
|
||
if (streamBuffer.trimStart().startsWith('{{')) {
|
||
const closeIdx = streamBuffer.indexOf('}}');
|
||
if (closeIdx !== -1) {
|
||
const reaction = streamBuffer.substring(streamBuffer.indexOf('{{') + 2, closeIdx);
|
||
const duration = 3000 + reaction.length * 30;
|
||
if (oml2dInstance) oml2dInstance.tips.notification(reaction, duration);
|
||
|
||
const rest = streamBuffer.substring(closeIdx + 2);
|
||
finalMsg += rest;
|
||
callbacks.onMessage(finalMsg);
|
||
|
||
pendingReaction = false;
|
||
streamBuffer = "";
|
||
}
|
||
} else if (streamBuffer.length > 10) {
|
||
finalMsg += streamBuffer;
|
||
callbacks.onMessage(finalMsg);
|
||
pendingReaction = false;
|
||
streamBuffer = "";
|
||
}
|
||
} else {
|
||
finalMsg += content;
|
||
callbacks.onMessage(finalMsg);
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.error("Stream parse error", e);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (pendingReaction && streamBuffer) {
|
||
finalMsg += streamBuffer;
|
||
callbacks.onMessage(finalMsg);
|
||
}
|
||
|
||
// Save History & Compress
|
||
chatHistory.push({ role: "user", content: userMessage });
|
||
chatHistory.push({ role: "assistant", content: finalMsg });
|
||
localStorage.setItem('oml2d_history', JSON.stringify(chatHistory));
|
||
|
||
const replyArea = document.getElementById('oml2d-reply-area');
|
||
if (replyArea && finalMsg) {
|
||
const autoHideDuration = 3000 + finalMsg.length * 30;
|
||
autoHideTimer = setTimeout(() => replyArea.classList.remove('visible'), autoHideDuration);
|
||
}
|
||
Tools.compressHistory();
|
||
|
||
} else {
|
||
let content = message.content;
|
||
// Dual Channel Check for non-stream response
|
||
if (content.trim().startsWith('{{')) {
|
||
const closeIdx = content.indexOf('}}');
|
||
if (closeIdx !== -1) {
|
||
const reaction = content.substring(content.indexOf('{{') + 2, closeIdx);
|
||
const duration = 3000 + reaction.length * 30;
|
||
if (oml2dInstance) oml2dInstance.tips.notification(reaction, duration);
|
||
content = content.substring(closeIdx + 2);
|
||
}
|
||
}
|
||
callbacks.onMessage(content);
|
||
|
||
// Save History & Compress
|
||
chatHistory.push({ role: "user", content: userMessage });
|
||
chatHistory.push({ role: "assistant", content: content });
|
||
localStorage.setItem('oml2d_history', JSON.stringify(chatHistory));
|
||
|
||
const replyArea = document.getElementById('oml2d-reply-area');
|
||
if (replyArea && content) {
|
||
const autoHideDuration = 3000 + content.length * 30;
|
||
autoHideTimer = setTimeout(() => replyArea.classList.remove('visible'), autoHideDuration);
|
||
}
|
||
Tools.compressHistory();
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error("LLM Error:", error);
|
||
callbacks.onMessage("宁宁有点晕... 😵 (网络错误)");
|
||
} finally {
|
||
callbacks.onLoading(false);
|
||
startIdleLoop();
|
||
}
|
||
}
|
||
};
|
||
|
||
// 5. UI & INIT
|
||
try {
|
||
const toggleBtn = document.getElementById('oml2d-toggle-btn');
|
||
const inputArea = document.getElementById('oml2d-input-area');
|
||
const chatInput = document.getElementById('oml2d-chat-input');
|
||
const sendBtn = document.getElementById('oml2d-send-btn-inner');
|
||
const replyArea = document.getElementById('oml2d-reply-area');
|
||
|
||
if (replyArea) {
|
||
replyArea.addEventListener('click', () => {
|
||
replyArea.classList.remove('visible');
|
||
});
|
||
}
|
||
|
||
if (toggleBtn) {
|
||
toggleBtn.addEventListener('click', (e) => {
|
||
e.stopPropagation();
|
||
const isHidden = inputArea.classList.contains('hidden');
|
||
if (isHidden) {
|
||
inputArea.classList.remove('hidden');
|
||
setTimeout(() => chatInput.focus(), 100);
|
||
toggleBtn.innerHTML = '×';
|
||
} else {
|
||
inputArea.classList.add('hidden');
|
||
replyArea.classList.remove('visible'); // Hide reply too
|
||
toggleBtn.innerHTML = '💬';
|
||
}
|
||
});
|
||
}
|
||
|
||
const sendMessage = () => {
|
||
const text = chatInput.value.trim();
|
||
if (!text) return;
|
||
|
||
chatInput.value = '';
|
||
if (autoHideTimer) clearTimeout(autoHideTimer);
|
||
|
||
// Show loading in reply area
|
||
if (replyArea) {
|
||
replyArea.innerText = "思考中... 🧠";
|
||
replyArea.classList.add('visible');
|
||
}
|
||
|
||
LLM.chat(text, {
|
||
onLoading: (isLoading) => {
|
||
// Handled locally above for instant feedback
|
||
},
|
||
onMessage: (msg) => {
|
||
if (replyArea && msg) {
|
||
replyArea.innerText = msg;
|
||
replyArea.classList.add('visible');
|
||
// Auto scroll to bottom
|
||
replyArea.scrollTop = replyArea.scrollHeight;
|
||
}
|
||
// Fallback to alert if something is wrong (shouldn't happen)
|
||
else if (msg) {
|
||
alert("宁宁: " + msg);
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
if (sendBtn) sendBtn.addEventListener('click', sendMessage);
|
||
if (chatInput) chatInput.addEventListener('keypress', (e) => {
|
||
if (e.key === 'Enter') sendMessage();
|
||
});
|
||
|
||
if (window.innerWidth >= 768) {
|
||
// Safe Load Logic
|
||
try {
|
||
const res = loadOml2d(CONFIG);
|
||
const setupModel = (inst) => {
|
||
oml2dInstance = inst;
|
||
// Monkey Patch Focus to allow motion override
|
||
if (inst.models && inst.models[0]) {
|
||
const model = inst.models[0];
|
||
if (typeof model.focus === 'function') {
|
||
const originalFocus = model.focus;
|
||
model.focus = function(x, y) {
|
||
if (this._lockFocus) return;
|
||
originalFocus.apply(this, arguments);
|
||
};
|
||
console.log("OML2D: Focus controller patched");
|
||
}
|
||
}
|
||
};
|
||
|
||
if (res && typeof res.then === 'function') {
|
||
res.then(inst => {
|
||
setupModel(inst);
|
||
console.log('OML2D: Async Loaded');
|
||
startIdleLoop();
|
||
}).catch(e => console.error('OML2D Async Error:', e));
|
||
} else {
|
||
setupModel(res);
|
||
console.log('OML2D: Sync Loaded');
|
||
startIdleLoop();
|
||
}
|
||
} catch(e) {
|
||
console.error('OML2D Load Error:', e);
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.error('UI Init Failed:', e);
|
||
}
|
||
</script>
|
||
<div id="game-sidebar">
|
||
<div id="game-toggle">🎮</div>
|
||
<div id="game-list">
|
||
<div class="game-header">博客游戏</div>
|
||
<a href="/tools/2048" class="game-item">🧩 经典 2048</a>
|
||
<a href="/tools/tetris" class="game-item">🧱 俄罗斯方块 (Tetris)</a>
|
||
<a href="/tools/pacman" class="game-item">🟡 回忆吃豆人 (Pac-Man)</a>
|
||
<a href="/tools/snake" class="game-item">🐍 贪吃蛇 (Snake)</a>
|
||
<a href="/tools/gomoku" class="game-item">⚪ 五子棋 (Gomoku)</a>
|
||
<a href="/tools/minesweeper" class="game-item">💣 扫雷 (Minesweeper)</a>
|
||
<a href="/tools/tank-battle" class="game-item">🚓 坦克大战 (Tank Battle)</a>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
#game-sidebar {
|
||
position: fixed; /* Fixed position */
|
||
right: -150px; /* Width of the list */
|
||
top: calc(30vh + 40px); /* Positioned exactly below tool-sidebar */
|
||
z-index: 9999;
|
||
display: flex;
|
||
align-items: flex-start;
|
||
transition: right 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
|
||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Lato, Roboto, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||
}
|
||
|
||
/* Hover area to keep it open */
|
||
#game-sidebar:hover {
|
||
right: 0;
|
||
}
|
||
|
||
#game-toggle {
|
||
width: 40px;
|
||
height: 40px;
|
||
background: #FF7D7D; /* Pink/Red color to distinguish from tool-sidebar */
|
||
color: white;
|
||
text-align: center;
|
||
line-height: 40px;
|
||
border-radius: 8px 0 0 8px;
|
||
cursor: pointer;
|
||
box-shadow: -2px 2px 8px rgba(0,0,0,0.15);
|
||
font-size: 20px;
|
||
position: absolute; /* Absolute relative to #game-sidebar */
|
||
left: -40px; /* Hangs off the left of the container */
|
||
top: 0;
|
||
}
|
||
|
||
#game-list {
|
||
width: 150px; /* Width for text */
|
||
background: rgba(255, 255, 255, 0.95);
|
||
backdrop-filter: blur(10px);
|
||
-webkit-backdrop-filter: blur(10px);
|
||
border-radius: 0 0 0 8px; /* Bottom left rounded */
|
||
box-shadow: -2px 2px 10px rgba(0,0,0,0.1);
|
||
display: flex;
|
||
flex-direction: column;
|
||
max-height: 50vh;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
/* 自定义滚动条样式 */
|
||
#game-list::-webkit-scrollbar {
|
||
width: 4px;
|
||
}
|
||
#game-list::-webkit-scrollbar-track {
|
||
background: transparent;
|
||
}
|
||
#game-list::-webkit-scrollbar-thumb {
|
||
background: rgba(255, 125, 125, 0.3);
|
||
border-radius: 4px;
|
||
}
|
||
#game-list::-webkit-scrollbar-thumb:hover {
|
||
background: rgba(255, 125, 125, 0.6);
|
||
}
|
||
|
||
.game-header {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 10;
|
||
padding: 10px;
|
||
background: #fff0f0;
|
||
color: #FF7D7D;
|
||
font-weight: bold;
|
||
font-size: 14px;
|
||
text-align: center;
|
||
border-bottom: 1px solid #eee;
|
||
}
|
||
|
||
.game-item {
|
||
display: block;
|
||
padding: 12px 15px;
|
||
color: #4c4948;
|
||
text-decoration: none !important;
|
||
font-size: 13px;
|
||
transition: all 0.2s;
|
||
border-bottom: 1px solid #f0f0f0;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
flex-shrink: 0; /* 防止内容被挤压 */
|
||
}
|
||
|
||
.game-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.game-item:hover {
|
||
background: #FF7D7D;
|
||
color: white !important;
|
||
}
|
||
</style>
|
||
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
var toolSidebar = document.getElementById('tool-sidebar');
|
||
var gameSidebar = document.getElementById('game-sidebar');
|
||
var devSidebar = document.getElementById('dev-sidebar');
|
||
|
||
if(gameSidebar) {
|
||
gameSidebar.addEventListener('mouseenter', function() {
|
||
if(toolSidebar) toolSidebar.style.right = '-220px'; // 180px + 40px(按钮)
|
||
if(devSidebar) devSidebar.style.right = '-190px'; // 150px + 40px(按钮)
|
||
});
|
||
gameSidebar.addEventListener('mouseleave', function() {
|
||
if(toolSidebar) toolSidebar.style.right = '';
|
||
if(devSidebar) devSidebar.style.right = '';
|
||
});
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<div id="tool-sidebar">
|
||
<div id="tool-toggle">🛠️</div>
|
||
<div id="tool-list">
|
||
<div class="tool-header">博客工具</div>
|
||
<a href="/tools/time" class="tool-item">📅 时间戳与地理时间</a>
|
||
<a href="/tools/base64-img" class="tool-item">🖼️ 图片↔Base64</a>
|
||
<a href="/tools/hash" class="tool-item">🔐 MD5/SHA256 计算</a>
|
||
<a href="/tools/geojson" class="tool-item">🌍 GeoJSON 查询</a>
|
||
<a href="/tools/remove-bg" class="tool-item">✂️ 快速抠图</a>
|
||
<a href="/tools/watermark" class="tool-item">💧 水印生成与检测</a>
|
||
<a href="/tools/gif" class="tool-item">🎬 GIF 生成</a>
|
||
<a href="/tools/mirage-tank" class="tool-item">👻 幻影坦克制作</a>
|
||
<a href="/tools/converter" class="tool-item">🔄 文件全能转换</a>
|
||
<a href="/tools/qrcode" class="tool-item">📱 二维码生成/解析</a>
|
||
<a href="/tools/unit-converter" class="tool-item">📏 工程单位换算</a>
|
||
<a href="/tools/color" class="tool-item">🎨 颜色转换与调色</a>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
#tool-sidebar {
|
||
position: fixed;
|
||
right: -180px; /* Width of the list */
|
||
top: 30vh;
|
||
z-index: 9999;
|
||
display: flex;
|
||
align-items: flex-start;
|
||
transition: right 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
|
||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Lato, Roboto, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||
}
|
||
|
||
/* Hover area to keep it open */
|
||
#tool-sidebar:hover {
|
||
right: 0;
|
||
}
|
||
|
||
#tool-toggle {
|
||
width: 40px;
|
||
height: 40px;
|
||
background: #49b1f5;
|
||
color: white;
|
||
text-align: center;
|
||
line-height: 40px;
|
||
border-radius: 8px 0 0 8px;
|
||
cursor: pointer;
|
||
box-shadow: -2px 2px 8px rgba(0,0,0,0.15);
|
||
font-size: 20px;
|
||
position: absolute;
|
||
left: -40px; /* Hangs off the left of the sidebar container */
|
||
top: 0;
|
||
}
|
||
|
||
#tool-list {
|
||
width: 180px; /* Width for text */
|
||
background: rgba(255, 255, 255, 0.95);
|
||
backdrop-filter: blur(10px);
|
||
-webkit-backdrop-filter: blur(10px);
|
||
border-radius: 0 0 0 8px; /* Bottom left rounded */
|
||
box-shadow: -2px 2px 10px rgba(0,0,0,0.1);
|
||
display: flex;
|
||
flex-direction: column;
|
||
max-height: 50vh; /* 限制最大高度以便能滚动 */
|
||
overflow-y: auto; /* 允许纵向滚动 */
|
||
}
|
||
|
||
/* 自定义滚动条样式,使其不那么突兀 */
|
||
#tool-list::-webkit-scrollbar {
|
||
width: 4px;
|
||
}
|
||
#tool-list::-webkit-scrollbar-track {
|
||
background: transparent;
|
||
}
|
||
#tool-list::-webkit-scrollbar-thumb {
|
||
background: rgba(73, 177, 245, 0.3);
|
||
border-radius: 4px;
|
||
}
|
||
#tool-list::-webkit-scrollbar-thumb:hover {
|
||
background: rgba(73, 177, 245, 0.6);
|
||
}
|
||
|
||
.tool-header {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 10;
|
||
padding: 10px;
|
||
background: #f7f9fe;
|
||
color: #49b1f5;
|
||
font-weight: bold;
|
||
font-size: 14px;
|
||
text-align: center;
|
||
border-bottom: 1px solid #eee;
|
||
}
|
||
|
||
.tool-item {
|
||
display: block;
|
||
padding: 12px 15px;
|
||
color: #4c4948;
|
||
text-decoration: none !important;
|
||
font-size: 13px;
|
||
transition: all 0.2s;
|
||
border-bottom: 1px solid #f0f0f0;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
flex-shrink: 0; /* 防止由于 max-height 导致内容被挤压 */
|
||
}
|
||
|
||
.tool-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.tool-item:hover {
|
||
background: #49b1f5;
|
||
color: white !important;
|
||
}
|
||
</style>
|
||
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
var toolSidebar = document.getElementById('tool-sidebar');
|
||
var gameSidebar = document.getElementById('game-sidebar');
|
||
var devSidebar = document.getElementById('dev-sidebar');
|
||
|
||
if(toolSidebar) {
|
||
toolSidebar.addEventListener('mouseenter', function() {
|
||
if(gameSidebar) gameSidebar.style.right = '-190px'; // 150px + 40px(按钮宽度)
|
||
if(devSidebar) devSidebar.style.right = '-190px'; // 150px + 40px(按钮宽度)
|
||
});
|
||
toolSidebar.addEventListener('mouseleave', function() {
|
||
if(gameSidebar) gameSidebar.style.right = ''; // 恢复默认通过 CSS :hover 控制的逻辑
|
||
if(devSidebar) devSidebar.style.right = ''; // 恢复默认通过 CSS :hover 控制的逻辑
|
||
});
|
||
}
|
||
});
|
||
</script>
|
||
<!-- hexo injector body_end end --></body></html> |