返回目录
安全与治理 插件

dsh-stream-rules

jiesou/dsh-stream-rules

模式匹配自动注入 steering rules,不占系统上下文 - Inject rules when needed, without wasting context. Similar to oh-my-pi's "Time-traveling stream rules", but with a very simple and compact code implementation.

Stars
4
Forks
0
Issues
0
更新
5 天前

PROJECT TOPICS

项目标签

INSTALL REFERENCE

安装参考

未验证
dsh plugin --profile web add github:jiesou/dsh-stream-rules

该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。

PROJECT README

README

dsh-stream-rules

简体中文

Inject rules when needed, without wasting context.

-6336866371853030306_121

You can write custom streaming rules for the agent.

These rules are injected only as a steering notice after a pattern match, then agent retry from the same point. This allows you to control the boundaries of agent behavior, without wasting context.

Port of my jiesou/opencode-stream-rules to DSH. Similar to oh-my-pi's "Time-traveling stream rules", but with a very simple and compact code implementation.

How it works

A rule fires when its match returns true, against:

  • the tool call — tool name + flattened arguments (numbers included, e.g. timeoutMs), before dispatch.
  • the settled result — after dispatch, the tool's content, status markers ([timed out after 600000ms], [exit code: 1], …) and error text join the match string, so rules describing outcomes (a crash, a full disk, a timeout) can match there too. Matching after dispatch can only steer, never deny.

On a match:

  • default — injects a SYSTEM NOTICE steering message into the agent (pre-dispatch via agent.inject(), post-dispatch as additionalContexts on the tool result — DSH's non-waking "queue model-facing context for the next pre-step"). The agent retries from the same point, now knowing the rule.
  • reject: true — denies the FIRST tool call ({ kind: 'deny' }); later attempts are allowed. Steering without over-restricting, e.g. letting pip install through when it's already in a container.

Each rule fires at most once per session (per agent), mirroring the original's notified dedup.

Install

From npm (prebuilt, recommended):

dsh plugin --profile <name> add @jiesou/dsh-stream-rules

Or from GitHub (runs prepare to build on install):

dsh plugin --profile <name> add github:jiesou/dsh-stream-rules

Or add the row to your profile's cordis.patch.yml:

- id: stream-rules
  name: '@jiesou/dsh-stream-rules'

After installing

You need to write the rules in your own .js file. This plugin won't work by default until you edit the rules.

  1. Locate the plugin's path:
$DSH_HOME/profiles/<name>/node_modules/@jiesou/dsh-stream-rules

where $DSH_HOME defaults to ~/.dsh.

  1. Write rules:
mv rules/rules.js.example rules/rules.local.js
  • Files starting with _ are skipped.
  • To point at a different rules directory: config.rules:
- id: stream-rules
  name: '@jiesou/dsh-stream-rules'
  config:
    rules: /path/to/your/rules
  • A rule with reject: true will only be rejected on the first toolcall; subsequent attempts by the agent will be allowed. This provides steering while avoiding overly restricting the model (e.g., allowing pip install if it's already in a container).

Writing rules

// rules/rules.local.js
export default [
  {
    match: (v) =>
      v.includes('pip') &&
      v.includes('install') &&
      !v.includes('uv pip') &&
      !v.includes('uvx'),
    reject: true,
    prompt: 'Use `uvx` or `uv venv` + `uv pip` instead of `pip install` directly',
  },
  {
    match: (v) => v.includes('curl') && v.includes('api.github.com'),
    prompt: 'Prefer using `gh` cli over `curl https://api.github.com/...`. gh offers more requests limits.',
  },
  {
    match: (v) => v.includes('pdf'),
    prompt: 'Use the `markitdown` skill to read PDF files.',
  },
  // add your rules here
]
field required description
match ✅ (v: string) => boolean; every tool call is flattened to a string and matched — plus, after dispatch, the settled result's content, markers and error text
prompt ✅ The prompt for steering
reject If true, prevent the tool call first, instead of just steering

Compatibility

Declared in package.json under dsh.compatibility: DSH >=0.1.7-alpha.1 <0.2, Node.js ^22.19.0 || >=24.0.0, profiles web / headless.

>=0.1.7-alpha.1 is a hard floor, not a preference: that release retires the { kind: 'plugin', plugin: … } message source (session format v4), so the steering notice declares its own MessageSourceMap entry.

Per-release evidence (each release installed into a disposable profile with dsh plugin add <tarball>): the profile composes and cold-starts, the tool-call hook is exercised directly against that release's tools/pre-execute waterfall and agent.inject() (steering notice delivered, reject: true denies the first call and allows the retry), then the plugin is uninstalled and the profile boots again. The rows below are the evidence collected for the >=0.1.0-rc.6 declaration; the range declared above is not re-verified release by release yet.

DSH version install start hook uninstall
0.1.5-alpha.1 passed passed passed passed
0.1.5-alpha.2 passed passed passed passed
0.1.5-rc.1 passed passed passed passed

Implementation notes

  • A single src/index.ts (~80 lines).
  • Uses DSH's tools/pre-execute waterfall (deny), tools/post-execute (failure-text matching + additionalContexts) and agent.inject() (steering), the documented native extension points. No core changes, no monkey-patching.

CLASSIFICATION EVIDENCE

分类依据

项目类型插件
功能分类安全与治理
规则置信度高

系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: guardrail。