@aalis/plugin-session-confirm 0.5.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ace Nyan <ace@acenyan.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,11 @@
1
+ import type { Context } from '@aalis/core';
2
+ export declare const name = "@aalis/plugin-session-confirm";
3
+ export declare const displayName = "\u4F1A\u8BDD\u786E\u8BA4";
4
+ export declare const subsystem = "authority";
5
+ export declare const provides: string[];
6
+ export declare const inject: {
7
+ required: string[];
8
+ optional: string[];
9
+ };
10
+ export declare function apply(ctx: Context): Promise<void>;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAW3C,eAAO,MAAM,IAAI,kCAAkC,CAAC;AACpD,eAAO,MAAM,WAAW,6BAAS,CAAC;AAClC,eAAO,MAAM,SAAS,cAAc,CAAC;AACrC,eAAO,MAAM,QAAQ,UAAsB,CAAC;AAC5C,eAAO,MAAM,MAAM;;;CAGlB,CAAC;AAwGF,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BvD"}
package/dist/index.js ADDED
@@ -0,0 +1,143 @@
1
+ // ----- 会话确认:协调器实现 + onebot/cli 等「仅消息总线」平台的确认传输 -----
2
+ //
3
+ // 协调器(待确认登记 / 超时 / 解析 Y-YS / 文案)是平台无关的功能,**实现一份**于此,经
4
+ // `session-confirm` 服务(契约在 plugin-session-confirm-api)暴露 createChannel,供任何平台复用:
5
+ // - 本插件自用:bus 通道(投递走 gateway 总线)+ '*' fallback handler + inbound:confirm 相位拦截,
6
+ // 覆盖 onebot/cli 等仅靠消息总线的会话型平台。
7
+ // - WebUI:注入自己的 WS 投递拿一条通道,保留 WS type:'confirm'(前端「确认模式」信号),在
8
+ // WS-onmessage 调 feed —— 与本插件共用同一协调器实现,零重复。
9
+ //
10
+ // 纯协议(parseConfirmReply / composeConfirmPrompt)是本插件私有的无状态实现,内联于此——
11
+ // 契约包(authority-api)只放类型、不放实现(避免运行时跨包边 + 版本漂移)。
12
+ import { INBOUND_PHASE } from '@aalis/plugin-gateway-api';
13
+ export const name = '@aalis/plugin-session-confirm';
14
+ export const displayName = '会话确认';
15
+ export const subsystem = 'authority';
16
+ export const provides = ['session-confirm'];
17
+ export const inject = {
18
+ required: ['gateway'],
19
+ optional: ['authority'],
20
+ };
21
+ /** 确认等待超时(毫秒);超时默认拒(无人在场即安全失败)。 */
22
+ const CONFIRM_TIMEOUT_MS = 60_000;
23
+ /** YS(本会话放行)授予时长(秒)。 */
24
+ const SESSION_GRANT_SECONDS = 600;
25
+ /** 把一条确认回复文本解析为决策(纯函数):Y=本次、YS=本会话(always 不接受会话记忆)、其余=取消。 */
26
+ function parseConfirmReply(replyText, always, sessionGrantSeconds) {
27
+ const t = replyText.trim().toLowerCase();
28
+ const yes = t === 'y' || t === 'yes';
29
+ if (always)
30
+ return yes || t === 'ys' ? { allowed: true } : false;
31
+ if (t === 'ys')
32
+ return { allowed: true, grant: { scope: 'session', durationSeconds: sessionGrantSeconds } };
33
+ if (yes)
34
+ return { allowed: true, grant: { scope: 'once' } };
35
+ return false;
36
+ }
37
+ /** 组合确认提示文案(纯函数,所有平台一致)。 */
38
+ function composeConfirmPrompt(request, always, sessionGrantSeconds) {
39
+ const label = request.type === 'command' ? '指令' : '工具';
40
+ const nameStr = request.type === 'command' ? `/${request.name}` : request.name;
41
+ return always
42
+ ? `⚠️ ${label} ${nameStr} 是高危操作,每次都需确认。回复 Y 确认执行本次;其他任意输入取消。`
43
+ : `⚠️ ${label} ${nameStr} 是高危操作。回复 Y 仅允许本次;回复 YS 本会话 ${Math.round(sessionGrantSeconds / 60)} 分钟内放行;其他任意输入取消。`;
44
+ }
45
+ /** 协调器工厂(平台无关):注入投递,拿回 { handler, feed }。 */
46
+ function createChannel(deliver) {
47
+ // 每个 session 一条 FIFO 队列:确认是会话内一问一答,但同一回合并行工具可触发多个确认请求,
48
+ // 必须串行排队(队首发提示、应答/超时后出队投递下一个),不能抢占式互相 resolve(false)。
49
+ const queues = new Map();
50
+ /** 给队首发确认提示并启动其超时计时(首次入队 / 上一个结算出队后调用)。 */
51
+ const present = (sessionId) => {
52
+ const head = queues.get(sessionId)?.[0];
53
+ if (!head)
54
+ return;
55
+ head.timer = setTimeout(() => {
56
+ // 超时只结算队首:出队、投递、resolve,再推进下一个。
57
+ const q = queues.get(sessionId);
58
+ if (q?.[0])
59
+ q.shift();
60
+ if (q && q.length === 0)
61
+ queues.delete(sessionId);
62
+ deliver(head.request, '⏰ 操作确认已超时,已自动取消。');
63
+ head.resolve(false);
64
+ present(sessionId);
65
+ }, CONFIRM_TIMEOUT_MS);
66
+ head.timer.unref?.(); // 待确认定时器不阻止进程优雅退出
67
+ deliver(head.request, composeConfirmPrompt(head.request, head.always, SESSION_GRANT_SECONDS));
68
+ };
69
+ const handler = request => new Promise(resolve => {
70
+ const waiter = {
71
+ request,
72
+ resolve,
73
+ timer: undefined,
74
+ always: request.confirm === 'always',
75
+ userId: request.userId,
76
+ };
77
+ const q = queues.get(request.sessionId);
78
+ if (q) {
79
+ q.push(waiter); // 已有未决:排队,等队首结算后再发
80
+ }
81
+ else {
82
+ queues.set(request.sessionId, [waiter]);
83
+ present(request.sessionId); // 队首:立即发提示
84
+ }
85
+ });
86
+ const feed = (sessionId, replyText, replyUserId) => {
87
+ const q = queues.get(sessionId);
88
+ const head = q?.[0];
89
+ if (!q || !head)
90
+ return false;
91
+ // 仅触发者本人能应答:群里 sessionId=群,否则任意成员都能替授权方确认。
92
+ // 私聊/webui 触发者与应答者天然同人;二者皆 undefined 也视为同人(系统注入等无 userId 场景)。
93
+ if (head.userId !== replyUserId)
94
+ return false;
95
+ clearTimeout(head.timer);
96
+ q.shift();
97
+ if (q.length === 0)
98
+ queues.delete(sessionId);
99
+ head.resolve(parseConfirmReply(replyText, head.always, SESSION_GRANT_SECONDS));
100
+ present(sessionId); // 推进下一个未决确认
101
+ return true;
102
+ };
103
+ const dispose = () => {
104
+ // 卸载/热重载:清所有未决确认的超时定时器并安全拒掉(resolve false),避免 Promise 永挂 + 定时器卡退出。
105
+ for (const q of queues.values()) {
106
+ for (const w of q) {
107
+ clearTimeout(w.timer);
108
+ w.resolve(false);
109
+ }
110
+ }
111
+ queues.clear();
112
+ };
113
+ return { handler, feed, dispose };
114
+ }
115
+ export async function apply(ctx) {
116
+ const service = { createChannel };
117
+ ctx.provide('session-confirm', service);
118
+ // 自用 bus 通道:覆盖 onebot/cli 等仅靠消息总线的会话型平台。
119
+ const busChannel = createChannel((request, text) => {
120
+ const gateway = ctx.getService('gateway');
121
+ void gateway?.dispatchOutbound({
122
+ content: text,
123
+ sessionId: request.sessionId,
124
+ platform: request.platform,
125
+ source: 'system',
126
+ });
127
+ });
128
+ // authority 可能晚于本插件上线 → whenService 在其上线/重启时注册 '*' fallback(精确平台 handler 优先)。
129
+ ctx.whenService('authority', authority => {
130
+ if (authority.setConfirmHandler) {
131
+ authority.setConfirmHandler('*', busChannel.handler);
132
+ ctx.logger.debug('会话确认 fallback handler 已注册 (*)');
133
+ }
134
+ });
135
+ // inbound:confirm 相位(最前):命中未决确认即喂入解析并吞掉,避免触达 agent(防 abort 在途生成)。
136
+ ctx.middleware(INBOUND_PHASE.CONFIRM, async (data, next) => {
137
+ if (busChannel.feed(data.message.sessionId, data.message.content ?? '', data.message.userId))
138
+ return; // 吞掉确认回复
139
+ return next();
140
+ });
141
+ ctx.onDispose(() => busChannel.dispose());
142
+ }
143
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@aalis/plugin-session-confirm",
3
+ "version": "0.5.0",
4
+ "license": "MIT",
5
+ "description": "会话确认协调器:提供 session-confirm 服务(createChannel)供各平台复用,并经 gateway 总线覆盖 onebot/cli 等会话型平台",
6
+ "type": "module",
7
+ "keywords": [
8
+ "aalis",
9
+ "aalis-plugin"
10
+ ],
11
+ "main": "dist/index.js",
12
+ "types": "dist/index.d.ts",
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "dependencies": {
17
+ "@aalis/plugin-authority-api": "^0.5.0",
18
+ "@aalis/plugin-gateway-api": "^0.5.0"
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "^22.0.0",
22
+ "typescript": "^5.7.0",
23
+ "@aalis/core": "0.5.0",
24
+ "@aalis/plugin-session-confirm-api": "0.5.0"
25
+ },
26
+ "peerDependencies": {
27
+ "@aalis/core": ">=0.2.0 <1.0.0"
28
+ },
29
+ "aalis": {
30
+ "service": {
31
+ "required": [
32
+ "gateway"
33
+ ],
34
+ "optional": [
35
+ "authority"
36
+ ],
37
+ "provides": [
38
+ "session-confirm"
39
+ ]
40
+ }
41
+ },
42
+ "scripts": {
43
+ "build": "tsc",
44
+ "dev": "tsc --watch"
45
+ }
46
+ }