## 协议
- 新增 Methods.Event = 'event':协议中唯一的**无 id 通知**(JSON-RPC notification),
被控端 → 控制端主动推送,控制端不回复
- 4 项能力:event.watch / event.unwatch / event.list / event.poll
- 能力处理器签名扩展为 (args, ctx?):ctx 携带 owner(连接标识)与 emit(推送出口)
## 被控端(apps/agent/src/events.ts)
三类 watcher:
- file —— fs.watch(支持 recursive + glob 过滤),报 created_or_removed / modified
- process —— 轮询 tasklist(win)/ps(posix) 做差分,报 process_started / process_exited
- net —— 轮询 netstat 提取 LISTEN 端口做差分,报 port_opened / port_closed
两条出口并存:
1) **推送**:通过 event 通知实时发给创建订阅的连接
2) **环形缓冲 + 游标**:500 条上限、seq 游标增量拉取(适配无法收推送的 MCP)
其它:首次采样只建基线(避免开订阅就刷出几百条);连接断开自动清理该连接的订阅(防泄漏)
## 控制端
- NodeAgentClient 新增 onEvent 回调;handleMessage 把无 id 的 event 通知分发过去
- CLI: nodeagent events [--kind file|process|net] [--path/--pattern/--recursive/--seconds]
无 --kind 则列出当前订阅
- MCP: na_event_watch / na_event_poll / na_event_list / na_event_unwatch
## 真机验证(三类全部实测)
- 文件:创建/修改/删除 t1.txt -> 3 个事件实时推送(14:16:33/34/35)
- 进程:启动并关闭 Notepad.exe -> process_started / process_exited
- 端口:开-关 8899 -> port_opened / port_closed(基线 45 个监听端口)
全部**零轮询**到达控制端(由被控端主动推)。
单测 61 -> 63(补 event.watch 枚举/边界与 event.poll 游标校验)、e2e 21/21 全绿
33 lines
1.1 KiB
TypeScript
33 lines
1.1 KiB
TypeScript
/** 协议方法名(控制面)。 */
|
||
export const Methods = {
|
||
/** 控制端 → 被控端:发起握手 */
|
||
Hello: 'hello',
|
||
/** 被控端 → 控制端:返回 nonce 挑战 */
|
||
Challenge: 'challenge',
|
||
/** 控制端 → 被控端:提交 HMAC 完成认证 */
|
||
Auth: 'auth',
|
||
/** 被控端 → 控制端:认证成功,返回能力清单 */
|
||
AuthOk: 'auth_ok',
|
||
/** 控制端 → 被控端:调用某项能力 */
|
||
Invoke: 'invoke',
|
||
/** 控制端 → 被控端:查询能力清单 */
|
||
Capabilities: 'capabilities',
|
||
/** 双向:心跳保活 */
|
||
Ping: 'ping',
|
||
/** 双向:心跳响应 */
|
||
Pong: 'pong',
|
||
/**
|
||
* 被控端 → 控制端:主动推送事件(v12 事件订阅)。
|
||
* 这是协议中唯一的**无 id 通知**(JSON-RPC notification)——控制端不应回复。
|
||
*/
|
||
Event: 'event',
|
||
} as const;
|
||
|
||
export type MethodName = (typeof Methods)[keyof typeof Methods];
|
||
|
||
/** 协议版本(MAJOR.MINOR)。 */
|
||
export const PROTOCOL_VERSION = '1.0';
|
||
|
||
/** 局域网发现的默认 UDP 端口(被控端广播目标 = 控制端监听端口)。 */
|
||
export const DEFAULT_DISCOVERY_PORT = 8766;
|