<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>空缺</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>https://kqnb.me/</id>
  <link href="https://kqnb.me/" rel="alternate"/>
  <link href="https://kqnb.me/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, 空缺</rights>
  <subtitle>生命不息折腾不止</subtitle>
  <title>空缺的博客</title>
  <updated>2026-08-27T01:18:04.942Z</updated>
  <entry>
    <author>
      <name>空缺</name>
    </author>
    <category term="技术折腾" scheme="https://kqnb.me/categories/%E6%8A%80%E6%9C%AF%E6%8A%98%E8%85%BE/"/>
    <category term="教程" scheme="https://kqnb.me/tags/%E6%95%99%E7%A8%8B/"/>
    <category term="AI" scheme="https://kqnb.me/tags/AI/"/>
    <category term="Harness" scheme="https://kqnb.me/tags/Harness/"/>
    <category term="插件" scheme="https://kqnb.me/tags/%E6%8F%92%E4%BB%B6/"/>
    <content>
      <![CDATA[<blockquote><p>生命不息，折腾不止。上次说好的「写插件」来了——今天手把手给 dsh 的 Agent 造一个 IP 查询工具，让它多一门手艺。</p></blockquote><p>从基础安装到接中转站，dsh 已经跑起来了。但光会用别人的东西，那只是「用户」；能往里加自己的东西，才叫「玩家」。dsh 最迷人的地方就在这：<strong>一切皆插件</strong>，工具、模型、会话、UI 全都可以自己换。今天就兑现承诺，写第一个插件。</p><h2 id="一、先搞懂：dsh-的「一切皆插件」到底是啥"><a href="#一、先搞懂：dsh-的「一切皆插件」到底是啥" class="headerlink" title="一、先搞懂：dsh 的「一切皆插件」到底是啥"></a>一、先搞懂：dsh 的「一切皆插件」到底是啥</h2><p>DeepSeek Harness（简称 dsh）的核心设计就一句话：<strong>一切皆插件</strong>。模型适配器、工具、会话存储、Agent 循环、甚至 Web UI 的面板，全都是插件。底层由 Cordis 这个元框架负责加载、卸载和依赖解析，插件之间通过「服务」和「事件」协作。</p><p>所以插件不是外挂，它可以替换或扩展 Agent 的任何部分。理解了这个，你就摸到了 dsh 的命门。</p><p>那一个插件到底长啥样？官方文档（仓库里的 <code>docs/user/develop/basic/index.zh.md</code>）说得很直白：</p><blockquote><p>插件是一个导出 <code>apply</code> 函数的 TypeScript 模块。框架在加载时调用 <code>apply</code>，传入一个 <code>ctx</code>（上下文对象），你通过 <code>ctx</code> 注册能力。</p></blockquote><p>最简单的插件，就这么几行：</p><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="keyword">type</span> &#123; <span class="title class_">Context</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;@deepseek-ai/cordis&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> name = <span class="string">&#x27;my-plugin&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">apply</span>(<span class="params"><span class="attr">ctx</span>: <span class="title class_">Context</span></span>) &#123;</span><br><span class="line">  <span class="comment">// 在这里注册你的能力</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>几个要点记一下：</p><ul><li><code>name</code>：插件名，要唯一</li><li><code>apply(ctx)</code>：入口函数，ctx 是「上下文对象」，注册工具、监听事件、开定时器都通过它</li><li><code>inject</code>：声明依赖，比如 <code>export const inject = [&#39;tools&#39;]</code>，框架会等工具注册表就绪后才调用你的 apply</li></ul><p>还有两个很贴心的设计：</p><ul><li><strong>自动清理</strong>：通过 ctx 注册的事件监听、工具、定时器，插件卸载时全部自动清理，你永远不用手写 removeListener</li><li><strong>ctx.effect()</strong>：如果你有网络连接这种要手动关闭的资源，用 <code>ctx.effect(() =&gt; { ...; return () =&gt; 清理 })</code> 告诉框架怎么收尾</li></ul><p>插件有三种写法：函数（日常够用）、对象（带生命周期钩子）、类（Service 子类，给别人提供服务）。写工具插件，函数形式基本就够了。</p><h2 id="二、最小闭环：先让-dsh-认你这个插件"><a href="#二、最小闭环：先让-dsh-认你这个插件" class="headerlink" title="二、最小闭环：先让 dsh 认你这个插件"></a>二、最小闭环：先让 dsh 认你这个插件</h2><p>环境要求：<strong>Node ^22.19 或 &gt;&#x3D;24</strong>，低于这个版本 dsh 起不来。还没装 dsh 的先把 Web 版跑起来：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npx @deepseek-ai/dsh web</span><br><span class="line"><span class="comment"># Web UI 地址：http://127.0.0.1:3080</span></span><br></pre></td></tr></table></figure><p>然后建个本地开发目录，写一个最朴素的插件：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> -p scratch-plugin/src</span><br></pre></td></tr></table></figure><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// scratch-plugin/src/hello-plugin.ts</span></span><br><span class="line"><span class="keyword">import</span> <span class="keyword">type</span> &#123; <span class="title class_">Context</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;@deepseek-ai/cordis&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> name = <span class="string">&#x27;hello-plugin&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">apply</span>(<span class="params"><span class="attr">ctx</span>: <span class="title class_">Context</span></span>) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;[hello-plugin] plugin loaded!&#x27;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>再建一个覆盖层文件 <code>cordis.yml</code>。注意：本地开发阶段，插件路径要写<strong>绝对路径</strong>，相对路径会解析失败：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># scratch-plugin/cordis.yml</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">insert:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">hello</span></span><br><span class="line">      <span class="attr">name:</span> <span class="string">&#x27;/绝对/路径/到/scratch-plugin/src/hello-plugin.ts&#x27;</span></span><br></pre></td></tr></table></figure><p>用覆盖层启动：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx @deepseek-ai/dsh web --patch ./scratch-plugin/cordis.yml</span><br></pre></td></tr></table></figure><p>启动日志里看到 <code>[hello-plugin] plugin loaded!</code>，说明 dsh 已经认你了。最小闭环达成：<strong>加载插件 → 注册能力 → 生效</strong>。</p><h2 id="三、实战：写一个-IP-归属地查询工具"><a href="#三、实战：写一个-IP-归属地查询工具" class="headerlink" title="三、实战：写一个 IP 归属地查询工具"></a>三、实战：写一个 IP 归属地查询工具</h2><p>插件本身没意思，给 Agent 加个真能干的工具才有意思。今天的目标：让 dsh 里的 Agent 学会查 IP 归属地——你说「帮我看看 8.8.8.8 是哪的」，它调工具给你返回「美国 弗吉尼亚州 Ashburn，运营商 Google LLC」。</p><p>我用纯 ESM 写（免构建，Node 直接跑），接口用 ip-api.com 的免费 JSON 接口，不用注册不用 key，自用完全够（免费版每分钟约 45 次限额，商用要付费，以官网为准）。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// index.js</span></span><br><span class="line"><span class="keyword">import</span> &#123; defineTool &#125; <span class="keyword">from</span> <span class="string">&#x27;@deepseek-ai/dsh-tools&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> name = <span class="string">&#x27;ip-lookup&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> inject = [<span class="string">&#x27;tools&#x27;</span>]</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">apply</span>(<span class="params">ctx</span>) &#123;</span><br><span class="line">  ctx.<span class="property">tools</span>.<span class="title function_">register</span>(<span class="title function_">defineTool</span>(&#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&#x27;ip_lookup&#x27;</span>,</span><br><span class="line">    <span class="attr">description</span>: <span class="string">&#x27;查询 IP 地址的归属地信息（国家、城市、运营商）&#x27;</span>,</span><br><span class="line">    <span class="attr">parameters</span>: &#123;</span><br><span class="line">      <span class="attr">ip</span>: &#123; <span class="attr">type</span>: <span class="string">&#x27;string&#x27;</span>, <span class="attr">required</span>: <span class="literal">true</span>, <span class="attr">description</span>: <span class="string">&#x27;要查询的 IP 地址，例如 8.8.8.8&#x27;</span> &#125;,</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="keyword">async</span> <span class="title function_">execute</span>(<span class="params">args</span>) &#123;</span><br><span class="line">      <span class="keyword">const</span> res = <span class="keyword">await</span> <span class="title function_">fetch</span>(<span class="string">`http://ip-api.com/json/<span class="subst">$&#123;args.ip&#125;</span>?lang=zh-CN`</span>)</span><br><span class="line">      <span class="keyword">const</span> data = <span class="keyword">await</span> res.<span class="title function_">json</span>()</span><br><span class="line">      <span class="keyword">if</span> (data.<span class="property">status</span> !== <span class="string">&#x27;success&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">`查询失败：<span class="subst">$&#123;data.message || <span class="string">&#x27;未知错误&#x27;</span>&#125;</span>`</span>)</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> &#123;</span><br><span class="line">        <span class="attr">ip</span>: data.<span class="property">query</span>,</span><br><span class="line">        <span class="attr">country</span>: data.<span class="property">country</span>,</span><br><span class="line">        <span class="attr">regionName</span>: data.<span class="property">regionName</span>,</span><br><span class="line">        <span class="attr">city</span>: data.<span class="property">city</span>,</span><br><span class="line">        <span class="attr">isp</span>: data.<span class="property">isp</span>,</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">output</span>: &#123;</span><br><span class="line">      <span class="attr">schema</span>: &#123;</span><br><span class="line">        <span class="attr">type</span>: <span class="string">&#x27;object&#x27;</span>,</span><br><span class="line">        <span class="attr">additionalProperties</span>: <span class="literal">true</span>, <span class="comment">// 这个必须写 true，否则注册直接失败</span></span><br><span class="line">        <span class="attr">properties</span>: &#123;</span><br><span class="line">          <span class="attr">ip</span>: &#123; <span class="attr">type</span>: <span class="string">&#x27;string&#x27;</span> &#125;,</span><br><span class="line">          <span class="attr">country</span>: &#123; <span class="attr">type</span>: <span class="string">&#x27;string&#x27;</span> &#125;,</span><br><span class="line">          <span class="attr">regionName</span>: &#123; <span class="attr">type</span>: <span class="string">&#x27;string&#x27;</span> &#125;,</span><br><span class="line">          <span class="attr">city</span>: &#123; <span class="attr">type</span>: <span class="string">&#x27;string&#x27;</span> &#125;,</span><br><span class="line">          <span class="attr">isp</span>: &#123; <span class="attr">type</span>: <span class="string">&#x27;string&#x27;</span> &#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="title function_">render</span>(<span class="params">output</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">`IP <span class="subst">$&#123;output.ip&#125;</span> 归属地：<span class="subst">$&#123;output.country&#125;</span> <span class="subst">$&#123;output.regionName&#125;</span> <span class="subst">$&#123;output.city&#125;</span>，运营商：<span class="subst">$&#123;output.isp&#125;</span>`</span></span><br><span class="line">      &#125;,</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>代码不长，拆开讲：</p><ul><li><code>defineTool</code> 从 <code>@deepseek-ai/dsh-tools</code> 导入，帮你做参数校验和输出校验</li><li><code>parameters</code>：声明参数 schema，模型会照着这个自动生成调用参数</li><li><code>execute(args)</code>：真正干活的地方，这里就是调 ip-api.com 的 HTTP 接口</li><li><code>output.schema</code>：返回值校验；<code>output.render</code>：把结构化结果渲染成模型能直接读的话</li><li><strong>坑</strong>：object 类型的输出 schema 必须写 <code>additionalProperties: true</code>，不然注册直接失败——我在这上面栽过</li></ul><p>装进 profile 跑起来（两种方式二选一）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 方式一：本地路径直接装（需要 pnpm，没有就先 npm install -g pnpm）</span></span><br><span class="line">dsh plugin --profile web add .</span><br><span class="line"></span><br><span class="line"><span class="comment"># 方式二：开发时用覆盖层（不需要 pnpm）</span></span><br><span class="line">npx @deepseek-ai/dsh web --patch ./cordis.patch.yml</span><br></pre></td></tr></table></figure><p>然后在 Web UI 里开个新会话，直接说：</p><blockquote><p>帮我查一下 8.8.8.8 的归属地</p></blockquote><p>你会看到 Agent 展开工具调用：IN 传参、OUT 返回结果，一气呵成。至此「加载插件 → 注册工具 → 模型调用 → 返回结果」的完整闭环就通了。</p><p>顺带说一句：不想手敲这些代码的话，可以把插件开发文档扔给 DeepSeek 让它自己写——社区里已经有人这么干出了 arXiv 搜索插件。模型写插件、你负责验收，这就是 Agent 时代的生产方式。dsh 默认接 DeepSeek 官方，习惯走中转的朋友也可以在 provider 里配 ai.aklibk.com，基础接入方式前面那篇讲过了，不重复。</p><h2 id="四、从本地到发布：三件套打包"><a href="#四、从本地到发布：三件套打包" class="headerlink" title="四、从本地到发布：三件套打包"></a>四、从本地到发布：三件套打包</h2><p>本地能跑只是第一步，想让插件真正可安装、可分享，需要三件套：</p><p><strong>1. package.json</strong>（声明这是个 dsh 插件）</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;dsh-ip-lookup&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;version&quot;</span><span class="punctuation">:</span> <span class="string">&quot;0.1.0&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;module&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;main&quot;</span><span class="punctuation">:</span> <span class="string">&quot;index.js&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;files&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">&quot;index.js&quot;</span><span class="punctuation">,</span> <span class="string">&quot;cordis.patch.yml&quot;</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;keywords&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">&quot;dsh-plugin&quot;</span><span class="punctuation">,</span> <span class="string">&quot;deepseek-harness&quot;</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;dsh&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;bundle&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;patch&quot;</span><span class="punctuation">:</span> <span class="string">&quot;./cordis.patch.yml&quot;</span> <span class="punctuation">&#125;</span> <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p><strong>2. index.js</strong>——就是上面那个插件本体</p><p><strong>3. cordis.patch.yml</strong>（告诉 dsh 怎么挂载它）</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> <span class="attr">insert:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">ip-lookup</span></span><br><span class="line">      <span class="attr">name:</span> <span class="string">dsh-ip-lookup</span></span><br></pre></td></tr></table></figure><p>⚠️ <strong>files 数组里必须包含 cordis.patch.yml</strong>！漏了它，包能装上但插件层根本不生效——这是发布目录里最常见的翻车点，装完发现啥都没有，先查这个。</p><p>发布三步走：</p><ol><li>推到 GitHub 公开仓库</li><li>仓库打上 <code>dsh-plugin</code> topic——这是官方约定的发现机制，社区目录就靠它索引</li><li>README 里写清安装方式、插件能访问什么、测试过的 dsh 版本</li></ol><p>之后别人一条命令就能装：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dsh plugin --profile web add github:你的账号/dsh-ip-lookup</span><br></pre></td></tr></table></figure><p>装完重启 profile 就生效。如果插件装了但界面&#x2F;工具没出现，别急着猜，先看配置树：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dsh --profile web --dump-config</span><br></pre></td></tr></table></figure><p>它会打印当前真正组合出的插件树，你的插件在不在里面一目了然——不在就是安装环节的问题，不是代码问题。</p><h2 id="五、踩坑清单-安全提醒（必看）"><a href="#五、踩坑清单-安全提醒（必看）" class="headerlink" title="五、踩坑清单 &amp; 安全提醒（必看）"></a>五、踩坑清单 &amp; 安全提醒（必看）</h2><p>把这一路的坑汇总一下：</p><ol><li><strong>object 输出 schema 要写 <code>additionalProperties: true</code></strong>，否则 defineTool 注册直接失败</li><li><strong>files 漏掉 cordis.patch.yml</strong> → 装上了但没挂载层，等于白装</li><li><strong>patch 是整行替换，不是深合并</strong>：改配置要重述整行 config，只写想改的那个字段会丢掉其它配置</li><li><strong>插件是可信代码</strong>：dsh 插件跑在宿主进程里，能碰你的文件、网络、浏览器、终端。装社区插件前先看 README 和安装脚本，最好固定 tag&#x2F;commit，再单独开个 profile 试装，别拿主力工作区当试验场</li><li>本地开发挂本地路径时用<strong>绝对路径</strong>，相对路径会解析失败</li></ol><p>写完第一个插件，dsh 在你手里就不再是「开箱即用」的工具，而是「随你捏」的工作台了。</p><blockquote><p>生命不息，折腾不止。下一篇咱们玩个大的：把一个任务拆给多个 Agent 并行干——多 Agent 协作实战，看看 dsh 怎么让几个「分身」同时开跑、最后汇总结论。</p></blockquote>]]>
    </content>
    <id>https://kqnb.me/2026/08/27/deepseek-harness-plugin/</id>
    <link href="https://kqnb.me/2026/08/27/deepseek-harness-plugin/"/>
    <published>2026-08-27T12:00:00.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p>生命不息，折腾不止。上次说好的「写插件」来了——今天手把手给 dsh 的 Agent 造一个 IP 查询工具，让它多一门手艺。</p>
</blockquote>
<p>从基础安装到接中转站，dsh 已经跑起来了。但光会用别人的东西，那只是「用户」]]>
    </summary>
    <title>DeepSeek Harness 写第一个插件：给 Agent 加个 IP 查询工具</title>
    <updated>2026-08-27T01:18:04.942Z</updated>
  </entry>
  <entry>
    <author>
      <name>空缺</name>
    </author>
    <category term="技术折腾" scheme="https://kqnb.me/categories/%E6%8A%80%E6%9C%AF%E6%8A%98%E8%85%BE/"/>
    <category term="教程" scheme="https://kqnb.me/tags/%E6%95%99%E7%A8%8B/"/>
    <category term="AI" scheme="https://kqnb.me/tags/AI/"/>
    <category term="DeepSeek" scheme="https://kqnb.me/tags/DeepSeek/"/>
    <category term="Agent" scheme="https://kqnb.me/tags/Agent/"/>
    <category term="MCP" scheme="https://kqnb.me/tags/MCP/"/>
    <content>
      <![CDATA[<blockquote><p>生命不息，折腾不止。上一篇我们把代码从旧模型名迁到了 V4，今天再往前一步：把 MCP 接上，让 Agent 真正长出手和脚，能调工具、能干活。</p></blockquote><h2 id="一、MCP-是啥？为什么-2026-年你必须会"><a href="#一、MCP-是啥？为什么-2026-年你必须会" class="headerlink" title="一、MCP 是啥？为什么 2026 年你必须会"></a>一、MCP 是啥？为什么 2026 年你必须会</h2><p>先花 30 秒把概念捋清楚，不然下面全是黑话。</p><p><strong>MCP（Model Context Protocol，模型上下文协议）</strong> 是 Anthropic 在 2024 年 11 月开源的一个开放标准，江湖人称 <strong>「AI 应用的 USB-C 接口」</strong>。意思很直白：以前每个 AI 工具接一个新数据源，都要单独写一套集成代码，维护成本爆炸；MCP 把「工具提供方」和「AI 应用方」彻底解耦——<strong>一个 MCP Server 写一次，Claude、GPT、Gemini、DeepSeek 通吃</strong>。</p><p>这两年它已经从「Anthropic 家的小协议」长成事实标准了：OpenAI、Google、Microsoft 全都原生支持，Python + TypeScript 两个 SDK 月下载量逼近一个亿，官方 Registry 里登记的 Server 接近一万个。所以学 MCP 不是追新，是补 2026 年的基本功。</p><p>它的架构就三层，记住这张图：</p><ul><li><strong>Host（宿主）</strong>：你天天用的 AI 应用，比如 Claude Code、Cursor、Claude Desktop</li><li><strong>Client（客户端）</strong>：Host 内部为每个 Server 开的一条连接，你不需要管它</li><li><strong>Server（服务端）</strong>：提供外部能力的进程，比如 GitHub、数据库、文件系统、天气 API</li></ul><p>Server 对外只暴露三种东西：<strong>工具（Tools）</strong>——模型能调用的函数；<strong>资源（Resources）</strong>——模型能读的数据；<strong>提示词（Prompts）</strong>——预写的模板。日常折腾 90% 都在跟 Tools 打交道，今天的实战也围绕它展开。</p><p>传输方式有两种：<strong>stdio</strong>（本地进程，Claude Code &#x2F; Cursor 默认）和 <strong>Streamable HTTP</strong>（远程服务，2025 年 11 月规范引入，老掉牙的 SSE 已被官方淘汰）。</p><h2 id="二、DeepSeek-V4-接-MCP-的底牌：双兼容-一个致命坑"><a href="#二、DeepSeek-V4-接-MCP-的底牌：双兼容-一个致命坑" class="headerlink" title="二、DeepSeek V4 接 MCP 的底牌：双兼容 + 一个致命坑"></a>二、DeepSeek V4 接 MCP 的底牌：双兼容 + 一个致命坑</h2><p>DeepSeek V4（2026 年 4 月 24 日发布，MIT 协议）天生就是干这活的料，原因有仨：</p><p><strong>1. 接口双兼容，客户端即插即用。</strong> V4 同时提供 OpenAI 兼容和 Anthropic 兼容两套 API，base URL 都是 <code>https://api.deepseek.com</code>，官方文档的示例代码直接填这个地址即可。任何 MCP 客户端只要把模型名填成 <code>deepseek-v4-pro</code> 或 <code>deepseek-v4-flash</code>，直接就能用，不需要任何代理和中间层。</p><p><strong>2. 1M 上下文，长任务不爆。</strong> V4 两个模型都支持 100 万 token 上下文，配合它家新的混合注意力架构（KV 缓存省约 90%），以前跑长上下文 Agent 动不动 OOM 的场景，现在便宜又流畅。</p><p><strong>3. 便宜。</strong> MCP 干活是典型的「多轮工具调用」：模型列工具 → 调工具 → 读结果 → 再调……一个用户问题背后可能是 3-5 次 API 调用。这个场景下 V4 的价格优势被放大得很明显，flash 干杂活、pro 出结论，成本比国外旗舰低一个量级。</p><p><strong>但有个致命坑必须先说：别把 <code>deepseek-r1</code> 指给 MCP 客户端！</strong> R1 这个老模型从设计上就不支持 function calling（工具调用），V4 发布也没改变这一点。你把 MCP 客户端指向 r1，它不会报错，而是<strong>一本正经地编造工具输出</strong>——看起来像调了工具，实际全是幻觉，这在 Agent 场景里是灾难级的。记住：<strong>凡是要接 MCP、要调工具的活，一律用 <code>deepseek-v4-pro</code> 或 <code>deepseek-v4-flash</code></strong>。</p><h2 id="三、实战一：3-分钟把现成的-DeepSeek-MCP-Server-接进-Claude-Code"><a href="#三、实战一：3-分钟把现成的-DeepSeek-MCP-Server-接进-Claude-Code" class="headerlink" title="三、实战一：3 分钟把现成的 DeepSeek MCP Server 接进 Claude Code"></a>三、实战一：3 分钟把现成的 DeepSeek MCP Server 接进 Claude Code</h2><p>先说最省事的路径：社区有人把 DeepSeek 的 API 包装成了标准 MCP Server，装好直接当工具用。以 <code>@arikusi/deepseek-mcp-server</code> 为例（npm 包名 <code>deepseek-mcp-server</code>，MCP Registry 有登记，也有其他同类项目，比如 <code>DMontgomery40/deepseek-mcp-server</code>，原理一样）：</p><p><strong>第 1 步：拿到你的 DeepSeek API Key</strong></p><p>去 DeepSeek 开放平台（platform.deepseek.com）创建一个 Key，形如 <code>sk-xxx</code>。充个 20 块够折腾很久。</p><p><strong>第 2 步：一条命令注册进 Claude Code</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">claude mcp add -s user deepseek \</span><br><span class="line">  npx @arikusi/deepseek-mcp-server \</span><br><span class="line">  -e DEEPSEEK_API_KEY=sk-你的key</span><br></pre></td></tr></table></figure><p>解释一下：<code>-s user</code> 表示对当前用户全局生效（想只对某个项目生效就把 <code>-s user</code> 换成 <code>-s project</code>）；后面 <code>npx @arikusi/deepseek-mcp-server</code> 是启动命令，npm 会自动拉包，无需手动安装；<code>-e</code> 把 API Key 传进这个子进程的环境变量。</p><p><strong>第 3 步：重启 Claude Code，验证注册成功</strong></p><p>完全退出 Claude Code 再重新进入（MCP 配置只在启动时加载），然后敲：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/mcp</span><br></pre></td></tr></table></figure><p>能看到 <code>deepseek</code> 服务器出现在列表里就成功了。它的工具大概长这样：<code>deepseek_chat</code>（对话）、<code>deepseek_fim</code>（代码补全）、<code>deepseek_sessions</code>（多轮会话），还带成本统计。</p><p><strong>第 4 步：让它干活</strong></p><p>直接下指令试试，比如：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">用 deepseek 工具帮我写一个 Python 快排，要求带注释</span><br></pre></td></tr></table></figure><p>Claude Code 会把 <code>deepseek_chat</code> 工具连同你的问题一起发给模型（此时驱动 Claude Code 主循环的可以是任何模型），DeepSeek 返回结果后作为工具结果回传，你看到的是一套完整的「Agent 把活外包给 DeepSeek」的流程。默认模型是 <code>deepseek-v4-flash</code>，追求质量可以在调用参数里指定 <code>deepseek-v4-pro</code>。</p><p>想删掉这个工具：<code>claude mcp remove deepseek</code>。想查看配置详情：<code>claude mcp get deepseek</code>。</p><h2 id="四、实战二：20-行代码写一个自己的-MCP-Server"><a href="#四、实战二：20-行代码写一个自己的-MCP-Server" class="headerlink" title="四、实战二：20 行代码写一个自己的 MCP Server"></a>四、实战二：20 行代码写一个自己的 MCP Server</h2><p>现成的 Server 是别人给你做好的轮子，但<strong>真正的乐趣是给自己的数据写工具</strong>。用 Python 的 FastMCP 库，20 行代码搞定。以下以官方快速入门为基准，用最新版（FastMCP 3.x）写法：</p><p><strong>第 1 步：装环境（用 uv，一行命令装好）</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">curl -LsSf https://astral.sh/uv/install.sh | sh</span><br><span class="line">uv init my-mcp &amp;&amp; <span class="built_in">cd</span> my-mcp</span><br><span class="line">uv venv &amp;&amp; <span class="built_in">source</span> .venv/bin/activate</span><br><span class="line">uv add <span class="string">&quot;mcp[cli]&quot;</span> httpx</span><br></pre></td></tr></table></figure><p><strong>第 2 步：写你的第一个工具</strong></p><p>新建 <code>server.py</code>，复制粘贴：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> fastmcp <span class="keyword">import</span> FastMCP</span><br><span class="line"></span><br><span class="line">mcp = FastMCP(<span class="string">&quot;my-tools&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">@mcp.tool</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">add</span>(<span class="params">a: <span class="built_in">int</span>, b: <span class="built_in">int</span></span>) -&gt; <span class="built_in">int</span>:</span><br><span class="line">    <span class="string">&quot;&quot;&quot;两个整数相加，先拿它练手&quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">return</span> a + b</span><br><span class="line"></span><br><span class="line"><span class="meta">@mcp.tool</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">get_weather</span>(<span class="params">city: <span class="built_in">str</span></span>) -&gt; <span class="built_in">str</span>:</span><br><span class="line">    <span class="string">&quot;&quot;&quot;模拟查天气，真实项目里这里换成 requests 调天气 API 即可&quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">return</span> <span class="string">f&quot;<span class="subst">&#123;city&#125;</span> 今天晴，26℃&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">    mcp.run()  <span class="comment"># 默认 stdio 传输</span></span><br></pre></td></tr></table></figure><p>看到了吗？一个 <code>@mcp.tool</code> 装饰器，函数签名 + 中文注释，工具定义、参数校验、文档生成全自动。这就是 FastMCP 的全部魔法。</p><p><strong>第 3 步：先本地跑通（可选）</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fastmcp run server.py</span><br></pre></td></tr></table></figure><p>会以 stdio 模式启动。想远程访问就加传输参数：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fastmcp run server.py --transport http --port 8000</span><br></pre></td></tr></table></figure><p><strong>第 4 步：接进 Claude Code</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">claude mcp add -s user my-tools python /绝对路径/server.py</span><br></pre></td></tr></table></figure><p>重启 Claude Code 后 <code>/mcp</code> 里就能看到 <code>my-tools</code>。现在你可以让它「算一下 127 和 358 的和」，看它怎么一步步调用 <code>add</code> 工具；或者加个真天气 API，让 DeepSeek V4 帮你查全球任意城市的天气——<strong>模型负责理解，工具负责执行，这就是 Agent 的最小形态</strong>。</p><h2 id="五、避坑清单（都是真金白银换来的）"><a href="#五、避坑清单（都是真金白银换来的）" class="headerlink" title="五、避坑清单（都是真金白银换来的）"></a>五、避坑清单（都是真金白银换来的）</h2><ol><li><strong>模型名必须写对。</strong> MCP 客户端里只填 <code>deepseek-v4-pro</code> &#x2F; <code>deepseek-v4-flash</code>。填 <code>deepseek-r1</code> 会幻觉工具输出；填 <code>deepseek-chat</code> &#x2F; <code>deepseek-reasoner</code> 这些 2026 年 7 月已退役的旧名会直接报错。</li><li><strong>API Key 一定要传进 Server 进程。</strong> 用 <code>claude mcp add</code> 时 <code>-e DEEPSEEK_API_KEY=...</code> 不能漏；手动启动的话先 <code>export DEEPSEEK_API_KEY=sk-xxx</code>。忘了传的表现是 Server 起来但一问就 401。</li><li><strong>base URL 要认准。</strong> 官方是 <code>https://api.deepseek.com</code>，有些教程让你填别的兼容端点，请确认来源可信。走第三方兼容端点时，记得模型名也要按对方文档改（比如换成你自己的中转站模型名）。</li><li><strong>改完配置必须重启客户端。</strong> Claude Code 只在启动时加载 MCP，热改配置不生效，<code>claude mcp add</code> 完没重启然后到处找 bug 的，都是这一步栽的。</li><li><strong>别用 SSE 老传输。</strong> 2025 年 11 月之后的规范已经切到 Streamable HTTP，新写远程 Server 直接上 HTTP；看到「SSE」字样的老教程留个心眼，写法可能过时了（以官方文档 modelcontextprotocol.io 为准）。</li><li><strong>本地 Server 别开公网。</strong> 自己写的 stdio Server 只服务本机；要远程用就加 OAuth 认证，裸奔在公网等于把工具权限白送。</li></ol><h2 id="六、下一站：让-Agent-打组合拳"><a href="#六、下一站：让-Agent-打组合拳" class="headerlink" title="六、下一站：让 Agent 打组合拳"></a>六、下一站：让 Agent 打组合拳</h2><p>今天这两套实战下来，你已经能给 DeepSeek V4 接上「手和脚」了：现成的 Server 拿来即用，自定义工具 20 行就能上。接下来就是组合拳阶段——把 DeepSeek V4 接进 Claude Code 当主力模型，再配上 MCP 工具，一套完整的低成本 Agent 工作台就搭起来了。</p><p>顺带说一句，如果你想让 Claude &#x2F; GPT &#x2F; Gemini 这些国外模型也走同样的 MCP 玩法，又不想折腾海外信用卡和网络，可以看看 <strong>ai.aklibk.com</strong> 中转站：一个 Key 通吃 Claude &#x2F; GPT &#x2F; Gemini &#x2F; DeepSeek，人民币按量付费，国内直连免绑卡，DeepSeek 系模型价格还更便宜——同一套 MCP 配置，改个 base URL 和模型名就能切换底层模型，这正是「写一次、处处可用」的价值所在。</p><blockquote><p>生命不息，折腾不止。下一篇聊《DeepSeek V4 + Claude Code 实战：把 Agent 工具接上 DeepSeek》，手把手把整套 Agent 编程工作台搭起来，让 Claude Code 的干活主力变成 DeepSeek V4，配上 MCP 一起上阵。</p></blockquote>]]>
    </content>
    <id>https://kqnb.me/2026/08/26/deepseek-v4-mcp/</id>
    <link href="https://kqnb.me/2026/08/26/deepseek-v4-mcp/"/>
    <published>2026-08-26T13:00:00.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p>生命不息，折腾不止。上一篇我们把代码从旧模型名迁到了 V4，今天再往前一步：把 MCP 接上，让 Agent 真正长出手和脚，能调工具、能干活。</p>
</blockquote>
<h2 id="一、MCP-是啥？为什么-2026-年你必须会">]]>
    </summary>
    <title>DeepSeek V4 接入 MCP 实战：给 Agent 装上「手和脚」</title>
    <updated>2026-08-26T01:15:16.065Z</updated>
  </entry>
  <entry>
    <author>
      <name>空缺</name>
    </author>
    <category term="技术折腾" scheme="https://kqnb.me/categories/%E6%8A%80%E6%9C%AF%E6%8A%98%E8%85%BE/"/>
    <category term="教程" scheme="https://kqnb.me/tags/%E6%95%99%E7%A8%8B/"/>
    <category term="AI" scheme="https://kqnb.me/tags/AI/"/>
    <category term="DeepSeek" scheme="https://kqnb.me/tags/DeepSeek/"/>
    <category term="API" scheme="https://kqnb.me/tags/API/"/>
    <category term="迁移" scheme="https://kqnb.me/tags/%E8%BF%81%E7%A7%BB/"/>
    <content>
      <![CDATA[<blockquote><p>生命不息，折腾不止。DeepSeek 把用了两年的旧模型名 <code>deepseek-chat</code> 直接砍了，这篇带你 5 分钟完成迁移，顺带躲开账单刺客。</p></blockquote><p>如果你手上还有跑着的 DeepSeek 代码，先别慌，大概率就是改一个字符串的事。但你要是真以为「改个名字」就完事，那 thinking 模式、分时定价这两个新东西分分钟教做人。这篇把来龙去脉、迁移步骤、省钱技巧一次讲清楚。</p><h2 id="一、先搞清楚发生了什么"><a href="#一、先搞清楚发生了什么" class="headerlink" title="一、先搞清楚发生了什么"></a>一、先搞清楚发生了什么</h2><p>DeepSeek 在 <strong>2026 年 4 月 24 日</strong>发布了 V4 预览版（MIT 协议开源），API 里新增了两个正式模型名：<code>deepseek-v4-flash</code> 和 <code>deepseek-v4-pro</code>。当时旧的 <code>deepseek-chat</code> &#x2F; <code>deepseek-reasoner</code> 还在，只是被悄悄当作别名转发到 V4。</p><p>然后关键节点来了：<strong>2026 年 7 月 24 日 15:59 UTC（北京时间当天 23:59），旧模型名正式退役</strong>。之后任何请求只要还写 <code>deepseek-chat</code> 或 <code>deepseek-reasoner</code>，直接返回错误，没有宽限期，没有降级。</p><p>官方文档现在只列三个模型名：</p><table><thead><tr><th>模型</th><th>说明</th></tr></thead><tbody><tr><td><code>deepseek-v4-flash</code></td><td>日常主力，快、便宜（当前版本 V4-Flash-0731）</td></tr><tr><td><code>deepseek-v4-pro</code></td><td>旗舰，最强推理（当前版本 V4-Pro-0813）</td></tr><tr><td><code>deepseek-v4-flash-vision-exp</code></td><td>实验性视觉模型，支持图片输入</td></tr></tbody></table><p>好消息是 <strong>base URL 完全没变</strong>：OpenAI 格式还是 <code>https://api.deepseek.com</code>，Anthropic 格式是 <code>https://api.deepseek.com/anthropic</code>。所以绝大多数项目就是「改个模型名字符串」的事。</p><h2 id="二、Flash-还是-Pro？V4-家族怎么选"><a href="#二、Flash-还是-Pro？V4-家族怎么选" class="headerlink" title="二、Flash 还是 Pro？V4 家族怎么选"></a>二、Flash 还是 Pro？V4 家族怎么选</h2><p>先看参数和定位（官方公布）：</p><ul><li><strong>deepseek-v4-flash</strong>：284B 参数 MoE（每次激活 13B），官方称 SWE-bench Verified 72.1%，主打性价比，适合日常对话、批量任务、对延迟敏感的场景。</li><li><strong>deepseek-v4-pro</strong>：1.6T 参数 MoE（每次激活 49B），官方称 SWE-bench Verified 80.6%，复杂代码、深度推理场景选它。</li><li>两者都是 <strong>1M token 上下文窗口</strong>，最大输出 <strong>384K</strong>，支持 JSON 输出、Tool Calls、Responses API、Anthropic 兼容格式。</li></ul><p>价格（官方文档，单位：美元 &#x2F; 每 100 万 tokens）：</p><table><thead><tr><th>计费项</th><th>v4-flash（峰值&#x2F;非峰值）</th><th>v4-pro（峰值&#x2F;非峰值）</th></tr></thead><tbody><tr><td>输入·缓存命中</td><td>$0.014 &#x2F; $0.007</td><td>$0.044 &#x2F; $0.022</td></tr><tr><td>输入·缓存未命中</td><td>$0.44 &#x2F; $0.22</td><td>$1.32 &#x2F; $0.66</td></tr><tr><td>输出</td><td>$1.32 &#x2F; $0.66</td><td>$3.96 &#x2F; $1.98</td></tr></tbody></table><p>注意这个<strong>分时定价</strong>，DeepSeek 算是第一个这么玩的大厂：工作日（周一至周五）UTC 01:00-04:00 和 06:00-10:00（<strong>北京时间 09:00-12:00、14:00-18:00</strong>）是峰值，其余时间半价。习惯白天跑批量的同学，挪到晚上能省一半。</p><p>选型建议：<strong>无脑先上 flash</strong>，日常 90% 的场景它都扛得住；真遇到复杂推理和代码题感觉不够，再单独把那条链路切到 pro，别全局升级。</p><h2 id="三、迁移实操：改一个字符串，5-分钟收工"><a href="#三、迁移实操：改一个字符串，5-分钟收工" class="headerlink" title="三、迁移实操：改一个字符串，5 分钟收工"></a>三、迁移实操：改一个字符串，5 分钟收工</h2><p>旧代码搜索清单先摆出来，对着改就行：</p><ul><li><code>deepseek-chat</code> → <code>deepseek-v4-flash</code>（日常对话、非思考场景）</li><li><code>deepseek-reasoner</code> → <code>deepseek-v4-flash</code>（要省钱的推理场景）或 <code>deepseek-v4-pro</code>（要顶配推理）</li></ul><p>改完用 Python + OpenAI SDK 验证（官方示例）：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># pip install openai</span></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">from</span> openai <span class="keyword">import</span> OpenAI</span><br><span class="line"></span><br><span class="line">client = OpenAI(</span><br><span class="line">    api_key=os.environ.get(<span class="string">&quot;DEEPSEEK_API_KEY&quot;</span>),</span><br><span class="line">    base_url=<span class="string">&quot;https://api.deepseek.com&quot;</span>,</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">response = client.chat.completions.create(</span><br><span class="line">    model=<span class="string">&quot;deepseek-v4-flash&quot;</span>,</span><br><span class="line">    messages=[</span><br><span class="line">        &#123;<span class="string">&quot;role&quot;</span>: <span class="string">&quot;system&quot;</span>, <span class="string">&quot;content&quot;</span>: <span class="string">&quot;你是一个全能助手&quot;</span>&#125;,</span><br><span class="line">        &#123;<span class="string">&quot;role&quot;</span>: <span class="string">&quot;user&quot;</span>, <span class="string">&quot;content&quot;</span>: <span class="string">&quot;用一句话解释什么是 MoE&quot;</span>&#125;,</span><br><span class="line">    ],</span><br><span class="line">    stream=<span class="literal">False</span>,</span><br><span class="line">)</span><br><span class="line"><span class="built_in">print</span>(response.choices[<span class="number">0</span>].message.content)</span><br></pre></td></tr></table></figure><p>不写代码，直接 curl 验也行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">curl https://api.deepseek.com/chat/completions \</span><br><span class="line">  -H <span class="string">&quot;Content-Type: application/json&quot;</span> \</span><br><span class="line">  -H <span class="string">&quot;Authorization: Bearer <span class="variable">$&#123;DEEPSEEK_API_KEY&#125;</span>&quot;</span> \</span><br><span class="line">  -d <span class="string">&#x27;&#123;</span></span><br><span class="line"><span class="string">    &quot;model&quot;: &quot;deepseek-v4-flash&quot;,</span></span><br><span class="line"><span class="string">    &quot;messages&quot;: [&#123;&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;你好&quot;&#125;]</span></span><br><span class="line"><span class="string">  &#125;&#x27;</span></span><br></pre></td></tr></table></figure><p>注意一个小坑：<strong>thinking 模式默认是开的</strong>（默认档位 high），所以第一次调用如果发现返回结构里多了一个 <code>reasoning_content</code> 字段，别慌，那是思维链，正常现象。</p><h2 id="四、躲开账单刺客：thinking-模式和三个参数坑"><a href="#四、躲开账单刺客：thinking-模式和三个参数坑" class="headerlink" title="四、躲开账单刺客：thinking 模式和三个参数坑"></a>四、躲开账单刺客：thinking 模式和三个参数坑</h2><p>迁移完第一件事，建议打开你的账单对比一下。很多人（包括我）发现同样一批任务，跑完价格直接翻倍——原因就一个：<strong>V4 默认开 thinking 模式</strong>，输出前先吐一大段思维链，而思维链 token 是按输出价计费的，输出恰恰是最贵的部分。</p><p>三个参数坑，逐个说：</p><p><strong>1. 关 thinking &#x2F; 降档 effort。</strong> OpenAI 格式下 thinking 开关要放在 <code>extra_body</code> 里（Chat Completions 接口不支持顶层传）：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 关闭思维链：想省钱、只要快速答案的场景</span></span><br><span class="line">response = client.chat.completions.create(</span><br><span class="line">    model=<span class="string">&quot;deepseek-v4-flash&quot;</span>,</span><br><span class="line">    messages=[&#123;<span class="string">&quot;role&quot;</span>: <span class="string">&quot;user&quot;</span>, <span class="string">&quot;content&quot;</span>: <span class="string">&quot;今天杭州天气怎么样&quot;</span>&#125;],</span><br><span class="line">    extra_body=&#123;<span class="string">&quot;thinking&quot;</span>: &#123;<span class="string">&quot;type&quot;</span>: <span class="string">&quot;disabled&quot;</span>&#125;&#125;,</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 保留思维链但降档：日常够用，token 少很多</span></span><br><span class="line">response = client.chat.completions.create(</span><br><span class="line">    model=<span class="string">&quot;deepseek-v4-flash&quot;</span>,</span><br><span class="line">    messages=[&#123;<span class="string">&quot;role&quot;</span>: <span class="string">&quot;user&quot;</span>, <span class="string">&quot;content&quot;</span>: <span class="string">&quot;写一段二分查找&quot;</span>&#125;],</span><br><span class="line">    reasoning_effort=<span class="string">&quot;low&quot;</span>,</span><br><span class="line">    extra_body=&#123;<span class="string">&quot;thinking&quot;</span>: &#123;<span class="string">&quot;type&quot;</span>: <span class="string">&quot;enabled&quot;</span>&#125;&#125;,</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p><code>reasoning_effort</code> 支持 <code>low / high / max</code>（<code>medium</code>、<code>xhigh</code> 会被映射成 <code>high</code>）。如果走 Anthropic 格式，对应参数是 <code>reasoning: {&quot;effort&quot;: &quot;none/low/high/max&quot;}</code>，<code>none</code> 即关闭 thinking。</p><p><strong>2. thinking 模式下，<code>temperature</code>、<code>top_p</code>、<code>presence_penalty</code>、<code>frequency_penalty</code> 全部无效。</strong> 不报错，但静默失效。老代码里调这些参数的，迁移后别指望它们还起作用。</p><p><strong>3. 多轮对话 + 工具调用时，<code>reasoning_content</code> 必须原样回传。</strong> 请求带了 <code>tools</code> 参数的话，每一轮把 assistant 返回的 <code>reasoning_content</code> 拼进下一轮消息，哪怕那一轮没有工具调用，漏了直接 400 报错。不带 <code>tools</code> 的普通多轮则不用管，传了也会被忽略。</p><h2 id="五、进阶玩法：让-Claude-Code-用上-DeepSeek"><a href="#五、进阶玩法：让-Claude-Code-用上-DeepSeek" class="headerlink" title="五、进阶玩法：让 Claude Code 用上 DeepSeek"></a>五、进阶玩法：让 Claude Code 用上 DeepSeek</h2><p>V4 一个很香的点：官方把 <strong>Anthropic 兼容接口</strong>和 <strong>Agent 工具集成</strong>都做好了。Claude Code、GitHub Copilot、OpenCode 这类 Agent 工具，理论上可以直接把后端模型换成 DeepSeek，不用写代码，改环境变量指向 <code>https://api.deepseek.com/anthropic</code> 就行（具体变量名和配置方式以 DeepSeek 官方 Agent 集成文档为准，不同工具略有差异）。DeepSeek 官方还放出了自己的 agent harness —— DeepSeek Harness，现在还是 developer preview，想尝鲜的可以去官方指南看 quickstart。</p><p>另外多说一句：如果你嫌一个模型一个平台地注册、充值、管理 key 太麻烦，想一个 key 通吃 Claude &#x2F; GPT &#x2F; Gemini &#x2F; DeepSeek、人民币按量付费的话，可以看看 <strong>ai.aklibk.com</strong> 这个中转站，模型切换就是改个模型名的事，跟你今天学的这套玩法无缝衔接。DeepSeek 系列在里面价格也挺实在，多模型对接 + 便宜，正好互补。</p><blockquote><p>生命不息，折腾不止。下一篇可以聊聊怎么把 DeepSeek V4 接进自己的 MCP 服务，让 Agent 真正干起活来，敬请期待。</p></blockquote>]]>
    </content>
    <id>https://kqnb.me/2026/08/26/deepseek-v4-api-migration/</id>
    <link href="https://kqnb.me/2026/08/26/deepseek-v4-api-migration/"/>
    <published>2026-08-26T12:00:00.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p>生命不息，折腾不止。DeepSeek 把用了两年的旧模型名 <code>deepseek-chat</code> 直接砍了，这篇带你 5 分钟完成迁移，顺带躲开账单刺客。</p>
</blockquote>
<p>如果你手上还有跑着的 DeepSe]]>
    </summary>
    <title>DeepSeek V4 API 迁移实战：旧名已退役，5 分钟换新模型</title>
    <updated>2026-08-25T19:48:28.839Z</updated>
  </entry>
  <entry>
    <author>
      <name>空缺</name>
    </author>
    <category term="技术折腾" scheme="https://kqnb.me/categories/%E6%8A%80%E6%9C%AF%E6%8A%98%E8%85%BE/"/>
    <category term="教程" scheme="https://kqnb.me/tags/%E6%95%99%E7%A8%8B/"/>
    <category term="AI" scheme="https://kqnb.me/tags/AI/"/>
    <category term="DeepSeek" scheme="https://kqnb.me/tags/DeepSeek/"/>
    <category term="Agent" scheme="https://kqnb.me/tags/Agent/"/>
    <category term="Harness" scheme="https://kqnb.me/tags/Harness/"/>
    <category term="插件" scheme="https://kqnb.me/tags/%E6%8F%92%E4%BB%B6/"/>
    <content>
      <![CDATA[<blockquote><p>生命不息，折腾不止。上次把 DeepSeek Harness 接上中转站只是「会用」，这篇带你走进它的灵魂——自己动手写插件，30 行代码给 Agent 加一个会干活的工具。</p></blockquote><h2 id="一、插件到底是个啥：一切皆插件"><a href="#一、插件到底是个啥：一切皆插件" class="headerlink" title="一、插件到底是个啥：一切皆插件"></a>一、插件到底是个啥：一切皆插件</h2><p>DeepSeek Harness（命令行叫 <code>dsh</code>）是 DeepSeek 官方开源的 Agent 框架，它的核心设计就一句话：<strong>一切皆插件</strong>。这句话不是营销，是字面意思——模型适配器、工具注册表、会话日志、甚至 agent 主循环本身，全都是插件。整个产品就是启动时从若干层配置里组合出来的一棵插件树。</p><p>底层驱动是一个叫 <strong>Cordis</strong> 的插件框架（DeepSeek 魔改了一份 vendored 版本）。在 dsh 眼里，插件就是一个 TypeScript 模块，导出 <code>apply(ctx)</code> 函数，框架加载插件时会调用它，把 <code>ctx</code> 上下文对象传进来，你就在里面注册各种能力。</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="keyword">type</span> &#123; <span class="title class_">Context</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;@deepseek-ai/cordis&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> name = <span class="string">&#x27;my-plugin&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">apply</span>(<span class="params"><span class="attr">ctx</span>: <span class="title class_">Context</span></span>) &#123;</span><br><span class="line">  <span class="comment">// 在这里注册工具、监听事件、挂服务……</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这就是一个插件的全部骨架。好处显而易见：<strong>想加什么能力不用改主程序</strong>，写个插件挂上去就行；插件卸载时，通过 <code>ctx</code> 注册的一切（事件监听、工具、定时器）会自动清理，不用担心残留。</p><p>插件有三种形态：<strong>函数插件</strong>（最常见，上面的就是）、<strong>对象插件</strong>（带 <code>apply</code> 方法的对象）、<strong>类插件</strong>（<code>Service</code> 子类，适合对外提供服务）。在你需要公开服务之前，一直用函数形态就够了。</p><h2 id="二、环境准备：把源码仓库拉下来"><a href="#二、环境准备：把源码仓库拉下来" class="headerlink" title="二、环境准备：把源码仓库拉下来"></a>二、环境准备：把源码仓库拉下来</h2><p>写 dsh 插件，官方推荐在源码仓库里开发，这样能用仓库自带的命令行和脚本（typecheck &#x2F; lint &#x2F; test &#x2F; build），还能用 vendored 启动器做<strong>不需要 API Key 的纯链路验证</strong>。</p><p>环境要求：<strong>Node.js ^22.19 或 &gt;&#x3D;24</strong>，包管理器用 pnpm（仓库用 Corepack 锁了版本）。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com/deepseek-ai/deepseek-harness.git</span><br><span class="line"><span class="built_in">cd</span> deepseek-harness</span><br><span class="line">pnpm install</span><br></pre></td></tr></table></figure><p>装完先跑一把确认环境 OK：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">pnpm run typecheck   <span class="comment"># 类型检查（strict）</span></span><br><span class="line">pnpm run lint        <span class="comment"># oxlint</span></span><br><span class="line">pnpm run build       <span class="comment"># tsc + tsdown 产出 lib/</span></span><br></pre></td></tr></table></figure><blockquote><p>注意：dsh 目前是 developer preview（v0.1 预览版），README 里大写加粗写着「THERE WILL BE COMPATIBILITY-BREAKING CHANGES」——接口会变，插件开发时留意版本，后续文章会讲怎么 pin 版本。</p></blockquote><h2 id="三、30-行写第一个插件：hello-走一个"><a href="#三、30-行写第一个插件：hello-走一个" class="headerlink" title="三、30 行写第一个插件：hello 走一个"></a>三、30 行写第一个插件：hello 走一个</h2><p>在仓库根目录建个临时目录，创建 <code>tmp/hello-plugin/hello.ts</code>：</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="keyword">type</span> &#123; <span class="title class_">Context</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;@deepseek-ai/cordis&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> name = <span class="string">&#x27;hello&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">apply</span>(<span class="params"><span class="attr">ctx</span>: <span class="title class_">Context</span></span>) &#123;</span><br><span class="line">  ctx.<span class="property">logger</span>.<span class="title function_">info</span>(<span class="string">&#x27;hello from my first plugin&#x27;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>再建一个 <code>cordis.yml</code>（Cordis 配置清单，loader 按它挂插件）：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> <span class="attr">name:</span> <span class="string">&#x27;./hello.ts&#x27;</span></span><br></pre></td></tr></table></figure><p>然后从 <code>tmp/hello-plugin</code> 目录用仓库自带的 vendored 启动器跑起来（<strong>这一步不需要 API Key</strong>）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">node --import tsx ../../vendor/cordis/bin.js</span><br></pre></td></tr></table></figure><p>预期输出：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[info] hello from my first plugin</span><br></pre></td></tr></table></figure><p>发生了什么？启动器创建根 Context 并挂上 Loader 插件 → Loader 读取 <code>cordis.yml</code> → 把 <code>./hello.ts</code> 作为子插件挂载 → Cordis 调用你的 <code>apply(ctx)</code>。链路通了，插件的「最小闭环」就成立了。</p><p>一个正式的函数插件通常导出四样东西，认识一下：</p><table><thead><tr><th>导出</th><th>作用</th></tr></thead><tbody><tr><td><code>name</code></td><td>插件显示名，仅用于诊断日志</td></tr><tr><td><code>inject</code></td><td>声明依赖的服务（如 <code>[&#39;tools&#39;]</code>），loader 会等它们就绪才执行 <code>apply</code></td></tr><tr><td><code>Config</code></td><td>可选，部署期配置的校验 schema</td></tr><tr><td><code>apply(ctx, config)</code></td><td>插件主体，注册一切能力</td></tr></tbody></table><p>两个细节：<strong>函数插件必须用命名导出</strong>（<code>export function apply</code>），别配默认导出，否则 loader 会丢掉 <code>inject</code> 元数据；有 <code>Config</code> 时 <code>apply</code> 签名是 <code>(ctx, config)</code>，没有时是 <code>(ctx)</code>。</p><h2 id="四、把插件挂到-dsh-上：三条路"><a href="#四、把插件挂到-dsh-上：三条路" class="headerlink" title="四、把插件挂到 dsh 上：三条路"></a>四、把插件挂到 dsh 上：三条路</h2><p>写好的插件怎么让 dsh 真正加载？三条路，按场景选：</p><p><strong>路 1：临时 overlay（调试最快）</strong>。写一个 patch 文件，用 <code>--patch</code> 参数启动：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># scratch-plugin/cordis.yml</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">insert:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">hello</span></span><br><span class="line">      <span class="attr">name:</span> <span class="string">&#x27;/绝对路径/to/deepseek-harness/scratch-plugin/src/hello.ts&#x27;</span></span><br></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pnpm dsh web --patch ./scratch-plugin/cordis.yml</span><br></pre></td></tr></table></figure><p>打开 <code>http://127.0.0.1:3080</code>（dsh Web UI 默认端口），终端里能看到 <code>[hello-plugin] plugin loaded!</code>。注意插件路径<strong>必须写绝对路径</strong>。</p><p><strong>路 2：外置插件（正式安装，推荐）</strong>。把插件做成独立 npm 包（package.json 里声明 <code>&quot;dsh&quot;: { &quot;bundle&quot;: { &quot;patch&quot;: &quot;./cordis.patch.yml&quot; } }</code>），然后用 <code>dsh plugin</code> 子命令装进 profile——它本质是在 profile 目录里调 pnpm，所以 pnpm 的子命令全能透传：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">dsh plugin --profile web add ./hello-plugin          <span class="comment"># 本地包</span></span><br><span class="line">dsh plugin --profile web add github:你的账号/你的仓库   <span class="comment"># Git 源，可加 #commit 锁版本</span></span><br><span class="line">dsh plugin --profile web remove hello-plugin          <span class="comment"># 卸载</span></span><br><span class="line">dsh plugin --profile web update                       <span class="comment"># 更新全部</span></span><br></pre></td></tr></table></figure><blockquote><p>profile 是 dsh 的「可运行环境」，目录在 <code>$DSH_HOME/profiles/&lt;名字&gt;/</code>，web、headless 是内置模板。装完插件记得<strong>重启 dsh web</strong>，宿主代码在启动时加载，只刷新页面不够。</p></blockquote><p><strong>路 3：看插件树 debug</strong>。插件装了却没生效，别对着界面猜，直接打印最终组合出来的配置树：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dsh --profile web --dump-config</span><br></pre></td></tr></table></figure><p>任何打印出来的行，都可以用你自己的 patch 按行 <code>id</code> 替换。记住 dsh 配置的<strong>四层加载顺序</strong>：profile bundles → profile 的 <code>cordis.patch.yml</code> → 家目录 <code>$DSH_HOME/cordis.patch.yml</code> → 每个 <code>--patch</code> overlay。后层按行胜出，patch 替换的是整行 config（不是深度合并），改一个字段也得把整行键重述一遍——这是新手最常踩的坑。</p><h2 id="五、实战：给模型加一个会干活的工具"><a href="#五、实战：给模型加一个会干活的工具" class="headerlink" title="五、实战：给模型加一个会干活的工具"></a>五、实战：给模型加一个会干活的工具</h2><p>插件最常见的用途就是<strong>给模型加工具</strong>。工具注册在 <code>ctx.tools</code> 上，schema 会自动进入 prompt 组装，模型就能「看到」它并主动调用。</p><p>下面是一个完整可运行的最小工具插件（<strong>30 行上下，名副其实</strong>）：让 Agent 能读文件。核心 API 是 <code>defineTool</code>（来自 <code>@deepseek-ai/dsh-tools</code>）+ <code>ctx.tools.register()</code>：</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; readFile &#125; <span class="keyword">from</span> <span class="string">&#x27;node:fs/promises&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="keyword">type</span> &#123; <span class="title class_">Context</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;@deepseek-ai/cordis&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; defineTool &#125; <span class="keyword">from</span> <span class="string">&#x27;@deepseek-ai/dsh-tools&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> name = <span class="string">&#x27;demo-tool&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> inject = [<span class="string">&#x27;tools&#x27;</span>]</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">apply</span>(<span class="params"><span class="attr">ctx</span>: <span class="title class_">Context</span></span>) &#123;</span><br><span class="line">  ctx.<span class="property">tools</span>.<span class="title function_">register</span>(<span class="title function_">defineTool</span>(&#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&#x27;read_file&#x27;</span>,</span><br><span class="line">    <span class="attr">description</span>: <span class="string">&#x27;Read a file from disk.&#x27;</span>,        <span class="comment">// 模型看到的能力描述</span></span><br><span class="line">    <span class="attr">parameters</span>: &#123;</span><br><span class="line">      <span class="attr">path</span>: &#123; <span class="attr">type</span>: <span class="string">&#x27;string&#x27;</span>, <span class="attr">required</span>: <span class="literal">true</span>, <span class="attr">description</span>: <span class="string">&#x27;Absolute path&#x27;</span> &#125;,</span><br><span class="line">      <span class="attr">limit</span>: &#123; <span class="attr">type</span>: <span class="string">&#x27;number&#x27;</span> &#125;,                    <span class="comment">// 可选项，默认不要求提供</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">output</span>: &#123;</span><br><span class="line">      <span class="attr">schema</span>: &#123; <span class="attr">type</span>: <span class="string">&#x27;string&#x27;</span> &#125;,</span><br><span class="line">      <span class="attr">render</span>: <span class="function">(<span class="params">_args, value</span>) =&gt;</span> [&#123; <span class="attr">type</span>: <span class="string">&#x27;text&#x27;</span>, <span class="attr">text</span>: value &#125;],</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="keyword">async</span> <span class="title function_">execute</span>(<span class="params">args, exec</span>) &#123;</span><br><span class="line">      <span class="comment">// args 已经被 defineTool 按 schema 校验并推导出类型</span></span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">readFile</span>(args.<span class="property">path</span>, &#123; <span class="attr">encoding</span>: <span class="string">&#x27;utf8&#x27;</span>, <span class="attr">signal</span>: exec.<span class="property">signal</span> &#125;)</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>拆开看 <code>execute()</code> 契约的几条硬规则：</p><ul><li><strong>args 自动校验</strong>：<code>defineTool</code> 会在 <code>execute</code> 前校验模型生成的参数（类型、必填、枚举、嵌套），你拿到的 <code>args</code> 类型和 schema 一致；</li><li><strong>只返回一个规范 JSON 值</strong>：<code>output.schema</code> 定义返回值，<code>execute</code> 只返回它；抛异常 &#x3D; 出错（<code>isError</code>），业务上的非理想状态（比如非零退出码）也要放进规范值返回；</li><li><strong>遵守 <code>exec.signal</code></strong>：信号触发时要取消进行中的工作，别硬扛；</li><li><strong>只注册一次</strong>：注册借用的是只读定义，事后别改 schema；想换工具就释放它所属的 effect 再注册新的。</li></ul><p>这样一个插件装好后，你在 Web UI 里跟 Agent 说「读一下 <code>/opt/xxx/config.yaml</code> 的前 50 行」，模型就会自己调 <code>read_file</code> 工具，把内容读回来再回答你——<strong>这就是给 Agent 装「手」的过程</strong>。</p><h2 id="六、进阶玩法：inject-依赖与事件钩子"><a href="#六、进阶玩法：inject-依赖与事件钩子" class="headerlink" title="六、进阶玩法：inject 依赖与事件钩子"></a>六、进阶玩法：inject 依赖与事件钩子</h2><p>不想加新工具，只想在某个环节「插一脚」？用<strong>事件钩子</strong>。dsh 主循环是事件驱动的，钩子插件就是往这些事件上挂监听器。比如下面这个权限门插件，在每次工具调用前拦截，按规则允许或拒绝：</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="keyword">type</span> &#123; <span class="title class_">Context</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;@deepseek-ai/cordis&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="keyword">type</span> &#123; <span class="title class_">PreToolDecision</span>, <span class="title class_">ToolExecution</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;@deepseek-ai/dsh-tools&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">declare</span> <span class="keyword">function</span> <span class="title function_">isAllowed</span>(<span class="params"><span class="attr">exec</span>: <span class="title class_">ToolExecution</span></span>): <span class="title class_">Promise</span>&lt;<span class="built_in">boolean</span>&gt;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> name = <span class="string">&#x27;permission-gate&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">apply</span>(<span class="params"><span class="attr">ctx</span>: <span class="title class_">Context</span></span>) &#123;</span><br><span class="line">  ctx.<span class="title function_">on</span>(<span class="string">&#x27;tools/pre-execute&#x27;</span>, <span class="title function_">async</span> (exec, next): <span class="title class_">Promise</span>&lt;<span class="title class_">PreToolDecision</span>&gt; =&gt; &#123;</span><br><span class="line">    <span class="keyword">if</span> (!(<span class="keyword">await</span> <span class="title function_">isAllowed</span>(exec))) &#123;</span><br><span class="line">      <span class="keyword">return</span> &#123; <span class="attr">kind</span>: <span class="string">&#x27;deny&#x27;</span>, <span class="attr">reason</span>: <span class="string">&#x27;Denied by policy.&#x27;</span> &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">next</span>()</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>tools/pre-execute</code> 是 <strong>waterfall 事件</strong>：监听器收到 <code>(...args, next)</code>，必须调用 <code>next()</code> 把结果传给下一个监听器；不调 <code>next()</code> 直接 return 就是短路（截断整条链）。这是写监听器最容易踩的坑——<strong>忘了 <code>next()</code></strong>。</p><p>常用扩展点速查：</p><table><thead><tr><th>你想做什么</th><th>用哪个</th></tr></thead><tbody><tr><td>允许 &#x2F; 拒绝 &#x2F; 询问工具调用</td><td><code>tools/pre-execute</code>，返回 <code>{ kind: &#39;deny&#39; }</code> &#x2F; <code>{ kind: &#39;ask&#39; }</code></td></tr><tr><td>工具调用必须被最终否决、不可撤销</td><td><code>ctx.tools.guard()</code></td></tr><tr><td>包裹工具执行生命周期（超时&#x2F;重试&#x2F;指标）</td><td><code>tools/execute</code></td></tr><tr><td>改写工具结果或呈现内容</td><td><code>tools/post-execute</code></td></tr><tr><td>只观察最终结果（审计&#x2F;记录）</td><td><code>tools/result</code></td></tr></tbody></table><h2 id="七、避坑提醒"><a href="#七、避坑提醒" class="headerlink" title="七、避坑提醒"></a>七、避坑提醒</h2><ul><li><strong>安全第一</strong>：插件跑在 dsh 宿主进程里，属于<strong>可信代码</strong>——装第三方插件前，先看它仓库是否公开、许可证和维护者是否清楚、要什么权限，别因为一行安装命令就跳过检查（官方文档自己都反复强调）；</li><li><strong>预览版接口会变</strong>：dsh 还是 v0.1 preview，插件契约可能随版本变动，开发时把 harness 版本记进 README，跟 GitHub Discussions 的变更公告；</li><li><strong>函数插件别配默认导出</strong>：会丢 <code>inject</code> 元数据，导致依赖的服务没就绪就执行 <code>apply</code>；</li><li><strong>patch 替换整行</strong>：不是深度合并，改一个键也要重述整行；</li><li><strong>跑真实模型要 API Key</strong>：工具插件要真正被模型调用，得有模型可跑。官方 key 直接填 <code>DEEPSEEK_API_KEY</code> 就行；想一个 Key 玩遍 Claude、GPT、Gemini、DeepSeek 全系模型，可以接 <strong>ai.aklibk.com</strong> 中转站——OpenAI 兼容接口、人民币按量付费，DeepSeek 系模型价格还便宜，settings 里改个 base URL 就换底层模型，插件的价值直接翻倍。</li></ul><blockquote><p>生命不息，折腾不止。下一篇《DeepSeek Harness 多 Agent 协作实战》，教你把一个大任务拆给多个 Agent 并行干活，让 dsh 从「单打独斗」升级成「团队作战」。</p></blockquote>]]>
    </content>
    <id>https://kqnb.me/2026/08/26/deepseek-harness-first-plugin/</id>
    <link href="https://kqnb.me/2026/08/26/deepseek-harness-first-plugin/"/>
    <published>2026-08-26T12:00:00.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p>生命不息，折腾不止。上次把 DeepSeek Harness 接上中转站只是「会用」，这篇带你走进它的灵魂——自己动手写插件，30 行代码给 Agent 加一个会干活的工具。</p>
</blockquote>
<h2 id="一、插件到底是个啥：]]>
    </summary>
    <title>dsh 写第一个插件：30 行给 Agent 加个会干活的工具</title>
    <updated>2026-08-26T11:18:15.823Z</updated>
  </entry>
  <entry>
    <author>
      <name>空缺</name>
    </author>
    <category term="技术折腾" scheme="https://kqnb.me/categories/%E6%8A%80%E6%9C%AF%E6%8A%98%E8%85%BE/"/>
    <category term="教程" scheme="https://kqnb.me/tags/%E6%95%99%E7%A8%8B/"/>
    <category term="AI" scheme="https://kqnb.me/tags/AI/"/>
    <category term="中转站" scheme="https://kqnb.me/tags/%E4%B8%AD%E8%BD%AC%E7%AB%99/"/>
    <category term="Cursor" scheme="https://kqnb.me/tags/Cursor/"/>
    <content>
      <![CDATA[<blockquote><p>生命不息，折腾不止。Cursor 好用，但内置模型要开 Pro 订阅（$20&#x2F;月）、还得绑海外卡。这篇讲清楚怎么给它接上中转站——改一行 Base URL，Claude、GPT 随便用，人民币按量付费，不用订阅、不用绑卡。</p></blockquote><h2 id="一、Cursor-为什么接中转站"><a href="#一、Cursor-为什么接中转站" class="headerlink" title="一、Cursor 为什么接中转站"></a>一、Cursor 为什么接中转站</h2><p>Cursor 是国内开发者用得最多的 AI 代码编辑器，但它的模型分两条路：</p><ol><li><strong>内置模型</strong>（GPT-4o、Claude 等）—— 要开 Pro 订阅，$20&#x2F;月，绑海外信用卡；</li><li><strong>自定义 API Key</strong> —— 填自己的 OpenAI 兼容 key，按量付费。</li></ol><p>接中转站就是走第二条路，好处很直接：</p><ul><li><strong>不用买 $20&#x2F;月订阅</strong>，充几块钱就能用；</li><li>Claude、GPT、Gemini 全都能调，<strong>人民币按量付费</strong>，用多少花多少；</li><li>中转站接口<strong>国内直连</strong>，不用折腾网络和绑卡。</li></ul><h2 id="二、三步接好中转站"><a href="#二、三步接好中转站" class="headerlink" title="二、三步接好中转站"></a>二、三步接好中转站</h2><p><strong>第一步：打开模型设置</strong></p><p>点 Cursor 右上角齿轮进 <strong>Cursor Settings</strong>，找到 <strong>Models</strong>（有的版本叫 <code>Models &amp; API Keys</code>）。</p><p><strong>第二步：填 Key 和 Base URL</strong></p><p>在 OpenAI API Key 区域：</p><ol><li>粘贴中转站的 <code>sk-</code> 开头的 Key；</li><li>勾选 <strong>Override OpenAI Base URL</strong>（覆盖默认地址）；</li><li>Base URL 填：<code>https://ai.aklibk.com/v1</code></li></ol><blockquote><p>⚠️ 结尾是 <code>/v1</code>：不要只填域名、不要补全到 <code>/chat/completions</code>、也不要在末尾多加斜杠。这一个输入框是 90% 接入失败的根源。</p></blockquote><p><strong>第三步：加模型并验证</strong></p><p>添加你要用的模型（如 <code>claude-sonnet-4-5</code>、<code>gpt-4o</code>，以中转站后台模型列表为准），点 <strong>Verify</strong> 验证，通过就能正常用了。</p><h2 id="三、两个高频坑"><a href="#三、两个高频坑" class="headerlink" title="三、两个高频坑"></a>三、两个高频坑</h2><ol><li><strong>Base URL 格式</strong>：必须是 <code>https://ai.aklibk.com/v1</code>，结尾 <code>/v1</code>，别多别少；</li><li><strong>模型名</strong>：必须和中转站后台的模型 ID 完全一致，填错一个字符 Verify 就过不了。</li></ol><h2 id="四、常见问题"><a href="#四、常见问题" class="headerlink" title="四、常见问题"></a>四、常见问题</h2><ul><li><strong>Verify 失败</strong>：先查 Base URL 是不是 <code>/v1</code> 结尾，再核对模型名；</li><li><strong>报 401</strong>：Key 没填对，去中转站后台重新复制令牌；</li><li><strong>能用哪些模型</strong>：Claude、GPT、Gemini、DeepSeek 都行，看中转站开通了哪些。</li></ul><h2 id="五、写在最后"><a href="#五、写在最后" class="headerlink" title="五、写在最后"></a>五、写在最后</h2><p>Cursor + 中转站，是把 AI 编程成本压到最低的组合——不用 $20 订阅、不用绑卡，按量付费想用多少用多少。中转站我平时用 ai.aklibk.com，Claude&#x2F;GPT&#x2F;Gemini&#x2F;DeepSeek 全系都有，人民币按量、注册即用。</p><blockquote><p>生命不息，折腾不止。后续继续分享 Cline、Roo Code 这些 AI 编程工具的接法。</p></blockquote>]]>
    </content>
    <id>https://kqnb.me/2026/08/22/cursor-zhongzhuan/</id>
    <link href="https://kqnb.me/2026/08/22/cursor-zhongzhuan/"/>
    <published>2026-08-22T13:00:00.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p>生命不息，折腾不止。Cursor 好用，但内置模型要开 Pro 订阅（$20&#x2F;月）、还得绑海外卡。这篇讲清楚怎么给它接上中转站——改一行 Base URL，Claude、GPT 随便用，人民币按量付费，不用订阅、不用绑卡。</p>
</b]]>
    </summary>
    <title>Cursor 接入中转站教程：改一行 Base URL，Claude/GPT 国内直连还便宜</title>
    <updated>2026-08-22T18:11:28.928Z</updated>
  </entry>
  <entry>
    <author>
      <name>空缺</name>
    </author>
    <category term="技术折腾" scheme="https://kqnb.me/categories/%E6%8A%80%E6%9C%AF%E6%8A%98%E8%85%BE/"/>
    <category term="教程" scheme="https://kqnb.me/tags/%E6%95%99%E7%A8%8B/"/>
    <category term="AI" scheme="https://kqnb.me/tags/AI/"/>
    <category term="中转站" scheme="https://kqnb.me/tags/%E4%B8%AD%E8%BD%AC%E7%AB%99/"/>
    <category term="DeepSeek" scheme="https://kqnb.me/tags/DeepSeek/"/>
    <category term="Agent" scheme="https://kqnb.me/tags/Agent/"/>
    <content>
      <![CDATA[<blockquote><p>生命不息，折腾不止。DeepSeek Harness（dsh）是 DeepSeek 官方出的插件化 Agent 框架，虽然名字带 DeepSeek，但它是「一切皆插件」——通过自定义 provider，Claude、GPT、Gemini、DeepSeek 全都能接进来，一个工具想用哪个切哪个。再配个中转站，按量付费还便宜。</p></blockquote><h2 id="一、DeepSeek-Harness-是什么"><a href="#一、DeepSeek-Harness-是什么" class="headerlink" title="一、DeepSeek Harness 是什么"></a>一、DeepSeek Harness 是什么</h2><p>DeepSeek Harness（<code>dsh</code>）是 DeepSeek AI 开源的一个 Agent 框架，核心设计是「一切皆插件」，底层基于 Cordis 架构。你在本地跑一个 Web UI，让 AI Agent 读写项目文件、执行命令、分解任务、维护计划，可以理解为「本地版 AI 编程助手」。</p><p>它最值钱的一点：<strong>不锁死 DeepSeek</strong>。原生支持「自定义 provider」，任何 OpenAI 兼容的接口都能接进来，等于一个框架吃下所有主流模型。</p><h2 id="二、两个真正的好处：多模型-便宜"><a href="#二、两个真正的好处：多模型-便宜" class="headerlink" title="二、两个真正的好处：多模型 + 便宜"></a>二、两个真正的好处：多模型 + 便宜</h2><p><strong>1. 一个工具，用遍所有模型</strong></p><p>Harness 里可以同时配多个 provider——Claude 一个、GPT 一个、Gemini 一个、DeepSeek 一个。写代码用 Claude、跑推理用 DeepSeek、多模态用 Gemini，同一个工作流里随意切换，不用装一堆客户端。</p><p><strong>2. 按量付费，比官方便宜</strong></p><p>中转站把 Claude、GPT、Gemini、DeepSeek 这些官方接口转成<strong>人民币按量付费</strong>的 OpenAI 兼容接口：</p><ul><li>不用绑海外信用卡、不用买官方订阅，充几块钱就能试；</li><li>按 token 计费，用多少花多少，比官方订阅&#x2F;按刀计费灵活太多。</li></ul><p>对想一次试遍各家模型的开发者来说，这是成本最低的玩法。</p><h2 id="三、安装-Harness"><a href="#三、安装-Harness" class="headerlink" title="三、安装 Harness"></a>三、安装 Harness</h2><p>先装好 Node.js，一条命令启动：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx @deepseek-ai/dsh web</span><br></pre></td></tr></table></figure><p>Web UI 默认跑在 <code>http://127.0.0.1:3080</code>（本地自动开浏览器；SSH 环境加 <code>--no-open</code>）。</p><h2 id="四、接入中转站（核心步骤）"><a href="#四、接入中转站（核心步骤）" class="headerlink" title="四、接入中转站（核心步骤）"></a>四、接入中转站（核心步骤）</h2><ol><li>打开 <strong>Settings → Models</strong></li><li>点 <strong>Add a custom provider</strong>（不是 <code>Add provider</code>，那个是官方目录）</li><li>按下面填写：<ul><li><strong>Provider ID</strong>：小写、唯一，比如 <code>claude</code>、<code>gpt</code>、<code>gemini</code>、<code>deepseek</code>（想接几个模型就建几个）</li><li><strong>Display name</strong>：随意，比如「Aklibk · Claude」</li><li><strong>Base URL</strong>：<code>https://ai.aklibk.com/v1</code></li><li><strong>API protocol</strong>：选 <code>OpenAI Completions</code></li><li><strong>API key</strong>：中转站后台生成的令牌（同一个 key 通吃所有模型）</li><li><strong>Model</strong>：按需填，例如 <code>claude-sonnet-4-5</code>、<code>gpt-4o</code>、<code>gemini-2.5-pro</code>、<code>deepseek-chat</code>，以中转站后台模型列表为准</li></ul></li><li>保存即可，<strong>不用重启服务</strong>，下一条请求就生效。</li></ol><blockquote><p>中转站里一个 API key 就能调用全部模型，所以你只需要建多个 provider（区分模型），共用同一个 Base URL 和 key 就行。</p></blockquote><h2 id="五、（进阶）用配置文件批量配"><a href="#五、（进阶）用配置文件批量配" class="headerlink" title="五、（进阶）用配置文件批量配"></a>五、（进阶）用配置文件批量配</h2><p>不想点 UI，直接改 <code>$DSH_HOME/settings.yaml</code>，一次配齐多个模型：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">llm-pi-ai:</span></span><br><span class="line">  <span class="attr">providers:</span></span><br><span class="line">    <span class="attr">claude:</span></span><br><span class="line">      <span class="attr">apiKeyEnv:</span> <span class="string">AKLIBK_API_KEY</span></span><br><span class="line">      <span class="attr">api:</span> <span class="string">openai-completions</span></span><br><span class="line">      <span class="attr">baseURL:</span> <span class="string">https://ai.aklibk.com/v1</span></span><br><span class="line">      <span class="attr">models:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">claude-sonnet-4-5</span></span><br><span class="line">    <span class="attr">gpt:</span></span><br><span class="line">      <span class="attr">apiKeyEnv:</span> <span class="string">AKLIBK_API_KEY</span></span><br><span class="line">      <span class="attr">api:</span> <span class="string">openai-completions</span></span><br><span class="line">      <span class="attr">baseURL:</span> <span class="string">https://ai.aklibk.com/v1</span></span><br><span class="line">      <span class="attr">models:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">gpt-4o</span></span><br><span class="line">    <span class="attr">deepseek:</span></span><br><span class="line">      <span class="attr">apiKeyEnv:</span> <span class="string">AKLIBK_API_KEY</span></span><br><span class="line">      <span class="attr">api:</span> <span class="string">openai-completions</span></span><br><span class="line">      <span class="attr">baseURL:</span> <span class="string">https://ai.aklibk.com/v1</span></span><br><span class="line">      <span class="attr">models:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">deepseek-chat</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">deepseek-reasoner</span></span><br></pre></td></tr></table></figure><p>Key 存在 <code>$DSH_HOME/.credentials.yaml</code>，settings 里只留引用。</p><h2 id="六、常见问题"><a href="#六、常见问题" class="headerlink" title="六、常见问题"></a>六、常见问题</h2><ul><li><strong>模型列表拉不到</strong>：Base URL 或协议填错了，确认是 <code>https://ai.aklibk.com/v1</code> + <code>OpenAI Completions</code>；</li><li><strong>请求 401</strong>：API key 没填对，去中转站后台重新复制令牌；</li><li><strong>某模型报错</strong>：确认中转站开了这条线，换个模型 ID 试。</li></ul><h2 id="七、写在最后"><a href="#七、写在最后" class="headerlink" title="七、写在最后"></a>七、写在最后</h2><p>DeepSeek Harness + 中转站，是「一个框架玩转所有主流模型」最省心的组合。中转站我平时用 ai.aklibk.com，Claude、GPT、Gemini、DeepSeek 全系都有，人民币按量付费、注册即用，想试哪家切哪家，成本还低。</p><blockquote><p>生命不息，折腾不止。后续继续分享 DeepSeek Harness 写插件、跑多 Agent 协作的玩法。</p></blockquote>]]>
    </content>
    <id>https://kqnb.me/2026/08/22/deepseek-harness-zhongzhuan/</id>
    <link href="https://kqnb.me/2026/08/22/deepseek-harness-zhongzhuan/"/>
    <published>2026-08-22T12:00:00.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p>生命不息，折腾不止。DeepSeek Harness（dsh）是 DeepSeek 官方出的插件化 Agent 框架，虽然名字带 DeepSeek，但它是「一切皆插件」——通过自定义 provider，Claude、GPT、Gemini、DeepS]]>
    </summary>
    <title>DeepSeek Harness 接入中转站：一个工具用遍 Claude/GPT/Gemini，按量付费超便宜</title>
    <updated>2026-08-22T18:06:51.526Z</updated>
  </entry>
  <entry>
    <author>
      <name>空缺</name>
    </author>
    <category term="技术折腾" scheme="https://kqnb.me/categories/%E6%8A%80%E6%9C%AF%E6%8A%98%E8%85%BE/"/>
    <category term="教程" scheme="https://kqnb.me/tags/%E6%95%99%E7%A8%8B/"/>
    <category term="AI" scheme="https://kqnb.me/tags/AI/"/>
    <category term="Claude Code" scheme="https://kqnb.me/tags/Claude-Code/"/>
    <category term="中转站" scheme="https://kqnb.me/tags/%E4%B8%AD%E8%BD%AC%E7%AB%99/"/>
    <content>
      <![CDATA[<blockquote><p>生命不息，折腾不止。Claude Code 是 Anthropic 官方的终端 AI 编程工具，写代码体验一流，但国内直接用有两道门槛：网络连不上、官方 API 要绑海外信用卡。这篇讲清楚怎么在国内把它配好，用中转站一步到位。</p></blockquote><h2 id="一、Claude-Code-是什么"><a href="#一、Claude-Code-是什么" class="headerlink" title="一、Claude Code 是什么"></a>一、Claude Code 是什么</h2><p>Claude Code 是 Anthropic 推出的命令行 AI 编程助手，装进终端里，能用自然语言帮你写代码、改 bug、跑测试、做 code review。相比网页版，它直接读你本地项目、改文件，编程效率提升明显。</p><h2 id="二、国内直接用的两道坎"><a href="#二、国内直接用的两道坎" class="headerlink" title="二、国内直接用的两道坎"></a>二、国内直接用的两道坎</h2><ol><li><strong>网络</strong>：Anthropic 的 API 在国内无法直连，直连会一直超时；</li><li><strong>支付</strong>：官方 API 按 token 计费，需要海外信用卡才能充值。</li></ol><p>这两道坎，正好是”中转站”存在的意义。</p><h2 id="三、中转站是什么、怎么解决"><a href="#三、中转站是什么、怎么解决" class="headerlink" title="三、中转站是什么、怎么解决"></a>三、中转站是什么、怎么解决</h2><p>中转站（API 网关）把 Claude、GPT、Gemini 这些官方模型接口，转成<strong>国内能直连、人民币按量付费</strong>的接口。你不用翻墙、不用绑卡，注册充个几块钱就能用，成本比官方还低。</p><p>以中转站 ai.aklibk.com 为例，它支持 Claude 全系模型，接入方式就是改两个环境变量。</p><h2 id="四、配置步骤（3-分钟搞定）"><a href="#四、配置步骤（3-分钟搞定）" class="headerlink" title="四、配置步骤（3 分钟搞定）"></a>四、配置步骤（3 分钟搞定）</h2><ol><li><p><strong>注册中转站拿 Key</strong>：打开 ai.aklibk.com 注册，后台「订阅&#x2F;令牌」里生成一个 API Key（复制好备用）。</p></li><li><p><strong>装 Claude Code</strong>（任选一种）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 方式一：npm（推荐）</span></span><br><span class="line">npm install -g @anthropic-ai/claude-code</span><br><span class="line"></span><br><span class="line"><span class="comment"># 方式二：一键脚本</span></span><br><span class="line">curl -fsSL https://claude.ai/install.sh | bash</span><br></pre></td></tr></table></figure></li><li><p><strong>设置中转站环境变量</strong>（关键一步）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">export</span> ANTHROPIC_BASE_URL=https://ai.aklibk.com</span><br><span class="line"><span class="built_in">export</span> ANTHROPIC_API_KEY=你的中转站Key</span><br></pre></td></tr></table></figure><p>把这两行写进 <code>~/.bashrc</code> 或 <code>~/.zshrc</code>，以后就不用重复设。</p></li><li><p><strong>启动</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">claude</span><br></pre></td></tr></table></figure><p>首次会问你登录方式，选「使用 API Key」即可，然后就能直接对话、写代码了。</p></li></ol><h2 id="五、常见问题"><a href="#五、常见问题" class="headerlink" title="五、常见问题"></a>五、常见问题</h2><ul><li><strong>报 401 &#x2F; 403</strong>：Key 没填对，或 base_url 拼错，检查下有没有多余空格；</li><li><strong>报连接超时</strong>：base_url 没设成中转站地址，还在连官方；</li><li><strong>模型怎么选</strong>：中转站后台一般有 Claude 多档模型可选，按需选，代码场景选能力强的，省着用可以选便宜档；</li><li><strong>贵不贵</strong>：按量计费，写一下午代码也就几毛到几块钱，比官方订阅灵活多了。</li></ul><h2 id="六、写在最后"><a href="#六、写在最后" class="headerlink" title="六、写在最后"></a>六、写在最后</h2><p>Claude Code + 中转站这套组合，是目前国内用 Claude 编程最省心的路子之一。如果你也在折腾 AI 编程工具，中转站可以直接用 ai.aklibk.com，注册即用、人民币按量付费，不折腾网络和绑卡。</p><blockquote><p>生命不息，折腾不止。后面继续分享 Cursor、Codex 这些 AI 编程工具的国内配置方法。</p></blockquote>]]>
    </content>
    <id>https://kqnb.me/2026/08/22/claude-code-zhongzhuan/</id>
    <link href="https://kqnb.me/2026/08/22/claude-code-zhongzhuan/"/>
    <published>2026-08-22T10:00:00.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p>生命不息，折腾不止。Claude Code 是 Anthropic 官方的终端 AI 编程工具，写代码体验一流，但国内直接用有两道门槛：网络连不上、官方 API 要绑海外信用卡。这篇讲清楚怎么在国内把它配好，用中转站一步到位。</p>
</bloc]]>
    </summary>
    <title>Claude Code 国内配置教程：免翻墙免绑卡，用中转站一步到位</title>
    <updated>2026-08-21T21:01:30.962Z</updated>
  </entry>
  <entry>
    <author>
      <name>空缺</name>
    </author>
    <category term="技术折腾" scheme="https://kqnb.me/categories/%E6%8A%80%E6%9C%AF%E6%8A%98%E8%85%BE/"/>
    <category term="教程" scheme="https://kqnb.me/tags/%E6%95%99%E7%A8%8B/"/>
    <category term="AI" scheme="https://kqnb.me/tags/AI/"/>
    <category term="ChatGPT" scheme="https://kqnb.me/tags/ChatGPT/"/>
    <content>
      <![CDATA[<blockquote><p>生命不息，折腾不止。这篇整理一份 ChatGPT 在中国大陆的完整安装教程：从网络环境、注册账号，到各平台客户端的下载安装，一次讲清楚。</p></blockquote><p><img src="/img/chatgpt-logo.svg" alt="ChatGPT 官方 Logo"></p><h2 id="先说结论"><a href="#先说结论" class="headerlink" title="先说结论"></a>先说结论</h2><p>在中国大陆使用 ChatGPT，<strong>一共四步</strong>：网络环境 → 注册账号 → 下载安装 → 登录使用。</p><p><img src="/img/chatgpt-steps.svg" alt="安装四步流程"></p><p>其中最容易卡住的是第二步（注册）：OpenAI <strong>不接受中国大陆的 +86 手机号</strong>，这是绝大多数人第一次尝试时被挡下的地方。下面按顺序走。</p><h2 id="第一步：网络环境"><a href="#第一步：网络环境" class="headerlink" title="第一步：网络环境"></a>第一步：网络环境</h2><p>ChatGPT 官网（chat.openai.com &#x2F; chatgpt.com）和官方客户端<strong>在中国大陆无法直接访问</strong>，需要可访问国际网络的网络环境（代理&#x2F;VPN），这一步是前提，没有它后面都白搭。</p><blockquote><p>⚠️ 请确保你的网络环境符合当地法律法规，本文仅作技术交流。</p></blockquote><h2 id="第二步：注册账号"><a href="#第二步：注册账号" class="headerlink" title="第二步：注册账号"></a>第二步：注册账号</h2><p>访问 <a href="https://chat.openai.com/">https://chat.openai.com</a>，点 <strong>Sign up</strong> 注册，建议全程在稳定的网络环境下操作。</p><p><strong>需要的材料：</strong></p><table><thead><tr><th align="left">材料</th><th align="left">要求</th><th align="left">说明</th></tr></thead><tbody><tr><td align="left">邮箱</td><td align="left">海外邮箱优先</td><td align="left">Gmail、Outlook 等；不建议用国内邮箱，收验证信容易出问题</td></tr><tr><td align="left">手机号</td><td align="left"><strong>海外手机号，不接受 +86</strong></td><td align="left">可用接码平台（一次性，适合体验）或 eSIM 虚拟号（长期稳定，推荐）</td></tr></tbody></table><p><strong>注册流程：</strong></p><ol><li>打开官网 → 点 Sign up → 用邮箱或 Google&#x2F;Microsoft 账号注册</li><li>查收验证邮件，点击确认链接</li><li>输入手机号接收短信验证码（<strong>这是关键一步，必须是非中国大陆号码</strong>）</li><li>设置密码，完成注册</li></ol><blockquote><p>💡 小建议：如果只是临时体验，一次性接码号够用；如果打算长期使用甚至升级 Plus，建议一开始就用稳定的虚拟号，避免后面换号引发账号风控。</p></blockquote><h2 id="第三步：下载安装客户端"><a href="#第三步：下载安装客户端" class="headerlink" title="第三步：下载安装客户端"></a>第三步：下载安装客户端</h2><h3 id="🪟-Windows"><a href="#🪟-Windows" class="headerlink" title="🪟 Windows"></a>🪟 Windows</h3><ul><li><strong>官方桌面版</strong>：到官网 <a href="https://openai.com/chatgpt/download">https://openai.com/chatgpt/download</a> 下载 Windows 安装包</li><li><strong>Microsoft Store</strong>：直接搜索 “ChatGPT” 安装（微软商店版更新最省心）</li></ul><h3 id="🍎-macOS"><a href="#🍎-macOS" class="headerlink" title="🍎 macOS"></a>🍎 macOS</h3><p>官网下载 <code>.dmg</code> 安装包，拖进”应用程序”即可。</p><h3 id="📱-iPhone-iPad（iOS）"><a href="#📱-iPhone-iPad（iOS）" class="headerlink" title="📱 iPhone &#x2F; iPad（iOS）"></a>📱 iPhone &#x2F; iPad（iOS）</h3><p><strong>关键点：需要海外 Apple ID</strong>，因为中国大陆区的 App Store 没有 ChatGPT：</p><ol><li>注册&#x2F;切换一个海外区 Apple ID（美区等）</li><li>App Store 搜索 “ChatGPT” → 下载</li><li>下载完成后可以切回国内 ID，App 不受影响</li></ol><h3 id="🤖-Android"><a href="#🤖-Android" class="headerlink" title="🤖 Android"></a>🤖 Android</h3><ul><li>有 Google Play 的设备：直接在 Play 商店搜索 “ChatGPT” 安装</li><li>没有 Google Play：下载官方 APK 安装包手动安装（注意核对来源，认准官方渠道）</li></ul><h2 id="第四步：登录使用"><a href="#第四步：登录使用" class="headerlink" title="第四步：登录使用"></a>第四步：登录使用</h2><p>打开客户端 → 用刚才注册的账号登录 → 开始对话。</p><p>免费版就能满足日常问答、写作、翻译等需求。需要更强模型、更长上下文、更高频次的话，可以考虑升级：</p><table><thead><tr><th align="left">档位</th><th align="left">价格</th><th align="left">适合</th></tr></thead><tbody><tr><td align="left"><strong>Free</strong></td><td align="left">$0</td><td align="left">日常体验</td></tr><tr><td align="left"><strong>Plus</strong></td><td align="left">约 $20&#x2F;月</td><td align="left">日常高频使用</td></tr><tr><td align="left"><strong>Pro</strong></td><td align="left">约 $200&#x2F;月</td><td align="left">重度专业用户</td></tr></tbody></table><blockquote><p>💰 付费提醒：国内发行的信用卡在 OpenAI 支付页面<strong>大概率被风控拦截</strong>，需要用海外信用卡或虚拟信用卡（Visa&#x2F;Mastercard 虚拟卡）支付。</p></blockquote><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><p><strong>Q：收不到短信验证码？</strong><br>检查号码是否真的为海外号（+86 不行），或换一个接码平台重试。</p><p><strong>Q：登录时提示 “Unable to load site”？</strong><br>通常是网络环境不稳定，换个节点或刷新重试。</p><p><strong>Q：会不会封号？</strong><br>用一次性接码号注册、IP 频繁跳变、多账号同 IP 都容易触发风控。稳定使用建议：固定网络环境、正规虚拟号、别干批量注册的事。</p><p><strong>Q：扣款失败会怎样？</strong><br>虚拟卡额度不足或过期会导致续费失败，轻则降级，重则账号异常。订阅后记得保证卡内余额充足。</p><h2 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h2><p>如果只是偶尔想用 AI 写点东西，其实不一定要死磕 ChatGPT 官方这套流程——<strong>API 中转方式</strong>对国内用户更省心：</p><ul><li>不用折腾海外手机号、虚拟信用卡</li><li>人民币付款，按量计费</li><li>一个 Key 同时调用 GPT、Claude、Gemini 等主流模型</li></ul><p>我在用的中转站是 <a href="https://ai.aklibk.com/"><strong>Aklibk API 中转站</strong></a>（ai.aklibk.com），稳定、便宜，注册即用，也可以接 Claude Code、Codex 等编程工具，适合开发者或需要稳定调用的场景。</p><p>无论如何，希望这份教程能帮你顺利用上 ChatGPT。折腾快乐！</p>]]>
    </content>
    <id>https://kqnb.me/2026/08/14/chatgpt-china-install/</id>
    <link href="https://kqnb.me/2026/08/14/chatgpt-china-install/"/>
    <published>2026-08-14T14:30:00.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p>生命不息，折腾不止。这篇整理一份 ChatGPT 在中国大陆的完整安装教程：从网络环境、注册账号，到各平台客户端的下载安装，一次讲清楚。</p>
</blockquote>
<p><img src="/img/chatgpt-logo.svg" a]]>
    </summary>
    <title>ChatGPT 在中国大陆的安装教程</title>
    <updated>2026-08-14T16:14:08.790Z</updated>
  </entry>
  <entry>
    <author>
      <name>空缺</name>
    </author>
    <category term="技术折腾" scheme="https://kqnb.me/categories/%E6%8A%80%E6%9C%AF%E6%8A%98%E8%85%BE/"/>
    <category term="教程" scheme="https://kqnb.me/tags/%E6%95%99%E7%A8%8B/"/>
    <category term="AI" scheme="https://kqnb.me/tags/AI/"/>
    <category term="工具" scheme="https://kqnb.me/tags/%E5%B7%A5%E5%85%B7/"/>
    <content>
      <![CDATA[<blockquote><p>生命不息，折腾不止。上一篇写了 Sub2API 部署，这篇配套来一个桌面小工具：CC Switch —— 装好它，Claude Code、Codex 的 API 供应商配置就能像换壁纸一样一键切换。</p></blockquote><h2 id="这是什么"><a href="#这是什么" class="headerlink" title="这是什么"></a>这是什么</h2><p><a href="https://github.com/farion1231/cc-switch">CC Switch</a> 是一个开源的<strong>跨平台桌面工具</strong>（GitHub 上 <strong>127k+ stars</strong>），专为 AI 编程工具设计：</p><ul><li>支持 <strong>Claude Code、Codex、OpenCode、OpenClaw、Grok Build、Hermes Agent</strong> 等主流工具</li><li>把多个 <strong>API 供应商配置</strong>（官方、各种中转站）存起来，<strong>点一下就能切换</strong>，不用再手动改配置文件</li><li>还带 MCP 服务器管理、配置导入导出、<strong>速度测试</strong>（测每个中转的延迟）、会话历史浏览等功能</li></ul><p>简单说：<strong>你手里有 N 个中转站&#x2F;Key，CC Switch 就是它们的遥控器。</strong></p><p>技术栈：Tauri 2（Rust 后端 + React 前端）原生桌面应用，数据存在本地 SQLite（<code>~/.cc-switch/cc-switch.db</code>），轻量不占资源。</p><h2 id="下载安装"><a href="#下载安装" class="headerlink" title="下载安装"></a>下载安装</h2><p>最新版本 <strong>v3.19.2</strong>（2026-08-06 发布），下载地址：<a href="https://github.com/farion1231/cc-switch/releases">https://github.com/farion1231/cc-switch/releases</a></p><p><strong>系统要求</strong>：Windows 10+ &#x2F; macOS 12+ &#x2F; Linux（Ubuntu 22.04+、Debian 11+、Fedora 34+）</p><h3 id="🪟-Windows"><a href="#🪟-Windows" class="headerlink" title="🪟 Windows"></a>🪟 Windows</h3><p>二选一：</p><ol><li><strong>安装版</strong>：下载 <code>CC-Switch-v3.19.2-Windows.msi</code>，双击安装</li><li><strong>绿色版</strong>：下载 <code>CC-Switch-v3.19.2-Windows-Portable.zip</code>，解压即用，免安装</li></ol><h3 id="🍎-macOS"><a href="#🍎-macOS" class="headerlink" title="🍎 macOS"></a>🍎 macOS</h3><p><strong>方式一：Homebrew（推荐）</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew install --cask cc-switch</span><br></pre></td></tr></table></figure><p><strong>方式二：手动下载</strong> <code>CC-Switch-v3.19.2-macOS.dmg</code>，拖进应用程序即可。<br>（macOS 版已通过苹果签名公证，不会提示”无法打开”）</p><h3 id="🐧-Linux"><a href="#🐧-Linux" class="headerlink" title="🐧 Linux"></a>🐧 Linux</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Debian / Ubuntu</span></span><br><span class="line">wget https://github.com/farion1231/cc-switch/releases/download/v3.19.2/CC-Switch-v3.19.2-Linux-x86_64.deb</span><br><span class="line"><span class="built_in">sudo</span> dpkg -i CC-Switch-v3.19.2-Linux-x86_64.deb</span><br><span class="line"></span><br><span class="line"><span class="comment"># Fedora / RHEL</span></span><br><span class="line"><span class="built_in">sudo</span> dnf install CC-Switch-v3.19.2-Linux-x86_64.rpm</span><br><span class="line"></span><br><span class="line"><span class="comment"># 通用 AppImage（任何发行版）</span></span><br><span class="line"><span class="built_in">chmod</span> +x CC-Switch-v3.19.2-Linux-x86_64.AppImage</span><br><span class="line">./CC-Switch-v3.19.2-Linux-x86_64.AppImage</span><br><span class="line"></span><br><span class="line"><span class="comment"># Arch Linux</span></span><br><span class="line">paru -S cc-switch-bin</span><br></pre></td></tr></table></figure><h2 id="基本使用"><a href="#基本使用" class="headerlink" title="基本使用"></a>基本使用</h2><p>安装后打开，主界面长这样：</p><p><img src="/img/cc-switch-main.png" alt="CC Switch 主界面"></p><p>三步上手：</p><ol><li><strong>添加供应商</strong>：点”添加”，填入名称、API 地址、API Key（就是中转站给你的那串）</li></ol><p><img src="/img/cc-switch-add.png" alt="添加供应商"></p><ol start="2"><li><strong>设为当前</strong>：选中要用的供应商点”切换”，CC Switch 会自动写入 Claude Code &#x2F; Codex 的配置文件</li><li><strong>随时切换</strong>：换供应商点一下就行；还能用内置的<strong>速度测试</strong>比较各中转站的延迟，挑快的用</li></ol><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><ul><li><strong>供应商和工具怎么对应？</strong> 每个供应商可以单独设置支持哪些工具（Claude Code &#x2F; Codex &#x2F; …），切换时只影响勾选的那些</li><li><strong>数据存在哪？</strong> 本地 SQLite：<code>~/.cc-switch/cc-switch.db</code>，支持配置导入导出，换电脑可以直接备份</li><li><strong>macOS 打不开？</strong> 到”系统设置 → 隐私与安全性”里允许”仍要打开”（新版已签名公证，一般不会遇到）</li></ul><h2 id="其他版本"><a href="#其他版本" class="headerlink" title="其他版本"></a>其他版本</h2><ul><li><strong>CLI 版</strong>：<a href="https://github.com/SaladDay/cc-switch-cli">cc-switch-cli</a>（4.6k stars）——终端党专用，纯命令行切换</li><li><strong>Web 版</strong>：<a href="https://github.com/Laliet/cc-switch-web">cc-switch-web</a>（500 stars）——可部署到服务器，浏览器访问</li></ul><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li>项目主页：<a href="https://github.com/farion1231/cc-switch">https://github.com/farion1231/cc-switch</a></li><li>官方网站：<a href="https://ccswitch.io/">https://ccswitch.io</a></li><li>更新日志：<a href="https://github.com/farion1231/cc-switch/blob/main/CHANGELOG.md">https://github.com/farion1231/cc-switch/blob/main/CHANGELOG.md</a></li></ul>]]>
    </content>
    <id>https://kqnb.me/2026/08/14/cc-switch-install/</id>
    <link href="https://kqnb.me/2026/08/14/cc-switch-install/"/>
    <published>2026-08-14T14:00:00.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p>生命不息，折腾不止。上一篇写了 Sub2API 部署，这篇配套来一个桌面小工具：CC Switch —— 装好它，Claude Code、Codex 的 API 供应商配置就能像换壁纸一样一键切换。</p>
</blockquote>
<h2 id]]>
    </summary>
    <title>CC Switch 安装教程：AI 编程工具配置一键切换</title>
    <updated>2026-08-14T16:14:08.778Z</updated>
  </entry>
  <entry>
    <author>
      <name>空缺</name>
    </author>
    <category term="技术折腾" scheme="https://kqnb.me/categories/%E6%8A%80%E6%9C%AF%E6%8A%98%E8%85%BE/"/>
    <category term="AI" scheme="https://kqnb.me/tags/AI/"/>
    <category term="部署" scheme="https://kqnb.me/tags/%E9%83%A8%E7%BD%B2/"/>
    <category term="Docker" scheme="https://kqnb.me/tags/Docker/"/>
    <content>
      <![CDATA[<blockquote><p>生命不息，折腾不止。这篇记录一下 Sub2API 的完整部署过程，包括 Docker Compose 部署、反向代理、HTTPS 证书等实战经验。</p></blockquote><h2 id="这是什么"><a href="#这是什么" class="headerlink" title="这是什么"></a>这是什么</h2><p><a href="https://github.com/Wei-Shaw/sub2api">Sub2API</a> 是一个开源的 AI API 网关中转项目（GitHub 上 <strong>37k+ stars</strong>），核心功能是：</p><ul><li><strong>一个订阅，全家共享</strong>：把 Claude、ChatGPT、Gemini、Grok 等官方订阅接入进来，按配额分配给多个用户&#x2F;工具使用，也就是俗称的”拼车”</li><li><strong>原生工具无缝使用</strong>：接入后，Claude Code、Codex、Gemini CLI 等原生工具可以直接指向自己的服务地址，体验和官方几乎一致</li><li><strong>自带管理后台</strong>：账号管理、配额分配、用量统计，还内置了支付系统（易支付 &#x2F; 支付宝 &#x2F; 微信 &#x2F; Stripe），开箱即用</li></ul><p>简单说：<strong>订阅是”一个包月账号”，Sub2API 把它变成”一个 API 服务”，谁都能用。</strong></p><p>技术栈：Go 后端 + Vue 前端管理面板 + PostgreSQL + Redis，Docker 一键部署。</p><h2 id="架构一览"><a href="#架构一览" class="headerlink" title="架构一览"></a>架构一览</h2><p><img src="/img/sub2api-arch.svg" alt="Sub2API 部署架构"></p><p>整个链路分三块：</p><table><thead><tr><th align="left">部分</th><th align="left">说明</th></tr></thead><tbody><tr><td align="left"><strong>订阅源</strong></td><td align="left">Claude Pro &#x2F; ChatGPT Plus &#x2F; Gemini &#x2F; Grok 等官方订阅</td></tr><tr><td align="left"><strong>Sub2API 网关</strong></td><td align="left">核心服务（配额分配 + API 中转 + 管理后台），搭配 PostgreSQL（数据）和 Redis（缓存&#x2F;队列）</td></tr><tr><td align="left"><strong>使用端</strong></td><td align="left">Claude Code、Codex、Gemini CLI、任意 OpenAI 兼容客户端</td></tr></tbody></table><h2 id="部署步骤"><a href="#部署步骤" class="headerlink" title="部署步骤"></a>部署步骤</h2><h3 id="前置条件"><a href="#前置条件" class="headerlink" title="前置条件"></a>前置条件</h3><ul><li>一台 Linux 服务器（本教程用 Docker 方式，不需要会编程）</li><li>Docker 20.10+ 和 Docker Compose v2+</li></ul><h3 id="方式一：官方一键脚本（最省事）"><a href="#方式一：官方一键脚本（最省事）" class="headerlink" title="方式一：官方一键脚本（最省事）"></a>方式一：官方一键脚本（最省事）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建部署目录</span></span><br><span class="line"><span class="built_in">mkdir</span> -p sub2api-deploy &amp;&amp; <span class="built_in">cd</span> sub2api-deploy</span><br><span class="line"></span><br><span class="line"><span class="comment"># 下载并运行部署准备脚本（自动生成密钥、下载 compose 模板）</span></span><br><span class="line">curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动</span></span><br><span class="line">docker compose up -d</span><br></pre></td></tr></table></figure><p>脚本会自动生成 <code>JWT_SECRET</code>、<code>TOTP_ENCRYPTION_KEY</code>、<code>POSTGRES_PASSWORD</code> 等安全凭证并写入 <code>.env</code>，记得保存好输出的凭证。</p><h3 id="方式二：手动部署（可控性更强）"><a href="#方式二：手动部署（可控性更强）" class="headerlink" title="方式二：手动部署（可控性更强）"></a>方式二：手动部署（可控性更强）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 克隆仓库</span></span><br><span class="line">git <span class="built_in">clone</span> https://github.com/Wei-Shaw/sub2api.git</span><br><span class="line"><span class="built_in">cd</span> sub2api/deploy</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 复制环境变量模板</span></span><br><span class="line"><span class="built_in">cp</span> .env.example .<span class="built_in">env</span></span><br><span class="line"><span class="built_in">chmod</span> 600 .<span class="built_in">env</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 生成安全密钥</span></span><br><span class="line">openssl rand -hex 32   <span class="comment"># 用作 JWT_SECRET</span></span><br><span class="line">openssl rand -hex 32   <span class="comment"># 用作 TOTP_ENCRYPTION_KEY</span></span><br><span class="line">openssl rand -hex 32   <span class="comment"># 用作 POSTGRES_PASSWORD</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 编辑 .env，至少填这几项</span></span><br><span class="line"><span class="comment"># POSTGRES_PASSWORD=上面生成的</span></span><br><span class="line"><span class="comment"># JWT_SECRET=上面生成的</span></span><br><span class="line"><span class="comment"># TOTP_ENCRYPTION_KEY=上面生成的</span></span><br><span class="line"><span class="comment"># ADMIN_EMAIL=admin@example.com</span></span><br><span class="line"><span class="comment"># ADMIN_PASSWORD=你的管理员密码</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 创建数据目录并启动</span></span><br><span class="line"><span class="built_in">mkdir</span> -p data postgres_data redis_data</span><br><span class="line">docker compose up -d</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 查看状态和日志</span></span><br><span class="line">docker compose ps</span><br><span class="line">docker compose logs -f sub2api</span><br></pre></td></tr></table></figure><h3 id="两种-Compose-模板怎么选"><a href="#两种-Compose-模板怎么选" class="headerlink" title="两种 Compose 模板怎么选"></a>两种 Compose 模板怎么选</h3><table><thead><tr><th align="left">模板</th><th align="left">数据存储</th><th align="left">迁移便利性</th><th align="left">适用场景</th></tr></thead><tbody><tr><td align="left"><code>docker-compose.local.yml</code></td><td align="left">本地目录</td><td align="left">✅ 打包整个目录即可</td><td align="left">生产环境、频繁备份</td></tr><tr><td align="left"><code>docker-compose.yml</code></td><td align="left">Docker 命名卷</td><td align="left">⚠️ 需要 docker 命令</td><td align="left">简单体验</td></tr></tbody></table><p>推荐用 <code>docker-compose.local.yml</code>（数据在本地目录，备份迁移都方便）。</p><h3 id="初始管理员"><a href="#初始管理员" class="headerlink" title="初始管理员"></a>初始管理员</h3><p>如果是手动部署，首次启动后管理员账号密码会在日志里输出：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker compose logs sub2api | grep <span class="string">&quot;admin password&quot;</span></span><br></pre></td></tr></table></figure><p>用日志里的账号登录管理后台，<strong>首次登录会强制要求修改密码</strong>。之后就可以在后台添加订阅、创建用户、分配配额了。</p><h2 id="反向代理-HTTPS（实战经验）"><a href="#反向代理-HTTPS（实战经验）" class="headerlink" title="反向代理 + HTTPS（实战经验）"></a>反向代理 + HTTPS（实战经验）</h2><p>服务默认监听 <code>8080</code> 端口。<strong>安全第一</strong>：不要让 8080 直接暴露公网，建议：</p><ol><li><strong>只绑定本机回环地址</strong>（<code>.env</code> 里 <code>BIND_HOST=127.0.0.1</code>），对外只开放 80&#x2F;443</li><li>用 Nginx &#x2F; OpenResty 做反向代理</li><li>套一层 HTTPS 证书</li></ol><p>我的部署是：<strong>Cloudflare 灰云解析 → OpenResty 反向代理 → 127.0.0.1:8080</strong>，证书用 Let’s Encrypt（acme.sh 自动续期，到期前自动换新），HTTP 访问自动 301 跳转 HTTPS。</p><p>关键配置参考：</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">    <span class="attribute">listen</span> <span class="number">80</span>;</span><br><span class="line">    <span class="attribute">server_name</span> sub-api.example.com;</span><br><span class="line">    <span class="attribute">return</span> <span class="number">301</span> https://<span class="variable">$host</span><span class="variable">$request_uri</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">    <span class="attribute">listen</span> <span class="number">443</span> ssl;</span><br><span class="line">    <span class="attribute">server_name</span> sub-api.example.com;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">ssl_certificate</span>     /path/to/fullchain.pem;</span><br><span class="line">    <span class="attribute">ssl_certificate_key</span> /path/to/privkey.pem;</span><br><span class="line"></span><br><span class="line">    <span class="section">location</span> / &#123;</span><br><span class="line">        <span class="attribute">proxy_pass</span> http://127.0.0.1:8080;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> Host <span class="variable">$host</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> X-Real-IP <span class="variable">$remote_addr</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> X-Forwarded-For <span class="variable">$proxy_add_x_forwarded_for</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> X-Forwarded-Proto <span class="variable">$scheme</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>小坑提醒：如果 Nginx&#x2F;OpenResty 跑在 Docker 容器里，证书路径必须是<strong>挂载进容器的目录</strong>，容器内看不到宿主机其他路径的证书文件。</p></blockquote><h2 id="升级与维护"><a href="#升级与维护" class="headerlink" title="升级与维护"></a>升级与维护</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 拉取最新镜像</span></span><br><span class="line">docker compose pull</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重新创建容器</span></span><br><span class="line">docker compose up -d</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启</span></span><br><span class="line">docker compose restart</span><br></pre></td></tr></table></figure><p>也可以直接在**管理后台左上角点”检测更新”**在线升级（支持一键更新和回滚）。</p><p>日常维护就三件事：备份数据目录、定期升级、看日志。</p><h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><ul><li>⚠️ <strong>上游条款风险</strong>：该项目官方声明，使用它可能违反 Anthropic 等上游服务商的用户协议，账号风险自行承担，请确认合规后再使用</li><li>📖 项目仅供技术学习与研究，作者不对账号封禁、服务中断、数据丢失等损失负责</li><li>🚫 未经授权，请勿用本项目从事商业运营</li></ul><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li>项目主页：<a href="https://github.com/Wei-Shaw/sub2api">https://github.com/Wei-Shaw/sub2api</a></li><li>部署文档：仓库 <code>deploy/</code> 目录（含 Caddyfile、Docker 说明、数据管理进程说明等）</li></ul>]]>
    </content>
    <id>https://kqnb.me/2026/08/14/sub2api-deploy/</id>
    <link href="https://kqnb.me/2026/08/14/sub2api-deploy/"/>
    <published>2026-08-14T13:30:00.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p>生命不息，折腾不止。这篇记录一下 Sub2API 的完整部署过程，包括 Docker Compose 部署、反向代理、HTTPS 证书等实战经验。</p>
</blockquote>
<h2 id="这是什么"><a href="#这是什么" cl]]>
    </summary>
    <title>Sub2API 部署全记录：把 AI 订阅变成 API 中转</title>
    <updated>2026-08-14T16:14:08.790Z</updated>
  </entry>
</feed>
