@thesashadev/girl-agent 0.4.2 → 0.4.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.3
4
+
5
+ Дата: 2026-05-17
6
+
7
+ 🐛 Исправления
8
+
9
+ - Устранено дублирование сообщений, возникавшее при перефразировании ответов моделью — одинаковые или близкие по содержанию «пузыри» больше не появляются дважды.
10
+
11
+
3
12
  ## 0.4.2
4
13
 
5
14
  Дата: 2026-05-17
package/dist/cli.js CHANGED
@@ -5222,19 +5222,46 @@ import { EventEmitter } from "events";
5222
5222
  function normalizeForDuplicate(text) {
5223
5223
  return text.toLowerCase().replace(/\s+/g, " ").replace(/[.!?…)\]]+$/g, "").trim();
5224
5224
  }
5225
+ function bubbleTokens(text) {
5226
+ return normalizeForDuplicate(text).replace(/[^\p{L}\p{N}\s]/gu, " ").split(/\s+/).filter((t) => t.length > 1);
5227
+ }
5228
+ function bubbleIsContainedIn(shorter, longer) {
5229
+ const a = normalizeForDuplicate(shorter);
5230
+ const b = normalizeForDuplicate(longer);
5231
+ if (!a || !b || a === b) return false;
5232
+ if (a.length >= b.length) return false;
5233
+ if (b.includes(a)) return true;
5234
+ const shortTokens = bubbleTokens(shorter);
5235
+ if (shortTokens.length < 2) return false;
5236
+ const longSet = new Set(bubbleTokens(longer));
5237
+ const overlap = shortTokens.filter((t) => longSet.has(t)).length;
5238
+ return overlap / shortTokens.length >= 0.75;
5239
+ }
5225
5240
  function isDuplicateAssistantBubble(hist, text) {
5226
5241
  const normalized = normalizeForDuplicate(text);
5227
5242
  if (!normalized) return true;
5228
- return hist.slice(-8).filter((t) => t.role === "assistant").some((t) => normalizeForDuplicate(t.content) === normalized);
5243
+ const recent = hist.slice(-8).filter((t) => t.role === "assistant");
5244
+ return recent.some((t) => {
5245
+ const histNorm = normalizeForDuplicate(t.content);
5246
+ if (histNorm === normalized) return true;
5247
+ return bubbleIsContainedIn(text, t.content) || bubbleIsContainedIn(t.content, text);
5248
+ });
5229
5249
  }
5230
5250
  function dedupeBubbles(bubbles) {
5231
- const seen = /* @__PURE__ */ new Set();
5232
- return bubbles.filter((bubble) => {
5251
+ const kept = [];
5252
+ for (const bubble of bubbles) {
5233
5253
  const normalized = normalizeForDuplicate(bubble);
5234
- if (!normalized || seen.has(normalized)) return false;
5235
- seen.add(normalized);
5236
- return true;
5237
- });
5254
+ if (!normalized) continue;
5255
+ if (kept.some((k) => normalizeForDuplicate(k) === normalized)) continue;
5256
+ if (kept.some((k) => bubbleIsContainedIn(bubble, k))) continue;
5257
+ for (let i = kept.length - 1; i >= 0; i--) {
5258
+ if (bubbleIsContainedIn(kept[i], bubble)) {
5259
+ kept.splice(i, 1);
5260
+ }
5261
+ }
5262
+ kept.push(bubble);
5263
+ }
5264
+ return kept;
5238
5265
  }
5239
5266
  function smartSplitBubbles(reply, expectedBubbles) {
5240
5267
  const explicit = reply.split(/\n*---\n*/).map((s) => s.trim()).filter(Boolean);
@@ -6041,7 +6068,7 @@ ${m.text}` : media;
6041
6068
  intent=${tick.intent}
6042
6069
  \u043A\u043E\u043B-\u0432\u043E \u043F\u0443\u0437\u044B\u0440\u0435\u0439: ${tick.bubbles}${presenceHint ? `
6043
6070
  \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E\u0441\u0442\u044C: ${presenceHint}` : ""}
6044
- ${tick.intent === "short" ? "\u041E\u0442\u0432\u0435\u0447\u0430\u0439 \u043E\u0434\u043D\u043E\u0441\u043B\u043E\u0436\u043D\u043E: '\u043E\u043A', '\u044F\u0441\u043D\u043E', '\u0438?', '\u043D\u0443 \u043E\u043A'. \u0411\u0435\u0437 \u043E\u0431\u044A\u044F\u0441\u043D\u0435\u043D\u0438\u0439." : tick.bubbles > 1 ? "\u0420\u0430\u0437\u0431\u0435\u0439 \u043E\u0442\u0432\u0435\u0442 \u043D\u0430 \u043F\u0443\u0437\u044B\u0440\u0438 \u0421\u0422\u0420\u041E\u0413\u041E \u0441\u0442\u0440\u043E\u043A\u043E\u0439 '---' (\u0442\u0440\u0438 \u0434\u0435\u0444\u0438\u0441\u0430 \u043D\u0430 \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u043E\u0439 \u0441\u0442\u0440\u043E\u043A\u0435) \u043C\u0435\u0436\u0434\u0443 \u043D\u0438\u043C\u0438. \u041A\u0410\u0416\u0414\u042B\u0419 \u043F\u0443\u0437\u044B\u0440\u044C \u2014 \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u043E\u0435 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0432 \u0442\u0433. \u0417\u0410\u041F\u0420\u0415\u0429\u0415\u041D\u041E \u0440\u0430\u0441\u043A\u0438\u0434\u044B\u0432\u0430\u0442\u044C \u043E\u0434\u043D\u043E \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u043D\u0430 \u043D\u0435\u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0441\u0442\u0440\u043E\u043A \u0447\u0435\u0440\u0435\u0437 \u043F\u0435\u0440\u0435\u043D\u043E\u0441 \u0441\u0442\u0440\u043E\u043A\u0438 \u0431\u0435\u0437 '---' \u2014 \u0432 \u0442\u0433 \u044D\u0442\u043E \u0432\u044B\u0433\u043B\u044F\u0434\u0438\u0442 \u043A\u0430\u043A \u043E\u0434\u043D\u043E \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0432 \u0441\u0442\u043E\u043B\u0431\u0438\u043A, \u0447\u0442\u043E \u043F\u0430\u043B\u0438\u0442 \u0418\u0418. \u041F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E:\\n\\n\u043F\u0440\u0438\u0432\u0435\u0442\\n---\\n\u043A\u0430\u043A \u0441\u0430\u043C\\n\\n\u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E:\\n\\n\u043F\u0440\u0438\u0432\u0435\u0442\\n\u043A\u0430\u043A \u0441\u0430\u043C" : "\u041E\u0434\u0438\u043D \u043A\u043E\u0440\u043E\u0442\u043A\u0438\u0439 \u043E\u0442\u0432\u0435\u0442, \u0431\u0435\u0437 '---'."}${scopeHint}` },
6071
+ ${tick.intent === "short" ? "\u041E\u0442\u0432\u0435\u0447\u0430\u0439 \u043E\u0434\u043D\u043E\u0441\u043B\u043E\u0436\u043D\u043E: '\u043E\u043A', '\u044F\u0441\u043D\u043E', '\u0438?', '\u043D\u0443 \u043E\u043A'. \u0411\u0435\u0437 \u043E\u0431\u044A\u044F\u0441\u043D\u0435\u043D\u0438\u0439." : tick.bubbles > 1 ? "\u0420\u0430\u0437\u0431\u0435\u0439 \u043E\u0442\u0432\u0435\u0442 \u043D\u0430 \u043F\u0443\u0437\u044B\u0440\u0438 \u0421\u0422\u0420\u041E\u0413\u041E \u0441\u0442\u0440\u043E\u043A\u043E\u0439 '---' (\u0442\u0440\u0438 \u0434\u0435\u0444\u0438\u0441\u0430 \u043D\u0430 \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u043E\u0439 \u0441\u0442\u0440\u043E\u043A\u0435) \u043C\u0435\u0436\u0434\u0443 \u043D\u0438\u043C\u0438. \u041A\u0410\u0416\u0414\u042B\u0419 \u043F\u0443\u0437\u044B\u0440\u044C \u2014 \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u043E\u0435 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0432 \u0442\u0433. \u0417\u0410\u041F\u0420\u0415\u0429\u0415\u041D\u041E \u0440\u0430\u0441\u043A\u0438\u0434\u044B\u0432\u0430\u0442\u044C \u043E\u0434\u043D\u043E \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u043D\u0430 \u043D\u0435\u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0441\u0442\u0440\u043E\u043A \u0447\u0435\u0440\u0435\u0437 \u043F\u0435\u0440\u0435\u043D\u043E\u0441 \u0441\u0442\u0440\u043E\u043A\u0438 \u0431\u0435\u0437 '---' \u2014 \u0432 \u0442\u0433 \u044D\u0442\u043E \u0432\u044B\u0433\u043B\u044F\u0434\u0438\u0442 \u043A\u0430\u043A \u043E\u0434\u043D\u043E \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0432 \u0441\u0442\u043E\u043B\u0431\u0438\u043A, \u0447\u0442\u043E \u043F\u0430\u043B\u0438\u0442 \u0418\u0418. \u041F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E:\\n\\n\u043F\u0440\u0438\u0432\u0435\u0442\\n---\\n\u043A\u0430\u043A \u0441\u0430\u043C\\n\\n\u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E:\\n\\n\u043F\u0440\u0438\u0432\u0435\u0442\\n\u043A\u0430\u043A \u0441\u0430\u043C\n\n\u041A\u0420\u0418\u0422\u0418\u0427\u041D\u041E: \u043A\u0430\u0436\u0434\u044B\u0439 \u043F\u0443\u0437\u044B\u0440\u044C \u2014 \u041D\u041E\u0412\u0410\u042F \u043C\u044B\u0441\u043B\u044C. \u0417\u0410\u041F\u0420\u0415\u0429\u0415\u041D\u041E \u043F\u043E\u0432\u0442\u043E\u0440\u044F\u0442\u044C \u0438\u043B\u0438 \u043F\u0435\u0440\u0435\u0444\u0440\u0430\u0437\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0432 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u043C \u043F\u0443\u0437\u044B\u0440\u0435 \u0442\u043E \u0436\u0435, \u0447\u0442\u043E \u0441\u043A\u0430\u0437\u0430\u043B\u0430 \u0432 \u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0435\u043C. \u0415\u0441\u043B\u0438 \u0443\u0436\u0435 \u0441\u043A\u0430\u0437\u0430\u043B\u0430 '\u043F\u043E \u043F\u043E\u0432\u043E\u0434\u0443 \u0437\u0430\u0432\u0442\u0440\u0430' \u2014 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u043F\u0443\u0437\u044B\u0440\u044C \u041D\u0415 \u0434\u043E\u043B\u0436\u0435\u043D \u043D\u0430\u0447\u0438\u043D\u0430\u0442\u044C\u0441\u044F \u0441 '\u043F\u043E \u043F\u043E\u0432\u043E\u0434\u0443 \u0437\u0430\u0432\u0442\u0440\u0430 \u0435\u0449\u0451...'. \u041D\u0435 \u0446\u0438\u0442\u0438\u0440\u0443\u0439 \u0438 \u043D\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u044F\u0439 \u0441\u0432\u043E\u0438 \u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0435 \u043F\u0443\u0437\u044B\u0440\u0438. \u0424\u0438\u043D\u0430\u043B\u044C\u043D\u044B\u0439 \u043E\u0442\u0432\u0435\u0442 \u0432\u044B\u0434\u0430\u0439 \u041E\u0414\u0418\u041D \u0440\u0430\u0437, \u043D\u0435 \u043F\u0435\u0440\u0435\u043F\u0438\u0441\u044B\u0432\u0430\u0439 \u0435\u0433\u043E \u0434\u0440\u0443\u0433\u0438\u043C\u0438 \u0441\u043B\u043E\u0432\u0430\u043C\u0438." : "\u041E\u0434\u0438\u043D \u043A\u043E\u0440\u043E\u0442\u043A\u0438\u0439 \u043E\u0442\u0432\u0435\u0442, \u0431\u0435\u0437 '---'."}${scopeHint}` },
6045
6072
  ...hist.slice(-60).map((t) => ({ role: t.role, content: t.content }))
6046
6073
  ];
6047
6074
  const image = imagePartFromMedia(incoming?.media);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thesashadev/girl-agent",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Telegram AI persona engine with memory, schedule, relationship state and MTProto userbot mode.",
5
5
  "type": "module",
6
6
  "bin": {