@suifei/dsh-pmo-button 0.7.3 → 0.7.4

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.
Files changed (3) hide show
  1. package/client.js +2 -2
  2. package/index.js +8 -3
  3. package/package.json +1 -1
package/client.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * PMO button — Client half v0.7.3.
2
+ * PMO button — Client half v0.7.4.
3
3
  * Red start/stop control in `conversation.input.right` (idle: neutral circle
4
4
  * with red arrow; armed: red circle with pulse animation) plus a liveness
5
5
  * strip in `conversation.composer.dock`. State is owned by the Host half via
@@ -12,7 +12,7 @@ window.__ModuleLoader__.load({
12
12
  const React = require('react');
13
13
  const h = React.createElement;
14
14
  const BASE = '/pmo-button';
15
- const VER = 'v0.7.3';
15
+ const VER = 'v0.7.4';
16
16
  let loadError = null;
17
17
  let t = { start: 'Start PMO automation', stop: 'PMO running: click to stop', busy: 'PMO: pending…', offline: 'PMO: host unreachable' };
18
18
 
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * PMO button — Host half v0.7.3.
2
+ * PMO button — Host half v0.7.4.
3
3
  * Per-session armed set, turn buffers, child registry, and the once-per-session
4
4
  * identity-prompt flag are persisted (pmo-state.json), so restarts lose nothing.
5
5
  * The `session/event` feed drives two jobs for armed sessions:
@@ -180,6 +180,11 @@ export function apply(ctx, config) {
180
180
  if (t.length <= limit) return t
181
181
  return t.slice(0, limit) + `\n…(截断,原长 ${t.length} 字符)`
182
182
  }
183
+ /** Never let credential-looking strings (npm_ tokens etc.) reach the log,
184
+ * the review forward, or the child's durable session. */
185
+ function redact(s) {
186
+ return String(s ?? '').replace(/npm_[A-Za-z0-9]{20,}/g, 'npm_***已脱敏***')
187
+ }
183
188
  /** Auto-stop: dim the button and gate forwarding WITHOUT deafening the
184
189
  * session listener — turn logging keeps running, and user speech (or a
185
190
  * button re-light) releases the gate so the loop can auto-resume. */
@@ -315,7 +320,7 @@ export function apply(ctx, config) {
315
320
  otherTasks.forEach((t) => parts.push(`[注入:${t.src}] ${t.text}`))
316
321
  attachTasks.forEach((t) => parts.push(t.text))
317
322
  if (b.texts?.length > 0) parts.push(`[主代理] ${b.texts.join('\n\n---\n\n')}`)
318
- const forward = clip(`【PMO 轮次转发 · turn=${turn}】\n` + parts.join('\n'), config.maxChars * 2)
323
+ const forward = clip(redact(`【PMO 轮次转发 · turn=${turn}】\n` + parts.join('\n')), config.maxChars * 2)
319
324
  const agents = ctx.get('agents')
320
325
  const agent = agents && typeof agents.get === 'function' ? agents.get(sid) : undefined
321
326
  const subagentsSvc = ctx.get('subagents')
@@ -424,7 +429,7 @@ export function apply(ctx, config) {
424
429
  const srcKind = text.trimStart().startsWith('<system-reminder>')
425
430
  ? 'system-reminder'
426
431
  : sourceKind(event.data)
427
- b.tasks.push({ src: srcKind, text })
432
+ b.tasks.push({ src: srcKind, text: redact(text) })
428
433
  for (const s of nonTextSummaries(event.data)) b.tasks.push({ src: '__attach__', text: s })
429
434
  // Recognize the PMO child's STATUS protocol from its settlement notice
430
435
  // or direct adjacent message, and record the review verdict.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suifei/dsh-pmo-button",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "description": "PMO 审查循环按钮 for DeepSeek Harness — 持久审查子代理 + 轮次转发 + STATUS 协议(CONTINUE/DONE/NEED_HUMAN)自动循环推进",
5
5
  "keywords": [
6
6
  "deepseek-harness", "dsh", "dsh-plugin", "pmo", "code-review",