@dreb/telegram 2.34.1 â 2.34.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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buddy.d.ts","sourceRoot":"","sources":["../../src/handlers/buddy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAkB,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAuC,MAAM,0BAA0B,CAAC;AAChG,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAElC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAM1C,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAmBhD,CAAC;AAUF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAgC1D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAErF;AAMD;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC5C,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,GAClB,eAAe,
|
|
1
|
+
{"version":3,"file":"buddy.d.ts","sourceRoot":"","sources":["../../src/handlers/buddy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAkB,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAuC,MAAM,0BAA0B,CAAC;AAChG,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAElC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAM1C,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAmBhD,CAAC;AAUF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAgC1D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAErF;AAMD;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC5C,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,GAClB,eAAe,CA8CjB","sourcesContent":["/**\n * Telegram buddy handler â creates and configures a BuddyController\n * with Telegram-specific rendering callbacks and formatting.\n */\n\nimport type { BuddyCallbacks, BuddyState } from \"@dreb/coding-agent/buddy\";\nimport { BuddyController, BuddyManager, STAT_NAMES, type Stat } from \"@dreb/coding-agent/buddy\";\nimport type { Api } from \"grammy\";\nimport { ensureBridgeWithSession } from \"../bridge-lifecycle.js\";\nimport type { Config } from \"../config.js\";\nimport type { UserState } from \"../types.js\";\nimport type { SendFn } from \"./events.js\";\n\n// ---------------------------------------------------------------------------\n// Species emoji mapping\n// ---------------------------------------------------------------------------\n\nexport const SPECIES_EMOJI: Record<string, string> = {\n\tDuck: \"đĻ\",\n\tGoose: \"đĒŋ\",\n\tBlob: \"đĸ\",\n\tCat: \"đą\",\n\tDragon: \"đ\",\n\tOctopus: \"đ\",\n\tOwl: \"đĻ\",\n\tPenguin: \"đ§\",\n\tTurtle: \"đĸ\",\n\tSnail: \"đ\",\n\tGhost: \"đģ\",\n\tAxolotl: \"đĢ\",\n\tCapybara: \"đĻĢ\",\n\tCactus: \"đĩ\",\n\tRobot: \"đ¤\",\n\tRabbit: \"đ°\",\n\tMushroom: \"đ\",\n\tChonk: \"đš\",\n};\n\nfunction speciesEmoji(species: string): string {\n\treturn SPECIES_EMOJI[species] ?? \"đŖ\";\n}\n\n// ---------------------------------------------------------------------------\n// Formatting helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Format a stats panel as a Telegram code block.\n * Shows stat bars using â and â characters.\n */\nexport function formatBuddyStats(state: BuddyState): string {\n\tconst emoji = speciesEmoji(state.species);\n\tconst shiny = state.shiny ? \" ⨠SHINY!\" : \"\";\n\tconst maxBar = 10;\n\tconst personality = state.personality.replace(/\\n/g, \" \");\n\tconst backstory = state.backstory.replace(/\\n/g, \" \");\n\tconst hatched = state.hatchedAt ? new Date(state.hatchedAt).toLocaleDateString() : \"unknown\";\n\n\tconst statLines = STAT_NAMES.map((s: string) => {\n\t\tconst value = state.stats[s as Stat];\n\t\tconst filled = Math.round((value / 100) * maxBar);\n\t\tconst bar = \"â\".repeat(filled) + \"â\".repeat(maxBar - filled);\n\t\treturn `â ${s.padEnd(12)} ${bar} ${value}`;\n\t});\n\n\treturn [\n\t\t`\\`\\`\\``,\n\t\t`ââ ${emoji} ${state.name} ${shiny} âââââââââââââââââââŽ`,\n\t\t`â Species: ${state.species}`,\n\t\t`â Rarity: ${state.rarity}`,\n\t\t`â Eyes: ${state.eyeStyle} Hat: ${state.hat || \"none\"}`,\n\t\t`â Hatched: ${hatched}`,\n\t\t`â Re-rolls: ${state.rerollCount}`,\n\t\t`â`,\n\t\t`â Stats:`,\n\t\t...statLines,\n\t\t`â`,\n\t\t`â Personality: ${personality}`,\n\t\t`â Backstory: ${backstory}`,\n\t\t`â°âââââââââââââââââââââââââââââââââââ¯`,\n\t\t`\\`\\`\\``,\n\t].join(\"\\n\");\n}\n\n/**\n * Format a buddy speech/reaction message.\n */\nexport function formatBuddySpeech(name: string, species: string, text: string): string {\n\treturn `${speciesEmoji(species)} ${name}: \"${text}\"`;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a BuddyController wired up with Telegram-specific callbacks.\n *\n * @param send â outbox send function (enqueueSend) for reliable delivery\n * @param api â grammy Api instance for chat actions and reactions\n * @param chatId â Telegram chat ID for this user\n * @param config â bot config (for bridge resolution in hatch/reroll)\n * @param userState â per-user state (for bridge resolution in hatch/reroll)\n */\nexport function createTelegramBuddyController(\n\tsend: SendFn,\n\tapi: Api,\n\tchatId: number,\n\tconfig: Config,\n\tuserState: UserState,\n): BuddyController {\n\tconst manager = new BuddyManager();\n\n\tconst callbacks: BuddyCallbacks = {\n\t\tonSpeech(text: string): void {\n\t\t\tconst name = manager.getName() ?? \"Buddy\";\n\t\t\tconst state = manager.getState();\n\t\t\tconst species = state?.species ?? \"\";\n\t\t\tsend(formatBuddySpeech(name, species, text));\n\t\t},\n\t\tonThinkingStart(): void {\n\t\t\t// Fire-and-forget typing indicator\n\t\t\tapi.sendChatAction(chatId, \"typing\").catch(() => {});\n\t\t},\n\t\tonThinkingEnd(): void {\n\t\t\t// No-op â can't cancel a chat action in Telegram\n\t\t},\n\t\tasync onHatch(_mgr): Promise<BuddyState> {\n\t\t\tconst bridge = await ensureBridgeWithSession(config, userState);\n\t\t\treturn bridge.buddyHatch();\n\t\t},\n\t\tasync onReroll(_mgr): Promise<BuddyState> {\n\t\t\tconst bridge = await ensureBridgeWithSession(config, userState);\n\t\t\treturn bridge.buddyReroll();\n\t\t},\n\t\tonVisibilityChange(_visible: boolean): void {\n\t\t\t// Telegram has no persistent buddy widget â reaction suppression and\n\t\t\t// re-enable already flow from the controller's `enabled` flag, which\n\t\t\t// syncHiddenState() updates from the shared buddy.json. Nothing to\n\t\t\t// mount/unmount here, so this is intentionally a no-op.\n\t\t},\n\t};\n\n\tconst controller = new BuddyController(manager, callbacks, {\n\t\tidleTimeoutMs: 30_000,\n\t\treactionCooldownMs: 60_000,\n\t\tcontextMaxEntries: 20,\n\t\tactivityGateMs: 7_200_000, // 2 hours\n\t\treactionsPerHour: 3,\n\t});\n\n\t// Auto-load buddy from shared buddy.json (same file TUI uses).\n\t// If a buddy exists and is visible, it'll be active immediately.\n\tcontroller.start();\n\n\treturn controller;\n}\n"]}
|
package/dist/handlers/buddy.js
CHANGED
|
@@ -110,6 +110,12 @@ export function createTelegramBuddyController(send, api, chatId, config, userSta
|
|
|
110
110
|
const bridge = await ensureBridgeWithSession(config, userState);
|
|
111
111
|
return bridge.buddyReroll();
|
|
112
112
|
},
|
|
113
|
+
onVisibilityChange(_visible) {
|
|
114
|
+
// Telegram has no persistent buddy widget â reaction suppression and
|
|
115
|
+
// re-enable already flow from the controller's `enabled` flag, which
|
|
116
|
+
// syncHiddenState() updates from the shared buddy.json. Nothing to
|
|
117
|
+
// mount/unmount here, so this is intentionally a no-op.
|
|
118
|
+
},
|
|
113
119
|
};
|
|
114
120
|
const controller = new BuddyController(manager, callbacks, {
|
|
115
121
|
idleTimeoutMs: 30_000,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buddy.js","sourceRoot":"","sources":["../../src/handlers/buddy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,EAAa,MAAM,0BAA0B,CAAC;AAEhG,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAKjE,8EAA8E;AAC9E,wBAAwB;AACxB,8EAA8E;AAE9E,MAAM,CAAC,MAAM,aAAa,GAA2B;IACpD,IAAI,EAAE,MAAG;IACT,KAAK,EAAE,MAAG;IACV,IAAI,EAAE,MAAG;IACT,GAAG,EAAE,MAAG;IACR,MAAM,EAAE,MAAG;IACX,OAAO,EAAE,MAAG;IACZ,GAAG,EAAE,MAAG;IACR,OAAO,EAAE,MAAG;IACZ,MAAM,EAAE,MAAG;IACX,KAAK,EAAE,MAAG;IACV,KAAK,EAAE,MAAG;IACV,OAAO,EAAE,MAAG;IACZ,QAAQ,EAAE,MAAG;IACb,MAAM,EAAE,MAAG;IACX,KAAK,EAAE,MAAG;IACV,MAAM,EAAE,MAAG;IACX,QAAQ,EAAE,MAAG;IACb,KAAK,EAAE,MAAG;CACV,CAAC;AAEF,SAAS,YAAY,CAAC,OAAe,EAAU;IAC9C,OAAO,aAAa,CAAC,OAAO,CAAC,IAAI,MAAG,CAAC;AAAA,CACrC;AAED,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAiB,EAAU;IAC3D,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,aAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7C,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAE7F,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAS,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,KAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,KAAG,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QAC7D,OAAO,OAAK,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;IAAA,CAC3C,CAAC,CAAC;IAEH,OAAO;QACN,QAAQ;QACR,UAAM,KAAK,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,4DAAsB;QACxD,mBAAiB,KAAK,CAAC,OAAO,EAAE;QAChC,mBAAiB,KAAK,CAAC,MAAM,EAAE;QAC/B,mBAAiB,KAAK,CAAC,QAAQ,UAAU,KAAK,CAAC,GAAG,IAAI,MAAM,EAAE;QAC9D,mBAAiB,OAAO,EAAE;QAC1B,mBAAiB,KAAK,CAAC,WAAW,EAAE;QACpC,KAAG;QACH,YAAU;QACV,GAAG,SAAS;QACZ,KAAG;QACH,oBAAkB,WAAW,EAAE;QAC/B,mBAAiB,SAAS,EAAE;QAC5B,8GAAsC;QACtC,QAAQ;KACR,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CACb;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,OAAe,EAAE,IAAY,EAAU;IACtF,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,IAAI,MAAM,IAAI,GAAG,CAAC;AAAA,CACrD;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,UAAU,6BAA6B,CAC5C,IAAY,EACZ,GAAQ,EACR,MAAc,EACd,MAAc,EACd,SAAoB,EACF;IAClB,MAAM,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;IAEnC,MAAM,SAAS,GAAmB;QACjC,QAAQ,CAAC,IAAY,EAAQ;YAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,IAAI,OAAO,CAAC;YAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,IAAI,EAAE,CAAC;YACrC,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAAA,CAC7C;QACD,eAAe,GAAS;YACvB,mCAAmC;YACnC,GAAG,CAAC,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAC,CAAC,CAAC,CAAC;QAAA,CACrD;QACD,aAAa,GAAS;YACrB,mDAAiD;QAD3B,CAEtB;QACD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAuB;YACxC,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YAChE,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC;QAAA,CAC3B;QACD,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAuB;YACzC,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YAChE,OAAO,MAAM,CAAC,WAAW,EAAE,CAAC;QAAA,CAC5B;KACD,CAAC;IAEF,MAAM,UAAU,GAAG,IAAI,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE;QAC1D,aAAa,EAAE,MAAM;QACrB,kBAAkB,EAAE,MAAM;QAC1B,iBAAiB,EAAE,EAAE;QACrB,cAAc,EAAE,SAAS,EAAE,UAAU;QACrC,gBAAgB,EAAE,CAAC;KACnB,CAAC,CAAC;IAEH,+DAA+D;IAC/D,iEAAiE;IACjE,UAAU,CAAC,KAAK,EAAE,CAAC;IAEnB,OAAO,UAAU,CAAC;AAAA,CAClB","sourcesContent":["/**\n * Telegram buddy handler â creates and configures a BuddyController\n * with Telegram-specific rendering callbacks and formatting.\n */\n\nimport type { BuddyCallbacks, BuddyState } from \"@dreb/coding-agent/buddy\";\nimport { BuddyController, BuddyManager, STAT_NAMES, type Stat } from \"@dreb/coding-agent/buddy\";\nimport type { Api } from \"grammy\";\nimport { ensureBridgeWithSession } from \"../bridge-lifecycle.js\";\nimport type { Config } from \"../config.js\";\nimport type { UserState } from \"../types.js\";\nimport type { SendFn } from \"./events.js\";\n\n// ---------------------------------------------------------------------------\n// Species emoji mapping\n// ---------------------------------------------------------------------------\n\nexport const SPECIES_EMOJI: Record<string, string> = {\n\tDuck: \"đĻ\",\n\tGoose: \"đĒŋ\",\n\tBlob: \"đĸ\",\n\tCat: \"đą\",\n\tDragon: \"đ\",\n\tOctopus: \"đ\",\n\tOwl: \"đĻ\",\n\tPenguin: \"đ§\",\n\tTurtle: \"đĸ\",\n\tSnail: \"đ\",\n\tGhost: \"đģ\",\n\tAxolotl: \"đĢ\",\n\tCapybara: \"đĻĢ\",\n\tCactus: \"đĩ\",\n\tRobot: \"đ¤\",\n\tRabbit: \"đ°\",\n\tMushroom: \"đ\",\n\tChonk: \"đš\",\n};\n\nfunction speciesEmoji(species: string): string {\n\treturn SPECIES_EMOJI[species] ?? \"đŖ\";\n}\n\n// ---------------------------------------------------------------------------\n// Formatting helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Format a stats panel as a Telegram code block.\n * Shows stat bars using â and â characters.\n */\nexport function formatBuddyStats(state: BuddyState): string {\n\tconst emoji = speciesEmoji(state.species);\n\tconst shiny = state.shiny ? \" ⨠SHINY!\" : \"\";\n\tconst maxBar = 10;\n\tconst personality = state.personality.replace(/\\n/g, \" \");\n\tconst backstory = state.backstory.replace(/\\n/g, \" \");\n\tconst hatched = state.hatchedAt ? new Date(state.hatchedAt).toLocaleDateString() : \"unknown\";\n\n\tconst statLines = STAT_NAMES.map((s: string) => {\n\t\tconst value = state.stats[s as Stat];\n\t\tconst filled = Math.round((value / 100) * maxBar);\n\t\tconst bar = \"â\".repeat(filled) + \"â\".repeat(maxBar - filled);\n\t\treturn `â ${s.padEnd(12)} ${bar} ${value}`;\n\t});\n\n\treturn [\n\t\t`\\`\\`\\``,\n\t\t`ââ ${emoji} ${state.name} ${shiny} âââââââââââââââââââŽ`,\n\t\t`â Species: ${state.species}`,\n\t\t`â Rarity: ${state.rarity}`,\n\t\t`â Eyes: ${state.eyeStyle} Hat: ${state.hat || \"none\"}`,\n\t\t`â Hatched: ${hatched}`,\n\t\t`â Re-rolls: ${state.rerollCount}`,\n\t\t`â`,\n\t\t`â Stats:`,\n\t\t...statLines,\n\t\t`â`,\n\t\t`â Personality: ${personality}`,\n\t\t`â Backstory: ${backstory}`,\n\t\t`â°âââââââââââââââââââââââââââââââââââ¯`,\n\t\t`\\`\\`\\``,\n\t].join(\"\\n\");\n}\n\n/**\n * Format a buddy speech/reaction message.\n */\nexport function formatBuddySpeech(name: string, species: string, text: string): string {\n\treturn `${speciesEmoji(species)} ${name}: \"${text}\"`;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a BuddyController wired up with Telegram-specific callbacks.\n *\n * @param send â outbox send function (enqueueSend) for reliable delivery\n * @param api â grammy Api instance for chat actions and reactions\n * @param chatId â Telegram chat ID for this user\n * @param config â bot config (for bridge resolution in hatch/reroll)\n * @param userState â per-user state (for bridge resolution in hatch/reroll)\n */\nexport function createTelegramBuddyController(\n\tsend: SendFn,\n\tapi: Api,\n\tchatId: number,\n\tconfig: Config,\n\tuserState: UserState,\n): BuddyController {\n\tconst manager = new BuddyManager();\n\n\tconst callbacks: BuddyCallbacks = {\n\t\tonSpeech(text: string): void {\n\t\t\tconst name = manager.getName() ?? \"Buddy\";\n\t\t\tconst state = manager.getState();\n\t\t\tconst species = state?.species ?? \"\";\n\t\t\tsend(formatBuddySpeech(name, species, text));\n\t\t},\n\t\tonThinkingStart(): void {\n\t\t\t// Fire-and-forget typing indicator\n\t\t\tapi.sendChatAction(chatId, \"typing\").catch(() => {});\n\t\t},\n\t\tonThinkingEnd(): void {\n\t\t\t// No-op â can't cancel a chat action in Telegram\n\t\t},\n\t\tasync onHatch(_mgr): Promise<BuddyState> {\n\t\t\tconst bridge = await ensureBridgeWithSession(config, userState);\n\t\t\treturn bridge.buddyHatch();\n\t\t},\n\t\tasync onReroll(_mgr): Promise<BuddyState> {\n\t\t\tconst bridge = await ensureBridgeWithSession(config, userState);\n\t\t\treturn bridge.buddyReroll();\n\t\t},\n\t};\n\n\tconst controller = new BuddyController(manager, callbacks, {\n\t\tidleTimeoutMs: 30_000,\n\t\treactionCooldownMs: 60_000,\n\t\tcontextMaxEntries: 20,\n\t\tactivityGateMs: 7_200_000, // 2 hours\n\t\treactionsPerHour: 3,\n\t});\n\n\t// Auto-load buddy from shared buddy.json (same file TUI uses).\n\t// If a buddy exists and is visible, it'll be active immediately.\n\tcontroller.start();\n\n\treturn controller;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"buddy.js","sourceRoot":"","sources":["../../src/handlers/buddy.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Telegram buddy handler â creates and configures a BuddyController\n * with Telegram-specific rendering callbacks and formatting.\n */\n\nimport type { BuddyCallbacks, BuddyState } from \"@dreb/coding-agent/buddy\";\nimport { BuddyController, BuddyManager, STAT_NAMES, type Stat } from \"@dreb/coding-agent/buddy\";\nimport type { Api } from \"grammy\";\nimport { ensureBridgeWithSession } from \"../bridge-lifecycle.js\";\nimport type { Config } from \"../config.js\";\nimport type { UserState } from \"../types.js\";\nimport type { SendFn } from \"./events.js\";\n\n// ---------------------------------------------------------------------------\n// Species emoji mapping\n// ---------------------------------------------------------------------------\n\nexport const SPECIES_EMOJI: Record<string, string> = {\n\tDuck: \"đĻ\",\n\tGoose: \"đĒŋ\",\n\tBlob: \"đĸ\",\n\tCat: \"đą\",\n\tDragon: \"đ\",\n\tOctopus: \"đ\",\n\tOwl: \"đĻ\",\n\tPenguin: \"đ§\",\n\tTurtle: \"đĸ\",\n\tSnail: \"đ\",\n\tGhost: \"đģ\",\n\tAxolotl: \"đĢ\",\n\tCapybara: \"đĻĢ\",\n\tCactus: \"đĩ\",\n\tRobot: \"đ¤\",\n\tRabbit: \"đ°\",\n\tMushroom: \"đ\",\n\tChonk: \"đš\",\n};\n\nfunction speciesEmoji(species: string): string {\n\treturn SPECIES_EMOJI[species] ?? \"đŖ\";\n}\n\n// ---------------------------------------------------------------------------\n// Formatting helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Format a stats panel as a Telegram code block.\n * Shows stat bars using â and â characters.\n */\nexport function formatBuddyStats(state: BuddyState): string {\n\tconst emoji = speciesEmoji(state.species);\n\tconst shiny = state.shiny ? \" ⨠SHINY!\" : \"\";\n\tconst maxBar = 10;\n\tconst personality = state.personality.replace(/\\n/g, \" \");\n\tconst backstory = state.backstory.replace(/\\n/g, \" \");\n\tconst hatched = state.hatchedAt ? new Date(state.hatchedAt).toLocaleDateString() : \"unknown\";\n\n\tconst statLines = STAT_NAMES.map((s: string) => {\n\t\tconst value = state.stats[s as Stat];\n\t\tconst filled = Math.round((value / 100) * maxBar);\n\t\tconst bar = \"â\".repeat(filled) + \"â\".repeat(maxBar - filled);\n\t\treturn `â ${s.padEnd(12)} ${bar} ${value}`;\n\t});\n\n\treturn [\n\t\t`\\`\\`\\``,\n\t\t`ââ ${emoji} ${state.name} ${shiny} âââââââââââââââââââŽ`,\n\t\t`â Species: ${state.species}`,\n\t\t`â Rarity: ${state.rarity}`,\n\t\t`â Eyes: ${state.eyeStyle} Hat: ${state.hat || \"none\"}`,\n\t\t`â Hatched: ${hatched}`,\n\t\t`â Re-rolls: ${state.rerollCount}`,\n\t\t`â`,\n\t\t`â Stats:`,\n\t\t...statLines,\n\t\t`â`,\n\t\t`â Personality: ${personality}`,\n\t\t`â Backstory: ${backstory}`,\n\t\t`â°âââââââââââââââââââââââââââââââââââ¯`,\n\t\t`\\`\\`\\``,\n\t].join(\"\\n\");\n}\n\n/**\n * Format a buddy speech/reaction message.\n */\nexport function formatBuddySpeech(name: string, species: string, text: string): string {\n\treturn `${speciesEmoji(species)} ${name}: \"${text}\"`;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a BuddyController wired up with Telegram-specific callbacks.\n *\n * @param send â outbox send function (enqueueSend) for reliable delivery\n * @param api â grammy Api instance for chat actions and reactions\n * @param chatId â Telegram chat ID for this user\n * @param config â bot config (for bridge resolution in hatch/reroll)\n * @param userState â per-user state (for bridge resolution in hatch/reroll)\n */\nexport function createTelegramBuddyController(\n\tsend: SendFn,\n\tapi: Api,\n\tchatId: number,\n\tconfig: Config,\n\tuserState: UserState,\n): BuddyController {\n\tconst manager = new BuddyManager();\n\n\tconst callbacks: BuddyCallbacks = {\n\t\tonSpeech(text: string): void {\n\t\t\tconst name = manager.getName() ?? \"Buddy\";\n\t\t\tconst state = manager.getState();\n\t\t\tconst species = state?.species ?? \"\";\n\t\t\tsend(formatBuddySpeech(name, species, text));\n\t\t},\n\t\tonThinkingStart(): void {\n\t\t\t// Fire-and-forget typing indicator\n\t\t\tapi.sendChatAction(chatId, \"typing\").catch(() => {});\n\t\t},\n\t\tonThinkingEnd(): void {\n\t\t\t// No-op â can't cancel a chat action in Telegram\n\t\t},\n\t\tasync onHatch(_mgr): Promise<BuddyState> {\n\t\t\tconst bridge = await ensureBridgeWithSession(config, userState);\n\t\t\treturn bridge.buddyHatch();\n\t\t},\n\t\tasync onReroll(_mgr): Promise<BuddyState> {\n\t\t\tconst bridge = await ensureBridgeWithSession(config, userState);\n\t\t\treturn bridge.buddyReroll();\n\t\t},\n\t\tonVisibilityChange(_visible: boolean): void {\n\t\t\t// Telegram has no persistent buddy widget â reaction suppression and\n\t\t\t// re-enable already flow from the controller's `enabled` flag, which\n\t\t\t// syncHiddenState() updates from the shared buddy.json. Nothing to\n\t\t\t// mount/unmount here, so this is intentionally a no-op.\n\t\t},\n\t};\n\n\tconst controller = new BuddyController(manager, callbacks, {\n\t\tidleTimeoutMs: 30_000,\n\t\treactionCooldownMs: 60_000,\n\t\tcontextMaxEntries: 20,\n\t\tactivityGateMs: 7_200_000, // 2 hours\n\t\treactionsPerHour: 3,\n\t});\n\n\t// Auto-load buddy from shared buddy.json (same file TUI uses).\n\t// If a buddy exists and is visible, it'll be active immediately.\n\tcontroller.start();\n\n\treturn controller;\n}\n"]}
|