MiniMax 搜索接入指南

August 21, 2026 · View on GitHub

让 DSH(以及经桥接器的钉钉会话)的 web_search 使用 MiniMax「coding_plan/search」 真实网页搜索, 替代随 DSH 内置但 key 失效的 DeepSeek 官方搜索(deepseek-official / dspark 无效 key)。 本文是已验证生效的一键指南(2026-08 本机完成)。


一、原理速览

MiniMax 搜索是纯 HTTP API,无需 MCP / 子进程:

POST https://api.minimaxi.com/v1/coding_plan/search   (国内 minimaxi.com)
POST https://api.minimax.io/v1/coding_plan/search     (国际 minimax.io)
Headers: Authorization: Bearer <MINIMAX_API_KEY>
Body:    { "q": "查询词" }
响应:    { organic: [{title, link, snippet, date}], related_searches: [...] }

接入动作三件套(都在 DSH 宿主侧):

#文件(仓库 deepseek-harness-plugin作用
1plugins/minimax-search/minimax-search.mjs插件源码(仓库唯一真相源)→ 脚手架同步到宿主
2宿主 ~/.dsh/profiles/web/cordis.patch.yml停用内置 DeepSeek + 把 web.searchProvider 指向 minimax + 插入插件行
3key 配置(三选一)新逻辑默认走 ctx.credentials(界面可写/轮换不重启);兼容 ~/.dsh/.envMINIMAX_API_KEY 与 patch 里字面 config.apiKey

2026-08-21 适配(dsh 0.1.1-rc.2):凭据解析已对齐官方 dsh-web-search-deepseek 的新逻辑—— 优先级 config.apiKey(字面)> ctx.credentials.resolve(apiKeyEnv) > launchEnvironment 快照, 并接入 @deepseek-ai/dsh-webWebErrorWEB_PROVIDER_ERROR / WEB_ABORTED)。


二、前置条件

  • 一台装了 DSH 并跑着 dsh web 的机器(profile 为 web)。
  • MiniMax API keysk- 开头,MiniMax 开放平台 / tokenPlan 套餐)——放 ~/.zshrc 或便于导出即可,最终会进 ~/.dsh/.env
  • 能访问 api.minimaxi.com(国内)或 api.minimax.io(国际)。

三、接入步骤

第 1 步:确认 key 可用(快速验证)

# 从 .zshrc 提取(不打印明文)
KEY=$(grep -m1 '^export MINIMAX_API_KEY=' ~/.zshrc | sed 's/^export MINIMAX_API_KEY=//; s/["'"'"']//g')
echo "key 长度: ${#KEY}, 前缀: ${KEY:0:4}"

# 验证 API
curl -s -X POST 'https://api.minimaxi.com/v1/coding_plan/search' \
  -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
  -d '{"q":"测试"}' | python3 -c "import json,sys; d=json.load(sys.stdin); print('organic 条数:', len(d.get('organic',[])))"

期望:organic 条数: >=1。(否则 key 无效或区域不对,换 api.minimax.io。)

第 2 步:用脚手架安装插件(仓库 → 宿主)

插件源码在本仓库 plugins/minimax-search/minimax-search.mjs仓库是唯一真相源。 用脚手架脚本同步到 DSH 宿主(不需要手动写宿主文件):

cd deepseek-harness-plugin        # 本仓库根目录
npm run install:plugins           # 同步 plugins/ → ~/.dsh/profiles/web/plugins/
# 若要装到别的 profile:DSH_PROFILE=tui npm run install:plugins

预期输出:

✅ 安装插件 [minimax-search] → /Users/.../.dsh/profiles/web/plugins/ (minimax-search.mjs)
已完成:共安装 1 个文件。

之后每次改 plugins/minimax-search/ 里的源码,重跑一次 npm run install:plugins 即可。 脚手架脚本见 scripts/install-plugins.mjs

要点(如需手写/看懂插件):

  • 导出 { name, inject: ['web'], apply(ctx, config) }(同步 apply)。
  • apply 里调用 ctx.web.registerSearchProvider(new MiniMaxSearchProvider({...}))
  • 凭据解析优先级 config.apiKey(字面)> ctx.credentials.resolve(apiKeyEnv) > launchEnvironment 快照; resolveApiKey() 每次调用实时解析,credentials 缺席自动降级(零配置可用)。
  • 错误走 @deepseek-ai/dsh-webWebErrorWEB_PROVIDER_ERROR / WEB_ABORTED),与官方 provider 同构。
  • 绝不使用 process.env:宿主插件环境没有 process(会抛 ReferenceError)。
  • fetch 是全局可用(与内置 dsh-web-search-deepseek 同款用法)。
  • 官方 seam 包经宿主锚点~/.dsh/profiles)惰性解析(createRequire),解析不到自动降级为纯 fetch + 环境变量的旧行为。

第 3 步:配置宿主 patch

编辑 ~/.dsh/profiles/web/cordis.patch.yml

# 1) 停用内置 DeepSeek 搜索(key 失效,会一直报 ****park is invalid)
- id: web-search-deepseek
  disabled: true

# 2) 把 web 的搜索选择指向我们的 minimax provider(关键!)
- id: web
  config:
    searchProvider: minimax

# 3) 插入我们的插件
- insert:
    - id: minimax-search
      name: ./plugins/minimax-search.mjs

⚠️ 为什么必须改 web.searchProviderdsh-base bundle 默认把 web.searchProvider 配成 deepseek-official。 只注册 minimax 不够,选择规则会因「已配置 id」永远选 DeepSeek。必须覆盖为 minimax

第 4 步:配置 API key(三选一,按推荐排序)

方式 A(新逻辑,推荐):写入 DSH 凭据服务 ~/.dsh/.credentials.yaml

DSH 0.1.1 起提供 ctx.credentials 凭据服务(dsh-base bundle 内置 dsh-credentials-local)。 把 key 存成凭据引用 MINIMAX_API_KEY,插件每次操作经 ctx.credentials.resolve() 实时解析—— 改配置界面即可轮换、无需重启 DSH、不进任何配置文件

# 写入凭据(source 层:local;同名进程环境会遮蔽它,见 dsh-credentials 文档)
# 官方 web 界面「Models」页写 DeepSeek key 走的就是这个通道;
# 手动命令行写入可参考官方 dsh-credentials-local 的写接口,或继续用方式 B。

方式 B(兼容,零配置):~/.dsh/.env(DSH 启动 loadLayeredEnv 会读它并注入 launchEnvironment 快照)

KEY=$(grep -m1 '^export MINIMAX_API_KEY=' ~/.zshrc | sed 's/^export MINIMAX_API_KEY=//; s/["'"'"']//g')
echo "MINIMAX_API_KEY=$KEY" > ~/.dsh/.env
chmod 600 ~/.dsh/.env

方式 C(最高优先级):patch 里字面 config.apiKey

- id: minimax-search
  name: ./plugins/minimax-search/minimax-search.mjs
  config:
    apiKey: sk-xxxx        # 字面量最高优先级(覆盖 credentials / 环境变量)
    apiKeyEnv: MINIMAX_API_KEY   # 可选:改凭据引用名(默认 MINIMAX_API_KEY)

第 5 步:生效与验证

  • patch 修改后 DSH 的 HMR 会自动重载,通常无需重启
  • 若 HMR 未生效(改插件文件本身时),重启 DSHkill <3080 监听 pid> && cd <harness 项目> && dsh web
  • 在任意 DSH 会话里调用 web_search 工具,应返回真实结果 + 来源链接:
输入: web_search("react 最新版本")
输出: 9 条真实结果(标题/URL/摘要),不再是 "Authentication Fails ... invalid"

四、坑与排错

现象原因解决
****park is invalid选到内置 DeepSeek(web.searchProvider 仍为 deepseek-official换成 minimax,且 web-search-deepseekdisabled: true
no usable web provider / WEB_PROVIDER_UNAVAILABLEminimax available() 为 false(key 没读到)检查 ~/.dsh/.envctx.credentials 有 key;插件 resolveApiKey 会实时解析
multiple usable ... AMBIGUOUS配了多个可用 provider 且未显式选web.config.searchProvider 里指定一个
插件不加载(lsof 看不到插件文件)patch 未生效 / 需重启确认 patch YAML 合法;重启 DSH
宿主插件里 process is not defined宿主环境无 process改用 launchEnvironmentOf(ctx) 读 env / key
WEB_ABORTED搜索被取消/超时(正常)无需处理;工具层会按取消处理

五、回滚

恢复 DSH 内置 DeepSeek 搜索(或换回原状):

# 1) 删掉宿主 patch 里的 minimax 相关条目
#    (web-search-deepseek disabled、web.searchProvider、insert)
# 2) 或直接备份还原 cordis.patch.yml
cp ~/.dsh/profiles/web/cordis.patch.yml ~/.dsh/profiles/web/cordis.patch.yml.bak   # 改前先备份
# 3) 想把插件文件也从宿主移除(仓库源码保留,不删)
rm ~/.dsh/profiles/web/plugins/minimax-search.mjs

建议:改宿主 patch 前先备份一份 cordis.patch.yml。 仓库 plugins/minimax-search/ 是源码;宿主是安装产物。回滚只在宿主侧操作即可,不动仓库源码。


附录 A:插件源码模板

当前实现见仓库 plugins/minimax-search/minimax-search.mjs唯一真相源,本附录为要点摘要; 用 npm run install:plugins 同步到宿主,勿手写宿主副本)。核心结构:

import { createRequire } from 'node:module'
import { join } from 'node:path'
import { homedir } from 'node:os'

// 宿主锚点解析官方 seam 包(~/.dsh/profiles 可触达全局 dsh 的 node_modules);
// 解析失败返回 null → 调用方降级,插件永远可加载。
function loadHostModule(name) {
  try {
    const req = createRequire(join(homedir(), '.dsh', 'profiles', '__probe__.cjs'))
    return req(name)
  } catch { return null }
}

export class MiniMaxSearchProvider {
  constructor({ id = 'minimax', resolveApiKey, resolveApiKeySync, env, WebErrorMod } = {}) {
    this.id = id
    this._resolveApiKey = resolveApiKey      // 每次操作实时解析(异步)
    this._resolveApiKeySync = resolveApiKeySync // 同步快照(available() 用)
    this._WebError = WebErrorMod || loadHostModule('@deepseek-ai/dsh-web')?.WebError || null
  }
  available() {
    if (this._resolveApiKeySync) { const k = this._resolveApiKeySync(); if (k) return true }
    return this._resolveApiKey !== undefined   // 有异步解析器视为可用(运行时再判,与官方一致)
  }
  async search(request, signal) {
    // ... fetch coding_plan/search;错误抛 WebError(WEB_PROVIDER_ERROR / WEB_ABORTED),
    //    无 WebError 时降级 Error + err.code(行为等价)
  }
}

export const name = 'minimax-search'
export const inject = ['web']
export function apply(ctx, config) {
  const apiKeyEnv = config?.apiKeyEnv || 'MINIMAX_API_KEY'
  const literalApiKey = config?.apiKey || ''
  const provider = new MiniMaxSearchProvider({
    id: 'minimax',
    resolveApiKey: async () => {
      // 1) 字面 key  2) ctx.credentials.resolve(apiKeyEnv)  3) launchEnvironment 快照
      if (literalApiKey) return literalApiKey
      const credentials = ctx.get?.('credentials')
      if (credentials) {
        const resolved = await credentials.resolve(apiKeyEnv)
        if (resolved?.value) return resolved.value
      }
      const env = ctx.get?.('launchEnvironment')
      return env?.get?.(apiKeyEnv)?.value || ''
    },
    resolveApiKeySync: () => {
      if (literalApiKey) return literalApiKey
      return ctx.get?.('launchEnvironment')?.get?.(apiKeyEnv)?.value || ''
    },
  })
  ctx.web.registerSearchProvider(provider)
}

提示:config 里可选配 apiKey(字面量,最高优先级)与 apiKeyEnv(凭据引用名,默认 MINIMAX_API_KEY)。 区域切换可把 endpoint 抽成 MINIMAX_API_HOST 驱动(见 docs/DSH-NOTES.md)。


相关文档