把每轮对话拆成可观测的调用链路并上报评估
25.8/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/30 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add litefuse/dsh-litefuse-plugin该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · dev
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 74 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
⚠︎ 实装验证未通过(unknown · 2026/10/9) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件发起外部网络请求
查看扫描证据(共 5 处,展示前 5 条)
- 写入本地文件src/log.ts:52
mkdirSync(dirname(file), { recursive: true }) - 写入本地文件src/log.ts:53
appendFileSync(file, `${new Date().toISOString()} [${level}] ${line}\n`) - 读取本地文件src/log.ts:73
if (statSync(file).size < ROTATE_BYTES) return - 写入本地文件src/log.ts:78
renameSync(file, `${file}.1`) - 发起网络请求src/otlp.ts:287
const response = await fetch(this.endpoint, {
扫描于 2026/11/1(0 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-compaction@deepseek-ai/dsh-credentials@deepseek-ai/dsh-llm@deepseek-ai/dsh-session@deepseek-ai/dsh-subagent@deepseek-ai/dsh-tools给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 拆分对话为调用链路
- 上报评估数据
- 智能体可观测性
README
由 DeepSeek 最新模型翻译生成dsh-litefuse-plugin
DeepSeek Harness Litefuse 插件,用于 Agent 可观测性与评估。
每个用户轮次都会成为一条 trace:一个 agent 根节点,每次模型调用对应一个 generation(包含真实延迟与 token 用量),每次工具执行对应一个 tool,以及该轮次委派的每个子代理对应一个嵌套容器。它实现了 Litefuse agent-trace spec v1.2。
DeepSeek Harness — Turn 3 AGENT 1.9s input: "why is the build failing?"
├── plan (2 tools) #1 GENERATION 820ms in 1.2k · out 96 · cache-read 18k ├── tool: bash (pnpm) #2 TOOL 410ms ├── tool: read (tsconfig.json) #3 TOOL 12ms ├── plan (1 tool) #4 GENERATION 640ms ├── tool (1 subagent) #5 TOOL 9.4s │ └── subagent AGENT 8.8s ← delegation overhead: 0.6s │ ├── plan (1 tool) #1 GENERATI
展开完整文档(README 剩余 1 节)
dsh-litefuse-plugin
DeepSeek Harness Litefuse 插件,用于 Agent 可观测性与评估。
每个用户轮次都会成为一条 trace:一个 agent 根节点,每次模型调用对应一个 generation(包含真实延迟与 token 用量),每次工具执行对应一个 tool,以及该轮次委派的每个子代理对应一个嵌套容器。它实现了 Litefuse agent-trace spec v1.2。
DeepSeek Harness — Turn 3 AGENT 1.9s input: "why is the build failing?"
├── plan (2 tools) #1 GENERATION 820ms in 1.2k · out 96 · cache-read 18k ├── tool: bash (pnpm) #2 TOOL 410ms ├── tool: read (tsconfig.json) #3 TOOL 12ms ├── plan (1 tool) #4 GENERATION 640ms ├── tool (1 subagent) #5 TOOL 9.4s │ └── subagent AGENT 8.8s ← delegation overhead: 0.6s │ ├── plan (1 tool) #1 GENERATION ← numbering restarts per container │ ├── tool: grep (TS2345) #2 TOOL │ └── subagent response GENERATION └── response GENERATION 1.1s output: the final answer
安装
npx @deepseek-ai/dsh plugin --profile web add -w dsh-litefuse-plugin
将你的项目密钥对放入 ~/.dsh/.env:
LITEFUSE_PUBLIC_KEY=pk-lf-…
LITEFUSE_SECRET_KEY=sk-lf-…
密钥来自 Litefuse 项目中的 Settings → API Keys → Create new API keys(在 注册)。
然后照常启动:
npx @deepseek-ai/dsh web
发送一条消息,然后打开 → 你的项目 → Tracing。trace 会在该轮次第一个 span 完成时立即出现,而不是在轮次结束时。
卸载
npx @deepseek-ai/dsh plugin --profile web remove -w dsh-litefuse-plugin
DSH_LITEFUSE_DISABLED=1 可在不卸载的情况下关闭导出。
配置
安装补丁从环境变量读取所有内容,因此大多数部署无需配置。如需覆盖,请在 ~/.dsh/profiles//cordis.patch.yml 中添加一个条目:
- id: litefuse
config:
environment: staging
agentName: My Agent
requestInput: delta
tags: [dsh, team-platform]
以 id 为目标的补丁会替换整个 config,因此请重新声明你要保留的字段。
| 字段 | 默认值 | 含义 |
| enabled | true | false 会挂载插件但不导出任何内容 |
| baseUrl | https://litefuse.cloud | Litefuse 端点;OTLP trace 路径会被追加 |
| publicKeyEnv / secretKeyEnv | LITEFUSE_PUBLIC_KEY / LITEFUSE_SECRET_KEY | 凭据引用;LANGFUSE_ 为回退 |
| environment | production | 每个 span 上的 Litefuse tracing 环境 |
| agentName | DeepSeek Harness | — Turn N 中的名称 |
| userId | $USER | trace 级别的 user.id |
| tags | [dsh] | trace 标签,与生成的 model: 并列 |
| release | — | 每条 trace 上可选的 release 标识符 |
| requestInput | full | full 发送整个请求;delta 只发送自上次调用以来新增的消息;none 省略输入 |
| maxValueChars | 1000000 | 每个输入/输出的截断预算,包括 trace 输入 |
| delegationTools | [subagent, subagent_fork] | 其进行中的调用承载 subagent 容器的工具名称 |
| exportDelayMillis | 1000 | 已结束的 span 在批量发送前等待同伴的时长 |
| requestTimeoutMillis | 10000 | 每个请求的截止时间 |
| shutdownTimeoutMillis | 3000 | 拆除时排空的外层时限 |
| logFile | $DSH_HOME/litefuse.log | 集成自身的日志 |
| debug | $DSH_LITEFUSE_DEBUG | 保留详细日志行 |
凭据是引用,而非值:配置指定一个环境变量,其值在挂载了 harness 凭据存储(~/.dsh/.credentials.yaml)时来自该存储,否则来自 ~/.dsh/.env 所供给的进程环境。此处绝不会将密钥写入文件,并且只会记录公钥的前十个字符。
工作原理
零运行时依赖——不使用 Langfuse SDK。Span 直接发往 OTLP 端点,声明 x-langfuse-ingestion-version: 4,这是针对内联写入完整 span 的自定义导出器所记录的 opt-in。
与 Litefuse 为其他 agent 提供的文件追踪收集器不同,此收集器在进程内运行于 harness 自身的会话事件流上,因此它记录的是实际发生的情况,而非从转录中重建出的含义:真实的每次调用延迟、首个 token 的时间、工具持续时间、不相交的缓存 token 核算,以及每次生成所发送的确切请求。
该插件订阅 session/event,即 harness 提交后的追加事件流,并将每一轮的事件折叠为 span:
| 会话事件 | 变为 |
| turn/start … turn/end | trace 及其 agent 根 span |
| user/message(source.kind: user) | trace 输入 |
| step/start … assistant/message | 一个 generation,以模型所做的事情命名 |
| assistant/chunk(某一步的第一个) | 该 generation 的 completion_start_time——首个 token 的时间 |
| tool/call … tool/result | 一个 tool span,通过 agent_plan_step 链接到其计划 |
| tool/code-dispatch-start … tool/code-dispatch | 一个 run_code 程序所做的每次调用对应一个嵌套 tool span |
| request/header、request/context | 模型名称、采样参数和上下文窗口 |
| compaction/end | 一个 context compaction 事件,用于解释下一次调用的 token 下降 |
| subagent/descriptor | 子运行属于哪个委派调用,以及该调用是否等待它 |
| 与某个委派调用匹配的子会话 | 该调用工具 span 下的一个 subagent 容器 |
Span 在容器下平铺挂载;唯一的深度是真实的子代理运行。代际和工具共享同一个步骤计数器,因此 #N 是单一的时间顺序序列,而 tool.agent_plan_step == generation.agent_step_index 将工具关联回请求它的调用。
每个 span 在结束时写入一次——OTel span 是不可变的,因此进行中的步骤在关闭之前被有意设为不可见。Trace 级属性会附加到每个 span 上,这正是让 trace 能够在其根 span 出现之前就出现的原因。
代码模式
run_code 程序直接调用工具,因此这些调用永远不会以 tool/call 的形式出现,否则整个程序的工作就会坍缩成一个不透明的 span。它们作为嵌套的 tool span 挂载在运行它们的调用之下——桥接器会在父级返回之前排空所有进行中的派发,因此这种包围关系是结构性的,而非推断出来的。它们不携带 #N:步骤计数器为模型的调用及其请求的工具编号,而派发两者都不是。因此 agent_tool_calls 只继续统计模型所请求的内容,旁边还有 agent_code_dispatches。
子代理
被委派的运行在 harness 中是自己的会话。当某个委派调用在其父级中处于进行中时,一个子代理启动,子级的步骤会挂载在一个 subagent 容器下,该容器以该调用的工具 span 为父级,编号从 #1 重新开始,其结束答案命名为 subagent response,其 token 用量并入父级 trace 的总量。工具 span 与容器之间的间隙就是委派的真实成本。
一个子级属于哪个调用,由身份一次性决定。 harness 不会把任何对生成它的调用的引用交给子级——只有一个全新的会话 id,以及一个仅标明父会话的头部。它确实会原样交出的,是委派的 description,作为子级自己的 subagent/descriptor 的 label,以及它的 prompt,作为子级的第一条用户消息。两者中任意一个都是精确的键,而其中之一正是让并发的委派彼此区分开来的依据——并发是常态,因为子代理工具自身的提示词要求模型在一条助手消息中一起启动相互独立的委派。
一个 span 在写入的那一刻就携带其 trace 和父级,而 OTel span 是不可变的,因此一个仍可能改变的绑定就是一个已经撒了谎的绑定。因此规则是在答案被确定的最早时刻进行绑定——精确的键匹配,或唯一的候选调用——并且绝不修改它。等待更久并非没有代价:一个 continuable 委派在启动子级后的几毫秒内就报告其工具结果,早于子级自己的提示词被记录,因此推迟到那么晚的决定将找不到任何剩余的候选。descriptor 正是让早期决定成为精确决定而非猜测的东西,而对于被生成的子级,它会在构造函数种子中到达,而 session/event 的 firehose 从不重新发布它——因此它直接从会话日志中读取。
一次委派调用返回并不总是意味着运行结束。 一次性委派以子级的答案作为结果,因此父级的 tool/result 会关闭该容器。而 continuable 委派在接受时即解析完成,此时整个运行仍在前方;若在此处关闭,就会封存一个空容器,并丢弃子级随后所做的一切。这类容器改为在子级自身的 turn/end 时关闭,将其令牌归入委派它们的那个回合。
只有 delegationTools 中命名的工具才能承载容器。一个恰好正在进行的普通调用被刻意地不作为回退:后台委派会在其子级尚未启动之前就报告结果,因此接受任何调用都会把整个代理运行——及其令牌——归到父级当时正在运行的任何无关工具之下。找不到进行中委派的子级则会获得自己的 trace,并在根元数据中带有 agent_parent_session_id。仅仅在会话中命名了 parentSession 也不够;是 harness 自身的 origin: subagent 分类才允许一个会话进入其父级的 trace,因此普通分叉会留在其外。
元数据
所有元数据都平铺在一个 agent_ 前缀之下——绝不用每个代理各自的命名空间——因此单个 Litefuse 仪表盘查询即可跨所有代理集成工作。缺失的字段会被省略,而不是用 null 填充。
- 根与子代理容器:agent_turn_number、agent_session_id、agent_parent_session_id、agent_cwd、agent_provider、agent_model、agent_api_calls、agent_tool_calls、agent_steps、agent_duration_ms、agent_context_window、agent_end_reason、agent_subagent、agent_code_dispatches,以及令牌汇总 agent_input_tokens / agent_output_tokens / agent_cache_read_tokens / agent_cache_write_tokens / agent_reasoning_tokens / agent_total_tokens / agent_accounted_generations
- 生成:agent_step_index、agent_api_duration_ms、agent_time_to_first_token_ms、agent_tool_call_count、agent_thinking_chars、agent_reasoning_tokens、agent_input_scope、截断标志
- 工具:agent_tool_name、agent_tool_call_id、agent_step_index、agent_plan_step、agent_duration_ms、agent_is_error、agent_error_code、agent_subagent_count、截断标志
- 代码分派:agent_code_dispatch(始终为 true)、agent_tool_name、agent_tool_call_id、agent_parent_call_id、agent_root_call_id、agent_duration_ms、agent_is_error、截断标志
元数据以逐键 span 属性的形式承载(langfuse.observation.metadata.agent_step_index),而不是作为一个序列化的 blob。JSON 字符串会与其解析后的副本一起被逐字存储,从而在原始属性集中留下嵌套在字符串内的 JSON;而 trace 规范禁止将预序列化的 JSON 作为元数据值,因为服务端将其展平会破坏转义。
Token 计数使用 Litefuse 定价和分类所依据的键:input、output、output_reasoning_tokens、cache_read_input_tokens、cache_creation_input_tokens。提示计数从 harness 到达时是不相交的,因此它们相加后等于计费的输入,保持不变。补全则相反——harness 将推理折叠进 outputTokens——因此推理会从 output 中减回,并作为其同级项报告。Litefuse 会将每个包含 output 的键相加到显示的 Output 数值中,而其自身的摄取处理器正是以这种方式规范化提供方负载,因此这种拆分既保持了明细正确,也保持了成本正确。模型定义应当将 output_reasoning_tokens 与 output 一同定价;随附的价格表已经为其已知的每个推理模型这样做了。
Token 汇总仅为元数据。 一个 agent span——无论是轮次根还是子代理容器——都会以 agent__tokens 的形式携带其自身及其下所有嵌套内容的总计,但绝不会作为 usage_details。Litefuse 通过对其 span 求和来为 trace 定价,因此一个同时声明了其子级 token 的容器会使账单翻倍。读取根上的 agent_total_tokens 可了解“这一轮有多大”;读取 totalCost 可了解其成本。
故障排查
什么都没有到达?以详细日志启动:
DSH_LITEFUSE_DEBUG=1 npx @deepseek-ai/dsh web
然后读取集成自身的日志:
tail -5 ~/.dsh/litefuse.log
正常安装会在启动时打印其端点,每完成一轮打印一行,每交付一批打印一行:
[info] v0.1.0 exporting to https://litefuse.cloud (key pk-lf-a1b2…)
[debug] turn closed "DeepSeek Harness — Turn 1" trace=… session=… steps=3 api=2 tools=1 duration=4120ms [debug] sent 4 span(s) -> https://litefuse.cloud/api/public/otel/v1/traces HTTP 200
该日志会说明未到达的原因——缺少凭据、HTTP 状态码或传输错误。UI 中 totalCost 为 0 不是收集问题:这意味着项目没有你的模型的价格条目(Settings → Models)。
设计说明
始终故障开放。 每个处理器都是自包含的,每个失败都会被记录并吞掉。会话分发会在抛出异常的监听器处停止,因此如果异常逃逸出此插件,会使之后注册的每个观察者都得不到执行。一个无法访问的 Litefuse 项目只会消耗一个请求截止时间,别无其他。
零运行时依赖。 构建后的插件不导入 node: 及其自身文件之外的任何内容——每个 harness 和 Cordis 导入都仅为类型导入,CI 会对该属性进行门禁。这是有意为之:一个安装到某个 profile 中的插件,如果该 profile 拉入了它自己的一份 @deepseek-ai/cordis,就会给宿主带来两个不同的 Context 类,服务装配会以非常难以诊断的方式失败。
trace 头会被重复,因此它保持很小。 每个 span 都携带 trace 的名称、标签、会话和用户,因此 trace 在其根写入之前就可查询。输入是唯一没有自然大小的头字段,重复它会让一个粘贴的文件按每个 span 计费一次,所以随行的是一个 4096 字符的预览——每个 span 上都是相同的文本,因此无论服务器将哪一个折叠进 trace 记录,读起来都一样。根 agent span 完整携带输入,最多到 maxValueChars。
scope 命名的是这个包,而不是某个 SDK。 批次以 instrumentation scope dsh-litefuse-plugin 到达。摄取会将 span 的整个原始属性映射复制到每个 observation 的 metadata 中,作为 attributes,除非该名称以 langfuse-sdk 开头;声明该前缀会抑制复制,某个版本确实这么做了,但 scope 是一个身份字段,而这不是 Langfuse SDK。复制的代价是噪音而非正确性——其中的每个属性都已经是一等字段,所以没有任何丢失或错误,只是以某种形式重复,而该形式会重新编码 model.parameters 和 usage_details 所要求为的 JSON 字符串。准确的修复属于摄取侧,它已经从该 exporter 接收到 x-langfuse-ingestion-version: 4:这是有文档记载的信号,表明客户端内联发送完整 span,而且对于任何这样做的自定义 exporter 都成立,而不是只对某个名称前缀成立。
它写自己的日志。 一个启动的 dsh profile 不组合任何 logger 插件,因此 ctx.logger 输出不可见。位于 $DSH_HOME/litefuse.log 的文件是这个集成报告的地方,与 Litefuse 的其他集成所做的一致。
加载时不重放。 该插件从下一个 turn/start 开始观察。加载时已经在进行中的 turn 会被跳过而不是重建,这正是防止它写入前一个进程已经发送过的 span 的原因。
已知限制
- 既不共享描述符也不共享其提示词的委托可能会错误绑定。 并发调用通过子项的 descriptor label 或通过原样传给它的 prompt 来区分。如果某个 provider 不记录 descriptor 并且重写提示词,或者某个委托工具以不同方式命名这些参数,就会回退到最近启动的调用——而在有多个调用正在进行时,子项可能会附着到错误的那个上。
- 后台一次性委托不会被嵌套。 它的调用报告一个 job id 并关闭,而子项可能在此之后才被创建,此时没有候选调用仍在进行中;该运行会获得自己的 trace,根 metadata 中有 agent_parent_session_id。continuable 委托确实会嵌套,因为它们的子项在调用报告之前就已存在。
- 进程外 subagent 会获得自己的 trace。 在另一个进程中运行子项的 provider(acp、codex、SDK provider)不会向此进程发布任何会话事件,因此它们的运行不是子树。进程内 provider——随附的 subagent 和 subagent_fork 工具所使用的——则是。
- 并行工具跨度可能高估持续时间。 测试框架按模型顺序提交工具结果,因此一个快速调用如果在一个慢速的兄弟调用之后完成,记录的是其结果时间戳,而不是它自身的完成时间。
- requestInput: full 会为每次模型调用折叠派生历史。 这是每次调用对会话日志的一次遍历——与一次模型往返相比可以忽略不计,但 delta 的存在是为了应对非常长的会话。
- 没有持久化发件箱。 进程死亡时缓冲的跨度会丢失。投递按设计是至多一次的;会话日志仍然是持久记录。
发布
发布就是推送一个标签;CI 会构建、测试并附带来源信息进行发布。
npm version patch # 或 minor / major —— 写入 package.json 并打标签
git push --follow-tags
工作流会拒绝与 package.json 不一致的标签,并且 prepack 会在打包前构建,因此 tarball 始终包含 lib/,安装程序永远不会编译任何东西。
工作流通过 npm Trusted Publishing 进行身份验证:它出示此仓库和工作流的 GitHub OIDC 身份,npm 将其换取一个短期凭证。任何地方都不存储令牌,无需轮换任何东西,并且账户的 2FA 永远不会被绕过——来源信息会自动附加,而不是通过标志附加。
Trusted Publishing 是在一个已经存在的包上配置的,因此新名称的第一次发布是无法使用它的那一次发布:手动创建一次包(npm publish --access public,响应账户的 2FA 提示),然后配置发布者,之后每次发布都无令牌运行。
开发
npm install
npm test # 51 tests over the real @deepseek-ai/dsh-session Session
npm run typecheck
npm run build
测试驱动的是随附的测试框架会话存储,而不是替代品,因此汇编器是针对它在生产环境中读取的真实追加验证、表面规则和派生历史投影进行检验的。
tests/plugin.spec.ts 针对 Litefuse 摄取端点的本地替代品启动插件,并断言 OTLP 线上格式、Basic 授权、单次写入跨度,以及在 500 错误、无法访问的主机和缺少凭证时的故障开放行为。
要在不等待模型往返的情况下检查真实的 Litefuse 部署:
node scripts/send-verification-trace.mjs
它通过一个脚本化的轮次驱动真实的 Session——一次工具调用加上一次委托的子代理运行——并将结果发布到 $LITEFUSE_BASE_URL,标记为 environment: development 并命名为 dsh-litefuse-plugin-verify — Turn 1,以免被误认为是代理流量。用 litefuse-cli 读回它:
npx -y litefuse-cli api traces get
请注意,traces list 不会投影跟踪元数据——即使元数据已存储,它也会报告 {}。使用 traces get 查看 agent_* 字段。
许可证
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
litefuse/dsh-litefuse-plugin
把每轮对话拆成可观测的调用链路并上报评估
相关插件 · 开发 / 工程
隐私简历生成器reactive-resume/reactive-resume
Reactive Resume 已迁至 GitHub 上的…
★ 45,125已汉化MCP
71.7
AI 架构文档生成器sopaco/deepwiki-rs
🚀 Litho 已进化为 Terrain —— 给你的 AI 智能体一张会呼吸的代码库地图。
★ 3,157已汉化DSH
70.8
长时任务执行闭环AMAP-ML/LongHorizon-Harness
面向 Computer-Use Agent 的 Loop Engineering
★ 1,764已汉化DSH
70.5
AI 编程纪律方法包GanyuanRan/Aegis
让 AI 编程 agent 变得可信:少返工、更安全、说“完成”前先给证据。
★ 1,384已汉化DSH
69.6
多代理编排运行时Enderfga/claw-orchestrator
面向编程智能体的运行时。把 Claude Code、Codex、Antigravity、Grok…
★ 586已汉化MCP
69.4
记忆进化插件csyangwen/dsh-memory-evolve
dsh-memory-evolve 使用场景指南
★ 461已汉化DSH
67.9