@suifei/dsh-pmo-button 0.7.2 → 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.
- package/README.md +1 -1
- package/client.js +2 -2
- package/index.js +12 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ dsh plugin --profile <你的profile> add github:suifei/dsh-pmo-button
|
|
|
51
51
|
|
|
52
52
|
| 字段 | 默认值 | 说明 |
|
|
53
53
|
|---|---|---|
|
|
54
|
-
| `logFile` |
|
|
54
|
+
| `logFile` | `~/.dsh/logs/pmo-button.log` | 轮次日志路径(默认在 Harness home 下,可改绝对路径) |
|
|
55
55
|
| `maxChars` | `4000` | 日志单块截断阈值(转发块为 2×) |
|
|
56
56
|
| `provider` | `spawn` | 子代理提供方(`ctx.subagents` 注册名) |
|
|
57
57
|
| `childLabel` | `PMO 子代理` | 持久子代理标签 |
|
package/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* PMO button — Client half v0.7.
|
|
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.
|
|
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.
|
|
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:
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* batch-flushed, while session/event is the documented post-commit surface.
|
|
16
16
|
*/
|
|
17
17
|
import fs from 'node:fs'
|
|
18
|
+
import os from 'node:os'
|
|
18
19
|
import path from 'node:path'
|
|
19
20
|
import Schema from '@deepseek-ai/schemastery'
|
|
20
21
|
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
|
@@ -53,7 +54,8 @@ const ROLE_PROMPT_DEFAULT = [
|
|
|
53
54
|
|
|
54
55
|
/** @typedef {{ logFile: string, maxChars: number, provider: string, childLabel: string, greet: string, rolePrompt: string }} Config */
|
|
55
56
|
export const Config = Schema.object({
|
|
56
|
-
|
|
57
|
+
/** Deterministic default: ~/.dsh/logs/pmo-button.log (cwd-relative defaults break on restarts). */
|
|
58
|
+
logFile: Schema.string().default(path.join(os.homedir(), '.dsh', 'logs', 'pmo-button.log')),
|
|
57
59
|
maxChars: Schema.number().default(4000),
|
|
58
60
|
/** Subagent provider name registered on ctx.subagents (spawn-in-process default). */
|
|
59
61
|
provider: Schema.string().default('spawn'),
|
|
@@ -178,6 +180,11 @@ export function apply(ctx, config) {
|
|
|
178
180
|
if (t.length <= limit) return t
|
|
179
181
|
return t.slice(0, limit) + `\n…(截断,原长 ${t.length} 字符)`
|
|
180
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
|
+
}
|
|
181
188
|
/** Auto-stop: dim the button and gate forwarding WITHOUT deafening the
|
|
182
189
|
* session listener — turn logging keeps running, and user speech (or a
|
|
183
190
|
* button re-light) releases the gate so the loop can auto-resume. */
|
|
@@ -204,7 +211,7 @@ export function apply(ctx, config) {
|
|
|
204
211
|
function sourceKind(data) {
|
|
205
212
|
return data?.message?.source?.kind ?? data?.source?.kind ?? 'user'
|
|
206
213
|
}
|
|
207
|
-
const OTHER_SOURCES = new Set(['inject', 'steering', 'time-context', 'agent-message', 'subagent-settled', 'system-reminder'])
|
|
214
|
+
const OTHER_SOURCES = new Set(['inject', 'steering', 'time-context', 'agent-message', 'subagent-settled', 'system-reminder', 'tool-jobs'])
|
|
208
215
|
/** Compact summary of non-text content blocks (images, files, references). */
|
|
209
216
|
function nonTextSummaries(data) {
|
|
210
217
|
const m = data?.message ?? data
|
|
@@ -313,7 +320,7 @@ export function apply(ctx, config) {
|
|
|
313
320
|
otherTasks.forEach((t) => parts.push(`[注入:${t.src}] ${t.text}`))
|
|
314
321
|
attachTasks.forEach((t) => parts.push(t.text))
|
|
315
322
|
if (b.texts?.length > 0) parts.push(`[主代理] ${b.texts.join('\n\n---\n\n')}`)
|
|
316
|
-
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)
|
|
317
324
|
const agents = ctx.get('agents')
|
|
318
325
|
const agent = agents && typeof agents.get === 'function' ? agents.get(sid) : undefined
|
|
319
326
|
const subagentsSvc = ctx.get('subagents')
|
|
@@ -422,7 +429,7 @@ export function apply(ctx, config) {
|
|
|
422
429
|
const srcKind = text.trimStart().startsWith('<system-reminder>')
|
|
423
430
|
? 'system-reminder'
|
|
424
431
|
: sourceKind(event.data)
|
|
425
|
-
b.tasks.push({ src: srcKind, text })
|
|
432
|
+
b.tasks.push({ src: srcKind, text: redact(text) })
|
|
426
433
|
for (const s of nonTextSummaries(event.data)) b.tasks.push({ src: '__attach__', text: s })
|
|
427
434
|
// Recognize the PMO child's STATUS protocol from its settlement notice
|
|
428
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
|
+
"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",
|