@thesashadev/girl-agent 0.1.10 → 0.1.11

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,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.11
4
+
5
+ Дата: 2026-05-07
6
+
7
+ - Merge pull request #53 from TheSashaDev/devin/1778183666-smart-busy-notify
8
+ - feat: smart busy-transition notification based on context, persona, stage, duration
9
+
3
10
  ## 0.1.10
4
11
 
5
12
  Дата: 2026-05-07
package/dist/cli.js CHANGED
@@ -2948,6 +2948,49 @@ function activeBusySlot(slots, day, minuteOfDay) {
2948
2948
  }
2949
2949
  return null;
2950
2950
  }
2951
+ function busyTransitionHint(stage, comm, remainingMin, checkAfterMin, recentExchangeCount) {
2952
+ const stageChance = {
2953
+ "met-irl-got-tg": 0.05,
2954
+ "tg-given-cold": 0.08,
2955
+ "tg-given-warming": 0.18,
2956
+ "convinced": 0.4,
2957
+ "first-date-done": 0.55,
2958
+ "dating-early": 0.7,
2959
+ "dating-stable": 0.8,
2960
+ "long-term": 0.75,
2961
+ "dumped": 0
2962
+ };
2963
+ let chance = stageChance[stage] ?? 0.3;
2964
+ if (comm.initiative === "high") chance += 0.15;
2965
+ else if (comm.initiative === "low") chance -= 0.15;
2966
+ if (comm.notifications === "priority") chance += 0.1;
2967
+ else if (comm.notifications === "muted") chance -= 0.1;
2968
+ if (comm.lifeSharing === "high") chance += 0.05;
2969
+ if (remainingMin <= 10) chance -= 0.2;
2970
+ else if (remainingMin <= 20) chance -= 0.05;
2971
+ else if (remainingMin >= 90) chance += 0.15;
2972
+ else if (remainingMin >= 45) chance += 0.08;
2973
+ if (checkAfterMin >= 30) chance += 0.15;
2974
+ else if (checkAfterMin >= 15) chance += 0.05;
2975
+ else if (checkAfterMin <= 8) chance -= 0.1;
2976
+ if (recentExchangeCount >= 6) chance += 0.1;
2977
+ else if (recentExchangeCount >= 4) chance += 0.05;
2978
+ chance = Math.max(0, Math.min(1, chance));
2979
+ if (Math.random() >= chance) return null;
2980
+ const isClose = ["dating-early", "dating-stable", "long-term"].includes(stage);
2981
+ const isWarm = comm.initiative === "high" || comm.lifeSharing === "high";
2982
+ const isCold = comm.initiative === "low" && comm.messageStyle === "one-liners";
2983
+ if (isCold) {
2984
+ return `\u041F\u0415\u0420\u0415\u0425\u041E\u0414 \u0412 \u0417\u0410\u041D\u042F\u0422\u041E\u0421\u0422\u042C: \u0443 \u0432\u0430\u0441 \u0431\u044B\u043B \u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0439 \u0434\u0438\u0430\u043B\u043E\u0433, \u043D\u043E \u043D\u0430\u0447\u0438\u043D\u0430\u0435\u0442\u0441\u044F ${remainingMin > 30 ? "\u0434\u043E\u043B\u0433\u043E\u0435" : "\u043A\u043E\u0440\u043E\u0442\u043A\u043E\u0435"} \u0434\u0435\u043B\u043E. \u041F\u0440\u0435\u0434\u0443\u043F\u0440\u0435\u0434\u0438 \u041A\u0420\u0410\u0422\u041A\u041E \u0438 \u0441\u0443\u0445\u043E, \u0432 \u0441\u0432\u043E\u0451\u043C \u0441\u0442\u0438\u043B\u0435 \u2014 \u043E\u0434\u043D\u043E-\u0434\u0432\u0430 \u0441\u043B\u043E\u0432\u0430 ("\u0443\u0448\u043B\u0430", "\u043F\u043E\u0442\u043E\u043C", "\u0437\u0430\u043D\u044F\u0442\u0430"). \u041D\u0435 \u043E\u0431\u044A\u044F\u0441\u043D\u044F\u0439 \u043F\u043E\u0434\u0440\u043E\u0431\u043D\u043E.`;
2985
+ }
2986
+ if (isClose && isWarm) {
2987
+ return `\u041F\u0415\u0420\u0415\u0425\u041E\u0414 \u0412 \u0417\u0410\u041D\u042F\u0422\u041E\u0421\u0422\u042C: \u0443 \u0432\u0430\u0441 \u0431\u044B\u043B \u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0439 \u0434\u0438\u0430\u043B\u043E\u0433, \u043D\u043E \u043D\u0430\u0447\u0438\u043D\u0430\u0435\u0442\u0441\u044F \u0437\u0430\u043D\u044F\u0442\u0438\u0435. \u041F\u0440\u0435\u0434\u0443\u043F\u0440\u0435\u0434\u0438 \u0435\u0433\u043E \u0442\u0435\u043F\u043B\u043E \u0438 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043D\u043D\u043E, \u0432 \u0441\u0442\u0438\u043B\u0435 \u0432\u0430\u0448\u0435\u0439 \u0431\u043B\u0438\u0437\u043E\u0441\u0442\u0438 (\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440: "\u043C\u0430\u043B\u044B\u0448 \u043C\u043D\u0435 \u043D\u0430\u0434\u043E \u0431\u0435\u0436\u0430\u0442\u044C \u043D\u0430 ${remainingMin > 45 ? "\u043F\u0430\u0440\u0443 \u0447\u0430\u0441\u043E\u0432" : "\u043D\u0435\u043C\u043D\u043E\u0433\u043E"}, \u043F\u043E\u0442\u043E\u043C \u043D\u0430\u043F\u0438\u0448\u0443" \u0438\u043B\u0438 "\u044F \u043F\u043E \u0434\u0435\u043B\u0430\u043C, \u0441\u043A\u0443\u0447\u0430\u0439"). \u0421\u0442\u0438\u043B\u044C \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043E\u0442 persona.`;
2988
+ }
2989
+ if (isClose) {
2990
+ return `\u041F\u0415\u0420\u0415\u0425\u041E\u0414 \u0412 \u0417\u0410\u041D\u042F\u0422\u041E\u0421\u0422\u042C: \u0443 \u0432\u0430\u0441 \u0431\u044B\u043B \u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0439 \u0434\u0438\u0430\u043B\u043E\u0433, \u043D\u043E \u043D\u0430\u0447\u0438\u043D\u0430\u0435\u0442\u0441\u044F \u0437\u0430\u043D\u044F\u0442\u0438\u0435. \u041F\u0440\u0435\u0434\u0443\u043F\u0440\u0435\u0434\u0438 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043D\u043D\u043E (\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440: "\u043C\u043D\u0435 \u043D\u0430\u0434\u043E \u043E\u0442\u043E\u0439\u0442\u0438, \u043F\u043E\u0437\u0436\u0435 \u043D\u0430\u043F\u0438\u0448\u0443" \u0438\u043B\u0438 "\u044F \u0437\u0430\u043D\u044F\u0442\u0430 \u0431\u0443\u0434\u0443 ${remainingMin > 45 ? "\u043F\u0430\u0440\u0443 \u0447\u0430\u0441\u043E\u0432" : "\u043D\u0435\u043C\u043D\u043E\u0433\u043E"}, \u043F\u043E\u0442\u043E\u043C \u043E\u0442\u0432\u0435\u0447\u0443").`;
2991
+ }
2992
+ return `\u041F\u0415\u0420\u0415\u0425\u041E\u0414 \u0412 \u0417\u0410\u041D\u042F\u0422\u041E\u0421\u0422\u042C: \u0443 \u0432\u0430\u0441 \u0431\u044B\u043B \u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0439 \u0434\u0438\u0430\u043B\u043E\u0433, \u043D\u043E \u043D\u0430\u0447\u0438\u043D\u0430\u0435\u0442\u0441\u044F \u0434\u0435\u043B\u043E. \u041C\u043E\u0436\u0435\u0448\u044C \u043A\u043E\u0440\u043E\u0442\u043A\u043E \u043F\u0440\u0435\u0434\u0443\u043F\u0440\u0435\u0434\u0438\u0442\u044C \u043E\u0431 \u0443\u0445\u043E\u0434\u0435 (\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440: "\u044F \u043F\u043E\u0431\u0435\u0436\u0430\u043B\u0430, \u043F\u043E\u0442\u043E\u043C \u043E\u0442\u0432\u0435\u0447\u0443" \u0438\u043B\u0438 "\u043C\u043D\u0435 \u043F\u043E\u0440\u0430, \u043F\u043E\u0437\u0436\u0435"). \u0421\u0442\u0438\u043B\u044C \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043E\u0442 \u0443\u0440\u043E\u0432\u043D\u044F \u0432\u0430\u0448\u0438\u0445 \u043E\u0442\u043D\u043E\u0448\u0435\u043D\u0438\u0439 \u0438 persona.`;
2993
+ }
2951
2994
  function computePresenceState(cfg, profile, lastUserMsgTs, lastHerReplyTs, recentExchangeCount, forcedWake = false, conflict = null) {
2952
2995
  const local = localParts(cfg.tz);
2953
2996
  const communication = normalizeCommunicationProfile(cfg);
@@ -3033,6 +3076,10 @@ function computePresenceState(cfg, profile, lastUserMsgTs, lastHerReplyTs, recen
3033
3076
  hint = `\u041D\u0430 ${busy.label} (\u0434\u043E ${busy.until}), \u043D\u043E \u0441\u043A\u0443\u0447\u043D\u043E \u2014 \u043F\u0435\u0440\u0438\u043E\u0434\u0438\u0447\u0435\u0441\u043A\u0438 \u0437\u0430\u0445\u043E\u0434\u0438\u0448\u044C \u0432 Telegram \u043C\u0435\u0436\u0434\u0443 \u0434\u0435\u043B\u043E\u043C. \u041C\u043E\u0436\u0435\u0448\u044C \u0431\u044B\u0441\u0442\u0440\u043E \u043E\u0442\u0432\u0435\u0442\u0438\u0442\u044C, \u043D\u043E \u043C\u043E\u0436\u0435\u0448\u044C \u0438 \u043F\u0440\u043E\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u043C\u043E\u043C\u0435\u043D\u0442.`;
3034
3077
  } else {
3035
3078
  hint = `\u0421\u0435\u0439\u0447\u0430\u0441 \u0437\u0430\u043D\u044F\u0442\u0430: ${busy.label} \u0434\u043E ${busy.until}. \u041D\u0435 \u043C\u043E\u0436\u0435\u0448\u044C \u043D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u043E \u043E\u0442\u0432\u0435\u0447\u0430\u0442\u044C. \u041F\u043E\u0441\u043B\u0435 \u044D\u0442\u043E\u0433\u043E \u0437\u0430\u0439\u0434\u0451\u0448\u044C \u043F\u0440\u043E\u0432\u0435\u0440\u0438\u0442\u044C Telegram \u0447\u0435\u0440\u0435\u0437 ${busy.checkAfterMin} \u043C\u0438\u043D; \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u043D\u043E \u0438 \u043E\u0442\u0432\u0435\u0442 \u0431\u0443\u0434\u0435\u0442 \u0442\u043E\u043B\u044C\u043A\u043E \u0442\u043E\u0433\u0434\u0430.`;
3079
+ if (inActiveDialog && busySlot) {
3080
+ const notifyHint = busyTransitionHint(cfg.stage, communication, busySlot.remainingMin, busy.checkAfterMin ?? 15, recentExchangeCount);
3081
+ if (notifyHint) hint += "\n\n" + notifyHint;
3082
+ }
3036
3083
  }
3037
3084
  } else if (online) {
3038
3085
  if (inActiveDialog) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thesashadev/girl-agent",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Telegram AI persona engine with memory, schedule, relationship state and MTProto userbot mode.",
5
5
  "type": "module",
6
6
  "bin": {