@tritard/waterbrother 0.16.52 → 0.16.53

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/gateway.js +20 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tritard/waterbrother",
3
- "version": "0.16.52",
3
+ "version": "0.16.53",
4
4
  "description": "Waterbrother: bring-your-own-model coding CLI with local tools, sessions, operator modes, and approval controls",
5
5
  "type": "module",
6
6
  "bin": {
package/src/gateway.js CHANGED
@@ -1043,6 +1043,15 @@ class TelegramGateway {
1043
1043
  if (!value) {
1044
1044
  throw new Error("member target is required");
1045
1045
  }
1046
+ const replied = this.describeTelegramUser(message?.reply_to_message?.from || {});
1047
+ const normalizedPronoun = value.toLowerCase().replace(/[?.!]+$/g, "").trim();
1048
+ if (["him", "her", "them", "this person", "this user", "that person", "that user"].includes(normalizedPronoun)) {
1049
+ if (replied.userId) {
1050
+ const knownReply = this.listKnownChatPeople(message).find((person) => person.userId === replied.userId) || replied;
1051
+ return { userId: replied.userId, displayName: knownReply.displayName || replied.displayName || replied.userId };
1052
+ }
1053
+ throw new Error("Reply to the person's message first, or use /people to choose them by name or id.");
1054
+ }
1046
1055
  if (/^\d+$/.test(value) || value.startsWith("@")) {
1047
1056
  const match = this.resolveInviteTarget(message, value);
1048
1057
  return { userId: match.userId, displayName: match.displayName };
@@ -1054,6 +1063,17 @@ class TelegramGateway {
1054
1063
  if (exact) {
1055
1064
  return { userId: exact.userId, displayName: exact.displayName || exact.userId };
1056
1065
  }
1066
+ const byFirstName = known.filter((person) => {
1067
+ const display = String(person.displayName || "").trim().toLowerCase();
1068
+ const first = display.split(/\s+/).filter(Boolean)[0] || "";
1069
+ return first === normalized;
1070
+ });
1071
+ if (byFirstName.length === 1) {
1072
+ return { userId: byFirstName[0].userId, displayName: byFirstName[0].displayName || byFirstName[0].userId };
1073
+ }
1074
+ if (byFirstName.length > 1) {
1075
+ throw new Error(`Multiple Telegram users matched first name ${value}. Use /people and choose by id or full name.`);
1076
+ }
1057
1077
  const partial = known.filter((person) => {
1058
1078
  const display = String(person.displayName || "").trim().toLowerCase();
1059
1079
  const handle = String(person.usernameHandle || "").trim().toLowerCase();