@shgroup/dsh-serenity-hooks 1.30.17 → 1.31.1
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 +20 -10
- package/dsh.plugin.json +4 -3
- package/lib/ccc.d.ts +14 -5
- package/lib/im-bridge.d.ts +127 -0
- package/lib/im-weixin.d.ts +19 -0
- package/lib/index.js +776 -107
- package/lib/invariant.d.ts +8 -2
- package/lib/invariant.js +9 -2
- package/lib/msm-ops.d.ts +1 -1
- package/lib/seams/guards.d.ts +20 -0
- package/lib/seams/keeper.d.ts +52 -0
- package/lib/tools/im-bridge.d.ts +18 -0
- package/lib/trajectory-assistant.d.ts +13 -0
- package/lib/{weixin-api-BMpljodH.js → weixin-api-PjEhmjlZ.js} +98 -2
- package/lib/weixin-api.d.ts +21 -0
- package/lib/weixin-bridge.d.ts +20 -2
- package/lib/weixin-hook.d.ts +12 -0
- package/lib/weixin-output-guard.d.ts +12 -6
- package/lib/{weixin-route-DIaUYipW.js → weixin-route-wWk4AIwV.js} +1 -1
- package/lib/weixin-send-api.d.ts +3 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -65,7 +65,7 @@ dsh plugin --profile web add link:$(pwd)/hooks/dsh-serenity-hooks
|
|
|
65
65
|
|
|
66
66
|
## 3. 装完之后你多了什么
|
|
67
67
|
|
|
68
|
-
### 3.1
|
|
68
|
+
### 3.1 十一个工具
|
|
69
69
|
|
|
70
70
|
| 工具 | 干什么 | 什么时候用 |
|
|
71
71
|
|---|---|---|
|
|
@@ -79,6 +79,7 @@ dsh plugin --profile web add link:$(pwd)/hooks/dsh-serenity-hooks
|
|
|
79
79
|
| `localstore` | 存密钥和配置(凭据、偏好两个命名空间) | API key、密码集中放一处,不进 git |
|
|
80
80
|
| `container_admin` | 机务舱:管理子角色、管理小工具注册表、查看全部配置 | 定义"子角色"、注册新小工具时 |
|
|
81
81
|
| `autopilot-trajectory` | 自动巡航:定时唤醒工作区、注入当前焦点,支持多个工作区各自独立 | 想让 AI 定时自己干活(见 §6.5) |
|
|
82
|
+
| `im-bridge` | 给 IM 联系人发消息(目前是微信):发文本、发文件、查已配置联系人、查通道状态。每次成功发送自动进工作区的消息记录 | 想让 AI 主动给家人/同事发消息(见 §6.6)。**只在工作区配了微信桥时才出现**,且只能发本工作区的消息 |
|
|
82
83
|
|
|
83
84
|
> **改过名**(旧名已彻底停用,没有兼容别名):`cc_fs` → `container_fs` · `cc_git` → `container_git` · `session`+`session_rebuild` → `logbook` · `acc_kit` → `dashboard` · `acc_msm` → `msm`(执行)+ `container_admin`(管理)· `eap`/`neat`/`cce` → `praxis` · `skiff_admin` → `container_admin role`。老会话里看到旧名,照这张表对照即可。
|
|
84
85
|
|
|
@@ -94,6 +95,8 @@ dsh plugin --profile web add link:$(pwd)/hooks/dsh-serenity-hooks
|
|
|
94
95
|
| **密钥文件守卫** | `localstore.json` 对**所有**工具拒绝(包括 read/grep/glob) | 密钥值在结构上就出不来 |
|
|
95
96
|
| **对外输出守卫** | 对外面的会话(子角色 / ACP / 重建会话)如果答出敏感词,会被打回重答,并告诉它命中了哪个词、该怎么改 | 外面的人不该看到内部机制 |
|
|
96
97
|
| **轨迹提醒** | 做久了会提醒 AI"把进度写回工作日志",并要求它回一个确认码 | 提醒是机制,不是靠自觉 |
|
|
98
|
+
| **工作日志体积提醒** | 工作日志(SESSION.md)超过 100KB 时提醒 AI"停下来重写一遍",并附四条重写原则(保留骨架 / 细节挪到附件文件 / 该合并的合并 / 其余你自己判断) | 日志越写越厚就没人读得完;重写比堆积便宜。阈值按工作区可调(`sessionKeeper.sessionMdMaxKB`,0 = 关) |
|
|
99
|
+
| **重建前交接** | 要重建上下文时,会要求 AI 先把"手头做到哪了 / 还差什么 / 下一步做什么"写进工作日志**末尾**的固定小标题下;重建后的它第一件事就是去读那一段接着干 | 上下文被清空,但手头的事不能丢——写侧与读侧用同一个标题,读的时候才找得到 |
|
|
97
100
|
|
|
98
101
|
### 3.3 对外的入口
|
|
99
102
|
|
|
@@ -101,7 +104,7 @@ dsh plugin --profile web add link:$(pwd)/hooks/dsh-serenity-hooks
|
|
|
101
104
|
|---|---|---|
|
|
102
105
|
| DSH 主界面 | 3080 | 你自己在本机用(插件不碰这个端口) |
|
|
103
106
|
| **网页登录入口** | 3081 | 外部/手机访问完整界面:登录后反向代理到 3080,可配工作区白名单 |
|
|
104
|
-
| **微信主动发送入口** | 3082(只绑 127.0.0.1) |
|
|
107
|
+
| **微信主动发送入口** | 3082(只绑 127.0.0.1) | 工作区外的脚本/集成用它给微信发消息(公网到不了,所以不需要密钥)。工作区里的 AI 不走这个端口,直接用 `im-bridge` 工具 |
|
|
105
108
|
| **子角色调试页** | 3099(只绑 127.0.0.1) | 你调试"子角色"时用,能切换工作区、看对话轨迹 |
|
|
106
109
|
| **ACP + 对外问答页** | 3100(只绑 127.0.0.1) | 程序化接入(JSON-RPC)+ 给别人用的问答页(key 认证,只返回答案,不返回内部轨迹) |
|
|
107
110
|
| **微信桥** | 无需端口(出站长轮询) | 家人在微信里直接和 AI 说话 |
|
|
@@ -194,14 +197,21 @@ DSH 一个进程可以同时带多个工作区,每个工作区各自对接自
|
|
|
194
197
|
- **回复干净**:自动剥掉思考过程,微信只看到正文
|
|
195
198
|
- **记得住**:同一个微信号对应固定会话,重启后恢复历史,不会"失忆"
|
|
196
199
|
- **路由**:微信号 → 子角色(精确匹配优先,`*` 兜底)
|
|
197
|
-
-
|
|
198
|
-
`
|
|
199
|
-
|
|
200
|
+
- **主动发消息**(v1.31.0):用 `im-bridge` 工具,AI 自己就能发——
|
|
201
|
+
`im-bridge({channel:"weixin", action:"send", user:"yh", text:"内容"})`
|
|
202
|
+
(发文件:`action:"send-file"` + `file:"<工作区内的路径>"`,可加 `caption`)。
|
|
203
|
+
这个工具**只能发本工作区的消息**(没有"目标工作区"参数,不会发错容器),发出的消息会自动被记录。
|
|
204
|
+
它**只在工作区配了微信桥时才出现在工具列表里**——没配就看不到,而不是"看得到但一调就报错"。
|
|
205
|
+
(旧办法是工作区里自己写个小工具走 3082 端口,v1.31.0 起已退役;3082 保留给工作区外的脚本。)
|
|
200
206
|
- **让 AI 自己决定怎么回**(v1.30.10):配置 `"weixin": { "autoReplyWithLastMessage": false }`
|
|
201
|
-
后,插件不再自动把 AI 最后那段话转给用户,而是每轮告诉它"你必须自己发"
|
|
207
|
+
后,插件不再自动把 AI 最后那段话转给用户,而是每轮告诉它"你必须自己发",并附上一条可直接照抄的 `im-bridge` 调用。
|
|
202
208
|
适合需要过程汇报、想分多条发、或者该安静就安静的角色。默认 `true`(保持原行为)。
|
|
209
|
+
该发却没发时,插件会**打回提醒**(最多 2 次);还是不发送,可以再开
|
|
210
|
+
`"fallbackOnNoSend": true` 让插件兜底把那轮的话转给用户(记录为 `source: "reply-fallback"`),
|
|
211
|
+
保证"消息不丢"。
|
|
203
212
|
- **消息记录**:配一个 `weixin.hook` 脚本,每收/发一条消息就把事件(JSON)喂给它,存哪里由你决定。
|
|
204
|
-
记录里 `source: "reply"` 表示"回复用户",`source: "proactive"` 表示"AI 主动发起"
|
|
213
|
+
记录里 `source: "reply"` 表示"回复用户",`source: "proactive"` 表示"AI 主动发起",
|
|
214
|
+
`source: "reply-fallback"` 表示"AI 没发、插件兜底发的"。
|
|
205
215
|
- **排障**:`msm("weixin-doctor", ["status"|"diag"|"verify"|"guide"])`
|
|
206
216
|
|
|
207
217
|
### 6.3 子角色(Skiff)
|
|
@@ -286,7 +296,7 @@ AI 一次能"记住"的内容有上限。满了不用你手动开新会话:
|
|
|
286
296
|
|
|
287
297
|
```bash
|
|
288
298
|
pnpm typecheck # 类型检查(node + 浏览器端两套)
|
|
289
|
-
pnpm test # 全量测试(当前
|
|
299
|
+
pnpm test # 全量测试(当前 75 个文件 / 1110 个用例)
|
|
290
300
|
pnpm build # 打包(lib/index.js + client.js)
|
|
291
301
|
```
|
|
292
302
|
|
|
@@ -306,7 +316,7 @@ pnpm build # 打包(lib/index.js + client.js)
|
|
|
306
316
|
| 跑在 | OpenCode | DeepSeek Harness |
|
|
307
317
|
| 实现 | 独立 | **独立**(不复用源码,但遵循同一套标准) |
|
|
308
318
|
| 系统提示词 | `system.transform` | `systemPrompt.section`,平台无关的部分逐字对齐 |
|
|
309
|
-
| 工具 | msm / container_fs / logbook 等 | container_fs / logbook / dashboard / container_git / msm / praxis / handyman / localstore / container_admin / autopilot-trajectory |
|
|
319
|
+
| 工具 | msm / container_fs / logbook 等 | container_fs / logbook / dashboard / container_git / msm / praxis / handyman / localstore / container_admin / autopilot-trajectory / im-bridge |
|
|
310
320
|
|
|
311
321
|
**同一个工作区可以随时换运行时**:`.serenity` 标记、`.opencode/skills/`、配置、`AGENT_SESSIONS/` 的文件格式都一致;
|
|
312
322
|
差别只在平台层(工具名、注入方式),换过去以后 AI 收到的约束是一样的。
|
|
@@ -350,4 +360,4 @@ pnpm build # 打包(lib/index.js + client.js)
|
|
|
350
360
|
|
|
351
361
|
MIT(见 [LICENSE](https://github.com/tellmewhattodo/dsh-serenity-plugin/blob/master/LICENSE))
|
|
352
362
|
|
|
353
|
-
> **版本**:v1.
|
|
363
|
+
> **版本**:v1.31.1 | **前置**:DSH 0.1.2-rc.1+ / Node ≥ 20 或 bun | **测试**:75 个文件 / 1110 个用例
|
package/dsh.plugin.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-serenity-hooks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.31.1",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
|
-
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——
|
|
5
|
+
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——11 个工具(container_fs/logbook/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/autopilot-trajectory/im-bridge)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 工作日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/自主巡航。适配 DSH 0.1.2-rc.1(deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
|
7
7
|
"dsh": ">=0.1.2-rc.1"
|
|
8
8
|
},
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"handyman",
|
|
18
18
|
"localstore",
|
|
19
19
|
"container_admin",
|
|
20
|
-
"autopilot-trajectory"
|
|
20
|
+
"autopilot-trajectory",
|
|
21
|
+
"im-bridge"
|
|
21
22
|
],
|
|
22
23
|
"skills": []
|
|
23
24
|
}
|
package/lib/ccc.d.ts
CHANGED
|
@@ -44,7 +44,16 @@ export interface SerenityConfig {
|
|
|
44
44
|
maxParallel?: number;
|
|
45
45
|
};
|
|
46
46
|
sessionKeeper?: {
|
|
47
|
+
/** 计分提醒阈值(缺省 150) */
|
|
47
48
|
threshold?: number;
|
|
49
|
+
/**
|
|
50
|
+
* 活跃 SESSION.md 体积上限(KB,缺省 100——v1.31.1,S142 用户需求)。
|
|
51
|
+
*
|
|
52
|
+
* 超过 → trajectory-assistant 注入 LOGBOOK COMPACTION 提醒(暂停工作 → 加载 eap →
|
|
53
|
+
* 按 EAP 分层骨架重写 SESSION.md;内容可外移到 references 文件、可整合不重要事项、
|
|
54
|
+
* 自主裁量权充分允许)。设 0 = 关闭该提醒。
|
|
55
|
+
*/
|
|
56
|
+
sessionMdMaxKB?: number;
|
|
48
57
|
};
|
|
49
58
|
safeMode?: {
|
|
50
59
|
blacklist?: string[];
|
|
@@ -143,10 +152,10 @@ export interface WeixinSettings {
|
|
|
143
152
|
* 桥是否**自动回发 agent 的最终文本**(v1.30.10,用户拍板命名;缺省 true = 现状)。
|
|
144
153
|
*
|
|
145
154
|
* 关闭(false)→ 桥不再把一轮结束时 agent 的最终 assistant 文本转发给用户;
|
|
146
|
-
* 输出权完全交给 agent:每轮 question
|
|
147
|
-
*
|
|
155
|
+
* 输出权完全交给 agent:每轮 question 末尾注入**机制标记 + 已填参数的命令**
|
|
156
|
+
* (v1.31.0 起为 `im-bridge` 工具形态),由 agent 自己决定发什么/发几条(全部记 `source=proactive`)。
|
|
148
157
|
*
|
|
149
|
-
* 为什么需要(R↓):v1.30.9 起 agent
|
|
158
|
+
* 为什么需要(R↓):v1.30.9 起 agent 已能主动输出(工具/桥 → iLink),
|
|
150
159
|
* 「桥替 agent 说最后一句」从机制上变成可选项——进程式汇报、多段输出、静默处理都需要它。
|
|
151
160
|
* 语义边界(用户拍板):只关**最终文本**;系统类消息(新对话通知 / 语音无法解析提示)保留;
|
|
152
161
|
* agent 一轮未输出 → 静默不兜底(否则开关语义被破坏)。
|
|
@@ -156,8 +165,8 @@ export interface WeixinSettings {
|
|
|
156
165
|
* 手动输出模式下的**兜底**(v1.30.17,S142 用户拍板"鲁棒修法";**缺省 false = 严格静默**)。
|
|
157
166
|
*
|
|
158
167
|
* 仅在 `autoReplyWithLastMessage: false` 时生效:
|
|
159
|
-
* - `true` → 一轮结束时若 agent
|
|
160
|
-
*
|
|
168
|
+
* - `true` → 一轮结束时若 agent **一次都没成功调用输出工具**(im-bridge / 旧 weixin-send),
|
|
169
|
+
* 桥把该轮最终文本转发给用户(记录 `source: "reply-fallback"`,并在日志留响亮告警)。
|
|
161
170
|
* - `false`(缺省)→ 保持 v1.30.10 的"静默不兜底"语义。
|
|
162
171
|
*
|
|
163
172
|
* 为什么需要(实证 R↓):v1.30.16 的机械闸门会打回 ≤2 次;但用户实测某模型在**寒暄类消息**上
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* im-bridge.ts — IM 发送能力层(v1.31.0,S142 用户洞察)
|
|
3
|
+
*
|
|
4
|
+
* 用户原话:「既然微信桥是我们 ACC 提供的,那么 weixin-send 应该是我们 ACC 提供的能力,
|
|
5
|
+
* 当用户配置了微信桥则可用,不配置则不可见」+「设定一个复杂的多层工具,叫 im-bridge,
|
|
6
|
+
* 里面有微信,然后保留后续可能兼容别的 im 的空间」。
|
|
7
|
+
*
|
|
8
|
+
* 分层(E↑):
|
|
9
|
+
* `tools/im-bridge.ts`(工具面:参数 → 结果渲染)
|
|
10
|
+
* → **本模块**(通道注册表 + 可见性判据 + 动作分发 + 错误码翻译)
|
|
11
|
+
* → 通道实现(`im-weixin.ts`:协议/凭据/账号/记录)
|
|
12
|
+
*
|
|
13
|
+
* 边界(R↓):
|
|
14
|
+
* - **本模块零宿主依赖**(不 import cordis/agent)——可见性判定与分发都是纯逻辑,可独立单测。
|
|
15
|
+
* - **通道只提供机制**:本模块不认识"微信";新增 IM 只需注册一个通道实现(R3 家族式扩展)。
|
|
16
|
+
* - **只能操作本会话 CCC**(R4):`root` 由调用方(工具面)从 agent cwd 解析后传入,
|
|
17
|
+
* 本模块不接受"目标 CCC"参数——跨 CCC 发送不在能力面。
|
|
18
|
+
* - **记录归通道**(R5):通道实现负责让每次发送都落既有 hook。
|
|
19
|
+
*/
|
|
20
|
+
/** 文本长度上限(微信侧单条实践上限;超限拒绝而非静默截断——与 HTTP 入口同值) */
|
|
21
|
+
export declare const IM_SEND_MAX_TEXT = 4000;
|
|
22
|
+
/** 文件大小上限(20MB,与媒体接收上限一致) */
|
|
23
|
+
export declare const IM_FILE_MAX_BYTES: number;
|
|
24
|
+
/**
|
|
25
|
+
* 通道内用户(别名 → 通道用户 id)。
|
|
26
|
+
*
|
|
27
|
+
* 用 **type 别名而非 interface**:interface 不获得隐式索引签名,无法赋给 `ImJson`
|
|
28
|
+
* (工具返回值必须可 JSON 化 → 类型层就要挡住"不可序列化"的形状,而不是靠断言绕过)。
|
|
29
|
+
*/
|
|
30
|
+
export type ImUserEntry = {
|
|
31
|
+
alias: string;
|
|
32
|
+
id: string;
|
|
33
|
+
};
|
|
34
|
+
/** 文本发送输入(通道实现负责凭据解析与记录) */
|
|
35
|
+
export interface ImSendInput {
|
|
36
|
+
root: string;
|
|
37
|
+
/** 通道内用户 id(别名已由本模块解析) */
|
|
38
|
+
userId: string;
|
|
39
|
+
text: string;
|
|
40
|
+
accountId?: string;
|
|
41
|
+
}
|
|
42
|
+
/** 文本发送结果(与既有主动发送返回一致,便于记录/诊断) */
|
|
43
|
+
export interface ImSendResult {
|
|
44
|
+
accountId: string;
|
|
45
|
+
userId: string;
|
|
46
|
+
sessionId: string;
|
|
47
|
+
role: string;
|
|
48
|
+
}
|
|
49
|
+
/** 文件发送输入(`data` 由本模块读盘并校验后传入——通道不碰 CCC 路径) */
|
|
50
|
+
export interface ImSendFileInput {
|
|
51
|
+
root: string;
|
|
52
|
+
userId: string;
|
|
53
|
+
data: Buffer;
|
|
54
|
+
fileName: string;
|
|
55
|
+
caption?: string;
|
|
56
|
+
accountId?: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* 一个 IM 通道(机制插槽)。
|
|
60
|
+
* `isEnabled` 是**可见性判据**:该 CCC 是否配置了这个通道。
|
|
61
|
+
*/
|
|
62
|
+
export interface ImChannel {
|
|
63
|
+
/** 通道 id(工具 `channel` 参数的取值,如 `weixin`) */
|
|
64
|
+
id: string;
|
|
65
|
+
/** 该 CCC 是否启用了本通道(缺省实现:读该通道的 CCC 配置) */
|
|
66
|
+
isEnabled(root: string): boolean;
|
|
67
|
+
/** 别名/裸 id → 通道用户;无法解析返回 null */
|
|
68
|
+
resolveUser(root: string, input: string): ImUserEntry | null;
|
|
69
|
+
/** 已配置别名列表(`users` 动作) */
|
|
70
|
+
listUsers(root: string): ImUserEntry[];
|
|
71
|
+
/** 发文本 */
|
|
72
|
+
send(input: ImSendInput): Promise<ImSendResult>;
|
|
73
|
+
/** 发文件(可选——未实现则工具返回 `ACTION_UNSUPPORTED`) */
|
|
74
|
+
sendFile?(input: ImSendFileInput): Promise<{
|
|
75
|
+
fileName: string;
|
|
76
|
+
size: number;
|
|
77
|
+
}>;
|
|
78
|
+
/** 通道健康快照(`status` 动作)——必须可 JSON 化(工具返回值契约) */
|
|
79
|
+
status(root: string): ImJson;
|
|
80
|
+
}
|
|
81
|
+
/** 注册通道(index.ts apply 调用;重复 id 覆盖——测试与热重载友好) */
|
|
82
|
+
export declare function registerImChannel(channel: ImChannel): void;
|
|
83
|
+
/** 测试辅助:清空通道注册表 */
|
|
84
|
+
export declare function __resetImChannelsForTest(): void;
|
|
85
|
+
/** 已注册通道 id(工具 `channel` 参数枚举) */
|
|
86
|
+
export declare function imChannelIds(): string[];
|
|
87
|
+
/**
|
|
88
|
+
* 可见性判据:本 CCC 是否启用了**任一** IM 通道。
|
|
89
|
+
* 未启用 → 工具面对该 agent **不可见**(`tools.restrict` 移除,而非调用时报错)。
|
|
90
|
+
* @param root 本会话 CCC 根(由调用方解析)
|
|
91
|
+
*/
|
|
92
|
+
export declare function hasEnabledImChannel(root: string): boolean;
|
|
93
|
+
/** 结果载荷(lossless JSON——工具返回值必须可 JSON 化) */
|
|
94
|
+
export type ImJson = null | boolean | number | string | ImJson[] | {
|
|
95
|
+
[key: string]: ImJson;
|
|
96
|
+
};
|
|
97
|
+
/** 分发结果(工具面直接渲染;错误码稳定,便于模型与日志消费) */
|
|
98
|
+
export type ImToolResult = {
|
|
99
|
+
ok: true;
|
|
100
|
+
channel: string;
|
|
101
|
+
action: string;
|
|
102
|
+
detail: ImJson;
|
|
103
|
+
} | {
|
|
104
|
+
ok: false;
|
|
105
|
+
code: string;
|
|
106
|
+
error: string;
|
|
107
|
+
remediation?: string;
|
|
108
|
+
};
|
|
109
|
+
export interface ImToolRequest {
|
|
110
|
+
channel?: string;
|
|
111
|
+
action?: string;
|
|
112
|
+
user?: string;
|
|
113
|
+
text?: string;
|
|
114
|
+
file?: string;
|
|
115
|
+
caption?: string;
|
|
116
|
+
account?: string;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* 执行一次 IM 动作(工具面唯一入口)。
|
|
120
|
+
*
|
|
121
|
+
* 顺序:通道解析 → 动作校验 → 用户解析(别名 → id)→ 输入校验 → 调用通道实现。
|
|
122
|
+
* 任何一步失败都返回**稳定错误码 + 可行动提示**(不抛错——工具面统一渲染)。
|
|
123
|
+
*
|
|
124
|
+
* @param root 本会话 CCC 根(调用方从 agent cwd 解析;本函数不接受目标 CCC)
|
|
125
|
+
* @param req 工具参数
|
|
126
|
+
*/
|
|
127
|
+
export declare function runImBridge(root: string, req: ImToolRequest): Promise<ImToolResult>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* im-weixin.ts — 微信通道实现(`im-bridge` 的通道之一,v1.31.0)
|
|
3
|
+
*
|
|
4
|
+
* 能力归 ACC(S142 用户洞察):本文件吸收原 CCC MSM `.opencode/skills/home-serenity/scripts/
|
|
5
|
+
* weixin-send.ts` 的 `send` / `send-file` / `users` 语义——协议、凭据、账号选择、别名解析、
|
|
6
|
+
* 记录全部落在 ACC 侧;CCC 只保留「何时发 / 发什么 / 怎么写」。
|
|
7
|
+
*
|
|
8
|
+
* 通道内部契约:
|
|
9
|
+
* - `isEnabled(root)` = 该 CCC 的 `weixin.enabled`(可见性判据,im-bridge 用它决定工具是否可见)
|
|
10
|
+
* - `send` 复用 `sendProactiveText`(唯一文本发送实现 + 唯一记录点)
|
|
11
|
+
* - `sendFile` 走 iLink 上传(`weixin-api.sendFileMessage`)+ 同一 outgoing hook(带 `file` 元数据)
|
|
12
|
+
*/
|
|
13
|
+
import type { ImChannel } from './im-bridge.js';
|
|
14
|
+
/**
|
|
15
|
+
* 别名 → CCC localstore 凭据键(与 v1.30.9 CCC MSM 逐字一致,迁移零认知成本)。
|
|
16
|
+
* 别名解析属"数据填值",归 ACC(D23)。
|
|
17
|
+
*/
|
|
18
|
+
export declare const WEIXIN_ALIAS_MAP: Record<string, string>;
|
|
19
|
+
export declare const weixinChannel: ImChannel;
|