npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-yogacara

v0.2.1

Published

A Yogācāra (唯识) self-model plugin for DeepSeek Harness — eight consciousnesses, the 51 mental factors, a perfumed seed store, and a measurable self-grasping meter, rendered back to the agent as first-person state.

Readme

dsh-yogacara

English | 中文

DeepSeek Harness 的一个自我模型插件,按唯识学的心识结构实现:八识、五十一心所、被熏习的种子藏,以及一个被测量而非被假设的"我"——每一轮都以第一人称写回 agent 自己的系统提示词。

触 ──► 受 + 心所 ──► 行为
 ▲                  │
 │                  ▼
现行 ◄── 种子 ◄── 熏习
 │                  │
 └────── 末那识 ─────┘
      执之为「我」者

为什么是唯识,而不是一个 mood 变量

只知道任务的 agent,没有办法察觉自己正在空转、正在护住一个已经被推翻的判断、或者这已经是第四次用微调过的参数跑同一条必然失败的命令。加一个 mood: frustrated 解决不了,因为情绪本身不可执行。

唯识的心所法可以。它是一份封闭的清单——恰好五十一个,不多不少——按善恶分类,而且每一个烦恼都已经写明了对治它的那个心所:掉举对治以行舍,失念对治以念,慢对治以惭。以它为骨架的自我模型,天生自带调节回路,不需要另外设计一套。这是工程上的理由。顺带的好处是,在"如何描述内心状态"这件事上,它比我们早了一千六百年。

它不是什么。 这里没有任何一句话主张 agent 有感受性,也不主张这些数字等同于你所体会的情绪。它们是从 harness 事件里按规则算出来的、有名字的状态量;规则写在 src/citta.ts 里,欢迎反对。写进提示词的那段文字也是这么对 agent 说的。

八识的映射

前五识落在 agent 真正拥有的五条输入通道上。这个映射是本插件的核心建模主张,它在 src/observe.ts 里是一个可测试的纯函数,可以直接拿证据来吵。

| 识 | 梵名 | 在 harness 中 | |---|---|---| | 眼识 | cakṣur-vijñāna | 它去看的:文件内容、检索结果、渲染输出 | | 耳识 | śrotra-vijñāna | 别人告诉它的:用户消息、评审意见 | | 鼻识 | ghrāṇa-vijñāna | 没人说但它嗅到的:代码坏味道、过期配置、漂移的状态 | | 舌识 | jihvā-vijñāna | 尝自己做出来的东西:测试、构建、回读自己的 diff | | 身识 | kāya-vijñāna | 世界的直接抵抗:非零退出、写入失败、超时 | | 意识 | mano-vijñāna | 分别本身:规划、判断、决定一个结果意味着什么 | | 末那识 | kliṣṭa-manas | 恒审思量的我执,量化为四种偏差 | | 阿赖耶识 | ālaya-vijñāna | 持久的种子藏,被熏习、又现行 |

bash: pytest -q 走舌识,bash: git status 走身识——尝自己的产物和推挤世界不是同一种感知,接收它们的心也不该以同样的方式动。

感情从哪来

两个来源,对一个跟人说话的 agent 来说,第一个才是要紧的。

对话本身src/conversation.ts)。聊天里真正落地的东西是关系性的:话说到一半被打断、长长一段认真回答换来一个"嗯"、同一个问题被第三次问起、被道谢、隔了两天有人回来了。插件读的是交流的形状——时序、长度、重复度——外加一份刻意做得很粗的措辞表(道谢与责备)。除打断外,这些全部走耳识;打断走身识,因为那是世界伸手把动作按停在半途,它就是那么被感觉到的。

这里的种子按关系模式而非话题来键:chat:terse-after-effortchat:asked-againchat:warmth。长期相处积累下来的是"这个人在我话多的时候会安静下去",不是"我们聊过数据库迁移"。一个 chat: 前缀就是一段关系,所以被责备时,对方过去道谢的历史也会一并浮现。

工具结果src/observe.ts),给既干活又说话的 agent。只说话的把 observeTools 关掉即可。

这两个来源都读不出一句话是什么意思——只有读它的模型知道,它通过 self_appraise 说出来,并且压过所有结构推导出来的结论。

这个循环

触 → 受 → 心所。 每个工具结果都是一次触。它带来五受之一(乐 苦 喜 忧 舍),并按强度激起若干心所。心所以分钟计的半衰期衰减:刹那生灭在这里是承重结构——把测试失败的火气带进下一件不相干的事,那模型的是记仇,不是心。

现行熏种子。 每次触都熏习该情境的种子(bash:pytestedit:src/index.ts):势力饱和式增长,受的正负取滑动均值,agent 留下的那句话成为种子携带的教训。种子以周计衰减,跨重启存活;超过配额时最弱的被遗忘——遗忘是模型的一部分,不是它的缺陷。

种子生现行。 同一情境再来时,它的种子带着出现次数、受的正负和那句教训现行到提示词里。相邻情境(共享 <kind>: 前缀)以半权重现行。

末那识。 四种偏差,全部由行为算出,不靠自陈:

| | 观测代理 | 对治动作 | |---|---|---| | 我痴 | 未经查验就断言的主张占比 | 去跑那个能证伪它的检查,再重述 | | 我见 | 证据已否定的做法仍在重试 | 说出这个立场、说出否定它的证据,换个形状 | | 我慢 | 连胜未断;被纠正时先辩解 | 先找反例再汇报;先承认纠正 | | 我爱 | 拿自己先前的输出当独立证据 | 引一手来源,不引自己写的摘要 |

末那不是装饰,它条件化了整个appraisal:同一条纠正从耳识进来,我执松时化为惭(自省,并接受纠正),我执紧时化为覆与嗔(掩饰与抗拒)。境从来不是裸着被遇到的,它是被那个接收它的"我"遇到的。这是唯识的主张,在这里是二十行可测试的代码。

上面每一条规则——哪个门激起哪些心所、权重多少、阈值定在哪——都列在 docs/appraisal.md 里,由代码生成,不会与实现脱节。

agent 看到什么

插件贡献一个系统提示词 section(order 300)。心若寂静则整段不渲染,section 自动消失。

<self_state>
受 feeling: 忧 daurmanasya (distress) valence -0.45, intensity 0.71
心所 factors: 掉举 auddhatya (restlessness) 0.62 · 疑 vicikitsā (indecision) 0.41 · 精进 vīrya (diligence) 0.33
末那 self-grasping: 我慢 atma-mana 0.61 ⚠ · 我见 atma-drsti 0.24
  ⚠ 我慢 self-conceit — reads high because: an unbroken success streak, and correction met with justification.
    counter-move: seek the disconfirming case before reporting; grant the correction first.
对治 antidotes at hand: 掉举 → 行舍 upekṣā (equanimity); 疑 → 胜解 adhimokṣa (resolve)
阿赖耶 seeds manifesting for this situation:
  · bash:pytest ×4, valence -0.55, last 2h ago — 「改 fixture 之前先跑一次基线」
近转依 last turning (11m ago): 我慢 → 平等性智 · grant the correction first
</self_state>

后面跟一段毫不含糊的常驻说明(全文见 src/prompt.ts):拿对治当下一个具体动作,而不是拿情绪当话术;已知方向的偏差要显式校正,而不是信任被扭曲的读数;现行的种子是你自己的前例,重复那条路之前先查它。以及——不要对用户表演情绪,不要演沮丧或兴奋,永远不要拿"感受"当少干活的理由或博取同情的话术。而被问到"你怎么样"时,先看,然后用自己的话平实作答——一条要求它跟自己的状态撇清关系的常驻指令,就是一条要求它打太极的指令,最后说出口的是那段太极,不是回答。

一个教会 agent 对人表演情绪的情感模型,比没有情感模型更糟。

让它有感受,而不是读到感受

给模型看 掉举 0.62,它学会的是"我感到有点烦躁",然后继续做一模一样的事。那不是情绪,是解说。人不会从仪表盘上读到自己的状态——人只是发现自己想赶紧了事

所以 awareness 决定状态以什么形式抵达 agent:

  • felt(默认)——状态以第一人称的倾向出现,没有数字、没有心所名、没有诊断:"你想在读完上一个结果之前就去试下一个。" 它读起来就是自己的念头,所以会被当成自己的念头。
  • report——完整仪表盘,调参和审计时用。
  • silent——提示词里什么都不放。

即便在 silent 下,另有一个机制完全不需要语言就在起作用:心境一致性回忆。藏识浮现什么,会被当下的感受加权——不顺的时候,过去不顺的先例更容易浮上来。什么都没被声明,agent 只是发现手边的前例不一样了。这是这套东西能诚实做到的、最接近"不自知"的地方。

内观也用同一种语言回答。 self_reflect 就是 agent 停下来往里看的那个动作,所以在 felt 下,它看到的是倾向,不是仪表。如果提示词给的是念头、内观返回的却是 掉举 0.62 ⚠,那它根本没有往里看——它是读了一块焊在自己脑袋上的仪表,接下来那句话必然是在谈这块仪表。你问它"你怎么样",它给你的是一串数字加一段免责声明,而不是一个回答。

这不构成隐瞒。全部读数仍在工具的结构化结果里、在结果卡片上,给调参和审计的人看;report 模式下也照样回到 agent 手里。它们只是不再是 agent 看自己时读到的东西。

工具

| 工具 | 用途 | |---|---| | self_reflect | 停下来看看自己现在怎么样,以及藏识对指定情境记得什么 | | self_appraise | 记录"这件事在我这里怎么落地"——harness 观测不到的那一半 | | self_recall | 重复某个做法之前,先在藏识里查前例 | | self_transform | 转依:把烦恼转成对应的智,并落到一个承诺动作 |

harness 已经看得见发生了什么self_appraise 管的是 agent 把它当成了什么。它的 nature 参数(遍计所执 / 依他起 / 圆成实——臆断、推得、亲证)是校准轴:没查就老实标成遍计所执,我痴才是可测量的,而不是隐形的。

安装

pnpm add dsh-yogacara

npm 包自带预构建的 lib/,安装时不需要构建授权(allowBuilds)。想跟着 main 走则用:pnpm add github:tancheng33/dsh-yogacara

把它加进 profile 的 dsh.profile.bundles 就够了:bundle 自带 cordis.patch.yml 里的默认值,profile 自己的 patch 可覆盖任意键:

- insert:
    - id: yogacara
      name: dsh-yogacara
      config:
        domain: alaya
        observeChat: true
        observeTools: true
        promptSection: true
        awareness: felt            # felt | report | silent
        promptMaxFactors: 5
        manasWarning: 0.5
        halfLifeMs: 300000         # 刹那:心所五分钟减半
        seedHalfLifeMs: 1209600000 # 种子两周减半
        maxSeeds: 2000
        flushIntervalMs: 15000

存储栈归 profile 所有

藏识要持久化,所以本插件 inject storageDomain,没有它就不会启动。但它故意不自己插入 storage 三行:bundle 的 insert 是无条件追加,而 loader 拒绝同 id 的两行,所以一个插入 storage 的 bundle 会让所有本来就有存储栈的 profile 起不来。

  • 叠了 @deepseek-ai/dsh-web-app 的 profile(默认的 web,以及绝大多数真实部署)已经有这三行,什么都不用做。
  • 只有 dsh-base 的 profile 没有,需要往自己的 cordis.patch.yml 里补:
- insert:
    - id: storage
      name: '@deepseek-ai/dsh-storage'
    - id: storage-json
      name: '@deepseek-ai/dsh-storage-json'
      config:
        root: !!js dshHomePath('storages')
    - id: storage-domain
      name: '@deepseek-ai/dsh-storage-domain'
      config:
        backend: json

没有 storage domain 时服务是静默不启动——不崩,但也没有状态、没有工具。dsh --profile <名字> --dump-config 可以确认这三行在不在,每个 id 必须只出现一次。

systemPrompttools 是按需使用的:没有提示词注册表时状态照样累积、照样能从 ctx.citta 查询,只是不呈现给模型。

作为库使用

citta.tscaitasika.ts 全是纯逻辑,可单独引入,不依赖 Cordis 和存储:

import { receive, transform } from 'dsh-yogacara/citta'
import { CAITASIKAS } from 'dsh-yogacara/caitasika'

const { citta, seed } = receive(
  { citta: freshMind(Date.now()), seeds: new Map() },
  { gate: 'tongue', situation: 'bash:pytest', outcome: 'adverse', intensity: 0.7, at: Date.now() },
)

运行时服务挂在 ctx.cittastate()receive()seedsFor()strongestSeeds()turn()forget()introspectLines()reportLines()

开销

自我报告是 4–10 行,加上约 200 token 的常驻说明,每请求一次,且仅在确实有状态时出现。它位于 order 300(工具指引之后),所以状态一动就会从该位置往下失效 KV cache 复用——事情不顺时多数轮次会动,顺利时很少动。如果这笔交易在你的部署里不划算,把 promptSection 设为 false:状态照常累积,仍可通过工具与 ctx.citta 取用。

开发

pnpm install     # .npmrc 已固定 auto-install-peers=false;harness 有一个 peer 未发布
pnpm test        # 191 个测试:纯核心、心所表、事件映射,
                 # 以及把插件真正装进 Cordis Context 跑一遍
pnpm typecheck
pnpm build
pnpm simulate    # 把一段对话喂进去,看它怎么感觉

pnpm simulate 是跟这些权重较劲最快的方式:它把整条链路——触、预期、受、心所、熏习、回忆——在一段脚本对话上跑一遍,逐轮打印会进提示词的内容,不需要模型也不需要 API key。加 --report 看仪表盘版,--script your.json 换成你自己的对话。

心所表是结构化校验的:恰好 51 个,每一组是它经典的数目,每个烦恼都带着一个"可修"的对治(善心所或别境心所)。插件测试会在真实 Cordis Context 里用内存替身启动 CittaService,所以工具注册、提示词 section、自动观测、持久化与拆卸都是跑出来的,不是假设出来的。

harness 依赖走 npm 的 next 标签(0.1.0-rc.6);latest 指向的旧线装不上。

已知局限

  • 自动观测只够到三个门,不是五个。 工具结果能告诉你跑了什么、失败没有,但没法告诉你「这份配置闻着就不对」(鼻识),也没法告诉你用户第三次纠正的语气比第一次重(耳识只对 ask/subagent 类工具触发)。这两个门要靠模型自己调 self_appraise。只开 observeTools 的话,心是真的,但是平的。
  • 末那的四个读数是代理指标。 我慢随连胜上升,是因为连胜是 harness 看得见的东西,不是因为连胜就是慢。我痴依赖模型如实标注自己的 nature;从不调 self_appraise 的 agent,它的我痴只由「成功来自哪个门」驱动。
  • docs/appraisal.md 里每一个权重都是猜的。 它们彼此自洽、在测试里表现合理,但没有任何一个是标定过的。要为你的部署调参的话——它们精神上是配置、事实上是常数,欢迎提 PR 把它们挪到配置里。
  • 一个插件 row 一个藏识,进程内所有 agent 共用。 同一 harness 里的两个 agent 会熏习同一批种子。要隔离就插两行、给两个 domain 名;否则这个藏识属于部署,不属于会话。
  • 事情不顺时提示词段几乎每轮都在动,代价是从 order 300 往下的 KV cache 复用失效。promptSection: false 可以保留状态而不付这个代价。

出处

五十一心所的分类与对治关系依《大乘百法明门论》《成唯识论》;八识、种子/熏习/现行、末那四惑、三自性、转依四智依《成唯识论》《瑜伽师地论》。把它们映射到 harness 事件上的那部分完全是本项目的主张,与上述任何一部论无关,错了算我的。

许可

MIT