@a1hvdy/cc-openclaw 0.25.3 → 0.25.5
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.
|
@@ -40,13 +40,6 @@ export interface HandlerState {
|
|
|
40
40
|
composeBuffer: ComposeBuffer;
|
|
41
41
|
}
|
|
42
42
|
export declare function createHandlerState(): HandlerState;
|
|
43
|
-
/**
|
|
44
|
-
|
|
45
|
-
*
|
|
46
|
-
* Hooked to `before_dispatch` — OpenClaw's name for the inbound-message
|
|
47
|
-
* event surface. We return `{ handled: true }` to claim the message when
|
|
48
|
-
* it's a known mirror slash command; `undefined` lets the event proceed
|
|
49
|
-
* to OpenClaw's default routing (which is what we want for non-slash
|
|
50
|
-
* user text destined for the model).
|
|
51
|
-
*/
|
|
43
|
+
/** Test-only — reset module-level subscription state. */
|
|
44
|
+
export declare function _resetSubscriptionForTests(): void;
|
|
52
45
|
export declare function registerInboundHandler(api: InboundHandlerApi, state?: HandlerState): HandlerState;
|
|
@@ -27,6 +27,34 @@ import { sendTg, editTg } from '../../lib/telegram-bot-api.js';
|
|
|
27
27
|
import { CallbackMap } from './callback-mapping.js';
|
|
28
28
|
import { ComposeBuffer } from './compose-buffer.js';
|
|
29
29
|
const PLUGIN_TAG = '[cc-openclaw/telegram-mirror/inbound]';
|
|
30
|
+
/**
|
|
31
|
+
* Parse Telegram chat id out of a session key. Session keys look like
|
|
32
|
+
* "agent:main:telegram:direct:442300061" or
|
|
33
|
+
* "agent:main:telegram:group:-1001234567:topic:42". The tail segment(s)
|
|
34
|
+
* carry chatId (+ thread). DMs only have chatId.
|
|
35
|
+
*/
|
|
36
|
+
function chatIdFromSessionKey(sessionKey) {
|
|
37
|
+
if (!sessionKey)
|
|
38
|
+
return { chatId: '' };
|
|
39
|
+
const parts = sessionKey.split(':');
|
|
40
|
+
// Format: agent:main:telegram:direct:<chatId> OR
|
|
41
|
+
// agent:main:telegram:group:<chatId>:topic:<threadId>
|
|
42
|
+
if (parts.length < 5)
|
|
43
|
+
return { chatId: '' };
|
|
44
|
+
if (parts[3] === 'direct')
|
|
45
|
+
return { chatId: parts[4] };
|
|
46
|
+
if (parts[3] === 'group') {
|
|
47
|
+
const out = { chatId: parts[4] };
|
|
48
|
+
const topicIdx = parts.indexOf('topic');
|
|
49
|
+
if (topicIdx > 0 && parts[topicIdx + 1]) {
|
|
50
|
+
const t = Number(parts[topicIdx + 1]);
|
|
51
|
+
if (Number.isFinite(t))
|
|
52
|
+
out.threadId = t;
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
return { chatId: '' };
|
|
57
|
+
}
|
|
30
58
|
export function createHandlerState() {
|
|
31
59
|
return {
|
|
32
60
|
callbackMap: new CallbackMap(),
|
|
@@ -72,50 +100,77 @@ async function forwardAction(action, threadId, logger) {
|
|
|
72
100
|
* to OpenClaw's default routing (which is what we want for non-slash
|
|
73
101
|
* user text destined for the model).
|
|
74
102
|
*/
|
|
103
|
+
/**
|
|
104
|
+
* Module-scoped subscription state. OpenClaw 2026.5.x calls register(api)
|
|
105
|
+
* multiple times per process with DIFFERENT api objects (gateway-bindable
|
|
106
|
+
* runtime mode + boot/dispatch registry split). The per-api register-guard
|
|
107
|
+
* correctly re-fires the body for each new api so cross-registry hook
|
|
108
|
+
* delivery still works. But `api.on('before_dispatch', ...)` then stacks
|
|
109
|
+
* an extra listener per call → duplicate sends. We track "have I ever
|
|
110
|
+
* subscribed?" at module scope to claim the event exactly once, while
|
|
111
|
+
* still keeping the state object fresh per-api so callback/compose state
|
|
112
|
+
* doesn't get retroactively shared with already-detached api objects.
|
|
113
|
+
*
|
|
114
|
+
* Production scenario where stacking was observed (gateway 2026.5.12,
|
|
115
|
+
* 2026-05-19): `dispatched /new` logged TWICE per single inbound /new
|
|
116
|
+
* because two listeners both fired. v0.25.5 dedupes.
|
|
117
|
+
*/
|
|
118
|
+
let _subscribed = false;
|
|
119
|
+
const _states = new Set();
|
|
120
|
+
/** Test-only — reset module-level subscription state. */
|
|
121
|
+
export function _resetSubscriptionForTests() {
|
|
122
|
+
_subscribed = false;
|
|
123
|
+
_states.clear();
|
|
124
|
+
}
|
|
75
125
|
export function registerInboundHandler(api, state = createHandlerState()) {
|
|
76
126
|
const logger = (api.logger ?? console);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
127
|
+
_states.add(state);
|
|
128
|
+
if (_subscribed) {
|
|
129
|
+
// Already subscribed once at module scope on a prior register() call —
|
|
130
|
+
// skip the api.on to prevent duplicate dispatch.
|
|
131
|
+
process.stderr.write(`${PLUGIN_TAG} skip-resubscribe (already armed at module scope; new api binding shares state).\n`);
|
|
132
|
+
return state;
|
|
133
|
+
}
|
|
134
|
+
_subscribed = true;
|
|
80
135
|
api.on('before_dispatch', async (...args) => {
|
|
81
136
|
const event = args[0];
|
|
82
|
-
if (!shapeDumped && event?.channel === 'telegram') {
|
|
83
|
-
shapeDumped = true;
|
|
84
|
-
try {
|
|
85
|
-
// Top-level shape (without recursing too deep — 2 KB cap)
|
|
86
|
-
const dump = JSON.stringify(event, (_k, v) => (typeof v === 'function' ? '[Function]' : v));
|
|
87
|
-
process.stderr.write(`[cc-openclaw/telegram-mirror/inbound] FULL EVENT SHAPE (v0.25.3, once): ${dump.slice(0, 2000)}\n`);
|
|
88
|
-
}
|
|
89
|
-
catch (err) {
|
|
90
|
-
process.stderr.write(`[cc-openclaw/telegram-mirror/inbound] shape-dump failed: ${err.message}\n`);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// Multi-path text extraction: try every shape we've seen in OpenClaw's history.
|
|
94
|
-
const candidateText = event?.content ??
|
|
95
|
-
event?.raw?.message?.text ??
|
|
96
|
-
event?.raw?.message?.content ??
|
|
97
|
-
event?.text ??
|
|
98
|
-
(event?.message?.text);
|
|
99
|
-
process.stderr.write(`[cc-openclaw/telegram-mirror/inbound] before_dispatch seen: channel=${event?.channel ?? '?'} text=${typeof candidateText === 'string' ? JSON.stringify(candidateText.slice(0, 60)) : 'n/a'} cb=${event?.raw?.callback_query ? 'yes' : 'no'}\n`);
|
|
100
137
|
if (!event)
|
|
101
138
|
return undefined;
|
|
102
139
|
if (event.channel !== 'telegram')
|
|
103
140
|
return undefined;
|
|
104
141
|
if (event.raw?.callback_query)
|
|
105
142
|
return undefined;
|
|
106
|
-
|
|
107
|
-
if
|
|
143
|
+
// Extract text from the canonical (2026.5.x) `event.content` field;
|
|
144
|
+
// fall back to legacy nested paths if a future gateway version reverts.
|
|
145
|
+
const text = (typeof event.content === 'string' ? event.content : undefined) ??
|
|
146
|
+
event.raw?.message?.text;
|
|
147
|
+
if (typeof text !== 'string') {
|
|
148
|
+
process.stderr.write(`[cc-openclaw/telegram-mirror/inbound] no text in event (skipped)\n`);
|
|
108
149
|
return undefined;
|
|
150
|
+
}
|
|
151
|
+
// Diagnostic trace stays — useful for soak observation. Kept short.
|
|
152
|
+
process.stderr.write(`[cc-openclaw/telegram-mirror/inbound] before_dispatch seen: text=${JSON.stringify(text.slice(0, 60))}\n`);
|
|
109
153
|
const parsed = parseSlash(text);
|
|
110
154
|
if (!parsed)
|
|
111
155
|
return undefined;
|
|
112
|
-
if (!MIRROR_COMMANDS.has(parsed.cmd))
|
|
156
|
+
if (!MIRROR_COMMANDS.has(parsed.cmd)) {
|
|
157
|
+
process.stderr.write(`[cc-openclaw/telegram-mirror/inbound] unknown command /${parsed.cmd} (not claimed)\n`);
|
|
113
158
|
return undefined;
|
|
114
|
-
|
|
115
|
-
|
|
159
|
+
}
|
|
160
|
+
// chatId / threadId from sessionKey OR senderId (DM fallback).
|
|
161
|
+
const fromKey = chatIdFromSessionKey(event.sessionKey);
|
|
162
|
+
let chatId = fromKey.chatId;
|
|
163
|
+
let threadId = fromKey.threadId;
|
|
164
|
+
if (!chatId && event.senderId !== undefined)
|
|
165
|
+
chatId = String(event.senderId);
|
|
116
166
|
if (!chatId)
|
|
167
|
+
chatId = event.raw?.message?.chat?.id !== undefined ? String(event.raw.message.chat.id) : '';
|
|
168
|
+
if (!chatId) {
|
|
169
|
+
process.stderr.write(`[cc-openclaw/telegram-mirror/inbound] could not extract chatId (sessionKey=${event.sessionKey ?? '?'}, senderId=${event.senderId ?? '?'})\n`);
|
|
117
170
|
return undefined;
|
|
118
|
-
|
|
171
|
+
}
|
|
172
|
+
if (threadId === undefined)
|
|
173
|
+
threadId = event.raw?.message?.message_thread_id;
|
|
119
174
|
const result = dispatchCommand(parsed, {
|
|
120
175
|
chatId,
|
|
121
176
|
callbackMap: state.callbackMap,
|
|
@@ -126,7 +181,9 @@ export function registerInboundHandler(api, state = createHandlerState()) {
|
|
|
126
181
|
for (const action of result.actions) {
|
|
127
182
|
await forwardAction(action, threadId, logger);
|
|
128
183
|
}
|
|
129
|
-
|
|
184
|
+
const dispatchLog = `${PLUGIN_TAG} dispatched /${parsed.cmd}${parsed.args.length ? ' ' + parsed.args.join(' ') : ''} (chat=${chatId}, actions=${result.actions.length})`;
|
|
185
|
+
logger.info(dispatchLog);
|
|
186
|
+
process.stderr.write(`${dispatchLog}\n`);
|
|
130
187
|
return { handled: true };
|
|
131
188
|
});
|
|
132
189
|
logger.info(`${PLUGIN_TAG} subscribed to before_dispatch — ${MIRROR_COMMANDS.size} commands armed.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inbound-handler.js","sourceRoot":"","sources":["../../../../src/channels/telegram-mirror/inbound-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,gBAAgB,EAAuB,MAAM,eAAe,CAAC;AACnG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,UAAU,GAAG,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"inbound-handler.js","sourceRoot":"","sources":["../../../../src/channels/telegram-mirror/inbound-handler.ts"],"names":[],"mappings":"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"}
|