@ascegu/teamily 1.0.12 → 1.0.14
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/package.json +1 -1
- package/src/channel.ts +14 -2
- package/src/monitor.ts +13 -2
- package/src/types.ts +8 -0
package/package.json
CHANGED
package/src/channel.ts
CHANGED
|
@@ -26,7 +26,7 @@ import { normalizeTeamilyTarget, normalizeTeamilyAllowEntry } from "./normalize.
|
|
|
26
26
|
import { probeTeamily } from "./probe.js";
|
|
27
27
|
import { getTeamilyRuntime } from "./runtime.js";
|
|
28
28
|
import type { ResolvedTeamilyAccount } from "./types.js";
|
|
29
|
-
import {
|
|
29
|
+
import { isGroupSession } from "./types.js";
|
|
30
30
|
|
|
31
31
|
const meta = {
|
|
32
32
|
id: "teamily",
|
|
@@ -243,8 +243,18 @@ export const teamilyPlugin: ChannelPlugin<ResolvedTeamilyAccount> = {
|
|
|
243
243
|
const rt = getTeamilyRuntime();
|
|
244
244
|
const currentCfg = rt.config.loadConfig();
|
|
245
245
|
|
|
246
|
-
const isGroup = message.sessionType
|
|
246
|
+
const isGroup = isGroupSession(message.sessionType);
|
|
247
247
|
const from = message.sendID;
|
|
248
|
+
|
|
249
|
+
log?.info?.(
|
|
250
|
+
`[${accountId}] Incoming message: sessionType=${message.sessionType}, isGroup=${isGroup}, ` +
|
|
251
|
+
`from=${from}, recvID=${message.recvID}, isAtSelf=${message.isAtSelf ?? false}`,
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
// In group chats, all messages are dispatched to the agent for context,
|
|
255
|
+
// but only @-mentioned messages trigger a reply.
|
|
256
|
+
const shouldReply = !isGroup || !!message.isAtSelf;
|
|
257
|
+
|
|
248
258
|
const text = message.content?.text || "";
|
|
249
259
|
const sessionKey = isGroup ? `teamily:group:${message.recvID}` : `teamily:${from}`;
|
|
250
260
|
|
|
@@ -296,11 +306,13 @@ export const teamilyPlugin: ChannelPlugin<ResolvedTeamilyAccount> = {
|
|
|
296
306
|
cfg: currentCfg,
|
|
297
307
|
dispatcherOptions: {
|
|
298
308
|
deliver: async (payload: { text?: string; body?: string }) => {
|
|
309
|
+
if (!shouldReply) return;
|
|
299
310
|
const replyText = payload?.text ?? payload?.body;
|
|
300
311
|
if (replyText) {
|
|
301
312
|
const monitor = getTeamilyMonitor(accountId);
|
|
302
313
|
if (!monitor) throw new Error(`Teamily monitor not running for account ${accountId}`);
|
|
303
314
|
const replyTo = isGroup ? `group:${message.recvID}` : from;
|
|
315
|
+
log?.info?.(`[${accountId}] Sending reply to: ${replyTo} (isGroup=${isGroup})`);
|
|
304
316
|
const target = normalizeTeamilyTarget(replyTo);
|
|
305
317
|
await monitor.sendText(target, replyText);
|
|
306
318
|
}
|
package/src/monitor.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
TeamilyVideoContent,
|
|
7
7
|
TeamilyAudioContent,
|
|
8
8
|
} from "./types.js";
|
|
9
|
-
import { CONTENT_TYPES, SESSION_TYPES } from "./types.js";
|
|
9
|
+
import { CONTENT_TYPES, SESSION_TYPES, isGroupSession } from "./types.js";
|
|
10
10
|
|
|
11
11
|
export type TeamilyMessageHandler = (message: TeamilyMessage) => Promise<void> | void;
|
|
12
12
|
export type TeamilyConnectionState = "connecting" | "connected" | "disconnected" | "error";
|
|
@@ -232,14 +232,21 @@ function convertSdkMessage(msg: MessageItem, selfUserID: string): TeamilyMessage
|
|
|
232
232
|
return null;
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
+
// Determine whether this message @-mentions the bot
|
|
236
|
+
const isAtSelf =
|
|
237
|
+
contentType === CONTENT_TYPES.AT_TEXT &&
|
|
238
|
+
(msg.atTextElem?.isAtSelf === true ||
|
|
239
|
+
(msg.atTextElem?.atUserList ?? []).includes(selfUserID));
|
|
240
|
+
|
|
235
241
|
return {
|
|
236
242
|
serverMsgID: msg.serverMsgID || msg.clientMsgID || `${Date.now()}_${Math.random()}`,
|
|
237
243
|
sendID: msg.sendID || "unknown",
|
|
238
|
-
recvID: sessionType
|
|
244
|
+
recvID: isGroupSession(sessionType) ? (msg.groupID || "") : (msg.recvID || selfUserID),
|
|
239
245
|
content,
|
|
240
246
|
contentType,
|
|
241
247
|
sessionType,
|
|
242
248
|
sendTime: msg.sendTime || Date.now(),
|
|
249
|
+
isAtSelf,
|
|
243
250
|
};
|
|
244
251
|
}
|
|
245
252
|
|
|
@@ -259,6 +266,10 @@ function parseSdkContent(msg: MessageItem, contentType: number): TeamilyMessage[
|
|
|
259
266
|
return { video: msg.videoElem as unknown as TeamilyVideoContent };
|
|
260
267
|
}
|
|
261
268
|
return {};
|
|
269
|
+
case CONTENT_TYPES.AT_TEXT: {
|
|
270
|
+
const text = msg.atTextElem?.text ?? tryParseTextContent(msg.content);
|
|
271
|
+
return text ? { text } : {};
|
|
272
|
+
}
|
|
262
273
|
case CONTENT_TYPES.VOICE:
|
|
263
274
|
if (msg.soundElem?.sourceUrl) {
|
|
264
275
|
return { audio: msg.soundElem as unknown as TeamilyAudioContent };
|
package/src/types.ts
CHANGED
|
@@ -57,6 +57,8 @@ export interface TeamilyMessage {
|
|
|
57
57
|
contentType: number;
|
|
58
58
|
sessionType: number;
|
|
59
59
|
sendTime: number;
|
|
60
|
+
/** True when the message is an @-mention that includes the bot's own userID. */
|
|
61
|
+
isAtSelf?: boolean;
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
export interface TeamilyPictureContent {
|
|
@@ -119,6 +121,12 @@ export const CONTENT_TYPES = {
|
|
|
119
121
|
// Session type constants
|
|
120
122
|
export const SESSION_TYPES = {
|
|
121
123
|
SINGLE: 1,
|
|
124
|
+
SUPER_GROUP: 2,
|
|
122
125
|
GROUP: 3,
|
|
123
126
|
NOTIFICATION: 4,
|
|
124
127
|
} as const;
|
|
128
|
+
|
|
129
|
+
/** Returns true when the session type represents any kind of group chat. */
|
|
130
|
+
export function isGroupSession(sessionType: number): boolean {
|
|
131
|
+
return sessionType === SESSION_TYPES.GROUP || sessionType === SESSION_TYPES.SUPER_GROUP;
|
|
132
|
+
}
|