dsh-aloof
把 Aloof 接成 DeepSeek Harness(dsh)的原生工具。一张自带地址的接入令牌,粘一串就能用。
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 20, 2026
- Updated
- Aug 20, 2026
Introduction
dsh-aloof
把 Aloof(企业团队知识协同平台)接成 DeepSeek Harness(dsh)的原生工具。
装上之后,你在 dsh 里问「Aloof 连上了吗」「我在哪几台机器上接了」这类话,模型能自己去查。
这一版只做「连上」这件事——两个只读工具,用来确认这台机器真的接到了公司那台 Aloof 上、而且 Aloof 那边认出了你是谁。团队资料库的读写工具跟着资料库那一期一起来。
先说清楚:这是个客户端插件,得配一台 Aloof 才有用。 Aloof 是私有部署的企业平台,服务端不在这个仓库、也不公开。手上没有 Aloof 实例的话,装上这个插件只会得到一句「没配 ALOOF_TOKEN」——它不是能独立干活的工具集。
要什么
- Node ≥ 22
- dsh
- 一台跑着的 Aloof,以及你在上面生成的一张 dsh 接入令牌
装
dsh plugin --profile web add dsh-aloof
想跟着改代码就用本地开发链接:
git clone https://github.com/aloof-ai/dsh-aloof.git
dsh plugin --profile web add /绝对路径/dsh-aloof
配
只有一个东西要配:那张票。
在 Aloof 网页上点左下角自己的名字 →「dsh 接入」→ 生成,复制出来长这样:
alf_xxxxxxxxxxxx@https://aloof.你们公司
整串放进环境变量 ALOOF_TOKEN,或者写进 $DSH_HOME/.credentials.yaml:
ALOOF_TOKEN: alf_xxxxxxxxxxxx@https://aloof.你们公司
地址是跟着票一起来的,所以不用再配服务器地址。这不是为了少打几个字:地址和票如果是两个各自可填的字段,「填串了、把票发到别人服务器上」这件事就永远可能发生;粘在一起之后它在物理上就不成立了。
注意别只粘前半截——@ 后面那截就是地址,少了它插件不知道该往哪儿发(真发生了会有一句明确的报错告诉你去重新复制)。
放的必须是接入令牌,不是网页的登录票。 登录票带着这个人的全部权限、而且没法单独作废;接入令牌读全放行、写只走白名单,并且能按设备单独吊销——某台机器丢了,在网页上把那一张吊掉就行,不影响你其他机器。
改了 credentials 不用重启 dsh:它盯着 .credentials.yaml 热更新,改完下一次调用就走新票(实测半秒内)。唯一的例外是把票写成了环境变量——那份在进程启动时冻结,而且优先级压过文件,所以「文件明明改了却没生效」先怀疑有个同名环境变量。
票会在两种情况下自己失效,都不是 bug:
- 你改了 Aloof 的密码。改密会吊销你名下所有令牌(改密的场合通常是「怀疑泄露了」,只换密码不撤令牌等于换了大门锁却留着侧门钥匙)。回网页重新生成一张。
- 那张票设了有效期而且到期了。生成时可以选,默认是永不过期。
两种情况 /aloof 和工具报的错都会直说是哪一种,照着做就行。
有哪两个工具
| 工具 | 干什么 |
|---|---|
aloof_whoami | 连上了吗、Aloof 认出我是谁。连不上会直接说是哪一种问题 |
aloof_devices | 我有哪几台机器连着,每台最后一次什么时候、从哪个 IP 连的 |
发新票和吊销都只能在网页上做,这里故意没有对应的工具——不能让模型给自己续期或者增发。
/aloof:不问模型,直接看通没通
/aloof
打出这台 dsh 连的是哪个地址、票的前几位、Aloof 认出你是谁。
为什么要有它、而不是让人问模型:「连上了吗」是个关于环境的事实问题,答案必须确定。走模型的话它可能不调工具就凭上下文猜、可能把报错重新表述一遍、也可能因为工具报错就开始自己排查。这条命令由插件直接执行,不经过模型——所以它的输出可以当证据用。
连不上的时候它会一起给出排查顺序。先看它打出来的那个地址对不对:票带着地址走,从线上页面生成的票拿到本机来用,它会去连线上那台;这种情况报的是 fetch failed,看着百分百像网络问题,能让人(和 AI)白查一轮 DNS 和证书。
右下角那颗按钮
dsh 界面右下角常驻一颗带 logo 的圆钮,角上一个红绿灯:绿的通着、红的断了、灰的正在看。点开是连的哪台、认出你是谁、用的哪张票;断的时候把报错和排查顺序一起摆出来。
它和 /aloof 读的是同一个状态(经插件自己的 GET /dsh-aloof/status),所以两处不会打架。区别只是你要不要开口:红绿灯是你没问它也在看的那一路——票会在别处失效(被吊销、改密连带、到期),30 秒复查一次,灯自己就变了,不用等到某次调用失败才发现。不想点开的话,鼠标悬上去也能看到同一句话。
票不会到浏览器里。页面问的是本机插件,插件在 Node 那边拿票去问 Aloof,只把结论发回页面。票留在 $DSH_HOME/.credentials.yaml,不进 devtools、不进浏览器扩展、也不在 XSS 的射程内。
可选配置
平常一行都不用写。真需要时在 cordis 配置里给:
| 键 | 默认 | 什么时候动它 |
|---|---|---|
tokenEnv | ALOOF_TOKEN | 一台机器上要接两套 Aloof,各用一个凭据名 |
timeoutMs | 20000 | 服务端在很慢的网络后面 |
baseUrl | 空(跟着票走) | 反向代理、内网另有入口,网页地址和 dsh 能到达的地址不是同一个。填了以它为准 |
连不上的时候
报错都是照着「哪一种问题」写的,直接照做:
| 看到 | 意思 |
|---|---|
没配 ALOOF_TOKEN | 票没放进环境变量,也没写进 .credentials.yaml |
…那串票不带地址 | 只粘了 @ 前面那半截,回网页重新整串复制 |
连不上 Aloof(…) | 地址通不了:服务没起、端口不对、或者不在同一个网里。先核对括号里那个地址是不是你想连的那台 |
令牌无效 | 票不对(粘漏了、或者那台 Aloof 上没有这张) |
已被吊销 | 有人在网页上把它吊了 |
改密码时被一起吊销 | 你改过 Aloof 的密码,回网页重新生成一张 |
已过期 | 这张票当初设了有效期,到了。重新生成一张(可以选永不过期) |
Aloof 403 | 票是好的,但这个接口对接入令牌关着(写操作默认关闭) |
跟服务端的关系
插件调的是 Aloof 的 HTTP 接口,两边是锁步演进的:服务端接口一改,这里可能要跟着改。服务端接口契约以那边导出的 openapi.json 为准。
这个插件整份 index.js 里没有一句 import,是故意的:defineTool 这些都在 @deepseek-ai/dsh-* 包里,用了就把插件钉死在某个 dsh 内部版本上,而且插件被软链进 profile 时 Node 会从真实路径往上找 node_modules、找不到那些包。所以这里直接手写 JSON Schema、只用 ctx 上的服务。对一个只做 HTTP 转发的薄壳来说,代价只是少了编译期类型推导。
client.js(浏览器半部)走的是同一条路,而且理由更硬:dsh 的 client 产物形状是固定的——一个包在 window.__ModuleLoader__.load({ id, factory }) 里的 CJS 闭包工厂,react 之类的「平台模块」由宿主的 require 表提供、不打进包。官方包用 tsdown 的 preset 生成这个形状;这里直接手写产物,因为一颗悬浮按钮除了 react 什么都不需要,而引那条流水线换来的是 tsc + tsdown + 一串 @deepseek-ai/dsh-client-* 开发依赖——那些包在 npm 上的版本比宿主实际跑的旧,等于照着旧类型写、跑在新宿主上。代价是这份文件里不能用 JSX 和 CSS Modules,用 React.createElement 和一段注入的 <style> 顶替。
所以这个包没有构建步骤:npm pack 出来的就是源码本身。改 client.js 之后重启 dsh 即可,不用 build。