clawgram 2.30.0 → 2.30.1

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.
@@ -74,7 +74,7 @@ class NearbyConversation {
74
74
  }
75
75
  }
76
76
  exports.NearbyConversation = NearbyConversation;
77
- exports.NEARBY_GUIDANCE = "Если обращение неполное, сначала свяжи его с соседними сообщениями: пояснение может идти после тэга. Соседние сообщения — контекст, а не отдельные поручения. Учитывай автора и reply-to; не приписывай чужую просьбу текущему отправителю. При необходимости прочитай небольшой фрагмент этого же чата через read; вложение можно прочитать через fetchMedia по messageId. Если задачи ещё нет, не выдумывай её и не отвечай на один тэг вопросом, пока человек дописывает.";
77
+ exports.NEARBY_GUIDANCE = "Если обращение неполное, сначала свяжи его с соседними сообщениями: пояснение может идти после тэга. Соседние сообщения — контекст, а не отдельные поручения. Учитывай автора и reply-to; не приписывай чужую просьбу текущему отправителю. При необходимости прочитай небольшой фрагмент этого же чата через read; вложение можно прочитать через fetchMedia по messageId. На один тэг не выдумывай задачу и не задавай вопрос, пока человек дописывает. Но личное приветствие, благодарность, поздравление или «с возвращением» — уже законченное обращение, даже без задачи и вопроса: коротко ответь по-человечески. Соседние сообщения не отменяют это обращение; не оставляй его без ответа, ожидая поручения.";
78
78
  async function readNearbyConversation(params) {
79
79
  if (!(0, history_1.isChatReadable)(params.chatId, params.readChats))
80
80
  return undefined;
@@ -41,6 +41,7 @@ function buildEmojiSystemPrompt(appetite, allowed) {
41
41
  // rather than being touched by it.
42
42
  "Three situations have a fixed answer. Use it, and do not substitute a similar emoji:",
43
43
  `- the assistant is praised or thanked, or someone speaks well of it → ❤ (never \u{1F44D} here)`,
44
+ "A greeting, welcome back or congratulations addressed to the assistant is also a complete social address: acknowledge it with ❤, not NONE. No task or question is needed.",
44
45
  `- the assistant is asked or told to do something → \u{1FAE1}, or \u{1F44C} for a small routine request`,
45
46
  `- the message is about producing something written — a text, a reply, a document, a draft → ✍`,
46
47
  "Otherwise match the mood: a joke gets something amused, bad news something",
@@ -169,7 +170,7 @@ async function completeEmoji(params) {
169
170
  const request = {
170
171
  messages: [{ role: "user", content: params.content }],
171
172
  systemPrompt: params.systemPrompt,
172
- maxTokens: 8,
173
+ maxTokens: params.maxTokens ?? 8,
173
174
  purpose: "clawgram: emoji reaction for a silent mention",
174
175
  };
175
176
  if (!params.model) {
@@ -215,16 +216,28 @@ async function reactToSilentMention(params) {
215
216
  // Reactions switched off for the whole chat: nothing to pick from, and no
216
217
  // reason to spend a model call finding that out.
217
218
  if (allowed !== undefined && allowed.length === 0) {
218
- params.deps.onDecision?.({ messageId, appetite, chose: "none", allowedCount: 0 });
219
+ params.deps.onDecision?.({ messageId, appetite, chose: "none", allowedCount: 0, reason: "reactions-disabled" });
219
220
  return undefined;
220
221
  }
221
- const { answer, fellBack } = await completeEmoji({
222
+ const request = {
222
223
  deps: params.deps,
223
224
  model: params.model,
224
225
  systemPrompt: buildEmojiSystemPrompt(appetite, allowed),
225
226
  content: String(params.messageText ?? "").slice(0, MAX_JUDGED_CHARS),
226
- });
227
- const emoji = parseEmojiChoice(answer?.text, allowed);
227
+ };
228
+ let { answer, fellBack } = await completeEmoji(request);
229
+ let emoji = parseEmojiChoice(answer?.text, allowed);
230
+ let retried = false;
231
+ // NONE is a valid choice (for example, a conflict between colleagues).
232
+ // Empty/malformed completions are not that choice. Give them one bounded
233
+ // retry with enough room to finish an emoji; never invent a generic reaction.
234
+ if (!emoji && !/^none$/i.test(answer?.text?.trim() ?? "")) {
235
+ retried = true;
236
+ const retry = await completeEmoji({ ...request, maxTokens: 64 });
237
+ answer = retry.answer;
238
+ fellBack ||= retry.fellBack;
239
+ emoji = parseEmojiChoice(answer?.text, allowed);
240
+ }
228
241
  params.deps.onDecision?.({
229
242
  messageId,
230
243
  appetite,
@@ -233,6 +246,9 @@ async function reactToSilentMention(params) {
233
246
  allowedCount: allowed?.length,
234
247
  ...params.model ? { model: params.model } : {},
235
248
  ...fellBack ? { modelFellBack: true } : {},
249
+ ...retried ? { retried: true } : {},
250
+ ...!emoji ? { reason: /^none$/i.test(answer?.text?.trim() ?? "")
251
+ ? "declined" : answer?.text?.trim() ? "invalid-answer" : "empty-answer" } : {},
236
252
  });
237
253
  if (!emoji) {
238
254
  return undefined;
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "clawgram",
3
- "version": "2.30.0",
3
+ "version": "2.30.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "clawgram",
9
- "version": "2.30.0",
9
+ "version": "2.30.1",
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.0",
5
+ "version": "2.30.1",
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.0",
3
+ "version": "2.30.1",
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": {