@tritard/waterbrother 0.16.49 → 0.16.50

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
@@ -297,7 +297,7 @@ Current Telegram behavior:
297
297
  - pending pairings are explicit and expire automatically after 12 hours unless approved
298
298
  - paired Telegram users drive the same live session and permissions as the terminal operator when the TUI bridge is attached
299
299
  - Telegram now supports remote workspace control with `/project`, `/project use <path|name>`, `/project new <name>`, `/project share`, plus the lower-level `/cwd`, `/use <path>`, `/desktop`, and `/new-project <name>` commands
300
- - Telegram owners can pair visible chat participants conversationally or with `/pair <user-id|@username>`, then continue with shared-room invites without dropping back to the terminal
300
+ - Telegram owners can pair visible chat participants conversationally or with `/pair <user-id|@username>`, and owner requests like “add Austin as editor” now pair the person if needed and add them to the shared project directly
301
301
  - Telegram owners can also use conversational project and member requests like “share this project in this chat”, “switch to TelegramTest”, or “add Austin as editor”, and Waterbrother routes those through the same project and shared-room actions
302
302
  - shared projects now support `/room`, `/events`, `/members`, `/invites`, `/whoami`, `/people`, `/tasks`, `/mode`, `/claim`, `/release`, `/invite`, `/accept-invite`, `/approve-invite`, `/reject-invite`, `/remove-member`, `/room-runtime`, and `/task ...` from Telegram
303
303
  - Telegram now supports `/whoami` for Telegram-id and shared-room membership visibility, plus `/events` for recent shared-room activity
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tritard/waterbrother",
3
- "version": "0.16.49",
3
+ "version": "0.16.50",
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
@@ -1022,21 +1022,28 @@ class TelegramGateway {
1022
1022
  markup: `Updated <code>${escapeTelegramHtml(target.displayName || target.userId)}</code> to <code>${escapeTelegramHtml(intent.role)}</code> in this shared project.`
1023
1023
  };
1024
1024
  }
1025
- const result = await createSharedInvite(
1025
+ const known = this.listKnownChatPeople(message);
1026
+ const knownPerson = known.find((person) => String(person.userId || "").trim() === target.userId) || null;
1027
+ let pairedNow = false;
1028
+ if (!knownPerson?.paired) {
1029
+ await this.pairKnownTelegramUser(message, target.userId, { skipOwnerCheck: true });
1030
+ pairedNow = true;
1031
+ }
1032
+ const nextProject = await upsertSharedMember(
1026
1033
  session.cwd || this.cwd,
1027
- { id: target.userId, role: intent.role, name: target.displayName || target.userId, paired: true },
1034
+ { id: target.userId, name: target.displayName || target.userId, role: intent.role, paired: true },
1028
1035
  { actorId, actorName }
1029
1036
  );
1030
1037
  return {
1031
- kind: "invite",
1032
- project: result.project,
1033
- markup: `Created pending invite <code>${escapeTelegramHtml(result.invite.id)}</code> for <code>${escapeTelegramHtml(target.displayName || target.userId)}</code> as <code>${escapeTelegramHtml(result.invite.role)}</code>.\nAsk them to run <code>/accept-invite ${escapeTelegramHtml(result.invite.id)}</code>.`
1038
+ kind: "member",
1039
+ project: nextProject,
1040
+ markup: `${pairedNow ? `Paired <code>${escapeTelegramHtml(target.displayName || target.userId)}</code> <i>(${escapeTelegramHtml(target.userId)})</i> and ` : ""}added <code>${escapeTelegramHtml(target.displayName || target.userId)}</code> to this shared project as <code>${escapeTelegramHtml(intent.role)}</code>.`
1034
1041
  };
1035
1042
  }
1036
1043
 
1037
- async pairKnownTelegramUser(message, target) {
1044
+ async pairKnownTelegramUser(message, target, { skipOwnerCheck = false } = {}) {
1038
1045
  const { session, project } = await this.bindSharedRoomForMessage(message, await this.ensurePeerSession(message));
1039
- if (project?.enabled) {
1046
+ if (project?.enabled && !skipOwnerCheck) {
1040
1047
  const owner = Array.isArray(project.members)
1041
1048
  ? project.members.find((entry) => String(entry?.id || "").trim() === String(message?.from?.id || "").trim())
1042
1049
  : null;