dsh-rules 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,7 +25,7 @@ Glob-activated rule prompts for [DeepSeek Harness](https://github.com/deepseek-a
25
25
 
26
26
  - **Glob activation** — rules activate per file the agent touches: `**`, `*`, `?`, `{a,b}`, `[abc]`, and `!` negation (picomatch).
27
27
  - **Claude Code compatible** — plain rule files (`.dsh/rules/*.md`) *and* `# Path:` sections inside `CLAUDE.md` / `AGENTS.md`.
28
- - **Visible & durable** — active rules are injected as a user message the UI shows and the session log persists; each snapshot supersedes earlier ones, so the model always sees the current set.
28
+ - **Visible & durable** — active rules are injected as a user message the UI shows and the session log persists; each injection appears in the chat as a collapsible row (same chrome as tool-call rows) with a one-line notice — e.g. `dsh-rules · Active rules: typescript, docs` — expanding to the full rules text. Each snapshot supersedes earlier ones, so the model always sees the current set.
29
29
  - **Budget-bounded** — byte-budget rendering (32 KB default): low-priority rules are dropped first, then the last rule is truncated; content is escaped so it can never break out of the framing tags.
30
30
  - **Resume-friendly** — on session resume the last snapshot and its matched files are restored from the log, preventing duplicate injection.
31
31
  - **Per-session tracking** — every agent/session tracks its own touched files (subagents included); global rules (no `path:`) are always active.
package/README.zh.md CHANGED
@@ -25,7 +25,7 @@
25
25
 
26
26
  - **glob 激活** —— 按 agent 触碰的文件逐个激活规则:`**`、`*`、`?`、`{a,b}`、`[abc]`、`!` 取反(picomatch)。
27
27
  - **Claude Code 兼容** —— 既支持规则文件(`.dsh/rules/*.md`),也支持 `CLAUDE.md` / `AGENTS.md` 内的 `# Path:` 段落。
28
- - **可见且持久** —— 激活的规则以用户消息注入,UI 可见、会话日志持久化;每个快照取代更早快照,模型始终看到最新集合。
28
+ - **可见且持久** —— 激活的规则以用户消息注入,UI 可见、会话日志持久化;每次注入在对话里显示为一行可折叠的通知(与工具调用行同款外观,如 `dsh-rules · Active rules: typescript, docs`),展开可见完整规则文本;每个快照取代更早快照,模型始终看到最新集合。
29
29
  - **预算可控** —— 字节预算渲染(默认 32 KB):先丢弃低优先级规则,再截断最后一条;正文转义,无法逃逸框架标签。
30
30
  - **恢复友好** —— 恢复会话时从日志恢复最近一次快照与已匹配文件列表,避免重复注入。
31
31
  - **按会话跟踪** —— 每个 agent/会话独立跟踪触碰文件(含子代理);无 `path:` 的全局规则恒激活。
package/lib/index.js CHANGED
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * @module dsh-rules
12
12
  */
13
- import { createUserMessage } from "@deepseek-ai/dsh-llm";
13
+ import { boundContextSummary, createUserMessage } from "@deepseek-ai/dsh-llm";
14
14
  import { dshHomeDisplay, resolveDshHome } from "@deepseek-ai/dsh-home-paths";
15
15
  import z from "@deepseek-ai/schemastery";
16
16
  import { dirname, join, resolve } from "node:path";
@@ -264,11 +264,11 @@ var RulesState = class {
264
264
  if (desiredText === null) {
265
265
  if (previous === void 0 || previous === null || previous === EMPTY_RULES_TEXT) return void 0;
266
266
  this.lastInjected.set(sessionId, EMPTY_RULES_TEXT);
267
- return rulesMessage(EMPTY_RULES_TEXT);
267
+ return rulesMessage(EMPTY_RULES_TEXT, "No active rules");
268
268
  }
269
269
  if (previous === desiredText) return void 0;
270
270
  this.lastInjected.set(sessionId, desiredText);
271
- return rulesMessage(desiredText);
271
+ return rulesMessage(desiredText, rulesSummary(active));
272
272
  }
273
273
  /** Restore the last injected snapshot (and matched files) from a resumed session log. */
274
274
  seedFromSession(session) {
@@ -277,7 +277,8 @@ var RulesState = class {
277
277
  const event = events[index];
278
278
  if (event?.type !== "user/message") continue;
279
279
  const source = event.data?.source;
280
- if (source?.kind !== "plugin" || source.plugin !== name || source.form !== "rules") continue;
280
+ if (source?.kind !== "plugin" || source.plugin !== name) continue;
281
+ if (source.form !== "rules" && source.form !== "notice") continue;
281
282
  const [block] = event.data.content;
282
283
  const text = event.data.content.length === 1 && block?.type === "text" ? block.text : void 0;
283
284
  if (text === void 0) break;
@@ -427,14 +428,34 @@ var RulesState = class {
427
428
  }
428
429
  };
429
430
 
430
- /** Build the user-role message carrying one rules snapshot. */
431
- function rulesMessage(text) {
431
+ /** Build the user-role message carrying one rules snapshot.
432
+ *
433
+ * The message source uses the host's `notice` context form (`form` +
434
+ * one-line `summary`): the DSH web UI renders every plugin-sourced user
435
+ * message as a collapsible context row (same chrome as tool-call rows), and a
436
+ * `notice` form makes the summary visible on the collapsed row — e.g.
437
+ * `dsh-rules · Active rules: typescript, docs` — with the full snapshot
438
+ * behind the disclosure. */
439
+ function rulesMessage(text, summary) {
432
440
  return createUserMessage({
433
441
  content: [{ type: "text", text }],
434
- source: { kind: "plugin", plugin: name, form: "rules" }
442
+ source: {
443
+ kind: "plugin",
444
+ plugin: name,
445
+ form: "notice",
446
+ summary: boundContextSummary(summary)
447
+ }
435
448
  });
436
449
  }
437
450
 
451
+ /** One-line account of the active rule set, in rendering order (rank, name). */
452
+ function rulesSummary(active) {
453
+ const names = [...active]
454
+ .sort((left, right) => left.rank - right.rank || (left.name < right.name ? -1 : left.name > right.name ? 1 : 0))
455
+ .map((rule) => rule.name);
456
+ return `Active rules: ${names.join(", ")}`;
457
+ }
458
+
438
459
  /** Whether one message is our rules snapshot with the same text as another. */
439
460
  function sameRulesMessage(message, desired) {
440
461
  if (message.source?.kind !== "plugin" || message.source?.plugin !== name) return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-rules",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "DSH rules plugin: activate rule prompts / markdown documents by glob-matching the files an agent reads or edits (Claude Code rules.md style).",
5
5
  "keywords": [
6
6
  "dsh",
@@ -12,6 +12,10 @@
12
12
  "prompt"
13
13
  ],
14
14
  "license": "MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/rj-jiangyichen/dsh-rules.git"
18
+ },
15
19
  "type": "module",
16
20
  "main": "lib/index.js",
17
21
  "exports": {