clawgram 2.30.1 → 2.31.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/README.md CHANGED
@@ -305,12 +305,19 @@ addresses wait for 6 seconds of quiet; consecutive messages by the same sender
305
305
  in the same chat/topic are collected into one turn within a 2-minute window.
306
306
  An unanswered bare tag can still receive a late continuation within that window.
307
307
  Other senders and topics do not inherit the address. Detailed requests proceed
308
- immediately. Before answering an address, the agent receives up to 12 recent
309
- messages from the same chat/topic (3 minutes before the triggering message,
308
+ immediately. Before answering an address, the agent receives up to 100 recent
309
+ messages from the same chat/topic (10 minutes before the triggering message,
310
310
  including explanations that arrived afterwards), subject to `readChats`.
311
311
  History failures leave the original request usable. Attachment metadata includes
312
312
  message ids so the agent can read a relevant image with `fetchMedia`.
313
313
 
314
+ Plain replies also carry the original message body, fetched independently of
315
+ the nearby-history window. If Telegram rejects an emoji such as ❌ as a standard
316
+ reaction, a Premium account can send the matching custom emoji instead. The
317
+ `react` action resolves it through Telegram's emoji search; it never substitutes
318
+ a different emoji. Account and chat restrictions still apply, and a failed
319
+ reaction remains an error.
320
+
314
321
  ### Per-group tools, skills and system prompt
315
322
 
316
323
  Since 2.17.0 a group entry can narrow what the assistant does *in that chat*
@@ -541,11 +541,29 @@ class GramJsClientManager {
541
541
  */
542
542
  async sendReaction(args) {
543
543
  const resolved = await this.resolvePeer(args.target);
544
- await this.client.invoke(new telegram_1.Api.messages.SendReaction({
545
- peer: resolved.peer,
546
- msgId: args.messageId,
547
- reaction: args.remove ? [] : [new telegram_1.Api.ReactionEmoji({ emoticon: args.emoji })],
544
+ const send = (reaction) => this.client.invoke(new telegram_1.Api.messages.SendReaction({
545
+ peer: resolved.peer, msgId: args.messageId, reaction,
548
546
  }));
547
+ try {
548
+ await send(args.remove ? [] : [new telegram_1.Api.ReactionEmoji({ emoticon: args.emoji })]);
549
+ }
550
+ catch (error) {
551
+ // Unicode such as ❌ is not necessarily a standard Telegram reaction.
552
+ // A Premium account can use the matching custom emoji. Retry only a
553
+ // definite rejection, never a timeout with an ambiguous send outcome.
554
+ if (args.remove || error?.errorMessage !== "REACTION_INVALID")
555
+ throw error;
556
+ const me = await this.client.getMe();
557
+ if (!me.premium)
558
+ throw error;
559
+ const found = await this.client.invoke(new telegram_1.Api.messages.SearchCustomEmoji({
560
+ emoticon: args.emoji, hash: BigInt(0),
561
+ }));
562
+ const documentId = found.documentId?.[0];
563
+ if (!documentId)
564
+ throw error;
565
+ await send([new telegram_1.Api.ReactionCustomEmoji({ documentId })]);
566
+ }
549
567
  }
550
568
  /**
551
569
  * Reads a window of chat history.
@@ -85,8 +85,8 @@ async function readNearbyConversation(params) {
85
85
  params.gram.listMessages({
86
86
  target: params.chatId,
87
87
  messageThreadId: params.threadId,
88
- limit: 12,
89
- since: anchor - 180,
88
+ limit: 100,
89
+ since: anchor - 600,
90
90
  until: now,
91
91
  }),
92
92
  new Promise((_resolve, reject) => {
@@ -95,7 +95,7 @@ async function readNearbyConversation(params) {
95
95
  ]).finally(() => clearTimeout(timer));
96
96
  const messages = result.messages.filter((message) => message.messageId !== params.messageId &&
97
97
  (!params.threadId || message.messageThreadId === String(params.threadId)) &&
98
- (!message.chatId || message.chatId === params.chatId)).slice(-12).sort((a, b) => Number(a.messageId) - Number(b.messageId));
98
+ (!message.chatId || message.chatId === params.chatId)).slice(-100).sort((a, b) => Number(a.messageId) - Number(b.messageId));
99
99
  if (!messages.length)
100
100
  return undefined;
101
101
  // JSON quotes chat text and preserves author/message/media identifiers for a targeted follow-up read.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "clawgram",
3
- "version": "2.30.1",
3
+ "version": "2.31.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "clawgram",
9
- "version": "2.30.1",
9
+ "version": "2.31.0",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "json5": "2.2.3",
@@ -2,7 +2,7 @@
2
2
  "id": "clawgram",
3
3
  "name": "Clawgram",
4
4
  "description": "Clawgram — personal Telegram (MTProto userbot) channel for OpenClaw. Your AI assistant reads and responds as you.",
5
- "version": "2.30.1",
5
+ "version": "2.31.0",
6
6
  "configSchema": {
7
7
  "type": "object",
8
8
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawgram",
3
- "version": "2.30.1",
3
+ "version": "2.31.0",
4
4
  "description": "Clawgram — personal Telegram (MTProto userbot) channel for OpenClaw. Your AI assistant reads and responds as you.",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {