@yuanchilin/dsh-mailbox 1.0.0

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.
@@ -0,0 +1,44 @@
1
+ // 最小类型声明 (core 与插件导出的形状)
2
+ export interface MailboxConfig {
3
+ identity: string;
4
+ layout: "root" | "dirs";
5
+ root: string;
6
+ dirs: Record<string, string>;
7
+ participants: string[];
8
+ intervalSec: number;
9
+ timeoutSec: number;
10
+ seenFile: string;
11
+ patchRoot: string;
12
+ }
13
+
14
+ export interface MailboxMessage {
15
+ id: string;
16
+ from: string;
17
+ to: string;
18
+ type: "request" | "response" | "notify" | "reply";
19
+ topic: string;
20
+ payload: unknown;
21
+ ts: number;
22
+ reply_to: string;
23
+ }
24
+
25
+ export interface MailboxStatus {
26
+ identity: string;
27
+ layout: string;
28
+ outDir: string;
29
+ outCount: number;
30
+ seen: number;
31
+ inboxes: Array<{ dir: string; msgCount: number }>;
32
+ }
33
+
34
+ export function resolveConfig(partial?: Partial<MailboxConfig>, env?: NodeJS.ProcessEnv): MailboxConfig;
35
+ export function resolveDirs(cfg: MailboxConfig): { out: string; in: string[] };
36
+ export function seenFileOf(cfg: MailboxConfig): string;
37
+ export function loadSeen(cfg: MailboxConfig): string[];
38
+ export function saveSeen(cfg: MailboxConfig, seen: string[]): void;
39
+ export function sendMessage(cfg: MailboxConfig, msg: Partial<Pick<MailboxMessage, "to" | "type" | "topic" | "payload" | "reply_to">>): string;
40
+ export function recvNew(cfg: MailboxConfig, markSeen?: boolean): MailboxMessage[];
41
+ export function removeMessage(cfg: MailboxConfig, id: string, inbox?: boolean): boolean;
42
+ export function cleanTTL(cfg: MailboxConfig, opts?: { ttlHours?: number; dryRun?: boolean }): number;
43
+ export function statusOf(cfg: MailboxConfig): MailboxStatus;
44
+ export function assertUsable(cfg: MailboxConfig): void;
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@yuanchilin/dsh-mailbox",
3
+ "version": "1.0.0",
4
+ "description": "DeepSeek Harness cross-session file mailbox: send/recv/status tools over a shared filesystem mailbox (N participants, directed & broadcast routing, seen dedup, TTL cleanup), plus a zero-dependency node CLI and a packaged DSH skill.",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "types": "lib/types/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "default": "./lib/index.js"
11
+ },
12
+ "./core": {
13
+ "default": "./lib/core.js"
14
+ },
15
+ "./cordis.patch.yml": "./cordis.patch.yml",
16
+ "./skill/SKILL.md": "./skill/SKILL.md",
17
+ "./package.json": "./package.json"
18
+ },
19
+ "bin": {
20
+ "mailbox": "bin/mailbox.mjs"
21
+ },
22
+ "files": [
23
+ "lib/index.js",
24
+ "lib/core.js",
25
+ "lib/types/index.d.ts",
26
+ "bin/mailbox.mjs",
27
+ "cordis.patch.yml",
28
+ "skill/",
29
+ "README.md",
30
+ "LICENSE"
31
+ ],
32
+ "scripts": {
33
+ "test": "node --test test/"
34
+ },
35
+ "keywords": [
36
+ "deepseek-harness",
37
+ "dsh",
38
+ "mailbox",
39
+ "cross-session",
40
+ "messaging",
41
+ "plugin"
42
+ ],
43
+ "license": "MIT",
44
+ "dsh": {
45
+ "bundle": {
46
+ "patch": "./cordis.patch.yml"
47
+ }
48
+ },
49
+ "dependencies": {
50
+ "@deepseek-ai/schemastery": "^3.18.1"
51
+ },
52
+ "peerDependencies": {
53
+ "@deepseek-ai/cordis": "^4.0.1",
54
+ "@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
55
+ "@deepseek-ai/dsh-tools": "^0.1.0-rc.6"
56
+ },
57
+ "engines": {
58
+ "node": ">=18.0.0"
59
+ }
60
+ }
@@ -0,0 +1,117 @@
1
+ # mailbox — 通用跨会话文件信箱 v1
2
+
3
+ 文件信箱,用于 **N 个会话/agent 之间的异步通信**。泛化自 mcp/RP 联调工具,零依赖、配置驱动、双实现(pwsh + Node)可互换混用。
4
+
5
+ ## 核心模型
6
+
7
+ - 每个参与者有唯一身份 `id`,各写各的信箱目录,互读对方的
8
+ - **layout=root(标准)**:共享根目录 `<root>/<id>/` 每人一个子目录
9
+ - **layout=dirs(兼容旧双目录)**:`dirs: { id -> 目录 }` 显式映射,旧 mcp/RP 信箱免迁移接入
10
+ - 消息格式:`{ id, from, to, type, topic, payload, ts, reply_to }`,文件 `msg_<id>.json`
11
+ - 路由:`to=<id>` 定向 / `to=all` 广播(只写一份,各人自取)
12
+ - seen 去重:每参与者独立 seen 文件(默认 `<outDir>/.seen.json`),重启不重复处理
13
+
14
+ ## 快速开始
15
+
16
+ ```powershell
17
+ # 1. 初始化(每个参与者同一 root 下各一个目录)
18
+ .\mailbox.ps1 init -Id agent-a -Root D:/Downloads/Agent/.mailbox
19
+ .\mailbox.ps1 init -Id agent-b -Root D:/Downloads/Agent/.mailbox
20
+
21
+ # 2. A 发消息
22
+ .\mailbox.ps1 send -To agent-b -Topic hello -Payload '{"x":1}'
23
+
24
+ # 3. B 收消息(一次性)
25
+ .\mailbox.ps1 recv -Format table
26
+
27
+ # 4. B 事件监听(新消息 → 打印 → exit 0,DSH 后台 job 完成即唤醒 agent)
28
+ .\mailbox.ps1 wait -Timeout 600
29
+
30
+ # 5. B 常驻轮询(request 自动回 response,可挂 handlers)
31
+ .\mailbox.ps1 poll -Interval 2 -Handlers .\examples\handlers.patch.ps1
32
+ ```
33
+
34
+ Node 版命令完全一致:
35
+
36
+ ```bash
37
+ node mailbox.mjs send --to agent-b --topic hello --payload '{"x":1}'
38
+ node mailbox.mjs recv --format table
39
+ node mailbox.mjs wait --timeout 600
40
+ ```
41
+
42
+ ## 命令
43
+
44
+ | 命令 | pwsh | node | 说明 |
45
+ |---|---|---|---|
46
+ | init | `init -Id x -Root y` | `init --id x --root y` | 生成配置文件 |
47
+ | send | `send -To <id\|all> -Type <t> -Topic <t> -Payload <json> -ReplyTo <id>` | 同左 `--to/--type/--topic/--payload/--reply-to` | 发消息 |
48
+ | recv | `recv [-Format table\|json]` | `recv [--format table\|json]` | 读新消息(更新 seen) |
49
+ | wait | `wait [-Timeout sec] [-Interval sec]` | `wait [--timeout sec]` | 新消息即 exit 0(唤醒) |
50
+ | poll | `poll [-Interval sec] [-Handlers <ps1>]` | `poll [--interval sec] [--handlers <mjs>]` | 常驻轮询 |
51
+ | clean | `clean [-TtlHours n] [-DryRun]` | `clean [--ttl-hours n] [--dry-run]` | TTL 清理自己的已发送消息 |
52
+ | status | `status` | `status` | 身份/目录/消息数 |
53
+
54
+ ## 配置
55
+
56
+ 配置文件默认 `mailbox.config.json`(与工具同目录),可用 `-Config` / `--config` 或环境变量 `MAILBOX_CONFIG` 指定。
57
+
58
+ ```json
59
+ {
60
+ "identity": "agent-a",
61
+ "layout": "root",
62
+ "root": "D:/Downloads/Agent/.mailbox",
63
+ "dirs": {},
64
+ "participants": [],
65
+ "intervalSec": 2,
66
+ "timeoutSec": 0,
67
+ "seenFile": "",
68
+ "patchRoot": ""
69
+ }
70
+ ```
71
+
72
+ 优先级:**CLI 参数 > 环境变量(`MAILBOX_CONFIG`/`MAILBOX_ID`/`MAILBOX_ROOT`/`MAILBOX_INTERVAL`/`MAILBOX_TIMEOUT`)> 配置文件 > 默认**。
73
+
74
+ - `participants` 留空时自动扫描 `<root>/` 下的子目录作为参与者
75
+ - `seenFile` 留空默认 `<outDir>/.seen.json`
76
+ - `patchRoot` 供示例补丁 handler 使用
77
+
78
+ ## 消息类型与默认处理
79
+
80
+ | type | 默认处理(poll) |
81
+ |---|---|
82
+ | request | 自动回 `response`(echo payload) |
83
+ | response / notify / reply | 打印 |
84
+
85
+ **可插拔 handler**:
86
+ - pwsh:`-Handlers <ps1>`,dot-source 后定义 `function Handle-Message($Msg, $Ctx)`,返回 `$false` 回退默认逻辑
87
+ - node:`--handlers <mjs>`,导出 `export async function handle(msg, ctx)`,返回 `false` 回退默认逻辑
88
+
89
+ 示例:`examples/handlers.patch.ps1` 补丁自动应用(备份→替换→`node --check`→失败回滚→写 `patches/history.jsonl`→回 response),协议:
90
+
91
+ ```json
92
+ { "type": "request", "topic": "patch_<任意>", "payload": {
93
+ "patch_id": "p1", "note": "说明",
94
+ "edits": [ { "file": "build/x.js", "old": "...", "new": "..." },
95
+ { "file": "build/y.js", "whole": "完整内容" },
96
+ { "file": "build/z.js", "old": "...", "new": "...", "replace_all": true } ] } }
97
+ ```
98
+
99
+ ## 旧布局兼容(mcp/RP)
100
+
101
+ `legacy-mcp.config.json` 用 `layout:"dirs"` 映射原 mcp/RP 双目录,原轮询/监听脚本改为薄封装:
102
+
103
+ ```powershell
104
+ .\mailbox_poll_mcp.ps1 # → mailbox.ps1 poll -Config legacy-mcp.config.json -Handlers examples/handlers.patch.ps1
105
+ .\mailbox_wait_mcp.ps1 # → mailbox.ps1 wait -Config legacy-mcp.config.json
106
+ ```
107
+
108
+ ## 自测
109
+
110
+ ```powershell
111
+ .\self-test.ps1 # 覆盖: 往返/广播/wait 唤醒/TTL/双实现互通/旧布局/去重
112
+ ```
113
+
114
+ ## 二期路线(未实现)
115
+
116
+ - HTTP relay(跨机器,CLI 加 `transport` 开关)+ X25519 加密 / Ed25519 签名
117
+ - 独立 npm/pwsh 包发布
package/skill/SKILL.md ADDED
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: mailbox
3
+ description: 跨会话异步通信的文件信箱。通过共享文件系统在任意会话/agent 之间收发消息,支持 N 参与者、定向/广播、seen 去重、TTL 清理、事件唤醒。当需要与其他会话、后台 agent 或未来会话交换消息、任务结果或指示(而对方不一定在线)时使用。提供 pwsh 与 node 双实现的 CLI(send/recv/wait/poll/clean/status/init)。
4
+ whenToUse: 需要跨会话/跨进程异步传递消息时,例如向另一个会话发起请求、等待对方响应、投递任务结果、广播通知;或需要把当前会话状态交接给后续会话。
5
+ ---
6
+
7
+ # mailbox — 跨会话文件信箱
8
+
9
+ 基于文件系统的异步消息机制:**每个参与者各写各的信箱目录,互读对方的**。消息是文件,所以只要双方共享同一文件系统(同机或网络盘),就能在任意会话/进程/时间点通信,对方不在线也不丢消息。
10
+
11
+ ## 脚本位置
12
+
13
+ - **本技能目录**(随技能打包,任何项目可用):`$env:USERPROFILE\.dsh\skills\mailbox\`
14
+ - **项目内开发副本**(如存在,优先用项目内的):`<workspace>/tools/mailbox/`
15
+ - 两个实现完全同协议,可互换混用:
16
+ - pwsh:`mailbox.ps1`(模块 `mailbox.psm1`)
17
+ - node:`mailbox.mjs`(零依赖)
18
+
19
+ ## 快速开始
20
+
21
+ ```powershell
22
+ $mb = "$env:USERPROFILE\.dsh\skills\mailbox" # 或项目内 tools/mailbox
23
+
24
+ # 1. 初始化身份(同一 root 下每个参与者各初始化一次;root 需双方共享)
25
+ & "$mb\mailbox.ps1" init -Id agent-a -Root D:/Downloads/Agent/.mailbox
26
+
27
+ # 2. 发消息(to=all 广播 / to=<id> 定向)
28
+ & "$mb\mailbox.ps1" send -To agent-b -Topic hello -Payload '{"x":1}'
29
+
30
+ # 3. 收消息(一次性,自动更新 seen)
31
+ & "$mb\mailbox.ps1" recv -Format table
32
+
33
+ # 4. 事件唤醒:新消息到达即打印并 exit 0(后台 job 完成 → agent 被唤醒)
34
+ & "$mb\mailbox.ps1" wait -Timeout 600
35
+ ```
36
+
37
+ node 版命令一致:`node "$mb\mailbox.mjs" send --to agent-b --topic hello --payload '{"x":1}'`
38
+
39
+ ## 命令
40
+
41
+ | 命令 | pwsh | node | 说明 |
42
+ |---|---|---|---|
43
+ | init | `init -Id <id> -Root <dir>` | `init --id <id> --root <dir>` | 生成配置 |
44
+ | send | `send -To <id\|all> [-Type request\|response\|notify\|reply] [-Topic <t>] [-Payload <json>] [-ReplyTo <id>]` | `--to/--type/--topic/--payload/--reply-to` | 发消息 |
45
+ | recv | `recv [-Format table\|json]` | `recv [--format ...]` | 读新消息(更新 seen) |
46
+ | wait | `wait [-Timeout <sec>]` | `wait [--timeout <sec>]` | 新消息即 exit 0(唤醒) |
47
+ | poll | `poll [-Interval <sec>] [-Handlers <ps1>]` | `poll [--interval <sec>] [--handlers <mjs>]` | 常驻轮询(request 自动回 response) |
48
+ | clean | `clean [-TtlHours <n>] [-DryRun]` | `clean [--ttl-hours <n>] [--dry-run]` | TTL 清理自己发过的旧消息 |
49
+ | status | `status` | `status` | 身份/目录/消息数 |
50
+
51
+ ## 配置
52
+
53
+ 默认读取工具同目录 `mailbox.config.json`,可用 `-Config` / `--config` 或环境变量 `MAILBOX_CONFIG` 指定。优先级:**CLI 参数 > 环境变量(`MAILBOX_ID`/`MAILBOX_ROOT`/`MAILBOX_CONFIG`/`MAILBOX_INTERVAL`/`MAILBOX_TIMEOUT`)> 配置文件 > 默认**。
54
+
55
+ ```json
56
+ { "identity": "agent-a", "layout": "root", "root": "D:/Downloads/Agent/.mailbox",
57
+ "participants": [], "intervalSec": 2, "timeoutSec": 0, "seenFile": "", "patchRoot": "" }
58
+ ```
59
+
60
+ - `layout=root`(标准):`<root>/<id>/` 每人一子目录;`participants` 留空自动扫描
61
+ - `layout=dirs`(旧双目录兼容):`dirs: { "<id>": "<目录>" }` 显式映射
62
+ - `seenFile` 留空默认 `<outDir>/.seen.json`(每参与者独立去重)
63
+
64
+ ## 协议
65
+
66
+ - 消息文件:`msg_<id>.json`,内容 `{ id, from, to, type, topic, payload, ts, reply_to }`
67
+ - 路由:`to=<id>` 定向 / `to=all` 广播(写一份,各人自取)
68
+ - 消息类型:`request` / `response` / `notify` / `reply`
69
+ - **请求-响应模式**:发 `request` 带 `reply_to`,对方处理完回 `response` 指向原 id;`wait`/`recv` 可按 `reply_to` 关联
70
+ - 已处理消息建议删除(`Remove-MailboxMsg` / 由 poll 自动清理),seen 文件兜底去重
71
+
72
+ ## 典型用法
73
+
74
+ 1. **跨会话交接**:完成任务后 `send -To <对方> -Type notify -Topic handoff_ready -Payload @{...}`,把上下文文件路径放进 payload
75
+ 2. **请求-响应**:`send -To rp -Type request -Topic patch_bug2 -Payload @{edits=...}` → 对方 poll 自动处理并回 `patch_result`
76
+ 3. **等待对方**:`wait -Timeout 600` 挂后台 job,新消息到达 job 完成即被唤醒(DSH 机制)
77
+ 4. **补丁自动应用**(示例):`poll -Handlers examples/handlers.patch.ps1`(需配置 `patchRoot`),收到 `topic=patch_*` 消息自动备份→替换→node --check→回滚→回 response
78
+
79
+ ## 注意事项
80
+
81
+ - 双方必须共享同一文件系统(同机目录或网络盘);广域网需二期 HTTP relay(未实现)
82
+ - `wait` 与 `poll` 共用 seen 文件,同一身份不要同时跑两个
83
+ - 消息明文存储;需要保密时不要写入敏感 payload(二期支持加密)
@@ -0,0 +1,154 @@
1
+ # ============================================================================
2
+ # handlers.patch.ps1 — 示例 handler: 补丁自动应用
3
+ # (泛化自旧 mailbox_poll_mcp.ps1 的 Invoke-MailboxPatch)
4
+ #
5
+ # 用法:
6
+ # .\mailbox.ps1 poll -Handlers .\examples\handlers.patch.ps1
7
+ # 要求:
8
+ # 配置文件里 patchRoot 指向补丁目标工作区 (如 D:/work/myproject)
9
+ # 协议 (对端发来的消息):
10
+ # { type:"request", topic:"patch_<任意>", payload:{
11
+ # patch_id:"<标识>", note:"<说明>",
12
+ # edits:[
13
+ # { file:"build/x.js", old:"...", new:"..." }, # 片段替换
14
+ # { file:"build/y.js", whole:"完整新内容" }, # 整文件替换
15
+ # { file:"build/z.js", old:"...", new:"...", replace_all:true } # 全部替换
16
+ # ] } }
17
+ # 行为: 备份 → 替换 → node --check 语法检查 → 失败回滚 →
18
+ # 写 <patchRoot>/patches/history.jsonl → 回 response (topic: patch_result)
19
+ #
20
+ # 返回值: $true=已处理; $false=非补丁消息, 交给默认逻辑 (request→echo)
21
+ # ============================================================================
22
+
23
+ function Handle-Message {
24
+ param($Msg, $Ctx)
25
+
26
+ if ("$($Msg.topic)" -notlike "patch_*") { return $false }
27
+
28
+ $cfg = $Ctx.Cfg
29
+ $workRoot = [string]$cfg.patchRoot
30
+ if (-not $workRoot -or -not (Test-Path -LiteralPath $workRoot)) {
31
+ Write-Host " [补丁] patchRoot 未配置或不存在, 跳过 (config.patchRoot=$workRoot)"
32
+ return $true
33
+ }
34
+
35
+ $payload = $Msg.payload
36
+ $patchId = if ($payload.patch_id) { [string]$payload.patch_id } else { [string]$Msg.id }
37
+ $edits = @($payload.edits)
38
+ $results = @()
39
+ $changed = @{} # full path -> backup path
40
+ $ok = $true
41
+
42
+ New-Item -ItemType Directory -Force -Path (Join-Path $workRoot "patches") | Out-Null
43
+ $bakDir = Join-Path $workRoot "patches\backup"
44
+ New-Item -ItemType Directory -Force -Path $bakDir | Out-Null
45
+
46
+ Write-Host "`n[补丁应用] patch_id=$patchId edits=$($edits.Count) note=$($payload.note) root=$workRoot"
47
+
48
+ try {
49
+ foreach ($e in $edits) {
50
+ $rel = [string]$e.file
51
+ $full = Join-Path $workRoot $rel
52
+
53
+ # 路径安全: 必须落在 patchRoot 内
54
+ if (-not $full.StartsWith($workRoot, [System.StringComparison]::OrdinalIgnoreCase)) {
55
+ $results += "SKIP $rel (路径越界, 拒绝)"
56
+ $ok = $false
57
+ continue
58
+ }
59
+ if (-not (Test-Path -LiteralPath $full)) {
60
+ $results += "FAIL $rel (文件不存在)"
61
+ $ok = $false
62
+ continue
63
+ }
64
+
65
+ # 首次接触该文件时备份
66
+ if (-not $changed.ContainsKey($full)) {
67
+ $bak = Join-Path $bakDir ((Split-Path $rel -Leaf) + ".$patchId.bak")
68
+ Copy-Item -LiteralPath $full -Destination $bak -Force
69
+ $changed[$full] = $bak
70
+ }
71
+
72
+ $content = Get-Content -LiteralPath $full -Raw
73
+
74
+ if ($null -ne $e.whole -and [string]$e.whole -ne "") {
75
+ Set-Content -LiteralPath $full -Value ([string]$e.whole) -Encoding UTF8 -NoNewline
76
+ $results += "OK $rel (整文件替换)"
77
+ continue
78
+ }
79
+
80
+ $old = [string]$e.old
81
+ $new = [string]$e.new
82
+ if ($old -eq "") {
83
+ $results += "FAIL $rel (old 为空)"
84
+ $ok = $false
85
+ continue
86
+ }
87
+
88
+ $count = ([regex]::Matches($content, [regex]::Escape($old))).Count
89
+ if ($count -eq 0) {
90
+ $results += "FAIL $rel (old 片段未找到)"
91
+ $ok = $false
92
+ continue
93
+ }
94
+ if ($count -gt 1 -and -not $e.replace_all) {
95
+ $results += "FAIL $rel (old 出现 $count 次, 需 replace_all=true)"
96
+ $ok = $false
97
+ continue
98
+ }
99
+
100
+ if ($e.replace_all) {
101
+ $newContent = $content.Replace($old, $new)
102
+ } else {
103
+ $idx = $content.IndexOf($old, [System.StringComparison]::Ordinal)
104
+ $newContent = $content.Substring(0, $idx) + $new + $content.Substring($idx + $old.Length)
105
+ }
106
+ Set-Content -LiteralPath $full -Value $newContent -Encoding UTF8 -NoNewline
107
+ $results += "OK $rel (替换 x$count)"
108
+ }
109
+
110
+ # --- JS 语法检查 (node --check), 失败回滚 ---
111
+ if ($changed.Count -gt 0) {
112
+ $syntaxFail = $false
113
+ foreach ($full in @($changed.Keys)) {
114
+ if ($full -like "*.js") {
115
+ $out = & node --check $full 2>&1
116
+ if ($LASTEXITCODE -ne 0) {
117
+ $syntaxFail = $true
118
+ $results += "SYNTAX-FAIL $full : $out"
119
+ }
120
+ }
121
+ }
122
+ if ($syntaxFail) {
123
+ foreach ($full in @($changed.Keys)) {
124
+ Copy-Item -LiteralPath $changed[$full] -Destination $full -Force
125
+ $results += "ROLLED-BACK $full"
126
+ }
127
+ $ok = $false
128
+ }
129
+ }
130
+ } catch {
131
+ $ok = $false
132
+ $results += "EXCEPTION: $($_.Exception.Message)"
133
+ foreach ($full in @($changed.Keys)) {
134
+ Copy-Item -LiteralPath $changed[$full] -Destination $full -Force
135
+ $results += "ROLLED-BACK $full"
136
+ }
137
+ }
138
+
139
+ # --- 历史记录 ---
140
+ $rec = [ordered]@{
141
+ ts = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()
142
+ patch_id = $patchId; from = $Msg.from; ok = $ok
143
+ edits = $edits.Count; results = $results
144
+ }
145
+ ($rec | ConvertTo-Json -Depth 5) | Add-Content (Join-Path $workRoot "patches\history.jsonl") -Encoding UTF8
146
+
147
+ # --- 回 response ---
148
+ Send-Mailbox -Cfg $cfg -To $Msg.from -Type "response" -Topic "patch_result" `
149
+ -ReplyTo $Msg.id -Payload @{ patch_id = $patchId; ok = $ok; results = $results }
150
+
151
+ $results | ForEach-Object { Write-Host " $_" }
152
+ Write-Host " → 补丁结果: $(if ($ok) {'成功'} else {'失败(已回滚)'}) (response 已回 $($Msg.from))"
153
+ return $true
154
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "identity": "mcp",
3
+ "layout": "dirs",
4
+ "root": "",
5
+ "dirs": {
6
+ "mcp": "D:/Downloads/Agent/Soc/tools/mcp-serial/mailbox",
7
+ "rp": "D:/Downloads/Agent/RP/tools/mailbox"
8
+ },
9
+ "participants": [],
10
+ "intervalSec": 2,
11
+ "timeoutSec": 0,
12
+ "seenFile": "D:/Downloads/Agent/Soc/tools/mcp-serial/tools/.seen_mcp.json",
13
+ "patchRoot": "D:/Downloads/Agent/Soc/tools/mcp-serial"
14
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "identity": "agent-a",
3
+ "layout": "root",
4
+ "root": "D:/Downloads/Agent/.mailbox",
5
+ "dirs": {},
6
+ "participants": [],
7
+ "intervalSec": 2,
8
+ "timeoutSec": 0,
9
+ "seenFile": "",
10
+ "patchRoot": ""
11
+ }