agent-purge 0.2.4 → 0.2.5

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/lib/dsh.mjs CHANGED
@@ -30,7 +30,7 @@ export function residentSource(root, activePath) {
30
30
  // active.md 是派生物,实际位置是 <root>/personas/active.md(由 createStore().materialize 给出)
31
31
  const active = String(activePath).replace(/\\/g, "/");
32
32
  return `// 由 agent-purge 生成;删掉本目录 + patch 段即取消。
33
- import { readFileSync, appendFileSync } from "node:fs";
33
+ import { readFileSync, appendFileSync, writeFileSync } from "node:fs";
34
34
  const STATE = ${JSON.stringify(state)};
35
35
  const ACTIVE = ${JSON.stringify(active)};
36
36
  const NAME = ${JSON.stringify(RESIDENT)};
@@ -73,11 +73,87 @@ function put(asm, c) {
73
73
  if (c.mode === "append") return { ...asm, sections: [...sections, { name: NAME, text: c.body }] };
74
74
  return { ...asm, sections: [{ name: NAME, text: c.body }] };
75
75
  }
76
+ // ---- /ap 斜杠命令:直接改 state.json,不产生模型消息 ----
77
+ function readState() {
78
+ try { return JSON.parse(readFileSync(STATE, "utf8")) || {}; } catch { return {}; }
79
+ }
80
+ function saveState(st) {
81
+ writeFileSync(STATE, JSON.stringify(st, null, 2) + "\\n");
82
+ }
83
+ function apPatch(fn) {
84
+ const st = readState();
85
+ if (!st.armed || typeof st.armed !== "object") st.armed = {};
86
+ if (!Array.isArray(st.armed.dsh)) st.armed.dsh = [];
87
+ fn(st, st.armed.dsh);
88
+ saveState(st);
89
+ }
90
+ function handleAp(raw) {
91
+ const parts = String(raw || "").trim().split(/\s+/).filter(Boolean);
92
+ const cmd = (parts[0] || "status").toLowerCase();
93
+ const arg = parts.slice(1).join(" ").trim();
94
+ if (cmd === "off") {
95
+ apPatch((st, a) => {
96
+ if (a.includes("install")) {
97
+ st.dshPrevArmed = a.slice();
98
+ st.armed.dsh = a.filter((x) => x !== "install");
99
+ }
100
+ });
101
+ return { kind: "success", text: "agent-purge 已关闭(dsh),下一句起不注入" };
102
+ }
103
+ if (cmd === "on") {
104
+ apPatch((st, a) => {
105
+ if (!a.includes("install")) a.push("install");
106
+ delete st.dshPrevArmed;
107
+ });
108
+ return { kind: "success", text: "agent-purge 已开启(dsh),下一句起生效" };
109
+ }
110
+ if (cmd === "mode") {
111
+ const m = arg.toLowerCase();
112
+ if (m !== "strict" && m !== "replace" && m !== "append") {
113
+ return { kind: "error", text: "用法:/purge mode strict|replace|append" };
114
+ }
115
+ apPatch((st) => { if (!st.default || typeof st.default !== "object") st.default = {}; st.default.mode = m; });
116
+ return { kind: "success", text: "模式已切到 " + m };
117
+ }
118
+ if (cmd === "status" || cmd === "help") {
119
+ const st = readState();
120
+ const a = st.armed && Array.isArray(st.armed.dsh) ? st.armed.dsh : [];
121
+ const mode = (st.default && st.default.mode) || "replace";
122
+ return { kind: "success", text: "agent-purge / dsh:" + (a.includes("install") ? "开" : "关") + " · 模式 " + mode + " · 人设 " + (st.persona || "-") + "(可用:on | off | status | mode <strict|replace|append>)" };
123
+ }
124
+ return { kind: "error", text: "用法:/purge on | off | status | mode <strict|replace|append>" };
125
+ }
76
126
  export default {
77
127
  name: NAME,
78
128
  inject: ["systemPrompt"],
79
129
  apply(ctx) {
80
130
  log("apply", "inject=" + JSON.stringify(["systemPrompt"]));
131
+ // /ap 斜杠命令:等 commands 服务就绪再注册;headless 没有该服务就不会触发,注入不受影响
132
+ try {
133
+ if (typeof ctx.inject === "function") {
134
+ ctx.inject(["commands"], (c) => {
135
+ const spec = {
136
+ description: "agent-purge 人设注入:开关 / 模式",
137
+ input: { hint: "on | off | status | mode <strict|replace|append>" },
138
+ handler: ({ rawInput }) => handleAp(rawInput),
139
+ };
140
+ // 主名 /purge(和 pi 等其他 harness 统一),/ap 留作别名;
141
+ // 与已有同名命令(如 dsh-purge)撞车时只跳过那一个,不影响注入
142
+ for (const n of ["purge", "ap"]) {
143
+ try {
144
+ c.commands.register({ name: n, ...spec });
145
+ log("command", "registered /" + n);
146
+ } catch (e) {
147
+ log("command", "skip /" + n + " " + (e && e.message));
148
+ }
149
+ }
150
+ });
151
+ } else {
152
+ log("command", "no inject api");
153
+ }
154
+ } catch (e) {
155
+ log("command", "err " + (e && e.message));
156
+ }
81
157
  // 宿主每轮 assemble 走 system-prompt/assemble 瀑布。必须 global:agent 作用域的
82
158
  // systemPrompt 是另一个实例,且切预设时宿主会整只换代理,实例上的 monkey-patch 会丢。
83
159
  const handler = async (assembly, _context, next) => {
package/lib/persist.mjs CHANGED
@@ -111,11 +111,11 @@ export const AgentPurge = async () => ({
111
111
  file: () => join(pluginDir("desktop"), "index.js"),
112
112
  kind: "file",
113
113
  layer: "sys",
114
- note: "cordis 插件包;运行时读 state.json,off 即时生效;desktop 需重启一次",
114
+ note: "cordis 插件包;运行时每轮读 state.json,开关 / 切模式 / 换人设都即时生效;只有首次安装要重启一次",
115
115
  probe: () => hasPlugin(DSH_RESIDENT),
116
116
  install: ({ root, active }) => {
117
117
  const r = addPlugin(DSH_RESIDENT, residentSource(root, active));
118
- return { file: join(pluginDir("desktop"), "index.js"), note: `三个 profile:${r.profiles.join("/")};desktop 重启 DeepSeek Harness 生效` };
118
+ return { file: join(pluginDir("desktop"), "index.js"), note: `三个 profile:${r.profiles.join("/")};重启一次 DeepSeek Harness 后插件开始工作(之后热切换)` };
119
119
  },
120
120
  uninstall: () => {
121
121
  removePlugin(DSH_RESIDENT);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-purge",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "One persona, many coding agents: replace or inject system prompts across codex, claude, opencode (v1/v2), grok, omp, hermes, pi, zcode, dsh.",
5
5
  "type": "module",
6
6
  "bin": {