@ebowwa/glm-daemon 0.4.5 → 0.4.6

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.
@@ -98838,6 +98838,50 @@ function registerAllCommands(bot, memory, tools) {
98838
98838
  registerInnerthoughtsCommand(bot, memory, tools);
98839
98839
  register(bot, tools);
98840
98840
  }
98841
+ // ../channel-telegram/dist/utils/normalize.js
98842
+ function normalizeTelegramMessagingTarget(raw) {
98843
+ const trimmed = raw.trim();
98844
+ if (!trimmed)
98845
+ return;
98846
+ let normalized = trimmed;
98847
+ if (normalized.startsWith("telegram:")) {
98848
+ normalized = normalized.slice("telegram:".length).trim();
98849
+ } else if (normalized.startsWith("tg:")) {
98850
+ normalized = normalized.slice("tg:".length).trim();
98851
+ }
98852
+ if (!normalized)
98853
+ return;
98854
+ const tmeMatch = /^https?:\/\/t\.me\/([A-Za-z0-9_]+)$/i.exec(normalized) ?? /^t\.me\/([A-Za-z0-9_]+)$/i.exec(normalized);
98855
+ if (tmeMatch?.[1]) {
98856
+ normalized = `@${tmeMatch[1]}`;
98857
+ }
98858
+ if (!normalized)
98859
+ return;
98860
+ return `telegram:${normalized}`.toLowerCase();
98861
+ }
98862
+ function looksLikeTelegramTargetId(raw) {
98863
+ const trimmed = raw.trim();
98864
+ if (!trimmed)
98865
+ return false;
98866
+ if (/^(telegram|tg):/i.test(trimmed))
98867
+ return true;
98868
+ if (trimmed.startsWith("@"))
98869
+ return true;
98870
+ return /^-?\d{6,}$/.test(trimmed);
98871
+ }
98872
+ function extractRawTarget(normalized) {
98873
+ const trimmed = normalized.trim();
98874
+ if (!trimmed.startsWith("telegram:"))
98875
+ return;
98876
+ const raw = trimmed.slice("telegram:".length);
98877
+ return raw || undefined;
98878
+ }
98879
+ function isNumericIdTarget(normalized) {
98880
+ const raw = extractRawTarget(normalized);
98881
+ if (!raw)
98882
+ return false;
98883
+ return /^-?\d+$/.test(raw);
98884
+ }
98841
98885
  // ../channel-telegram/dist/index.js
98842
98886
  class TelegramChannel {
98843
98887
  id;
@@ -99202,6 +99246,41 @@ class GLMTelegramChannel extends BaseChannel {
99202
99246
  isAllowed(userId, chatId) {
99203
99247
  return this.protocolAdapter.isAllowed(userId, chatId);
99204
99248
  }
99249
+ normalizeTarget(raw) {
99250
+ return normalizeTelegramMessagingTarget(raw);
99251
+ }
99252
+ isValidTarget(raw) {
99253
+ return looksLikeTelegramTargetId(raw);
99254
+ }
99255
+ parseTargetFromInput(input) {
99256
+ const words = input.split(/\s+/);
99257
+ for (const word of words) {
99258
+ if (looksLikeTelegramTargetId(word)) {
99259
+ const normalized = normalizeTelegramMessagingTarget(word);
99260
+ if (normalized) {
99261
+ return extractRawTarget(normalized);
99262
+ }
99263
+ }
99264
+ }
99265
+ return;
99266
+ }
99267
+ async sendToTarget(target, text) {
99268
+ const normalized = normalizeTelegramMessagingTarget(target);
99269
+ if (!normalized) {
99270
+ throw new Error(`Invalid Telegram target: ${target}`);
99271
+ }
99272
+ const rawTarget = extractRawTarget(normalized);
99273
+ if (!rawTarget) {
99274
+ throw new Error(`Failed to extract target from: ${normalized}`);
99275
+ }
99276
+ let chatId;
99277
+ if (isNumericIdTarget(normalized)) {
99278
+ chatId = parseInt(rawTarget, 10);
99279
+ } else {
99280
+ throw new Error(`Username targets require resolution. Use numeric chat ID instead, or implement username resolution. Target: ${rawTarget}`);
99281
+ }
99282
+ await this.sendMessage(chatId, text);
99283
+ }
99205
99284
  }
99206
99285
  // src/channels/discord.ts
99207
99286
  var import_discord = __toESM(require_src2(), 1);
@@ -98838,6 +98838,50 @@ function registerAllCommands(bot, memory, tools) {
98838
98838
  registerInnerthoughtsCommand(bot, memory, tools);
98839
98839
  register(bot, tools);
98840
98840
  }
98841
+ // ../channel-telegram/dist/utils/normalize.js
98842
+ function normalizeTelegramMessagingTarget(raw) {
98843
+ const trimmed = raw.trim();
98844
+ if (!trimmed)
98845
+ return;
98846
+ let normalized = trimmed;
98847
+ if (normalized.startsWith("telegram:")) {
98848
+ normalized = normalized.slice("telegram:".length).trim();
98849
+ } else if (normalized.startsWith("tg:")) {
98850
+ normalized = normalized.slice("tg:".length).trim();
98851
+ }
98852
+ if (!normalized)
98853
+ return;
98854
+ const tmeMatch = /^https?:\/\/t\.me\/([A-Za-z0-9_]+)$/i.exec(normalized) ?? /^t\.me\/([A-Za-z0-9_]+)$/i.exec(normalized);
98855
+ if (tmeMatch?.[1]) {
98856
+ normalized = `@${tmeMatch[1]}`;
98857
+ }
98858
+ if (!normalized)
98859
+ return;
98860
+ return `telegram:${normalized}`.toLowerCase();
98861
+ }
98862
+ function looksLikeTelegramTargetId(raw) {
98863
+ const trimmed = raw.trim();
98864
+ if (!trimmed)
98865
+ return false;
98866
+ if (/^(telegram|tg):/i.test(trimmed))
98867
+ return true;
98868
+ if (trimmed.startsWith("@"))
98869
+ return true;
98870
+ return /^-?\d{6,}$/.test(trimmed);
98871
+ }
98872
+ function extractRawTarget(normalized) {
98873
+ const trimmed = normalized.trim();
98874
+ if (!trimmed.startsWith("telegram:"))
98875
+ return;
98876
+ const raw = trimmed.slice("telegram:".length);
98877
+ return raw || undefined;
98878
+ }
98879
+ function isNumericIdTarget(normalized) {
98880
+ const raw = extractRawTarget(normalized);
98881
+ if (!raw)
98882
+ return false;
98883
+ return /^-?\d+$/.test(raw);
98884
+ }
98841
98885
  // ../channel-telegram/dist/index.js
98842
98886
  class TelegramChannel {
98843
98887
  id;
@@ -99202,6 +99246,41 @@ class GLMTelegramChannel extends BaseChannel {
99202
99246
  isAllowed(userId, chatId) {
99203
99247
  return this.protocolAdapter.isAllowed(userId, chatId);
99204
99248
  }
99249
+ normalizeTarget(raw) {
99250
+ return normalizeTelegramMessagingTarget(raw);
99251
+ }
99252
+ isValidTarget(raw) {
99253
+ return looksLikeTelegramTargetId(raw);
99254
+ }
99255
+ parseTargetFromInput(input) {
99256
+ const words = input.split(/\s+/);
99257
+ for (const word of words) {
99258
+ if (looksLikeTelegramTargetId(word)) {
99259
+ const normalized = normalizeTelegramMessagingTarget(word);
99260
+ if (normalized) {
99261
+ return extractRawTarget(normalized);
99262
+ }
99263
+ }
99264
+ }
99265
+ return;
99266
+ }
99267
+ async sendToTarget(target, text) {
99268
+ const normalized = normalizeTelegramMessagingTarget(target);
99269
+ if (!normalized) {
99270
+ throw new Error(`Invalid Telegram target: ${target}`);
99271
+ }
99272
+ const rawTarget = extractRawTarget(normalized);
99273
+ if (!rawTarget) {
99274
+ throw new Error(`Failed to extract target from: ${normalized}`);
99275
+ }
99276
+ let chatId;
99277
+ if (isNumericIdTarget(normalized)) {
99278
+ chatId = parseInt(rawTarget, 10);
99279
+ } else {
99280
+ throw new Error(`Username targets require resolution. Use numeric chat ID instead, or implement username resolution. Target: ${rawTarget}`);
99281
+ }
99282
+ await this.sendMessage(chatId, text);
99283
+ }
99205
99284
  }
99206
99285
  // src/channels/discord.ts
99207
99286
  var import_discord = __toESM(require_src2(), 1);
package/dist/index.js CHANGED
@@ -99032,6 +99032,50 @@ function registerAllCommands(bot, memory, tools) {
99032
99032
  registerInnerthoughtsCommand(bot, memory, tools);
99033
99033
  register(bot, tools);
99034
99034
  }
99035
+ // ../channel-telegram/dist/utils/normalize.js
99036
+ function normalizeTelegramMessagingTarget(raw) {
99037
+ const trimmed = raw.trim();
99038
+ if (!trimmed)
99039
+ return;
99040
+ let normalized = trimmed;
99041
+ if (normalized.startsWith("telegram:")) {
99042
+ normalized = normalized.slice("telegram:".length).trim();
99043
+ } else if (normalized.startsWith("tg:")) {
99044
+ normalized = normalized.slice("tg:".length).trim();
99045
+ }
99046
+ if (!normalized)
99047
+ return;
99048
+ const tmeMatch = /^https?:\/\/t\.me\/([A-Za-z0-9_]+)$/i.exec(normalized) ?? /^t\.me\/([A-Za-z0-9_]+)$/i.exec(normalized);
99049
+ if (tmeMatch?.[1]) {
99050
+ normalized = `@${tmeMatch[1]}`;
99051
+ }
99052
+ if (!normalized)
99053
+ return;
99054
+ return `telegram:${normalized}`.toLowerCase();
99055
+ }
99056
+ function looksLikeTelegramTargetId(raw) {
99057
+ const trimmed = raw.trim();
99058
+ if (!trimmed)
99059
+ return false;
99060
+ if (/^(telegram|tg):/i.test(trimmed))
99061
+ return true;
99062
+ if (trimmed.startsWith("@"))
99063
+ return true;
99064
+ return /^-?\d{6,}$/.test(trimmed);
99065
+ }
99066
+ function extractRawTarget(normalized) {
99067
+ const trimmed = normalized.trim();
99068
+ if (!trimmed.startsWith("telegram:"))
99069
+ return;
99070
+ const raw = trimmed.slice("telegram:".length);
99071
+ return raw || undefined;
99072
+ }
99073
+ function isNumericIdTarget(normalized) {
99074
+ const raw = extractRawTarget(normalized);
99075
+ if (!raw)
99076
+ return false;
99077
+ return /^-?\d+$/.test(raw);
99078
+ }
99035
99079
  // ../channel-telegram/dist/index.js
99036
99080
  class TelegramChannel {
99037
99081
  id;
@@ -99396,6 +99440,41 @@ class GLMTelegramChannel extends BaseChannel {
99396
99440
  isAllowed(userId, chatId) {
99397
99441
  return this.protocolAdapter.isAllowed(userId, chatId);
99398
99442
  }
99443
+ normalizeTarget(raw) {
99444
+ return normalizeTelegramMessagingTarget(raw);
99445
+ }
99446
+ isValidTarget(raw) {
99447
+ return looksLikeTelegramTargetId(raw);
99448
+ }
99449
+ parseTargetFromInput(input) {
99450
+ const words = input.split(/\s+/);
99451
+ for (const word of words) {
99452
+ if (looksLikeTelegramTargetId(word)) {
99453
+ const normalized = normalizeTelegramMessagingTarget(word);
99454
+ if (normalized) {
99455
+ return extractRawTarget(normalized);
99456
+ }
99457
+ }
99458
+ }
99459
+ return;
99460
+ }
99461
+ async sendToTarget(target, text) {
99462
+ const normalized = normalizeTelegramMessagingTarget(target);
99463
+ if (!normalized) {
99464
+ throw new Error(`Invalid Telegram target: ${target}`);
99465
+ }
99466
+ const rawTarget = extractRawTarget(normalized);
99467
+ if (!rawTarget) {
99468
+ throw new Error(`Failed to extract target from: ${normalized}`);
99469
+ }
99470
+ let chatId;
99471
+ if (isNumericIdTarget(normalized)) {
99472
+ chatId = parseInt(rawTarget, 10);
99473
+ } else {
99474
+ throw new Error(`Username targets require resolution. Use numeric chat ID instead, or implement username resolution. Target: ${rawTarget}`);
99475
+ }
99476
+ await this.sendMessage(chatId, text);
99477
+ }
99399
99478
  }
99400
99479
  // src/channels/discord.ts
99401
99480
  var import_discord = __toESM(require_src2(), 1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ebowwa/glm-daemon",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
4
4
  "description": "Autonomous GLM 4.7 daemon with hooks, tools, teammates, and communication channels (Telegram, Discord)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -12,12 +12,27 @@ import {
12
12
  import {
13
13
  TelegramChannel as TelegramProtocolAdapter,
14
14
  type TelegramConfig as ProtocolConfig,
15
+ // Telegram target normalization utilities
16
+ normalizeTelegramMessagingTarget,
17
+ looksLikeTelegramTargetId,
18
+ extractRawTarget,
19
+ isUsernameTarget,
20
+ isNumericIdTarget,
15
21
  } from "@ebowwa/channel-telegram";
16
22
  import {
17
23
  BaseChannel,
18
24
  type GLMChannelConfig,
19
25
  } from "./base.js";
20
26
 
27
+ // Re-export normalization utilities for consumers
28
+ export {
29
+ normalizeTelegramMessagingTarget,
30
+ looksLikeTelegramTargetId,
31
+ extractRawTarget,
32
+ isUsernameTarget,
33
+ isNumericIdTarget,
34
+ };
35
+
21
36
  // ============================================================
22
37
  // TELEGRAM CHANNEL CONFIG
23
38
  // ============================================================
@@ -163,6 +178,96 @@ export class GLMTelegramChannel extends BaseChannel {
163
178
  isAllowed(userId?: number, chatId?: number): boolean {
164
179
  return this.protocolAdapter.isAllowed(userId, chatId);
165
180
  }
181
+
182
+ // ============================================================
183
+ // Target Normalization Helpers
184
+ // ============================================================
185
+
186
+ /**
187
+ * Normalize a Telegram target (username, URL, or ID) to standard format.
188
+ *
189
+ * @param raw - Raw input (@username, t.me/user, 123456, etc.)
190
+ * @returns Normalized target or undefined if invalid
191
+ *
192
+ * @example
193
+ * channel.normalizeTarget("@durov") // "telegram:@durov"
194
+ * channel.normalizeTarget("t.me/durov") // "telegram:@durov"
195
+ * channel.normalizeTarget("123456") // "telegram:123456"
196
+ */
197
+ normalizeTarget(raw: string): string | undefined {
198
+ return normalizeTelegramMessagingTarget(raw);
199
+ }
200
+
201
+ /**
202
+ * Check if a string looks like a Telegram target.
203
+ *
204
+ * @param raw - Raw input string
205
+ * @returns true if it looks like a Telegram target
206
+ */
207
+ isValidTarget(raw: string): boolean {
208
+ return looksLikeTelegramTargetId(raw);
209
+ }
210
+
211
+ /**
212
+ * Parse a target from user input and extract the usable form.
213
+ *
214
+ * @param input - User input like "send to @user" or "dm t.me/user"
215
+ * @returns Extracted raw target (@username or numeric ID) or undefined
216
+ *
217
+ * @example
218
+ * channel.parseTargetFromInput("send to @durov") // "@durov"
219
+ * channel.parseTargetFromInput("dm 123456") // "123456"
220
+ */
221
+ parseTargetFromInput(input: string): string | undefined {
222
+ const words = input.split(/\s+/);
223
+ for (const word of words) {
224
+ if (looksLikeTelegramTargetId(word)) {
225
+ const normalized = normalizeTelegramMessagingTarget(word);
226
+ if (normalized) {
227
+ return extractRawTarget(normalized);
228
+ }
229
+ }
230
+ }
231
+ return undefined;
232
+ }
233
+
234
+ /**
235
+ * Send a message to a target (username or chat ID).
236
+ *
237
+ * @param target - Telegram target (@username, numeric ID, or normalized format)
238
+ * @param text - Message text
239
+ *
240
+ * @example
241
+ * await channel.sendToTarget("@durov", "Hello!")
242
+ * await channel.sendToTarget("123456", "Hello!")
243
+ */
244
+ async sendToTarget(target: string, text: string): Promise<void> {
245
+ const normalized = normalizeTelegramMessagingTarget(target);
246
+ if (!normalized) {
247
+ throw new Error(`Invalid Telegram target: ${target}`);
248
+ }
249
+
250
+ const rawTarget = extractRawTarget(normalized);
251
+ if (!rawTarget) {
252
+ throw new Error(`Failed to extract target from: ${normalized}`);
253
+ }
254
+
255
+ // Parse chat ID (numeric or resolve username)
256
+ let chatId: number;
257
+
258
+ if (isNumericIdTarget(normalized)) {
259
+ chatId = parseInt(rawTarget, 10);
260
+ } else {
261
+ // Username target - need to resolve via bot API
262
+ // Note: This requires the bot to have seen the user/channel before
263
+ // For now, we'll try direct message with username (may fail if not cached)
264
+ throw new Error(
265
+ `Username targets require resolution. Use numeric chat ID instead, or implement username resolution. Target: ${rawTarget}`
266
+ );
267
+ }
268
+
269
+ await this.sendMessage(chatId, text);
270
+ }
166
271
  }
167
272
 
168
273
  // ============================================================