@imadtg/tgsm 0.0.5 → 0.0.7

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/dist/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { createInterface as createInterface2 } from "readline/promises";
5
+ import { once } from "events";
5
6
  import process2 from "process";
6
7
  import { Command } from "commander";
7
8
 
@@ -532,8 +533,15 @@ function previewText(text, limit = 80) {
532
533
  import path3 from "path";
533
534
  import { createInterface } from "readline/promises";
534
535
  import { readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
535
- import { TelegramClient, getMarkedPeerId } from "@mtcute/node";
536
+ import { TelegramClient, getMarkedPeerId, networkMiddlewares } from "@mtcute/node";
537
+ var TELEGRAM_FLOOD_WAIT_MAX_MS = 3e4;
538
+ var TELEGRAM_CONNECT_TIMEOUT_MS = 3e4;
539
+ var TELEGRAM_RPC_TIMEOUT_MS = 45e3;
540
+ var TELEGRAM_DESTROY_TIMEOUT_MS = 5e3;
536
541
  var TelegramSource = class {
542
+ constructor(options = {}) {
543
+ this.options = options;
544
+ }
537
545
  backend = "telegram";
538
546
  async authLogin(accountDir, input) {
539
547
  const config = {
@@ -542,12 +550,14 @@ var TelegramSource = class {
542
550
  phone: input.phone
543
551
  };
544
552
  await saveTelegramConfig(accountDir, config);
545
- const client = createTelegramClient(accountDir, config);
553
+ this.debug("auth.config_saved", { account_dir: accountDir, phone: input.phone });
554
+ const client = createTelegramClient(accountDir, config, this.options);
546
555
  const rl = createInterface({
547
556
  input: process.stdin,
548
557
  output: process.stderr
549
558
  });
550
559
  try {
560
+ this.debug("auth.start.begin", { account_dir: accountDir });
551
561
  const user = await client.start({
552
562
  phone: input.phone,
553
563
  code: async () => {
@@ -567,6 +577,7 @@ var TelegramSource = class {
567
577
  `);
568
578
  }
569
579
  });
580
+ this.debug("auth.start.done", { user_id: String(user.id), display_name: user.displayName });
570
581
  return {
571
582
  authenticated: true,
572
583
  user: {
@@ -581,8 +592,10 @@ var TelegramSource = class {
581
592
  retryable: false
582
593
  });
583
594
  } finally {
595
+ this.debug("auth.cleanup.begin");
584
596
  rl.close();
585
- await destroyClientQuietly(client);
597
+ const cleanup = await destroyClientQuietly(client);
598
+ this.debug("auth.cleanup.done", { status: cleanup });
586
599
  }
587
600
  }
588
601
  async authStatus(accountDir) {
@@ -593,10 +606,16 @@ var TelegramSource = class {
593
606
  user: null
594
607
  };
595
608
  }
596
- const client = createTelegramClient(accountDir, config);
609
+ const client = createTelegramClient(accountDir, config, this.options);
597
610
  try {
598
- await client.start({});
611
+ this.debug("auth_status.start.begin", { account_dir: accountDir });
612
+ await withTimeout(
613
+ client.start({}),
614
+ TELEGRAM_CONNECT_TIMEOUT_MS,
615
+ "Timed out while connecting to Telegram."
616
+ );
599
617
  const me = await client.getMe();
618
+ this.debug("auth_status.start.done", { user_id: String(me.id), display_name: me.displayName });
600
619
  return {
601
620
  authenticated: true,
602
621
  user: {
@@ -605,12 +624,15 @@ var TelegramSource = class {
605
624
  }
606
625
  };
607
626
  } catch {
627
+ this.debug("auth_status.start.failed");
608
628
  return {
609
629
  authenticated: false,
610
630
  user: null
611
631
  };
612
632
  } finally {
613
- await destroyClientQuietly(client);
633
+ this.debug("auth_status.cleanup.begin");
634
+ const cleanup = await destroyClientQuietly(client);
635
+ this.debug("auth_status.cleanup.done", { status: cleanup });
614
636
  }
615
637
  }
616
638
  async sync(accountDir) {
@@ -623,18 +645,36 @@ var TelegramSource = class {
623
645
  suggestion: "Run `tgsm auth login` first."
624
646
  });
625
647
  }
626
- const client = createTelegramClient(accountDir, config);
648
+ const client = createTelegramClient(accountDir, config, this.options);
627
649
  try {
628
- const me = await client.start({});
650
+ this.debug("sync.start.begin", { account_dir: accountDir });
651
+ const me = await withTimeout(
652
+ client.start({}),
653
+ TELEGRAM_CONNECT_TIMEOUT_MS,
654
+ "Timed out while connecting to Telegram."
655
+ );
656
+ this.debug("sync.start.done", { user_id: String(me.id), display_name: me.displayName });
629
657
  const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
630
- const dialogsResponse = await client.call({
631
- _: "messages.getSavedDialogs",
632
- excludePinned: false,
633
- offsetDate: 0,
634
- offsetId: 0,
635
- offsetPeer: { _: "inputPeerEmpty" },
636
- limit: 1e3,
637
- hash: 0
658
+ this.debug("sync.dialogs.begin");
659
+ const dialogsResponse = await withTimeout(
660
+ client.call({
661
+ _: "messages.getSavedDialogs",
662
+ excludePinned: false,
663
+ offsetDate: 0,
664
+ offsetId: 0,
665
+ offsetPeer: { _: "inputPeerEmpty" },
666
+ limit: 1e3,
667
+ hash: 0
668
+ }, {
669
+ maxRetryCount: 5,
670
+ floodSleepThreshold: TELEGRAM_FLOOD_WAIT_MAX_MS
671
+ }),
672
+ TELEGRAM_RPC_TIMEOUT_MS,
673
+ "Timed out while fetching saved dialogs from Telegram."
674
+ );
675
+ this.debug("sync.dialogs.done", {
676
+ result_type: dialogsResponse._,
677
+ dialog_count: "dialogs" in dialogsResponse && Array.isArray(dialogsResponse.dialogs) ? dialogsResponse.dialogs.length : 0
638
678
  });
639
679
  if (dialogsResponse._ === "messages.savedDialogsNotModified") {
640
680
  return {
@@ -661,7 +701,17 @@ var TelegramSource = class {
661
701
  const savedPeerId = savedPeerIdFromPeer(dialog.peer, lookup.selfUserId);
662
702
  const peerInput = await client.resolvePeer(getMarkedPeerId(dialog.peer));
663
703
  const title = peerTitle(dialog.peer, lookup);
664
- const messages2 = await fetchSavedHistory(client, peerInput, lookup);
704
+ this.debug("sync.dialog_history.begin", {
705
+ saved_peer_id: savedPeerId,
706
+ title,
707
+ top_message_id: dialog.topMessage ?? null
708
+ });
709
+ const messages2 = await fetchSavedHistory(client, peerInput, lookup, this.options);
710
+ this.debug("sync.dialog_history.done", {
711
+ saved_peer_id: savedPeerId,
712
+ title,
713
+ message_count: messages2.length
714
+ });
665
715
  const topMessage = messages2.find((message) => message.message_id === dialog.topMessage) ?? messages2[0] ?? null;
666
716
  dialogs.push({
667
717
  saved_peer_id: savedPeerId,
@@ -690,46 +740,113 @@ var TelegramSource = class {
690
740
  synced_at: syncedAt
691
741
  };
692
742
  } catch (error) {
743
+ this.debug("sync.failed", {
744
+ message: error instanceof Error ? error.message : "Unknown sync error"
745
+ });
693
746
  throw new TgsmError({
694
747
  code: "TELEGRAM_SYNC_FAILED",
695
748
  message: error instanceof Error ? error.message : "Telegram sync failed.",
696
749
  retryable: true
697
750
  });
698
751
  } finally {
699
- await destroyClientQuietly(client);
752
+ this.debug("sync.cleanup.begin");
753
+ const cleanup = await destroyClientQuietly(client);
754
+ this.debug("sync.cleanup.done", { status: cleanup });
700
755
  }
701
756
  }
757
+ debug(event, fields = {}) {
758
+ if (!this.options.debug) return;
759
+ this.options.logger?.(event, fields);
760
+ }
702
761
  };
703
- function createTelegramClient(accountDir, config) {
704
- return new TelegramClient({
762
+ function createTelegramClient(accountDir, config, options) {
763
+ const client = new TelegramClient({
705
764
  apiId: config.apiId,
706
765
  apiHash: config.apiHash,
707
766
  storage: path3.join(accountDir, "mtcute-session"),
708
- logLevel: 0
767
+ logLevel: 0,
768
+ network: {
769
+ middlewares: networkMiddlewares.basic({
770
+ floodWaiter: {
771
+ maxWait: TELEGRAM_FLOOD_WAIT_MAX_MS,
772
+ maxRetries: 5,
773
+ onBeforeWait: (ctx, seconds) => {
774
+ options.logger?.("telegram.flood_wait", {
775
+ seconds,
776
+ method: ctx.request._
777
+ });
778
+ }
779
+ }
780
+ })
781
+ }
709
782
  });
783
+ if (options.debug) {
784
+ client.onConnectionState.add((state) => {
785
+ options.logger?.("telegram.connection_state", { state });
786
+ });
787
+ client.onError.add((error) => {
788
+ options.logger?.("telegram.client_error", {
789
+ message: error.message,
790
+ name: error.name
791
+ });
792
+ });
793
+ }
794
+ return client;
710
795
  }
711
796
  async function destroyClientQuietly(client) {
712
797
  try {
713
- await client.destroy();
714
- } catch {
798
+ await withTimeout(
799
+ client.destroy(),
800
+ TELEGRAM_DESTROY_TIMEOUT_MS,
801
+ "Timed out while closing Telegram client."
802
+ );
803
+ return "destroyed";
804
+ } catch (error) {
805
+ if (error instanceof Error && error.message === "Timed out while closing Telegram client.") {
806
+ return "timed_out";
807
+ }
808
+ return "failed";
715
809
  }
716
810
  }
717
- async function fetchSavedHistory(client, peer, lookup) {
811
+ async function fetchSavedHistory(client, peer, lookup, options) {
718
812
  let offsetId = 0;
719
813
  let offsetDate = 0;
720
814
  const records = /* @__PURE__ */ new Map();
815
+ let pages = 0;
721
816
  while (true) {
722
- const history = await client.call({
723
- _: "messages.getSavedHistory",
724
- peer,
725
- offsetId,
726
- offsetDate,
727
- addOffset: 0,
728
- limit: 100,
729
- maxId: 0,
730
- minId: 0,
731
- hash: 0
732
- });
817
+ pages += 1;
818
+ if (options.debug) {
819
+ options.logger?.("sync.dialog_history.page.begin", {
820
+ page: pages,
821
+ offset_id: offsetId,
822
+ offset_date: offsetDate
823
+ });
824
+ }
825
+ const history = await withTimeout(
826
+ client.call({
827
+ _: "messages.getSavedHistory",
828
+ peer,
829
+ offsetId,
830
+ offsetDate,
831
+ addOffset: 0,
832
+ limit: 100,
833
+ maxId: 0,
834
+ minId: 0,
835
+ hash: 0
836
+ }, {
837
+ maxRetryCount: 5,
838
+ floodSleepThreshold: TELEGRAM_FLOOD_WAIT_MAX_MS
839
+ }),
840
+ TELEGRAM_RPC_TIMEOUT_MS,
841
+ "Timed out while fetching saved history from Telegram."
842
+ );
843
+ if (options.debug) {
844
+ options.logger?.("sync.dialog_history.page.done", {
845
+ page: pages,
846
+ result_type: history._,
847
+ message_count: "messages" in history ? history.messages.length : 0
848
+ });
849
+ }
733
850
  if (!("messages" in history)) {
734
851
  break;
735
852
  }
@@ -767,7 +884,7 @@ function normalizeRawMessage(raw, lookup) {
767
884
  date: new Date(raw.date * 1e3).toISOString(),
768
885
  edit_date: editDate ? new Date(editDate * 1e3).toISOString() : null,
769
886
  text,
770
- from_self: peerIsSelf("fromId" in raw ? raw.fromId : null, lookup.selfUserId),
887
+ from_self: ("out" in raw ? Boolean(raw.out) : false) || peerIsSelf("fromId" in raw ? raw.fromId : null, lookup.selfUserId) || savedPeerId === "self" && !fwdFrom,
771
888
  forwarded: Boolean(fwdFrom),
772
889
  forward_origin: fwdFrom ? forwardOriginFromHeader(fwdFrom, lookup) : null,
773
890
  reply_to_message_id: replyHeader?.replyToMsgId ?? null,
@@ -884,6 +1001,23 @@ async function saveTelegramConfig(accountDir, config) {
884
1001
  "utf8"
885
1002
  );
886
1003
  }
1004
+ async function withTimeout(promise, timeoutMs, message) {
1005
+ let timer;
1006
+ try {
1007
+ return await Promise.race([
1008
+ promise,
1009
+ new Promise((_, reject) => {
1010
+ timer = setTimeout(() => {
1011
+ reject(new Error(message));
1012
+ }, timeoutMs);
1013
+ })
1014
+ ]);
1015
+ } finally {
1016
+ if (timer) {
1017
+ clearTimeout(timer);
1018
+ }
1019
+ }
1020
+ }
887
1021
 
888
1022
  // src/format.ts
889
1023
  function formatSyncResult(result) {
@@ -981,7 +1115,7 @@ function renderNode(node, prefix, isLast, lines) {
981
1115
  // package.json
982
1116
  var package_default = {
983
1117
  name: "@imadtg/tgsm",
984
- version: "0.0.5",
1118
+ version: "0.0.7",
985
1119
  type: "module",
986
1120
  description: "A retrieval-first CLI for navigating Telegram Saved Messages as structured, agent-readable context.",
987
1121
  license: "MIT",
@@ -1030,7 +1164,7 @@ var package_default = {
1030
1164
 
1031
1165
  // src/index.ts
1032
1166
  var program = new Command();
1033
- program.name("tgsm").description("Retrieval-first Telegram Saved Messages CLI").version(package_default.version, "-V, --version", "Display the tgsm version").option("--json", "Emit JSON instead of default text output").option("--backend <backend>", "telegram or fixture", "telegram").option("--fixture <path>", "Fixture path for the fixture backend").option("--home <path>", "Override TGSM home directory").option("--account <name>", "Account namespace", "default");
1167
+ program.name("tgsm").description("Retrieval-first Telegram Saved Messages CLI").version(package_default.version, "-V, --version", "Display the tgsm version").option("--json", "Emit JSON instead of default text output").option("--debug", "Emit debug telemetry to stderr").option("--backend <backend>", "telegram or fixture", "telegram").option("--fixture <path>", "Fixture path for the fixture backend").option("--home <path>", "Override TGSM home directory").option("--account <name>", "Account namespace", "default");
1034
1168
  program.command("auth").description("Telegram auth commands").addCommand(
1035
1169
  new Command("login").action(async (_, command) => {
1036
1170
  await withService(command.optsWithGlobals(), async (service, options) => {
@@ -1117,29 +1251,11 @@ program.command("threads").description("Thread commands").addCommand(
1117
1251
  });
1118
1252
  })
1119
1253
  );
1120
- program.parseAsync(process2.argv).catch((error) => {
1121
- const tgsmError = error instanceof TgsmError ? error : new TgsmError({
1122
- code: "UNEXPECTED_ERROR",
1123
- message: error instanceof Error ? error.message : "Unexpected error",
1124
- retryable: false
1125
- });
1126
- const options = program.opts();
1127
- if (options.json) {
1128
- process2.stdout.write(`${JSON.stringify(tgsmError.toJSON(), null, 2)}
1129
- `);
1130
- } else {
1131
- process2.stderr.write(`error: ${tgsmError.message}
1132
- `);
1133
- if (tgsmError.suggestion) {
1134
- process2.stderr.write(`suggestion: ${tgsmError.suggestion}
1135
- `);
1136
- }
1137
- }
1138
- process2.exitCode = errorCode(tgsmError.code);
1139
- });
1254
+ void main();
1140
1255
  async function withService(options, fn) {
1141
1256
  const normalized = {
1142
1257
  json: Boolean(options.json),
1258
+ debug: Boolean(options.debug),
1143
1259
  backend: options.backend ?? "telegram",
1144
1260
  fixture: options.fixture ?? "",
1145
1261
  home: options.home ?? "",
@@ -1153,6 +1269,13 @@ async function withService(options, fn) {
1153
1269
  homeDir: normalized.home || void 0,
1154
1270
  account: normalized.account
1155
1271
  });
1272
+ debugLog(normalized, "cli.service.setup", {
1273
+ backend: normalized.backend,
1274
+ account: normalized.account,
1275
+ cache_path: cachePath,
1276
+ home: normalized.home || void 0,
1277
+ fixture: normalized.fixture || void 0
1278
+ });
1156
1279
  const source = resolveSource(normalized);
1157
1280
  const service = new TgsmService({
1158
1281
  cachePath,
@@ -1171,7 +1294,12 @@ function resolveSource(options) {
1171
1294
  }
1172
1295
  return new FixtureSource(options.fixture);
1173
1296
  }
1174
- return new TelegramSource();
1297
+ return new TelegramSource({
1298
+ debug: options.debug,
1299
+ logger: (event, fields = {}) => {
1300
+ debugLog(options, event, fields);
1301
+ }
1302
+ });
1175
1303
  }
1176
1304
  function emit(value, options, format) {
1177
1305
  if (options.json) {
@@ -1187,4 +1315,58 @@ function errorCode(code) {
1187
1315
  if (code.includes("SYNC") || code.includes("TELEGRAM")) return 2;
1188
1316
  return 1;
1189
1317
  }
1318
+ function debugLog(options, event, fields = {}) {
1319
+ if (!options.debug) return;
1320
+ const detail = Object.entries(fields).filter(([, value]) => value !== void 0).map(([key, value]) => `${key}=${formatDebugValue(value)}`).join(" ");
1321
+ process2.stderr.write(
1322
+ `[tgsm debug ${(/* @__PURE__ */ new Date()).toISOString()}] ${event}${detail ? ` ${detail}` : ""}
1323
+ `
1324
+ );
1325
+ }
1326
+ function formatDebugValue(value) {
1327
+ if (typeof value === "string") return JSON.stringify(value);
1328
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
1329
+ if (value === null) return "null";
1330
+ try {
1331
+ return JSON.stringify(value);
1332
+ } catch {
1333
+ return String(value);
1334
+ }
1335
+ }
1336
+ async function main() {
1337
+ let exitCode = 0;
1338
+ try {
1339
+ await program.parseAsync(process2.argv);
1340
+ } catch (error) {
1341
+ const tgsmError = error instanceof TgsmError ? error : new TgsmError({
1342
+ code: "UNEXPECTED_ERROR",
1343
+ message: error instanceof Error ? error.message : "Unexpected error",
1344
+ retryable: false
1345
+ });
1346
+ const options = program.opts();
1347
+ if (options.json) {
1348
+ process2.stdout.write(`${JSON.stringify(tgsmError.toJSON(), null, 2)}
1349
+ `);
1350
+ } else {
1351
+ process2.stderr.write(`error: ${tgsmError.message}
1352
+ `);
1353
+ if (tgsmError.suggestion) {
1354
+ process2.stderr.write(`suggestion: ${tgsmError.suggestion}
1355
+ `);
1356
+ }
1357
+ }
1358
+ exitCode = errorCode(tgsmError.code);
1359
+ }
1360
+ await flushStreams();
1361
+ process2.exit(exitCode);
1362
+ }
1363
+ async function flushStreams() {
1364
+ await Promise.all([flushStream(process2.stdout), flushStream(process2.stderr)]);
1365
+ }
1366
+ async function flushStream(stream) {
1367
+ if (!stream.writableNeedDrain) {
1368
+ return;
1369
+ }
1370
+ await once(stream, "drain");
1371
+ }
1190
1372
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../../core/src/errors.ts","../../core/src/paths.ts","../../core/src/cache.ts","../../core/src/fixture.ts","../../core/src/service.ts","../../core/src/telegram.ts","../src/format.ts","../package.json"],"sourcesContent":["import { createInterface } from 'node:readline/promises'\nimport process from 'node:process'\nimport { Command } from 'commander'\nimport {\n FixtureSource,\n TgsmError,\n TgsmService,\n TelegramSource,\n ensureAccountDir,\n getCachePath,\n type GetMessageOptions,\n type ListMessagesOptions,\n type TgsmSourceAdapter,\n} from '@tgsm/core'\nimport {\n formatAuthStatus,\n formatContextBundle,\n formatMessagesPage,\n formatSavedDialogs,\n formatSyncResult,\n formatThread,\n} from './format'\nimport pkg from '../package.json'\n\ninterface GlobalOptions {\n json?: boolean\n backend?: 'telegram' | 'fixture'\n fixture?: string\n home?: string\n account?: string\n}\n\nconst program = new Command()\n\nprogram\n .name('tgsm')\n .description('Retrieval-first Telegram Saved Messages CLI')\n .version(pkg.version, '-V, --version', 'Display the tgsm version')\n .option('--json', 'Emit JSON instead of default text output')\n .option('--backend <backend>', 'telegram or fixture', 'telegram')\n .option('--fixture <path>', 'Fixture path for the fixture backend')\n .option('--home <path>', 'Override TGSM home directory')\n .option('--account <name>', 'Account namespace', 'default')\n\nprogram\n .command('auth')\n .description('Telegram auth commands')\n .addCommand(\n new Command('login').action(async (_, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n if (options.backend !== 'telegram') {\n throw new TgsmError({\n code: 'AUTH_UNSUPPORTED',\n message: 'Auth login is only supported with the telegram backend.',\n retryable: false,\n })\n }\n\n const rl = createInterface({\n input: process.stdin,\n output: process.stderr,\n })\n\n try {\n const apiId = Number(await rl.question('API ID: '))\n const apiHash = await rl.question('API Hash: ')\n const phone = await rl.question('Phone: ')\n\n const result = await service.authLogin({\n apiId,\n apiHash,\n phone,\n })\n\n emit(result, options, formatAuthStatus)\n } finally {\n rl.close()\n }\n })\n }),\n )\n .addCommand(\n new Command('status').action(async (_, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n emit(await service.authStatus(), options, formatAuthStatus)\n })\n }),\n )\n\nprogram.command('sync').action(async (_, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n emit(await service.sync(), options, formatSyncResult)\n })\n})\n\nprogram\n .command('saved-dialogs')\n .description('Saved dialog commands')\n .addCommand(\n new Command('list').action(async (_, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n emit(await service.listSavedDialogs(), options, formatSavedDialogs)\n })\n }),\n )\n\nconst messages = program.command('messages').description('Message commands')\n\nmessages\n .command('list')\n .option('--dialog <savedPeerId>')\n .option('--search <query>')\n .option('--limit <number>', 'Page size', '20')\n .option('--cursor <cursor>')\n .action(async (commandOptions, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n const result = await service.listMessages({\n dialog: commandOptions.dialog,\n search: commandOptions.search,\n limit: Number(commandOptions.limit),\n cursor: commandOptions.cursor,\n } satisfies ListMessagesOptions)\n emit(result, options, formatMessagesPage)\n })\n })\n\nmessages\n .command('get')\n .argument('<id>')\n .option('--dialog <savedPeerId>')\n .action(async (id, commandOptions, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n const result = await service.getMessage(Number(id), {\n dialog: commandOptions.dialog,\n } satisfies GetMessageOptions)\n emit(result, options, formatContextBundle)\n })\n })\n\nmessages\n .command('context')\n .argument('<id>')\n .option('--dialog <savedPeerId>')\n .action(async (id, commandOptions, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n const result = await service.getContext(Number(id), {\n dialog: commandOptions.dialog,\n } satisfies GetMessageOptions)\n emit(result, options, formatContextBundle)\n })\n })\n\nprogram\n .command('threads')\n .description('Thread commands')\n .addCommand(\n new Command('inspect')\n .argument('<id>')\n .option('--dialog <savedPeerId>')\n .action(async (id, commandOptions, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n const result = await service.inspectThread(Number(id), {\n dialog: commandOptions.dialog,\n } satisfies GetMessageOptions)\n emit(result, options, formatThread)\n })\n }),\n )\n\nprogram.parseAsync(process.argv).catch((error: unknown) => {\n const tgsmError =\n error instanceof TgsmError\n ? error\n : new TgsmError({\n code: 'UNEXPECTED_ERROR',\n message: error instanceof Error ? error.message : 'Unexpected error',\n retryable: false,\n })\n\n const options = program.opts<GlobalOptions>()\n if (options.json) {\n process.stdout.write(`${JSON.stringify(tgsmError.toJSON(), null, 2)}\\n`)\n } else {\n process.stderr.write(`error: ${tgsmError.message}\\n`)\n if (tgsmError.suggestion) {\n process.stderr.write(`suggestion: ${tgsmError.suggestion}\\n`)\n }\n }\n\n process.exitCode = errorCode(tgsmError.code)\n})\n\nasync function withService(\n options: GlobalOptions,\n fn: (service: TgsmService, options: Required<GlobalOptions>) => Promise<void>,\n): Promise<void> {\n const normalized: Required<GlobalOptions> = {\n json: Boolean(options.json),\n backend: (options.backend ?? 'telegram') as 'telegram' | 'fixture',\n fixture: options.fixture ?? '',\n home: options.home ?? '',\n account: options.account ?? 'default',\n }\n\n await ensureAccountDir({\n homeDir: normalized.home || undefined,\n account: normalized.account,\n })\n\n const cachePath = getCachePath({\n homeDir: normalized.home || undefined,\n account: normalized.account,\n })\n\n const source = resolveSource(normalized)\n const service = new TgsmService({\n cachePath,\n source,\n })\n\n await fn(service, normalized)\n}\n\nfunction resolveSource(options: Required<GlobalOptions>): TgsmSourceAdapter {\n if (options.backend === 'fixture') {\n if (!options.fixture) {\n throw new TgsmError({\n code: 'FIXTURE_REQUIRED',\n message: 'The fixture backend requires --fixture <path>.',\n retryable: false,\n })\n }\n return new FixtureSource(options.fixture)\n }\n\n return new TelegramSource()\n}\n\nfunction emit<T>(\n value: T,\n options: Required<GlobalOptions>,\n format?: (value: T) => string,\n): void {\n if (options.json) {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`)\n return\n }\n\n process.stdout.write(`${format ? format(value) : String(value)}\\n`)\n}\n\nfunction errorCode(code: string): number {\n if (code.startsWith('AUTH')) return 3\n if (code.includes('SYNC') || code.includes('TELEGRAM')) return 2\n return 1\n}\n","import type { OperationErrorShape } from './types'\n\nexport class TgsmError extends Error {\n readonly code: string\n readonly retryable: boolean\n readonly suggestion?: string\n\n constructor(shape: OperationErrorShape) {\n super(shape.message)\n this.name = 'TgsmError'\n this.code = shape.code\n this.retryable = shape.retryable\n this.suggestion = shape.suggestion\n }\n\n toJSON(): OperationErrorShape {\n return {\n code: this.code,\n message: this.message,\n retryable: this.retryable,\n suggestion: this.suggestion,\n }\n }\n}\n\nexport function asTgsmError(error: unknown): TgsmError {\n if (error instanceof TgsmError) {\n return error\n }\n\n if (error instanceof Error) {\n return new TgsmError({\n code: 'UNEXPECTED_ERROR',\n message: error.message,\n retryable: false,\n })\n }\n\n return new TgsmError({\n code: 'UNEXPECTED_ERROR',\n message: 'Unexpected error',\n retryable: false,\n })\n}\n","import os from 'node:os'\nimport path from 'node:path'\nimport { mkdir } from 'node:fs/promises'\n\nexport interface PathOptions {\n homeDir?: string\n account?: string\n}\n\nexport function getHomeDir(homeDir?: string): string {\n return homeDir ?? process.env.TGSM_HOME ?? path.join(os.homedir(), '.tgsm')\n}\n\nexport function getAccountName(account?: string): string {\n return account ?? 'default'\n}\n\nexport function getAccountDir(options: PathOptions = {}): string {\n return path.join(getHomeDir(options.homeDir), getAccountName(options.account))\n}\n\nexport function getCachePath(options: PathOptions = {}): string {\n return path.join(getAccountDir(options), 'cache.json')\n}\n\nexport function getTelegramConfigPath(options: PathOptions = {}): string {\n return path.join(getAccountDir(options), 'telegram.json')\n}\n\nexport function getTelegramSessionPath(options: PathOptions = {}): string {\n return path.join(getAccountDir(options), 'mtcute-session')\n}\n\nexport async function ensureAccountDir(options: PathOptions = {}): Promise<string> {\n const accountDir = getAccountDir(options)\n await mkdir(accountDir, { recursive: true })\n return accountDir\n}\n","import { readFile, writeFile } from 'node:fs/promises'\nimport type { CacheState, SourceSnapshot } from './types'\n\nexport const EMPTY_CACHE: CacheState = {\n version: 1,\n backend: 'fixture',\n account: null,\n synced_at: null,\n dialogs: [],\n messages: [],\n}\n\nexport async function readCache(cachePath: string): Promise<CacheState> {\n try {\n const raw = await readFile(cachePath, 'utf8')\n return JSON.parse(raw) as CacheState\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return EMPTY_CACHE\n }\n\n throw error\n }\n}\n\nexport async function writeCache(cachePath: string, snapshot: SourceSnapshot): Promise<void> {\n const state: CacheState = {\n version: 1,\n backend: snapshot.backend,\n account: snapshot.account,\n synced_at: snapshot.synced_at,\n dialogs: snapshot.dialogs,\n messages: snapshot.messages,\n }\n\n await writeFile(cachePath, `${JSON.stringify(state, null, 2)}\\n`, 'utf8')\n}\n","import { readFile } from 'node:fs/promises'\nimport { TgsmError } from './errors'\nimport type { AuthStatus, SourceSnapshot, TgsmSourceAdapter } from './types'\n\ninterface FixtureFile {\n account?: SourceSnapshot['account']\n dialogs: SourceSnapshot['dialogs']\n messages: SourceSnapshot['messages']\n}\n\nexport class FixtureSource implements TgsmSourceAdapter {\n readonly backend = 'fixture' as const\n\n constructor(private readonly fixturePath: string) {}\n\n async sync(): Promise<SourceSnapshot> {\n const raw = await readFile(this.fixturePath, 'utf8')\n const parsed = JSON.parse(raw) as FixtureFile\n\n if (!Array.isArray(parsed.dialogs) || !Array.isArray(parsed.messages)) {\n throw new TgsmError({\n code: 'INVALID_FIXTURE',\n message: `Fixture at ${this.fixturePath} is missing dialogs/messages arrays`,\n retryable: false,\n })\n }\n\n const syncedAt = new Date().toISOString()\n\n return {\n backend: this.backend,\n account:\n parsed.account ??\n ({\n id: 'fixture',\n display_name: 'Fixture Account',\n } as const),\n dialogs: parsed.dialogs.map((dialog) => ({\n ...dialog,\n last_synced_at: syncedAt,\n })),\n messages: parsed.messages,\n synced_at: syncedAt,\n }\n }\n\n async authStatus(): Promise<AuthStatus> {\n return {\n authenticated: true,\n user: {\n id: 'fixture',\n display_name: 'Fixture Account',\n },\n }\n }\n}\n","import path from 'node:path'\nimport { readCache, writeCache } from './cache'\nimport { TgsmError } from './errors'\nimport type {\n BackreplyEdgeSummary,\n CacheMessageRecord,\n CacheState,\n ContextMessage,\n GetMessageOptions,\n ListMessagesOptions,\n MessageContextBundle,\n MessageEnvelope,\n MessageListItem,\n MessageRef,\n SavedDialogSummary,\n SearchResultPage,\n SyncResult,\n ThreadInspectNode,\n ThreadInspectResult,\n TgsmSourceAdapter,\n} from './types'\n\nexport interface TgsmServiceOptions {\n cachePath: string\n source?: TgsmSourceAdapter\n}\n\ninterface Indexes {\n dialogsById: Map<string, SavedDialogSummary>\n messagesByKey: Map<string, CacheMessageRecord>\n messagesByGlobalId: Map<number, CacheMessageRecord[]>\n messagesByDialog: Map<string, CacheMessageRecord[]>\n backreplyIndex: Map<string, CacheMessageRecord[]>\n}\n\nconst DEFAULT_CHRONOLOGY_LIMIT = 20\n\nexport class TgsmService {\n constructor(private readonly options: TgsmServiceOptions) {}\n\n async authLogin(input: Parameters<NonNullable<TgsmSourceAdapter['authLogin']>>[1]) {\n if (!this.options.source?.authLogin) {\n throw new TgsmError({\n code: 'AUTH_UNSUPPORTED',\n message: 'This backend does not support auth login.',\n retryable: false,\n })\n }\n\n return this.options.source.authLogin(this.accountDir(), input)\n }\n\n async authStatus() {\n if (!this.options.source?.authStatus) {\n return {\n authenticated: false,\n user: null,\n }\n }\n\n return this.options.source.authStatus(this.accountDir())\n }\n\n async sync(): Promise<SyncResult> {\n if (!this.options.source) {\n throw new TgsmError({\n code: 'SYNC_UNAVAILABLE',\n message: 'No source backend configured for sync.',\n retryable: false,\n })\n }\n\n const snapshot = await this.options.source.sync(this.accountDir())\n await writeCache(this.options.cachePath, snapshot)\n\n return {\n backend: snapshot.backend,\n synced_at: snapshot.synced_at,\n synced_dialogs: snapshot.dialogs.length,\n synced_messages: snapshot.messages.length,\n }\n }\n\n async listSavedDialogs(): Promise<SavedDialogSummary[]> {\n const cache = await this.loadCache()\n return [...cache.dialogs].sort((a, b) => {\n const left = a.last_synced_at ?? ''\n const right = b.last_synced_at ?? ''\n return right.localeCompare(left) || a.saved_peer_id.localeCompare(b.saved_peer_id)\n })\n }\n\n async listMessages(options: ListMessagesOptions = {}): Promise<SearchResultPage<MessageListItem>> {\n const cache = await this.loadCache()\n const indexes = this.buildIndexes(cache)\n const dialogId = options.dialog ?? null\n\n if (dialogId && !indexes.dialogsById.has(dialogId)) {\n throw new TgsmError({\n code: 'DIALOG_NOT_FOUND',\n message: `Saved dialog ${dialogId} was not found.`,\n retryable: false,\n suggestion: 'Run `tgsm saved-dialogs list` to inspect available dialogs.',\n })\n }\n\n const scoped = dialogId\n ? indexes.messagesByDialog.get(dialogId) ?? []\n : cache.messages\n\n const filtered = options.search\n ? scoped.filter((message: CacheMessageRecord) => matchesSearch(message, options.search!))\n : scoped\n\n const sorted = [...filtered].sort(compareByDateDesc)\n const limit = Math.max(1, options.limit ?? 20)\n const offset = decodeCursor(options.cursor)\n const slice = sorted.slice(offset, offset + limit)\n\n return {\n items: slice.map((message) => this.toMessageListItem(message, indexes)),\n scope: dialogId ? 'saved_dialog' : 'all_saved_dialogs',\n saved_peer_id: dialogId,\n next_cursor: offset + limit < sorted.length ? encodeCursor(offset + limit) : null,\n result_count: filtered.length,\n }\n }\n\n async getMessage(messageId: number, options: GetMessageOptions = {}): Promise<MessageContextBundle> {\n const cache = await this.loadCache()\n const indexes = this.buildIndexes(cache)\n const target = this.findMessage(indexes, messageId, options.dialog)\n return this.buildContextBundle(target, indexes)\n }\n\n async getContext(messageId: number, options: GetMessageOptions = {}): Promise<MessageContextBundle> {\n return this.getMessage(messageId, options)\n }\n\n async inspectThread(messageId: number, options: GetMessageOptions = {}): Promise<ThreadInspectResult> {\n const cache = await this.loadCache()\n const indexes = this.buildIndexes(cache)\n const target = this.findMessage(indexes, messageId, options.dialog)\n const root = this.findThreadRoot(target, indexes)\n const dialog = indexes.dialogsById.get(root.saved_peer_id)\n\n if (!dialog) {\n throw new TgsmError({\n code: 'DIALOG_NOT_FOUND',\n message: `Saved dialog ${root.saved_peer_id} was not found.`,\n retryable: false,\n })\n }\n\n return {\n dialog,\n root: this.toEnvelope(root, indexes),\n nodes: [this.buildThreadNode(root, indexes, 0)],\n }\n }\n\n private accountDir(): string {\n return path.dirname(this.options.cachePath)\n }\n\n private async loadCache(): Promise<CacheState> {\n return readCache(this.options.cachePath)\n }\n\n private buildIndexes(cache: CacheState): Indexes {\n const dialogsById = new Map<string, SavedDialogSummary>(\n cache.dialogs.map((dialog: SavedDialogSummary) => [dialog.saved_peer_id, dialog]),\n )\n const messagesByKey = new Map<string, CacheMessageRecord>()\n const messagesByGlobalId = new Map<number, CacheMessageRecord[]>()\n const messagesByDialog = new Map<string, CacheMessageRecord[]>()\n const backreplyIndex = new Map<string, CacheMessageRecord[]>()\n\n for (const message of cache.messages) {\n messagesByKey.set(makeMessageKey(message.saved_peer_id, message.message_id), message)\n\n const existingGlobal = messagesByGlobalId.get(message.message_id) ?? []\n existingGlobal.push(message)\n messagesByGlobalId.set(message.message_id, existingGlobal)\n\n const dialogMessages = messagesByDialog.get(message.saved_peer_id) ?? []\n dialogMessages.push(message)\n messagesByDialog.set(message.saved_peer_id, dialogMessages)\n\n if (message.reply_to_message_id !== null) {\n const replyDialog = message.reply_to_saved_peer_id ?? message.saved_peer_id\n const key = makeMessageKey(replyDialog, message.reply_to_message_id)\n const children = backreplyIndex.get(key) ?? []\n children.push(message)\n backreplyIndex.set(key, children)\n }\n }\n\n for (const records of messagesByDialog.values()) {\n records.sort(compareByDateAsc)\n }\n\n for (const records of backreplyIndex.values()) {\n records.sort(compareByDateAsc)\n }\n\n return {\n dialogsById,\n messagesByKey,\n messagesByGlobalId,\n messagesByDialog,\n backreplyIndex,\n }\n }\n\n private findMessage(indexes: Indexes, messageId: number, dialog?: string): CacheMessageRecord {\n if (dialog) {\n const scoped = indexes.messagesByKey.get(makeMessageKey(dialog, messageId))\n if (!scoped) {\n throw new TgsmError({\n code: 'MESSAGE_NOT_FOUND',\n message: `Message ${messageId} was not found in dialog ${dialog}.`,\n retryable: false,\n suggestion: 'Run `tgsm messages list --dialog <saved_peer_id>` to inspect the dialog.',\n })\n }\n return scoped\n }\n\n const candidates = indexes.messagesByGlobalId.get(messageId) ?? []\n\n if (candidates.length === 0) {\n throw new TgsmError({\n code: 'MESSAGE_NOT_FOUND',\n message: `Message ${messageId} was not found in the selected scope.`,\n retryable: false,\n suggestion: 'Run `tgsm messages list` or narrow the dialog scope.',\n })\n }\n\n if (candidates.length > 1) {\n throw new TgsmError({\n code: 'AMBIGUOUS_MESSAGE_ID',\n message: `Message ID ${messageId} exists in multiple saved dialogs.`,\n retryable: false,\n suggestion: 'Pass `--dialog <saved_peer_id>` to disambiguate.',\n })\n }\n\n return candidates[0]!\n }\n\n private buildContextBundle(target: CacheMessageRecord, indexes: Indexes): MessageContextBundle {\n const dialog = indexes.dialogsById.get(target.saved_peer_id)\n\n if (!dialog) {\n throw new TgsmError({\n code: 'DIALOG_NOT_FOUND',\n message: `Saved dialog ${target.saved_peer_id} was not found.`,\n retryable: false,\n })\n }\n\n const chronological = indexes.messagesByDialog.get(target.saved_peer_id) ?? []\n const targetIndex = chronological.findIndex(\n (message) => message.message_id === target.message_id && message.saved_peer_id === target.saved_peer_id,\n )\n\n const maxEachSide = Math.floor(DEFAULT_CHRONOLOGY_LIMIT / 2)\n const before = chronological.slice(Math.max(0, targetIndex - maxEachSide), targetIndex)\n const after = chronological.slice(targetIndex + 1, targetIndex + 1 + maxEachSide)\n\n const replyParent = target.reply_to_message_id\n ? indexes.messagesByKey.get(\n makeMessageKey(target.reply_to_saved_peer_id ?? target.saved_peer_id, target.reply_to_message_id),\n ) ?? null\n : null\n\n const directBackreplies =\n indexes.backreplyIndex.get(makeMessageKey(target.saved_peer_id, target.message_id)) ?? []\n\n const notes: string[] = []\n if (target.reply_to_message_id !== null && !replyParent) {\n notes.push(`Reply target #${target.reply_to_message_id} could not be resolved in cache.`)\n }\n\n const contexts = new Map<string, ContextMessage>()\n const pushContext = (\n message: CacheMessageRecord,\n role: ContextMessage['context_roles'][number],\n ): void => {\n const key = makeMessageKey(message.saved_peer_id, message.message_id)\n const existing = contexts.get(key)\n if (existing) {\n if (!existing.context_roles.includes(role)) {\n existing.context_roles.push(role)\n }\n return\n }\n\n contexts.set(key, {\n message: this.toEnvelope(message, indexes),\n context_roles: [role],\n })\n }\n\n for (const message of before) pushContext(message, 'chronology_before')\n if (replyParent) pushContext(replyParent, 'reply_parent')\n pushContext(target, 'target')\n for (const message of directBackreplies) pushContext(message, 'backreply_child')\n for (const message of after) pushContext(message, 'chronology_after')\n\n const contextMessages = [...contexts.values()].sort((left, right) => {\n const rank = (roles: ContextMessage['context_roles']): number => {\n if (roles.includes('chronology_before')) return 1\n if (roles.includes('reply_parent')) return 2\n if (roles.includes('target')) return 3\n if (roles.includes('backreply_child')) return 4\n return 5\n }\n\n return (\n rank(left.context_roles) - rank(right.context_roles) ||\n left.message.date.localeCompare(right.message.date) ||\n left.message.message_id - right.message.message_id\n )\n })\n\n return {\n target: this.toEnvelope(target, indexes),\n dialog,\n context_messages: contextMessages,\n window: {\n chronology_total_limit: DEFAULT_CHRONOLOGY_LIMIT,\n chronology_before_count: before.length,\n chronology_after_count: after.length,\n direct_reply_ancestor_included: Boolean(replyParent),\n direct_backreply_count_included: directBackreplies.length,\n },\n notes,\n }\n }\n\n private toMessageListItem(message: CacheMessageRecord, indexes: Indexes): MessageListItem {\n const dialog = indexes.dialogsById.get(message.saved_peer_id)\n const directBackreplyCount =\n indexes.backreplyIndex.get(makeMessageKey(message.saved_peer_id, message.message_id))?.length ?? 0\n\n return {\n message_id: message.message_id,\n saved_peer_id: message.saved_peer_id,\n dialog_title: dialog?.title ?? message.saved_peer_id,\n date: message.date,\n text_preview: previewText(message.text),\n from_self: message.from_self,\n forwarded: message.forwarded,\n reply_to_message_id: message.reply_to_message_id,\n direct_backreply_count: directBackreplyCount,\n queued_for_delete: message.queued_for_delete,\n }\n }\n\n private toEnvelope(message: CacheMessageRecord, indexes: Indexes): MessageEnvelope {\n const replyTarget =\n message.reply_to_message_id !== null\n ? indexes.messagesByKey.get(\n makeMessageKey(message.reply_to_saved_peer_id ?? message.saved_peer_id, message.reply_to_message_id),\n ) ?? null\n : null\n\n const directBackreplies =\n indexes.backreplyIndex.get(makeMessageKey(message.saved_peer_id, message.message_id)) ?? []\n\n const reply: MessageEnvelope['reply'] =\n message.reply_to_message_id === null\n ? {\n exists: false,\n target: null,\n status: 'resolved',\n }\n : {\n exists: true,\n target: replyTarget\n ? this.toMessageRef(replyTarget, 'reply_to')\n : {\n message_id: message.reply_to_message_id,\n saved_peer_id: message.reply_to_saved_peer_id ?? message.saved_peer_id,\n text_preview: '(missing from cache)',\n date: '',\n relationship: 'reply_to',\n },\n status: replyTarget ? 'resolved' : 'missing',\n }\n\n const backreplies: BackreplyEdgeSummary[] = directBackreplies.map((child) => ({\n message: this.toMessageRef(child, 'backreply'),\n thread_depth_from_target: 1,\n subtree_size_hint: this.countDescendants(child, indexes),\n }))\n\n return {\n message_id: message.message_id,\n saved_peer_id: message.saved_peer_id,\n date: message.date,\n edit_date: message.edit_date,\n text: message.text,\n text_preview: previewText(message.text),\n from_self: message.from_self,\n forwarded: message.forwarded,\n forward_origin: message.forward_origin,\n reply,\n backreplies,\n thread: {\n ancestors_known: this.countAncestors(message, indexes),\n direct_backreply_count: backreplies.length,\n descendant_count_hint: this.countDescendants(message, indexes),\n max_known_depth: this.maxDepth(message, indexes),\n },\n links: message.links,\n media_summary: message.media_summary,\n queued_for_delete: message.queued_for_delete,\n }\n }\n\n private toMessageRef(\n message: CacheMessageRecord,\n relationship: MessageRef['relationship'],\n ): MessageRef {\n return {\n message_id: message.message_id,\n saved_peer_id: message.saved_peer_id,\n text_preview: previewText(message.text),\n date: message.date,\n relationship,\n }\n }\n\n private findThreadRoot(message: CacheMessageRecord, indexes: Indexes): CacheMessageRecord {\n let current = message\n\n while (current.reply_to_message_id !== null) {\n const parent = indexes.messagesByKey.get(\n makeMessageKey(current.reply_to_saved_peer_id ?? current.saved_peer_id, current.reply_to_message_id),\n )\n if (!parent || parent.saved_peer_id !== current.saved_peer_id) {\n break\n }\n current = parent\n }\n\n return current\n }\n\n private buildThreadNode(\n message: CacheMessageRecord,\n indexes: Indexes,\n depth: number,\n ): ThreadInspectNode {\n const children =\n indexes.backreplyIndex.get(makeMessageKey(message.saved_peer_id, message.message_id)) ?? []\n\n return {\n message: this.toEnvelope(message, indexes),\n depth,\n children: children.map((child) => this.buildThreadNode(child, indexes, depth + 1)),\n }\n }\n\n private countAncestors(message: CacheMessageRecord, indexes: Indexes): number {\n let count = 0\n let current = message\n\n while (current.reply_to_message_id !== null) {\n const parent = indexes.messagesByKey.get(\n makeMessageKey(current.reply_to_saved_peer_id ?? current.saved_peer_id, current.reply_to_message_id),\n )\n if (!parent) break\n count += 1\n current = parent\n }\n\n return count\n }\n\n private countDescendants(message: CacheMessageRecord, indexes: Indexes): number {\n const children =\n indexes.backreplyIndex.get(makeMessageKey(message.saved_peer_id, message.message_id)) ?? []\n\n return children.reduce((count, child) => count + 1 + this.countDescendants(child, indexes), 0)\n }\n\n private maxDepth(message: CacheMessageRecord, indexes: Indexes): number {\n const children =\n indexes.backreplyIndex.get(makeMessageKey(message.saved_peer_id, message.message_id)) ?? []\n if (children.length === 0) return 0\n return 1 + Math.max(...children.map((child) => this.maxDepth(child, indexes)))\n }\n}\n\nfunction makeMessageKey(savedPeerId: string, messageId: number): string {\n return `${savedPeerId}:${messageId}`\n}\n\nfunction encodeCursor(offset: number): string {\n return Buffer.from(String(offset), 'utf8').toString('base64url')\n}\n\nfunction decodeCursor(cursor?: string | null): number {\n if (!cursor) return 0\n\n try {\n const value = Number(Buffer.from(cursor, 'base64url').toString('utf8'))\n return Number.isFinite(value) && value >= 0 ? value : 0\n } catch {\n return 0\n }\n}\n\nfunction compareByDateAsc(left: CacheMessageRecord, right: CacheMessageRecord): number {\n return left.date.localeCompare(right.date) || left.message_id - right.message_id\n}\n\nfunction compareByDateDesc(left: CacheMessageRecord, right: CacheMessageRecord): number {\n return right.date.localeCompare(left.date) || right.message_id - left.message_id\n}\n\nfunction matchesSearch(message: CacheMessageRecord, query: string): boolean {\n const normalized = query.trim().toLowerCase()\n if (!normalized) return true\n\n return [\n message.text,\n message.forward_origin?.title ?? '',\n message.saved_peer_id,\n ]\n .join('\\n')\n .toLowerCase()\n .includes(normalized)\n}\n\nfunction previewText(text: string, limit = 80): string {\n const normalized = text.replace(/\\s+/g, ' ').trim()\n if (!normalized) return '(no text)'\n return normalized.length <= limit ? normalized : `${normalized.slice(0, limit - 1)}…`\n}\n","import path from 'node:path'\nimport { createInterface } from 'node:readline/promises'\nimport { readFile, writeFile } from 'node:fs/promises'\nimport { TelegramClient, getMarkedPeerId, type tl } from '@mtcute/node'\nimport { TgsmError } from './errors'\nimport type {\n AuthStatus,\n CacheMessageRecord,\n ForwardOriginSummary,\n LinkSummary,\n SavedDialogSummary,\n SourceSnapshot,\n TelegramLoginInput,\n TgsmSourceAdapter,\n} from './types'\n\ninterface TelegramConfig {\n apiId: number\n apiHash: string\n phone?: string\n}\n\ninterface EntityLookup {\n users: Map<number, tl.TypeUser>\n chats: Map<number, tl.TypeChat>\n selfUserId: number\n}\n\nexport class TelegramSource implements TgsmSourceAdapter {\n readonly backend = 'telegram' as const\n\n async authLogin(accountDir: string, input: TelegramLoginInput): Promise<AuthStatus> {\n const config: TelegramConfig = {\n apiId: input.apiId,\n apiHash: input.apiHash,\n phone: input.phone,\n }\n\n await saveTelegramConfig(accountDir, config)\n const client = createTelegramClient(accountDir, config)\n const rl = createInterface({\n input: process.stdin,\n output: process.stderr,\n })\n\n try {\n const user = await client.start({\n phone: input.phone,\n code: async () => {\n if (input.code && input.code.trim().length > 0) {\n return input.code\n }\n\n return rl.question('Code: ')\n },\n password: async () =>\n input.password ??\n (await rl.question('2FA password (leave empty if not enabled): ')),\n codeSentCallback: async (sentCode) => {\n const type =\n typeof sentCode.type === 'string'\n ? sentCode.type\n : 'unknown'\n process.stderr.write(`Login code requested via ${type}.\\n`)\n },\n invalidCodeCallback: async (type) => {\n process.stderr.write(`Invalid ${type}, please try again.\\n`)\n },\n })\n\n return {\n authenticated: true,\n user: {\n id: String(user.id),\n display_name: user.displayName,\n },\n }\n } catch (error) {\n throw new TgsmError({\n code: 'AUTH_FAILED',\n message: error instanceof Error ? error.message : 'Telegram auth failed.',\n retryable: false,\n })\n } finally {\n rl.close()\n await destroyClientQuietly(client)\n }\n }\n\n async authStatus(accountDir: string): Promise<AuthStatus> {\n const config = await loadTelegramConfig(accountDir)\n if (!config) {\n return {\n authenticated: false,\n user: null,\n }\n }\n\n const client = createTelegramClient(accountDir, config)\n\n try {\n await client.start({})\n const me = await client.getMe()\n return {\n authenticated: true,\n user: {\n id: String(me.id),\n display_name: me.displayName,\n },\n }\n } catch {\n return {\n authenticated: false,\n user: null,\n }\n } finally {\n await destroyClientQuietly(client)\n }\n }\n\n async sync(accountDir: string): Promise<SourceSnapshot> {\n const config = await loadTelegramConfig(accountDir)\n if (!config) {\n throw new TgsmError({\n code: 'AUTH_REQUIRED',\n message: 'Telegram credentials are not configured.',\n retryable: false,\n suggestion: 'Run `tgsm auth login` first.',\n })\n }\n\n const client = createTelegramClient(accountDir, config)\n\n try {\n const me = await client.start({})\n const syncedAt = new Date().toISOString()\n const dialogsResponse = await client.call({\n _: 'messages.getSavedDialogs',\n excludePinned: false,\n offsetDate: 0,\n offsetId: 0,\n offsetPeer: { _: 'inputPeerEmpty' },\n limit: 1000,\n hash: 0 as never,\n })\n\n if (dialogsResponse._ === 'messages.savedDialogsNotModified') {\n return {\n backend: this.backend,\n account: {\n id: String(me.id),\n display_name: me.displayName,\n },\n dialogs: [],\n messages: [],\n synced_at: syncedAt,\n }\n }\n\n const lookup: EntityLookup = {\n users: new Map(),\n chats: new Map(),\n selfUserId: Number(me.id),\n }\n\n ingestEntities(lookup, dialogsResponse.users, dialogsResponse.chats)\n\n const dialogs: SavedDialogSummary[] = []\n const messagesByKey = new Map<string, CacheMessageRecord>()\n\n for (const dialog of dialogsResponse.dialogs) {\n if (dialog._ !== 'savedDialog') continue\n\n const savedPeerId = savedPeerIdFromPeer(dialog.peer, lookup.selfUserId)\n const peerInput = await client.resolvePeer(getMarkedPeerId(dialog.peer))\n const title = peerTitle(dialog.peer, lookup)\n\n const messages = await fetchSavedHistory(client, peerInput, lookup)\n const topMessage = messages.find((message) => message.message_id === dialog.topMessage) ?? messages[0] ?? null\n\n dialogs.push({\n saved_peer_id: savedPeerId,\n kind: peerKindFromPeer(dialog.peer, lookup.selfUserId),\n title,\n top_message_id: dialog.topMessage ?? topMessage?.message_id ?? null,\n top_text_preview: topMessage ? previewText(topMessage.text) : null,\n message_count: messages.length,\n pinned: dialog.pinned ?? null,\n last_synced_at: syncedAt,\n })\n\n for (const message of messages) {\n messagesByKey.set(`${message.saved_peer_id}:${message.message_id}`, message)\n }\n }\n\n return {\n backend: this.backend,\n account: {\n id: String(me.id),\n display_name: me.displayName,\n },\n dialogs,\n messages: [...messagesByKey.values()].sort((a, b) =>\n a.saved_peer_id.localeCompare(b.saved_peer_id) || a.date.localeCompare(b.date) || a.message_id - b.message_id,\n ),\n synced_at: syncedAt,\n }\n } catch (error) {\n throw new TgsmError({\n code: 'TELEGRAM_SYNC_FAILED',\n message: error instanceof Error ? error.message : 'Telegram sync failed.',\n retryable: true,\n })\n } finally {\n await destroyClientQuietly(client)\n }\n }\n}\n\nfunction createTelegramClient(accountDir: string, config: TelegramConfig): TelegramClient {\n return new TelegramClient({\n apiId: config.apiId,\n apiHash: config.apiHash,\n storage: path.join(accountDir, 'mtcute-session'),\n logLevel: 0,\n })\n}\n\nasync function destroyClientQuietly(client: TelegramClient): Promise<void> {\n try {\n await client.destroy()\n } catch {\n // Best-effort cleanup only. The session is already persisted on disk.\n }\n}\n\nasync function fetchSavedHistory(\n client: TelegramClient,\n peer: tl.TypeInputPeer,\n lookup: EntityLookup,\n): Promise<CacheMessageRecord[]> {\n let offsetId = 0\n let offsetDate = 0\n const records = new Map<string, CacheMessageRecord>()\n\n while (true) {\n const history = await client.call({\n _: 'messages.getSavedHistory',\n peer,\n offsetId,\n offsetDate,\n addOffset: 0,\n limit: 100,\n maxId: 0,\n minId: 0,\n hash: 0 as never,\n })\n\n if (!('messages' in history)) {\n break\n }\n\n ingestEntities(lookup, history.users ?? [], history.chats ?? [])\n\n const rawMessages = history.messages.filter(\n (message: tl.TypeMessage): message is tl.RawMessage | tl.RawMessageService =>\n message._ === 'message' || message._ === 'messageService',\n )\n\n if (rawMessages.length === 0) {\n break\n }\n\n for (const raw of rawMessages) {\n const record = normalizeRawMessage(raw, lookup)\n records.set(`${record.saved_peer_id}:${record.message_id}`, record)\n }\n\n const oldest = rawMessages[rawMessages.length - 1]!\n offsetId = oldest.id\n offsetDate = oldest.date\n\n if (rawMessages.length < 100) {\n break\n }\n }\n\n return [...records.values()].sort((a, b) => a.date.localeCompare(b.date) || a.message_id - b.message_id)\n}\n\nfunction normalizeRawMessage(raw: tl.RawMessage | tl.RawMessageService, lookup: EntityLookup): CacheMessageRecord {\n const savedPeerId = savedPeerIdFromPeer(raw.peerId, lookup.selfUserId)\n const replyHeader =\n 'replyTo' in raw && raw.replyTo && raw.replyTo._ === 'messageReplyHeader' ? raw.replyTo : null\n const replyPeer = replyHeader?.replyToPeerId ?? raw.peerId\n const fwdFrom = 'fwdFrom' in raw ? raw.fwdFrom : undefined\n const editDate = 'editDate' in raw ? raw.editDate : undefined\n const media = 'media' in raw ? raw.media : undefined\n const text = 'message' in raw ? raw.message : ''\n\n return {\n message_id: raw.id,\n saved_peer_id: savedPeerId,\n date: new Date(raw.date * 1000).toISOString(),\n edit_date: editDate ? new Date(editDate * 1000).toISOString() : null,\n text,\n from_self: peerIsSelf('fromId' in raw ? raw.fromId : null, lookup.selfUserId),\n forwarded: Boolean(fwdFrom),\n forward_origin: fwdFrom ? forwardOriginFromHeader(fwdFrom, lookup) : null,\n reply_to_message_id: replyHeader?.replyToMsgId ?? null,\n reply_to_saved_peer_id: replyHeader?.replyToMsgId\n ? savedPeerIdFromPeer(replyPeer, lookup.selfUserId)\n : null,\n links: extractLinks(text),\n media_summary: mediaSummary(media),\n queued_for_delete: false,\n }\n}\n\nfunction forwardOriginFromHeader(\n header: tl.RawMessageFwdHeader,\n lookup: EntityLookup,\n): ForwardOriginSummary {\n if (header.savedFromPeer) {\n return {\n saved_peer_id: savedPeerIdFromPeer(header.savedFromPeer, lookup.selfUserId),\n title: peerTitle(header.savedFromPeer, lookup),\n message_id: header.savedFromMsgId ?? null,\n }\n }\n\n if (header.fromId) {\n return {\n saved_peer_id: savedPeerIdFromPeer(header.fromId, lookup.selfUserId),\n title: header.fromName ?? peerTitle(header.fromId, lookup),\n message_id: header.savedFromMsgId ?? null,\n }\n }\n\n return {\n saved_peer_id: null,\n title: header.fromName ?? header.savedFromName ?? null,\n message_id: header.savedFromMsgId ?? null,\n }\n}\n\nfunction peerIsSelf(peer: tl.TypePeer | undefined | null, selfUserId: number): boolean {\n return Boolean(peer && peer._ === 'peerUser' && peer.userId === selfUserId)\n}\n\nfunction peerKindFromPeer(peer: tl.TypePeer, selfUserId: number): SavedDialogSummary['kind'] {\n if (peer._ === 'peerUser' && peer.userId === selfUserId) return 'self'\n if (peer._ === 'peerUser' || peer._ === 'peerChat') return 'peer'\n if (peer._ === 'peerChannel') return 'channel'\n return 'unknown'\n}\n\nexport function savedPeerIdFromPeer(peer: tl.TypePeer, selfUserId: number): string {\n if (peer._ === 'peerUser' && peer.userId === selfUserId) {\n return 'self'\n }\n\n if (peer._ === 'peerUser') return `user:${peer.userId}`\n if (peer._ === 'peerChat') return `chat:${peer.chatId}`\n if (peer._ === 'peerChannel') return `channel:${peer.channelId}`\n return `unknown:${getMarkedPeerId(peer)}`\n}\n\nfunction peerTitle(peer: tl.TypePeer, lookup: EntityLookup): string {\n if (peer._ === 'peerUser') {\n if (peer.userId === lookup.selfUserId) return 'Self'\n const user = lookup.users.get(peer.userId)\n const firstName = user && user._ === 'user' ? user.firstName ?? '' : ''\n const lastName = user && user._ === 'user' ? user.lastName ?? '' : ''\n const username = user && user._ === 'user' ? user.username ?? '' : ''\n const parts = [firstName, lastName].filter(Boolean)\n return parts.join(' ').trim() || username || `User ${peer.userId}`\n }\n\n const entity = lookup.chats.get(peer._ === 'peerChat' ? peer.chatId : peer.channelId)\n if (entity && 'title' in entity) {\n return entity.title\n }\n\n if (peer._ === 'peerChat') return `Chat ${peer.chatId}`\n if (peer._ === 'peerChannel') return `Channel ${peer.channelId}`\n return 'Unknown'\n}\n\nfunction ingestEntities(lookup: EntityLookup, users: tl.TypeUser[], chats: tl.TypeChat[]): void {\n for (const user of users) {\n if ('id' in user) {\n lookup.users.set(Number(user.id), user)\n }\n }\n\n for (const chat of chats) {\n if ('id' in chat) {\n lookup.chats.set(Number(chat.id), chat)\n }\n }\n}\n\nfunction extractLinks(text: string): LinkSummary[] {\n const matches = text.matchAll(/https?:\\/\\/[^\\s)]+/g)\n const seen = new Set<string>()\n const links: LinkSummary[] = []\n\n for (const match of matches) {\n const url = match[0]!\n if (seen.has(url)) continue\n seen.add(url)\n links.push({ url })\n }\n\n return links\n}\n\nfunction mediaSummary(media: tl.TypeMessageMedia | undefined): string | null {\n if (!media) return null\n return media._\n}\n\nfunction previewText(text: string, limit = 80): string {\n const normalized = text.replace(/\\s+/g, ' ').trim()\n if (!normalized) return '(no text)'\n return normalized.length <= limit ? normalized : `${normalized.slice(0, limit - 1)}…`\n}\n\nasync function loadTelegramConfig(accountDir: string): Promise<TelegramConfig | null> {\n try {\n const raw = await readFile(path.join(accountDir, 'telegram.json'), 'utf8')\n return JSON.parse(raw) as TelegramConfig\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return null\n throw error\n }\n}\n\nasync function saveTelegramConfig(accountDir: string, config: TelegramConfig): Promise<void> {\n await writeFile(\n path.join(accountDir, 'telegram.json'),\n `${JSON.stringify(config, null, 2)}\\n`,\n 'utf8',\n )\n}\n","import type {\n AuthStatus,\n MessageContextBundle,\n MessageListItem,\n SavedDialogSummary,\n SearchResultPage,\n SyncResult,\n ThreadInspectNode,\n ThreadInspectResult,\n} from '@tgsm/core'\n\nexport function formatSyncResult(result: SyncResult): string {\n return [\n `sync backend=${result.backend}`,\n `synced_at=${result.synced_at}`,\n `dialogs=${result.synced_dialogs}`,\n `messages=${result.synced_messages}`,\n ].join('\\n')\n}\n\nexport function formatAuthStatus(status: AuthStatus): string {\n if (!status.authenticated || !status.user) {\n return 'authenticated: false'\n }\n\n return [`authenticated: true`, `user: ${status.user.display_name}`, `id: ${status.user.id}`].join('\\n')\n}\n\nexport function formatSavedDialogs(dialogs: SavedDialogSummary[]): string {\n if (dialogs.length === 0) return 'No saved dialogs found.'\n\n return dialogs\n .map((dialog) =>\n [\n `${dialog.saved_peer_id} (${dialog.kind})`,\n `title: ${dialog.title}`,\n `messages: ${dialog.message_count}`,\n `top_message_id: ${dialog.top_message_id ?? 'n/a'}`,\n `top_text: ${dialog.top_text_preview ?? '(none)'}`,\n ].join('\\n'),\n )\n .join('\\n\\n')\n}\n\nexport function formatMessagesPage(page: SearchResultPage<MessageListItem>): string {\n if (page.items.length === 0) return 'No messages found.'\n\n const header =\n page.scope === 'saved_dialog'\n ? `messages scope=${page.saved_peer_id} total=${page.result_count}`\n : `messages scope=all_saved_dialogs total=${page.result_count}`\n\n const blocks = page.items.map((item) =>\n [\n `#${item.message_id} ${item.date}`,\n `dialog: ${item.saved_peer_id} (${item.dialog_title})`,\n `from_self: ${item.from_self} forwarded: ${item.forwarded}`,\n `reply_to: ${item.reply_to_message_id ?? 'none'} backreplies: ${item.direct_backreply_count}`,\n `text: ${item.text_preview}`,\n ].join('\\n'),\n )\n\n return [header, ...blocks, page.next_cursor ? `next_cursor: ${page.next_cursor}` : ''].filter(Boolean).join('\\n\\n')\n}\n\nexport function formatContextBundle(bundle: MessageContextBundle): string {\n const lines: string[] = [\n `MESSAGE #${bundle.target.message_id}`,\n `dialog: ${bundle.dialog.saved_peer_id} (${bundle.dialog.title})`,\n `date: ${bundle.target.date}`,\n `from_self: ${bundle.target.from_self}`,\n `thread: direct_backreplies=${bundle.target.thread.direct_backreply_count} descendant_hint=${bundle.target.thread.descendant_count_hint ?? 0}`,\n '',\n 'text:',\n bundle.target.text || '(no text)',\n ]\n\n const replySection = bundle.target.reply.exists\n ? bundle.target.reply.target\n ? [``, 'reply_to:', `- #${bundle.target.reply.target.message_id} ${bundle.target.reply.target.text_preview}`]\n : [``, 'reply_to:', '- (missing from cache)']\n : []\n\n const backreplySection =\n bundle.target.backreplies.length > 0\n ? [\n '',\n 'backreplies:',\n ...bundle.target.backreplies.map(\n (item) => `- #${item.message.message_id} ${item.message.text_preview}`,\n ),\n ]\n : []\n\n const before = bundle.context_messages.filter((item) => item.context_roles.includes('chronology_before'))\n const after = bundle.context_messages.filter((item) => item.context_roles.includes('chronology_after'))\n\n if (before.length > 0) {\n lines.push('', 'chronology_before:')\n for (const item of before) lines.push(`- #${item.message.message_id} ${item.message.text_preview}`)\n }\n\n if (after.length > 0) {\n lines.push('', 'chronology_after:')\n for (const item of after) lines.push(`- #${item.message.message_id} ${item.message.text_preview}`)\n }\n\n lines.push(...replySection, ...backreplySection)\n\n if (bundle.notes.length > 0) {\n lines.push('', 'notes:')\n for (const note of bundle.notes) lines.push(`- ${note}`)\n }\n\n return lines.join('\\n')\n}\n\nexport function formatThread(result: ThreadInspectResult): string {\n const lines = [`THREAD #${result.root.message_id}`, `dialog: ${result.dialog.saved_peer_id} (${result.dialog.title})`, '']\n\n const root = result.nodes[0]\n if (!root) return lines.join('\\n')\n\n renderNode(root, '', true, lines)\n return lines.join('\\n')\n}\n\nfunction renderNode(node: ThreadInspectNode, prefix: string, isLast: boolean, lines: string[]): void {\n const branch = prefix ? `${prefix}${isLast ? '└── ' : '├── '}` : ''\n lines.push(`${branch}#${node.message.message_id} ${node.message.text_preview}`)\n\n const nextPrefix = prefix ? `${prefix}${isLast ? ' ' : '│ '}` : ''\n node.children.forEach((child, index) => {\n renderNode(child, nextPrefix, index === node.children.length - 1, lines)\n })\n}\n","{\n \"name\": \"@imadtg/tgsm\",\n \"version\": \"0.0.5\",\n \"type\": \"module\",\n \"description\": \"A retrieval-first CLI for navigating Telegram Saved Messages as structured, agent-readable context.\",\n \"license\": \"MIT\",\n \"homepage\": \"https://github.com/imadtg/tgsm\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/imadtg/tgsm.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/imadtg/tgsm/issues\"\n },\n \"keywords\": [\n \"telegram\",\n \"saved-messages\",\n \"cli\",\n \"agents\",\n \"mtproto\"\n ],\n \"engines\": {\n \"node\": \">=20\"\n },\n \"bin\": {\n \"tgsm\": \"dist/index.js\"\n },\n \"main\": \"./dist/index.js\",\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"test\": \"bun test\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"dependencies\": {\n \"@mtcute/node\": \"^0.28.2\",\n \"commander\": \"^14.0.1\"\n },\n \"devDependencies\": {\n \"@tgsm/core\": \"workspace:*\"\n }\n}\n"],"mappings":"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","names":["createInterface","process","readFile","readFile","path","path","path","readFile","writeFile","messages","previewText","path","readFile","writeFile","createInterface","process"]}
1
+ {"version":3,"sources":["../src/index.ts","../../core/src/errors.ts","../../core/src/paths.ts","../../core/src/cache.ts","../../core/src/fixture.ts","../../core/src/service.ts","../../core/src/telegram.ts","../src/format.ts","../package.json"],"sourcesContent":["import { createInterface } from 'node:readline/promises'\nimport { once } from 'node:events'\nimport process from 'node:process'\nimport { Command } from 'commander'\nimport {\n FixtureSource,\n TgsmError,\n TgsmService,\n TelegramSource,\n ensureAccountDir,\n getCachePath,\n type GetMessageOptions,\n type ListMessagesOptions,\n type TgsmSourceAdapter,\n} from '@tgsm/core'\nimport {\n formatAuthStatus,\n formatContextBundle,\n formatMessagesPage,\n formatSavedDialogs,\n formatSyncResult,\n formatThread,\n} from './format'\nimport pkg from '../package.json'\n\ninterface GlobalOptions {\n json?: boolean\n debug?: boolean\n backend?: 'telegram' | 'fixture'\n fixture?: string\n home?: string\n account?: string\n}\n\nconst program = new Command()\n\nprogram\n .name('tgsm')\n .description('Retrieval-first Telegram Saved Messages CLI')\n .version(pkg.version, '-V, --version', 'Display the tgsm version')\n .option('--json', 'Emit JSON instead of default text output')\n .option('--debug', 'Emit debug telemetry to stderr')\n .option('--backend <backend>', 'telegram or fixture', 'telegram')\n .option('--fixture <path>', 'Fixture path for the fixture backend')\n .option('--home <path>', 'Override TGSM home directory')\n .option('--account <name>', 'Account namespace', 'default')\n\nprogram\n .command('auth')\n .description('Telegram auth commands')\n .addCommand(\n new Command('login').action(async (_, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n if (options.backend !== 'telegram') {\n throw new TgsmError({\n code: 'AUTH_UNSUPPORTED',\n message: 'Auth login is only supported with the telegram backend.',\n retryable: false,\n })\n }\n\n const rl = createInterface({\n input: process.stdin,\n output: process.stderr,\n })\n\n try {\n const apiId = Number(await rl.question('API ID: '))\n const apiHash = await rl.question('API Hash: ')\n const phone = await rl.question('Phone: ')\n\n const result = await service.authLogin({\n apiId,\n apiHash,\n phone,\n })\n\n emit(result, options, formatAuthStatus)\n } finally {\n rl.close()\n }\n })\n }),\n )\n .addCommand(\n new Command('status').action(async (_, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n emit(await service.authStatus(), options, formatAuthStatus)\n })\n }),\n )\n\nprogram.command('sync').action(async (_, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n emit(await service.sync(), options, formatSyncResult)\n })\n})\n\nprogram\n .command('saved-dialogs')\n .description('Saved dialog commands')\n .addCommand(\n new Command('list').action(async (_, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n emit(await service.listSavedDialogs(), options, formatSavedDialogs)\n })\n }),\n )\n\nconst messages = program.command('messages').description('Message commands')\n\nmessages\n .command('list')\n .option('--dialog <savedPeerId>')\n .option('--search <query>')\n .option('--limit <number>', 'Page size', '20')\n .option('--cursor <cursor>')\n .action(async (commandOptions, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n const result = await service.listMessages({\n dialog: commandOptions.dialog,\n search: commandOptions.search,\n limit: Number(commandOptions.limit),\n cursor: commandOptions.cursor,\n } satisfies ListMessagesOptions)\n emit(result, options, formatMessagesPage)\n })\n })\n\nmessages\n .command('get')\n .argument('<id>')\n .option('--dialog <savedPeerId>')\n .action(async (id, commandOptions, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n const result = await service.getMessage(Number(id), {\n dialog: commandOptions.dialog,\n } satisfies GetMessageOptions)\n emit(result, options, formatContextBundle)\n })\n })\n\nmessages\n .command('context')\n .argument('<id>')\n .option('--dialog <savedPeerId>')\n .action(async (id, commandOptions, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n const result = await service.getContext(Number(id), {\n dialog: commandOptions.dialog,\n } satisfies GetMessageOptions)\n emit(result, options, formatContextBundle)\n })\n })\n\nprogram\n .command('threads')\n .description('Thread commands')\n .addCommand(\n new Command('inspect')\n .argument('<id>')\n .option('--dialog <savedPeerId>')\n .action(async (id, commandOptions, command) => {\n await withService(command.optsWithGlobals(), async (service, options) => {\n const result = await service.inspectThread(Number(id), {\n dialog: commandOptions.dialog,\n } satisfies GetMessageOptions)\n emit(result, options, formatThread)\n })\n }),\n )\n\nvoid main()\n\nasync function withService(\n options: GlobalOptions,\n fn: (service: TgsmService, options: Required<GlobalOptions>) => Promise<void>,\n): Promise<void> {\n const normalized: Required<GlobalOptions> = {\n json: Boolean(options.json),\n debug: Boolean(options.debug),\n backend: (options.backend ?? 'telegram') as 'telegram' | 'fixture',\n fixture: options.fixture ?? '',\n home: options.home ?? '',\n account: options.account ?? 'default',\n }\n\n await ensureAccountDir({\n homeDir: normalized.home || undefined,\n account: normalized.account,\n })\n\n const cachePath = getCachePath({\n homeDir: normalized.home || undefined,\n account: normalized.account,\n })\n\n debugLog(normalized, 'cli.service.setup', {\n backend: normalized.backend,\n account: normalized.account,\n cache_path: cachePath,\n home: normalized.home || undefined,\n fixture: normalized.fixture || undefined,\n })\n\n const source = resolveSource(normalized)\n const service = new TgsmService({\n cachePath,\n source,\n })\n\n await fn(service, normalized)\n}\n\nfunction resolveSource(options: Required<GlobalOptions>): TgsmSourceAdapter {\n if (options.backend === 'fixture') {\n if (!options.fixture) {\n throw new TgsmError({\n code: 'FIXTURE_REQUIRED',\n message: 'The fixture backend requires --fixture <path>.',\n retryable: false,\n })\n }\n return new FixtureSource(options.fixture)\n }\n\n return new TelegramSource({\n debug: options.debug,\n logger: (event, fields = {}) => {\n debugLog(options, event, fields)\n },\n })\n}\n\nfunction emit<T>(\n value: T,\n options: Required<GlobalOptions>,\n format?: (value: T) => string,\n): void {\n if (options.json) {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`)\n return\n }\n\n process.stdout.write(`${format ? format(value) : String(value)}\\n`)\n}\n\nfunction errorCode(code: string): number {\n if (code.startsWith('AUTH')) return 3\n if (code.includes('SYNC') || code.includes('TELEGRAM')) return 2\n return 1\n}\n\nfunction debugLog(\n options: Pick<Required<GlobalOptions>, 'debug'>,\n event: string,\n fields: Record<string, unknown> = {},\n): void {\n if (!options.debug) return\n\n const detail = Object.entries(fields)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => `${key}=${formatDebugValue(value)}`)\n .join(' ')\n\n process.stderr.write(\n `[tgsm debug ${new Date().toISOString()}] ${event}${detail ? ` ${detail}` : ''}\\n`,\n )\n}\n\nfunction formatDebugValue(value: unknown): string {\n if (typeof value === 'string') return JSON.stringify(value)\n if (typeof value === 'number' || typeof value === 'boolean') return String(value)\n if (value === null) return 'null'\n\n try {\n return JSON.stringify(value)\n } catch {\n return String(value)\n }\n}\n\nasync function main(): Promise<void> {\n let exitCode = 0\n\n try {\n await program.parseAsync(process.argv)\n } catch (error: unknown) {\n const tgsmError =\n error instanceof TgsmError\n ? error\n : new TgsmError({\n code: 'UNEXPECTED_ERROR',\n message: error instanceof Error ? error.message : 'Unexpected error',\n retryable: false,\n })\n\n const options = program.opts<GlobalOptions>()\n if (options.json) {\n process.stdout.write(`${JSON.stringify(tgsmError.toJSON(), null, 2)}\\n`)\n } else {\n process.stderr.write(`error: ${tgsmError.message}\\n`)\n if (tgsmError.suggestion) {\n process.stderr.write(`suggestion: ${tgsmError.suggestion}\\n`)\n }\n }\n\n exitCode = errorCode(tgsmError.code)\n }\n\n await flushStreams()\n process.exit(exitCode)\n}\n\nasync function flushStreams(): Promise<void> {\n await Promise.all([flushStream(process.stdout), flushStream(process.stderr)])\n}\n\nasync function flushStream(stream: NodeJS.WriteStream): Promise<void> {\n if (!stream.writableNeedDrain) {\n return\n }\n\n await once(stream, 'drain')\n}\n","import type { OperationErrorShape } from './types'\n\nexport class TgsmError extends Error {\n readonly code: string\n readonly retryable: boolean\n readonly suggestion?: string\n\n constructor(shape: OperationErrorShape) {\n super(shape.message)\n this.name = 'TgsmError'\n this.code = shape.code\n this.retryable = shape.retryable\n this.suggestion = shape.suggestion\n }\n\n toJSON(): OperationErrorShape {\n return {\n code: this.code,\n message: this.message,\n retryable: this.retryable,\n suggestion: this.suggestion,\n }\n }\n}\n\nexport function asTgsmError(error: unknown): TgsmError {\n if (error instanceof TgsmError) {\n return error\n }\n\n if (error instanceof Error) {\n return new TgsmError({\n code: 'UNEXPECTED_ERROR',\n message: error.message,\n retryable: false,\n })\n }\n\n return new TgsmError({\n code: 'UNEXPECTED_ERROR',\n message: 'Unexpected error',\n retryable: false,\n })\n}\n","import os from 'node:os'\nimport path from 'node:path'\nimport { mkdir } from 'node:fs/promises'\n\nexport interface PathOptions {\n homeDir?: string\n account?: string\n}\n\nexport function getHomeDir(homeDir?: string): string {\n return homeDir ?? process.env.TGSM_HOME ?? path.join(os.homedir(), '.tgsm')\n}\n\nexport function getAccountName(account?: string): string {\n return account ?? 'default'\n}\n\nexport function getAccountDir(options: PathOptions = {}): string {\n return path.join(getHomeDir(options.homeDir), getAccountName(options.account))\n}\n\nexport function getCachePath(options: PathOptions = {}): string {\n return path.join(getAccountDir(options), 'cache.json')\n}\n\nexport function getTelegramConfigPath(options: PathOptions = {}): string {\n return path.join(getAccountDir(options), 'telegram.json')\n}\n\nexport function getTelegramSessionPath(options: PathOptions = {}): string {\n return path.join(getAccountDir(options), 'mtcute-session')\n}\n\nexport async function ensureAccountDir(options: PathOptions = {}): Promise<string> {\n const accountDir = getAccountDir(options)\n await mkdir(accountDir, { recursive: true })\n return accountDir\n}\n","import { readFile, writeFile } from 'node:fs/promises'\nimport type { CacheState, SourceSnapshot } from './types'\n\nexport const EMPTY_CACHE: CacheState = {\n version: 1,\n backend: 'fixture',\n account: null,\n synced_at: null,\n dialogs: [],\n messages: [],\n}\n\nexport async function readCache(cachePath: string): Promise<CacheState> {\n try {\n const raw = await readFile(cachePath, 'utf8')\n return JSON.parse(raw) as CacheState\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return EMPTY_CACHE\n }\n\n throw error\n }\n}\n\nexport async function writeCache(cachePath: string, snapshot: SourceSnapshot): Promise<void> {\n const state: CacheState = {\n version: 1,\n backend: snapshot.backend,\n account: snapshot.account,\n synced_at: snapshot.synced_at,\n dialogs: snapshot.dialogs,\n messages: snapshot.messages,\n }\n\n await writeFile(cachePath, `${JSON.stringify(state, null, 2)}\\n`, 'utf8')\n}\n","import { readFile } from 'node:fs/promises'\nimport { TgsmError } from './errors'\nimport type { AuthStatus, SourceSnapshot, TgsmSourceAdapter } from './types'\n\ninterface FixtureFile {\n account?: SourceSnapshot['account']\n dialogs: SourceSnapshot['dialogs']\n messages: SourceSnapshot['messages']\n}\n\nexport class FixtureSource implements TgsmSourceAdapter {\n readonly backend = 'fixture' as const\n\n constructor(private readonly fixturePath: string) {}\n\n async sync(): Promise<SourceSnapshot> {\n const raw = await readFile(this.fixturePath, 'utf8')\n const parsed = JSON.parse(raw) as FixtureFile\n\n if (!Array.isArray(parsed.dialogs) || !Array.isArray(parsed.messages)) {\n throw new TgsmError({\n code: 'INVALID_FIXTURE',\n message: `Fixture at ${this.fixturePath} is missing dialogs/messages arrays`,\n retryable: false,\n })\n }\n\n const syncedAt = new Date().toISOString()\n\n return {\n backend: this.backend,\n account:\n parsed.account ??\n ({\n id: 'fixture',\n display_name: 'Fixture Account',\n } as const),\n dialogs: parsed.dialogs.map((dialog) => ({\n ...dialog,\n last_synced_at: syncedAt,\n })),\n messages: parsed.messages,\n synced_at: syncedAt,\n }\n }\n\n async authStatus(): Promise<AuthStatus> {\n return {\n authenticated: true,\n user: {\n id: 'fixture',\n display_name: 'Fixture Account',\n },\n }\n }\n}\n","import path from 'node:path'\nimport { readCache, writeCache } from './cache'\nimport { TgsmError } from './errors'\nimport type {\n BackreplyEdgeSummary,\n CacheMessageRecord,\n CacheState,\n ContextMessage,\n GetMessageOptions,\n ListMessagesOptions,\n MessageContextBundle,\n MessageEnvelope,\n MessageListItem,\n MessageRef,\n SavedDialogSummary,\n SearchResultPage,\n SyncResult,\n ThreadInspectNode,\n ThreadInspectResult,\n TgsmSourceAdapter,\n} from './types'\n\nexport interface TgsmServiceOptions {\n cachePath: string\n source?: TgsmSourceAdapter\n}\n\ninterface Indexes {\n dialogsById: Map<string, SavedDialogSummary>\n messagesByKey: Map<string, CacheMessageRecord>\n messagesByGlobalId: Map<number, CacheMessageRecord[]>\n messagesByDialog: Map<string, CacheMessageRecord[]>\n backreplyIndex: Map<string, CacheMessageRecord[]>\n}\n\nconst DEFAULT_CHRONOLOGY_LIMIT = 20\n\nexport class TgsmService {\n constructor(private readonly options: TgsmServiceOptions) {}\n\n async authLogin(input: Parameters<NonNullable<TgsmSourceAdapter['authLogin']>>[1]) {\n if (!this.options.source?.authLogin) {\n throw new TgsmError({\n code: 'AUTH_UNSUPPORTED',\n message: 'This backend does not support auth login.',\n retryable: false,\n })\n }\n\n return this.options.source.authLogin(this.accountDir(), input)\n }\n\n async authStatus() {\n if (!this.options.source?.authStatus) {\n return {\n authenticated: false,\n user: null,\n }\n }\n\n return this.options.source.authStatus(this.accountDir())\n }\n\n async sync(): Promise<SyncResult> {\n if (!this.options.source) {\n throw new TgsmError({\n code: 'SYNC_UNAVAILABLE',\n message: 'No source backend configured for sync.',\n retryable: false,\n })\n }\n\n const snapshot = await this.options.source.sync(this.accountDir())\n await writeCache(this.options.cachePath, snapshot)\n\n return {\n backend: snapshot.backend,\n synced_at: snapshot.synced_at,\n synced_dialogs: snapshot.dialogs.length,\n synced_messages: snapshot.messages.length,\n }\n }\n\n async listSavedDialogs(): Promise<SavedDialogSummary[]> {\n const cache = await this.loadCache()\n return [...cache.dialogs].sort((a, b) => {\n const left = a.last_synced_at ?? ''\n const right = b.last_synced_at ?? ''\n return right.localeCompare(left) || a.saved_peer_id.localeCompare(b.saved_peer_id)\n })\n }\n\n async listMessages(options: ListMessagesOptions = {}): Promise<SearchResultPage<MessageListItem>> {\n const cache = await this.loadCache()\n const indexes = this.buildIndexes(cache)\n const dialogId = options.dialog ?? null\n\n if (dialogId && !indexes.dialogsById.has(dialogId)) {\n throw new TgsmError({\n code: 'DIALOG_NOT_FOUND',\n message: `Saved dialog ${dialogId} was not found.`,\n retryable: false,\n suggestion: 'Run `tgsm saved-dialogs list` to inspect available dialogs.',\n })\n }\n\n const scoped = dialogId\n ? indexes.messagesByDialog.get(dialogId) ?? []\n : cache.messages\n\n const filtered = options.search\n ? scoped.filter((message: CacheMessageRecord) => matchesSearch(message, options.search!))\n : scoped\n\n const sorted = [...filtered].sort(compareByDateDesc)\n const limit = Math.max(1, options.limit ?? 20)\n const offset = decodeCursor(options.cursor)\n const slice = sorted.slice(offset, offset + limit)\n\n return {\n items: slice.map((message) => this.toMessageListItem(message, indexes)),\n scope: dialogId ? 'saved_dialog' : 'all_saved_dialogs',\n saved_peer_id: dialogId,\n next_cursor: offset + limit < sorted.length ? encodeCursor(offset + limit) : null,\n result_count: filtered.length,\n }\n }\n\n async getMessage(messageId: number, options: GetMessageOptions = {}): Promise<MessageContextBundle> {\n const cache = await this.loadCache()\n const indexes = this.buildIndexes(cache)\n const target = this.findMessage(indexes, messageId, options.dialog)\n return this.buildContextBundle(target, indexes)\n }\n\n async getContext(messageId: number, options: GetMessageOptions = {}): Promise<MessageContextBundle> {\n return this.getMessage(messageId, options)\n }\n\n async inspectThread(messageId: number, options: GetMessageOptions = {}): Promise<ThreadInspectResult> {\n const cache = await this.loadCache()\n const indexes = this.buildIndexes(cache)\n const target = this.findMessage(indexes, messageId, options.dialog)\n const root = this.findThreadRoot(target, indexes)\n const dialog = indexes.dialogsById.get(root.saved_peer_id)\n\n if (!dialog) {\n throw new TgsmError({\n code: 'DIALOG_NOT_FOUND',\n message: `Saved dialog ${root.saved_peer_id} was not found.`,\n retryable: false,\n })\n }\n\n return {\n dialog,\n root: this.toEnvelope(root, indexes),\n nodes: [this.buildThreadNode(root, indexes, 0)],\n }\n }\n\n private accountDir(): string {\n return path.dirname(this.options.cachePath)\n }\n\n private async loadCache(): Promise<CacheState> {\n return readCache(this.options.cachePath)\n }\n\n private buildIndexes(cache: CacheState): Indexes {\n const dialogsById = new Map<string, SavedDialogSummary>(\n cache.dialogs.map((dialog: SavedDialogSummary) => [dialog.saved_peer_id, dialog]),\n )\n const messagesByKey = new Map<string, CacheMessageRecord>()\n const messagesByGlobalId = new Map<number, CacheMessageRecord[]>()\n const messagesByDialog = new Map<string, CacheMessageRecord[]>()\n const backreplyIndex = new Map<string, CacheMessageRecord[]>()\n\n for (const message of cache.messages) {\n messagesByKey.set(makeMessageKey(message.saved_peer_id, message.message_id), message)\n\n const existingGlobal = messagesByGlobalId.get(message.message_id) ?? []\n existingGlobal.push(message)\n messagesByGlobalId.set(message.message_id, existingGlobal)\n\n const dialogMessages = messagesByDialog.get(message.saved_peer_id) ?? []\n dialogMessages.push(message)\n messagesByDialog.set(message.saved_peer_id, dialogMessages)\n\n if (message.reply_to_message_id !== null) {\n const replyDialog = message.reply_to_saved_peer_id ?? message.saved_peer_id\n const key = makeMessageKey(replyDialog, message.reply_to_message_id)\n const children = backreplyIndex.get(key) ?? []\n children.push(message)\n backreplyIndex.set(key, children)\n }\n }\n\n for (const records of messagesByDialog.values()) {\n records.sort(compareByDateAsc)\n }\n\n for (const records of backreplyIndex.values()) {\n records.sort(compareByDateAsc)\n }\n\n return {\n dialogsById,\n messagesByKey,\n messagesByGlobalId,\n messagesByDialog,\n backreplyIndex,\n }\n }\n\n private findMessage(indexes: Indexes, messageId: number, dialog?: string): CacheMessageRecord {\n if (dialog) {\n const scoped = indexes.messagesByKey.get(makeMessageKey(dialog, messageId))\n if (!scoped) {\n throw new TgsmError({\n code: 'MESSAGE_NOT_FOUND',\n message: `Message ${messageId} was not found in dialog ${dialog}.`,\n retryable: false,\n suggestion: 'Run `tgsm messages list --dialog <saved_peer_id>` to inspect the dialog.',\n })\n }\n return scoped\n }\n\n const candidates = indexes.messagesByGlobalId.get(messageId) ?? []\n\n if (candidates.length === 0) {\n throw new TgsmError({\n code: 'MESSAGE_NOT_FOUND',\n message: `Message ${messageId} was not found in the selected scope.`,\n retryable: false,\n suggestion: 'Run `tgsm messages list` or narrow the dialog scope.',\n })\n }\n\n if (candidates.length > 1) {\n throw new TgsmError({\n code: 'AMBIGUOUS_MESSAGE_ID',\n message: `Message ID ${messageId} exists in multiple saved dialogs.`,\n retryable: false,\n suggestion: 'Pass `--dialog <saved_peer_id>` to disambiguate.',\n })\n }\n\n return candidates[0]!\n }\n\n private buildContextBundle(target: CacheMessageRecord, indexes: Indexes): MessageContextBundle {\n const dialog = indexes.dialogsById.get(target.saved_peer_id)\n\n if (!dialog) {\n throw new TgsmError({\n code: 'DIALOG_NOT_FOUND',\n message: `Saved dialog ${target.saved_peer_id} was not found.`,\n retryable: false,\n })\n }\n\n const chronological = indexes.messagesByDialog.get(target.saved_peer_id) ?? []\n const targetIndex = chronological.findIndex(\n (message) => message.message_id === target.message_id && message.saved_peer_id === target.saved_peer_id,\n )\n\n const maxEachSide = Math.floor(DEFAULT_CHRONOLOGY_LIMIT / 2)\n const before = chronological.slice(Math.max(0, targetIndex - maxEachSide), targetIndex)\n const after = chronological.slice(targetIndex + 1, targetIndex + 1 + maxEachSide)\n\n const replyParent = target.reply_to_message_id\n ? indexes.messagesByKey.get(\n makeMessageKey(target.reply_to_saved_peer_id ?? target.saved_peer_id, target.reply_to_message_id),\n ) ?? null\n : null\n\n const directBackreplies =\n indexes.backreplyIndex.get(makeMessageKey(target.saved_peer_id, target.message_id)) ?? []\n\n const notes: string[] = []\n if (target.reply_to_message_id !== null && !replyParent) {\n notes.push(`Reply target #${target.reply_to_message_id} could not be resolved in cache.`)\n }\n\n const contexts = new Map<string, ContextMessage>()\n const pushContext = (\n message: CacheMessageRecord,\n role: ContextMessage['context_roles'][number],\n ): void => {\n const key = makeMessageKey(message.saved_peer_id, message.message_id)\n const existing = contexts.get(key)\n if (existing) {\n if (!existing.context_roles.includes(role)) {\n existing.context_roles.push(role)\n }\n return\n }\n\n contexts.set(key, {\n message: this.toEnvelope(message, indexes),\n context_roles: [role],\n })\n }\n\n for (const message of before) pushContext(message, 'chronology_before')\n if (replyParent) pushContext(replyParent, 'reply_parent')\n pushContext(target, 'target')\n for (const message of directBackreplies) pushContext(message, 'backreply_child')\n for (const message of after) pushContext(message, 'chronology_after')\n\n const contextMessages = [...contexts.values()].sort((left, right) => {\n const rank = (roles: ContextMessage['context_roles']): number => {\n if (roles.includes('chronology_before')) return 1\n if (roles.includes('reply_parent')) return 2\n if (roles.includes('target')) return 3\n if (roles.includes('backreply_child')) return 4\n return 5\n }\n\n return (\n rank(left.context_roles) - rank(right.context_roles) ||\n left.message.date.localeCompare(right.message.date) ||\n left.message.message_id - right.message.message_id\n )\n })\n\n return {\n target: this.toEnvelope(target, indexes),\n dialog,\n context_messages: contextMessages,\n window: {\n chronology_total_limit: DEFAULT_CHRONOLOGY_LIMIT,\n chronology_before_count: before.length,\n chronology_after_count: after.length,\n direct_reply_ancestor_included: Boolean(replyParent),\n direct_backreply_count_included: directBackreplies.length,\n },\n notes,\n }\n }\n\n private toMessageListItem(message: CacheMessageRecord, indexes: Indexes): MessageListItem {\n const dialog = indexes.dialogsById.get(message.saved_peer_id)\n const directBackreplyCount =\n indexes.backreplyIndex.get(makeMessageKey(message.saved_peer_id, message.message_id))?.length ?? 0\n\n return {\n message_id: message.message_id,\n saved_peer_id: message.saved_peer_id,\n dialog_title: dialog?.title ?? message.saved_peer_id,\n date: message.date,\n text_preview: previewText(message.text),\n from_self: message.from_self,\n forwarded: message.forwarded,\n reply_to_message_id: message.reply_to_message_id,\n direct_backreply_count: directBackreplyCount,\n queued_for_delete: message.queued_for_delete,\n }\n }\n\n private toEnvelope(message: CacheMessageRecord, indexes: Indexes): MessageEnvelope {\n const replyTarget =\n message.reply_to_message_id !== null\n ? indexes.messagesByKey.get(\n makeMessageKey(message.reply_to_saved_peer_id ?? message.saved_peer_id, message.reply_to_message_id),\n ) ?? null\n : null\n\n const directBackreplies =\n indexes.backreplyIndex.get(makeMessageKey(message.saved_peer_id, message.message_id)) ?? []\n\n const reply: MessageEnvelope['reply'] =\n message.reply_to_message_id === null\n ? {\n exists: false,\n target: null,\n status: 'resolved',\n }\n : {\n exists: true,\n target: replyTarget\n ? this.toMessageRef(replyTarget, 'reply_to')\n : {\n message_id: message.reply_to_message_id,\n saved_peer_id: message.reply_to_saved_peer_id ?? message.saved_peer_id,\n text_preview: '(missing from cache)',\n date: '',\n relationship: 'reply_to',\n },\n status: replyTarget ? 'resolved' : 'missing',\n }\n\n const backreplies: BackreplyEdgeSummary[] = directBackreplies.map((child) => ({\n message: this.toMessageRef(child, 'backreply'),\n thread_depth_from_target: 1,\n subtree_size_hint: this.countDescendants(child, indexes),\n }))\n\n return {\n message_id: message.message_id,\n saved_peer_id: message.saved_peer_id,\n date: message.date,\n edit_date: message.edit_date,\n text: message.text,\n text_preview: previewText(message.text),\n from_self: message.from_self,\n forwarded: message.forwarded,\n forward_origin: message.forward_origin,\n reply,\n backreplies,\n thread: {\n ancestors_known: this.countAncestors(message, indexes),\n direct_backreply_count: backreplies.length,\n descendant_count_hint: this.countDescendants(message, indexes),\n max_known_depth: this.maxDepth(message, indexes),\n },\n links: message.links,\n media_summary: message.media_summary,\n queued_for_delete: message.queued_for_delete,\n }\n }\n\n private toMessageRef(\n message: CacheMessageRecord,\n relationship: MessageRef['relationship'],\n ): MessageRef {\n return {\n message_id: message.message_id,\n saved_peer_id: message.saved_peer_id,\n text_preview: previewText(message.text),\n date: message.date,\n relationship,\n }\n }\n\n private findThreadRoot(message: CacheMessageRecord, indexes: Indexes): CacheMessageRecord {\n let current = message\n\n while (current.reply_to_message_id !== null) {\n const parent = indexes.messagesByKey.get(\n makeMessageKey(current.reply_to_saved_peer_id ?? current.saved_peer_id, current.reply_to_message_id),\n )\n if (!parent || parent.saved_peer_id !== current.saved_peer_id) {\n break\n }\n current = parent\n }\n\n return current\n }\n\n private buildThreadNode(\n message: CacheMessageRecord,\n indexes: Indexes,\n depth: number,\n ): ThreadInspectNode {\n const children =\n indexes.backreplyIndex.get(makeMessageKey(message.saved_peer_id, message.message_id)) ?? []\n\n return {\n message: this.toEnvelope(message, indexes),\n depth,\n children: children.map((child) => this.buildThreadNode(child, indexes, depth + 1)),\n }\n }\n\n private countAncestors(message: CacheMessageRecord, indexes: Indexes): number {\n let count = 0\n let current = message\n\n while (current.reply_to_message_id !== null) {\n const parent = indexes.messagesByKey.get(\n makeMessageKey(current.reply_to_saved_peer_id ?? current.saved_peer_id, current.reply_to_message_id),\n )\n if (!parent) break\n count += 1\n current = parent\n }\n\n return count\n }\n\n private countDescendants(message: CacheMessageRecord, indexes: Indexes): number {\n const children =\n indexes.backreplyIndex.get(makeMessageKey(message.saved_peer_id, message.message_id)) ?? []\n\n return children.reduce((count, child) => count + 1 + this.countDescendants(child, indexes), 0)\n }\n\n private maxDepth(message: CacheMessageRecord, indexes: Indexes): number {\n const children =\n indexes.backreplyIndex.get(makeMessageKey(message.saved_peer_id, message.message_id)) ?? []\n if (children.length === 0) return 0\n return 1 + Math.max(...children.map((child) => this.maxDepth(child, indexes)))\n }\n}\n\nfunction makeMessageKey(savedPeerId: string, messageId: number): string {\n return `${savedPeerId}:${messageId}`\n}\n\nfunction encodeCursor(offset: number): string {\n return Buffer.from(String(offset), 'utf8').toString('base64url')\n}\n\nfunction decodeCursor(cursor?: string | null): number {\n if (!cursor) return 0\n\n try {\n const value = Number(Buffer.from(cursor, 'base64url').toString('utf8'))\n return Number.isFinite(value) && value >= 0 ? value : 0\n } catch {\n return 0\n }\n}\n\nfunction compareByDateAsc(left: CacheMessageRecord, right: CacheMessageRecord): number {\n return left.date.localeCompare(right.date) || left.message_id - right.message_id\n}\n\nfunction compareByDateDesc(left: CacheMessageRecord, right: CacheMessageRecord): number {\n return right.date.localeCompare(left.date) || right.message_id - left.message_id\n}\n\nfunction matchesSearch(message: CacheMessageRecord, query: string): boolean {\n const normalized = query.trim().toLowerCase()\n if (!normalized) return true\n\n return [\n message.text,\n message.forward_origin?.title ?? '',\n message.saved_peer_id,\n ]\n .join('\\n')\n .toLowerCase()\n .includes(normalized)\n}\n\nfunction previewText(text: string, limit = 80): string {\n const normalized = text.replace(/\\s+/g, ' ').trim()\n if (!normalized) return '(no text)'\n return normalized.length <= limit ? normalized : `${normalized.slice(0, limit - 1)}…`\n}\n","import path from 'node:path'\nimport { createInterface } from 'node:readline/promises'\nimport { readFile, writeFile } from 'node:fs/promises'\nimport { TelegramClient, getMarkedPeerId, networkMiddlewares, type tl } from '@mtcute/node'\nimport { TgsmError } from './errors'\nimport type {\n AuthStatus,\n CacheMessageRecord,\n ForwardOriginSummary,\n LinkSummary,\n SavedDialogSummary,\n SourceSnapshot,\n TelegramLoginInput,\n TgsmSourceAdapter,\n} from './types'\n\ninterface TelegramConfig {\n apiId: number\n apiHash: string\n phone?: string\n}\n\ninterface EntityLookup {\n users: Map<number, tl.TypeUser>\n chats: Map<number, tl.TypeChat>\n selfUserId: number\n}\n\ninterface TelegramSourceOptions {\n debug?: boolean\n logger?: (event: string, fields?: Record<string, unknown>) => void\n}\n\nconst TELEGRAM_FLOOD_WAIT_MAX_MS = 30_000\nconst TELEGRAM_CONNECT_TIMEOUT_MS = 30_000\nconst TELEGRAM_RPC_TIMEOUT_MS = 45_000\nconst TELEGRAM_DESTROY_TIMEOUT_MS = 5_000\n\nexport class TelegramSource implements TgsmSourceAdapter {\n readonly backend = 'telegram' as const\n\n constructor(private readonly options: TelegramSourceOptions = {}) {}\n\n async authLogin(accountDir: string, input: TelegramLoginInput): Promise<AuthStatus> {\n const config: TelegramConfig = {\n apiId: input.apiId,\n apiHash: input.apiHash,\n phone: input.phone,\n }\n\n await saveTelegramConfig(accountDir, config)\n this.debug('auth.config_saved', { account_dir: accountDir, phone: input.phone })\n const client = createTelegramClient(accountDir, config, this.options)\n const rl = createInterface({\n input: process.stdin,\n output: process.stderr,\n })\n\n try {\n this.debug('auth.start.begin', { account_dir: accountDir })\n const user = await client.start({\n phone: input.phone,\n code: async () => {\n if (input.code && input.code.trim().length > 0) {\n return input.code\n }\n\n return rl.question('Code: ')\n },\n password: async () =>\n input.password ??\n (await rl.question('2FA password (leave empty if not enabled): ')),\n codeSentCallback: async (sentCode) => {\n const type =\n typeof sentCode.type === 'string'\n ? sentCode.type\n : 'unknown'\n process.stderr.write(`Login code requested via ${type}.\\n`)\n },\n invalidCodeCallback: async (type) => {\n process.stderr.write(`Invalid ${type}, please try again.\\n`)\n },\n })\n\n this.debug('auth.start.done', { user_id: String(user.id), display_name: user.displayName })\n return {\n authenticated: true,\n user: {\n id: String(user.id),\n display_name: user.displayName,\n },\n }\n } catch (error) {\n throw new TgsmError({\n code: 'AUTH_FAILED',\n message: error instanceof Error ? error.message : 'Telegram auth failed.',\n retryable: false,\n })\n } finally {\n this.debug('auth.cleanup.begin')\n rl.close()\n const cleanup = await destroyClientQuietly(client)\n this.debug('auth.cleanup.done', { status: cleanup })\n }\n }\n\n async authStatus(accountDir: string): Promise<AuthStatus> {\n const config = await loadTelegramConfig(accountDir)\n if (!config) {\n return {\n authenticated: false,\n user: null,\n }\n }\n\n const client = createTelegramClient(accountDir, config, this.options)\n\n try {\n this.debug('auth_status.start.begin', { account_dir: accountDir })\n await withTimeout(\n client.start({}),\n TELEGRAM_CONNECT_TIMEOUT_MS,\n 'Timed out while connecting to Telegram.',\n )\n const me = await client.getMe()\n this.debug('auth_status.start.done', { user_id: String(me.id), display_name: me.displayName })\n return {\n authenticated: true,\n user: {\n id: String(me.id),\n display_name: me.displayName,\n },\n }\n } catch {\n this.debug('auth_status.start.failed')\n return {\n authenticated: false,\n user: null,\n }\n } finally {\n this.debug('auth_status.cleanup.begin')\n const cleanup = await destroyClientQuietly(client)\n this.debug('auth_status.cleanup.done', { status: cleanup })\n }\n }\n\n async sync(accountDir: string): Promise<SourceSnapshot> {\n const config = await loadTelegramConfig(accountDir)\n if (!config) {\n throw new TgsmError({\n code: 'AUTH_REQUIRED',\n message: 'Telegram credentials are not configured.',\n retryable: false,\n suggestion: 'Run `tgsm auth login` first.',\n })\n }\n\n const client = createTelegramClient(accountDir, config, this.options)\n\n try {\n this.debug('sync.start.begin', { account_dir: accountDir })\n const me = await withTimeout(\n client.start({}),\n TELEGRAM_CONNECT_TIMEOUT_MS,\n 'Timed out while connecting to Telegram.',\n )\n this.debug('sync.start.done', { user_id: String(me.id), display_name: me.displayName })\n const syncedAt = new Date().toISOString()\n this.debug('sync.dialogs.begin')\n const dialogsResponse = await withTimeout(\n client.call({\n _: 'messages.getSavedDialogs',\n excludePinned: false,\n offsetDate: 0,\n offsetId: 0,\n offsetPeer: { _: 'inputPeerEmpty' },\n limit: 1000,\n hash: 0 as never,\n }, {\n maxRetryCount: 5,\n floodSleepThreshold: TELEGRAM_FLOOD_WAIT_MAX_MS,\n }),\n TELEGRAM_RPC_TIMEOUT_MS,\n 'Timed out while fetching saved dialogs from Telegram.',\n )\n this.debug('sync.dialogs.done', {\n result_type: dialogsResponse._,\n dialog_count:\n 'dialogs' in dialogsResponse && Array.isArray(dialogsResponse.dialogs)\n ? dialogsResponse.dialogs.length\n : 0,\n })\n\n if (dialogsResponse._ === 'messages.savedDialogsNotModified') {\n return {\n backend: this.backend,\n account: {\n id: String(me.id),\n display_name: me.displayName,\n },\n dialogs: [],\n messages: [],\n synced_at: syncedAt,\n }\n }\n\n const lookup: EntityLookup = {\n users: new Map(),\n chats: new Map(),\n selfUserId: Number(me.id),\n }\n\n ingestEntities(lookup, dialogsResponse.users, dialogsResponse.chats)\n\n const dialogs: SavedDialogSummary[] = []\n const messagesByKey = new Map<string, CacheMessageRecord>()\n\n for (const dialog of dialogsResponse.dialogs) {\n if (dialog._ !== 'savedDialog') continue\n\n const savedPeerId = savedPeerIdFromPeer(dialog.peer, lookup.selfUserId)\n const peerInput = await client.resolvePeer(getMarkedPeerId(dialog.peer))\n const title = peerTitle(dialog.peer, lookup)\n\n this.debug('sync.dialog_history.begin', {\n saved_peer_id: savedPeerId,\n title,\n top_message_id: dialog.topMessage ?? null,\n })\n const messages = await fetchSavedHistory(client, peerInput, lookup, this.options)\n this.debug('sync.dialog_history.done', {\n saved_peer_id: savedPeerId,\n title,\n message_count: messages.length,\n })\n const topMessage = messages.find((message) => message.message_id === dialog.topMessage) ?? messages[0] ?? null\n\n dialogs.push({\n saved_peer_id: savedPeerId,\n kind: peerKindFromPeer(dialog.peer, lookup.selfUserId),\n title,\n top_message_id: dialog.topMessage ?? topMessage?.message_id ?? null,\n top_text_preview: topMessage ? previewText(topMessage.text) : null,\n message_count: messages.length,\n pinned: dialog.pinned ?? null,\n last_synced_at: syncedAt,\n })\n\n for (const message of messages) {\n messagesByKey.set(`${message.saved_peer_id}:${message.message_id}`, message)\n }\n }\n\n return {\n backend: this.backend,\n account: {\n id: String(me.id),\n display_name: me.displayName,\n },\n dialogs,\n messages: [...messagesByKey.values()].sort((a, b) =>\n a.saved_peer_id.localeCompare(b.saved_peer_id) || a.date.localeCompare(b.date) || a.message_id - b.message_id,\n ),\n synced_at: syncedAt,\n }\n } catch (error) {\n this.debug('sync.failed', {\n message: error instanceof Error ? error.message : 'Unknown sync error',\n })\n throw new TgsmError({\n code: 'TELEGRAM_SYNC_FAILED',\n message: error instanceof Error ? error.message : 'Telegram sync failed.',\n retryable: true,\n })\n } finally {\n this.debug('sync.cleanup.begin')\n const cleanup = await destroyClientQuietly(client)\n this.debug('sync.cleanup.done', { status: cleanup })\n }\n }\n\n private debug(event: string, fields: Record<string, unknown> = {}): void {\n if (!this.options.debug) return\n this.options.logger?.(event, fields)\n }\n}\n\nfunction createTelegramClient(\n accountDir: string,\n config: TelegramConfig,\n options: TelegramSourceOptions,\n): TelegramClient {\n const client = new TelegramClient({\n apiId: config.apiId,\n apiHash: config.apiHash,\n storage: path.join(accountDir, 'mtcute-session'),\n logLevel: 0,\n network: {\n middlewares: networkMiddlewares.basic({\n floodWaiter: {\n maxWait: TELEGRAM_FLOOD_WAIT_MAX_MS,\n maxRetries: 5,\n onBeforeWait: (ctx, seconds) => {\n options.logger?.('telegram.flood_wait', {\n seconds,\n method: ctx.request._,\n })\n },\n },\n }),\n },\n })\n\n if (options.debug) {\n client.onConnectionState.add((state) => {\n options.logger?.('telegram.connection_state', { state })\n })\n client.onError.add((error) => {\n options.logger?.('telegram.client_error', {\n message: error.message,\n name: error.name,\n })\n })\n }\n\n return client\n}\n\nasync function destroyClientQuietly(client: TelegramClient): Promise<'destroyed' | 'timed_out' | 'failed'> {\n try {\n await withTimeout(\n client.destroy(),\n TELEGRAM_DESTROY_TIMEOUT_MS,\n 'Timed out while closing Telegram client.',\n )\n return 'destroyed'\n } catch (error) {\n if (error instanceof Error && error.message === 'Timed out while closing Telegram client.') {\n return 'timed_out'\n }\n return 'failed'\n }\n}\n\nasync function fetchSavedHistory(\n client: TelegramClient,\n peer: tl.TypeInputPeer,\n lookup: EntityLookup,\n options: TelegramSourceOptions,\n): Promise<CacheMessageRecord[]> {\n let offsetId = 0\n let offsetDate = 0\n const records = new Map<string, CacheMessageRecord>()\n let pages = 0\n\n while (true) {\n pages += 1\n if (options.debug) {\n options.logger?.('sync.dialog_history.page.begin', {\n page: pages,\n offset_id: offsetId,\n offset_date: offsetDate,\n })\n }\n const history = await withTimeout(\n client.call({\n _: 'messages.getSavedHistory',\n peer,\n offsetId,\n offsetDate,\n addOffset: 0,\n limit: 100,\n maxId: 0,\n minId: 0,\n hash: 0 as never,\n }, {\n maxRetryCount: 5,\n floodSleepThreshold: TELEGRAM_FLOOD_WAIT_MAX_MS,\n }),\n TELEGRAM_RPC_TIMEOUT_MS,\n 'Timed out while fetching saved history from Telegram.',\n )\n if (options.debug) {\n options.logger?.('sync.dialog_history.page.done', {\n page: pages,\n result_type: history._,\n message_count: 'messages' in history ? history.messages.length : 0,\n })\n }\n\n if (!('messages' in history)) {\n break\n }\n\n ingestEntities(lookup, history.users ?? [], history.chats ?? [])\n\n const rawMessages = history.messages.filter(\n (message: tl.TypeMessage): message is tl.RawMessage | tl.RawMessageService =>\n message._ === 'message' || message._ === 'messageService',\n )\n\n if (rawMessages.length === 0) {\n break\n }\n\n for (const raw of rawMessages) {\n const record = normalizeRawMessage(raw, lookup)\n records.set(`${record.saved_peer_id}:${record.message_id}`, record)\n }\n\n const oldest = rawMessages[rawMessages.length - 1]!\n offsetId = oldest.id\n offsetDate = oldest.date\n\n if (rawMessages.length < 100) {\n break\n }\n }\n\n return [...records.values()].sort((a, b) => a.date.localeCompare(b.date) || a.message_id - b.message_id)\n}\n\nexport function normalizeRawMessage(raw: tl.RawMessage | tl.RawMessageService, lookup: EntityLookup): CacheMessageRecord {\n const savedPeerId = savedPeerIdFromPeer(raw.peerId, lookup.selfUserId)\n const replyHeader =\n 'replyTo' in raw && raw.replyTo && raw.replyTo._ === 'messageReplyHeader' ? raw.replyTo : null\n const replyPeer = replyHeader?.replyToPeerId ?? raw.peerId\n const fwdFrom = 'fwdFrom' in raw ? raw.fwdFrom : undefined\n const editDate = 'editDate' in raw ? raw.editDate : undefined\n const media = 'media' in raw ? raw.media : undefined\n const text = 'message' in raw ? raw.message : ''\n\n return {\n message_id: raw.id,\n saved_peer_id: savedPeerId,\n date: new Date(raw.date * 1000).toISOString(),\n edit_date: editDate ? new Date(editDate * 1000).toISOString() : null,\n text,\n from_self:\n ('out' in raw ? Boolean(raw.out) : false) ||\n peerIsSelf('fromId' in raw ? raw.fromId : null, lookup.selfUserId) ||\n (savedPeerId === 'self' && !fwdFrom),\n forwarded: Boolean(fwdFrom),\n forward_origin: fwdFrom ? forwardOriginFromHeader(fwdFrom, lookup) : null,\n reply_to_message_id: replyHeader?.replyToMsgId ?? null,\n reply_to_saved_peer_id: replyHeader?.replyToMsgId\n ? savedPeerIdFromPeer(replyPeer, lookup.selfUserId)\n : null,\n links: extractLinks(text),\n media_summary: mediaSummary(media),\n queued_for_delete: false,\n }\n}\n\nfunction forwardOriginFromHeader(\n header: tl.RawMessageFwdHeader,\n lookup: EntityLookup,\n): ForwardOriginSummary {\n if (header.savedFromPeer) {\n return {\n saved_peer_id: savedPeerIdFromPeer(header.savedFromPeer, lookup.selfUserId),\n title: peerTitle(header.savedFromPeer, lookup),\n message_id: header.savedFromMsgId ?? null,\n }\n }\n\n if (header.fromId) {\n return {\n saved_peer_id: savedPeerIdFromPeer(header.fromId, lookup.selfUserId),\n title: header.fromName ?? peerTitle(header.fromId, lookup),\n message_id: header.savedFromMsgId ?? null,\n }\n }\n\n return {\n saved_peer_id: null,\n title: header.fromName ?? header.savedFromName ?? null,\n message_id: header.savedFromMsgId ?? null,\n }\n}\n\nfunction peerIsSelf(peer: tl.TypePeer | undefined | null, selfUserId: number): boolean {\n return Boolean(peer && peer._ === 'peerUser' && peer.userId === selfUserId)\n}\n\nfunction peerKindFromPeer(peer: tl.TypePeer, selfUserId: number): SavedDialogSummary['kind'] {\n if (peer._ === 'peerUser' && peer.userId === selfUserId) return 'self'\n if (peer._ === 'peerUser' || peer._ === 'peerChat') return 'peer'\n if (peer._ === 'peerChannel') return 'channel'\n return 'unknown'\n}\n\nexport function savedPeerIdFromPeer(peer: tl.TypePeer, selfUserId: number): string {\n if (peer._ === 'peerUser' && peer.userId === selfUserId) {\n return 'self'\n }\n\n if (peer._ === 'peerUser') return `user:${peer.userId}`\n if (peer._ === 'peerChat') return `chat:${peer.chatId}`\n if (peer._ === 'peerChannel') return `channel:${peer.channelId}`\n return `unknown:${getMarkedPeerId(peer)}`\n}\n\nfunction peerTitle(peer: tl.TypePeer, lookup: EntityLookup): string {\n if (peer._ === 'peerUser') {\n if (peer.userId === lookup.selfUserId) return 'Self'\n const user = lookup.users.get(peer.userId)\n const firstName = user && user._ === 'user' ? user.firstName ?? '' : ''\n const lastName = user && user._ === 'user' ? user.lastName ?? '' : ''\n const username = user && user._ === 'user' ? user.username ?? '' : ''\n const parts = [firstName, lastName].filter(Boolean)\n return parts.join(' ').trim() || username || `User ${peer.userId}`\n }\n\n const entity = lookup.chats.get(peer._ === 'peerChat' ? peer.chatId : peer.channelId)\n if (entity && 'title' in entity) {\n return entity.title\n }\n\n if (peer._ === 'peerChat') return `Chat ${peer.chatId}`\n if (peer._ === 'peerChannel') return `Channel ${peer.channelId}`\n return 'Unknown'\n}\n\nfunction ingestEntities(lookup: EntityLookup, users: tl.TypeUser[], chats: tl.TypeChat[]): void {\n for (const user of users) {\n if ('id' in user) {\n lookup.users.set(Number(user.id), user)\n }\n }\n\n for (const chat of chats) {\n if ('id' in chat) {\n lookup.chats.set(Number(chat.id), chat)\n }\n }\n}\n\nfunction extractLinks(text: string): LinkSummary[] {\n const matches = text.matchAll(/https?:\\/\\/[^\\s)]+/g)\n const seen = new Set<string>()\n const links: LinkSummary[] = []\n\n for (const match of matches) {\n const url = match[0]!\n if (seen.has(url)) continue\n seen.add(url)\n links.push({ url })\n }\n\n return links\n}\n\nfunction mediaSummary(media: tl.TypeMessageMedia | undefined): string | null {\n if (!media) return null\n return media._\n}\n\nfunction previewText(text: string, limit = 80): string {\n const normalized = text.replace(/\\s+/g, ' ').trim()\n if (!normalized) return '(no text)'\n return normalized.length <= limit ? normalized : `${normalized.slice(0, limit - 1)}…`\n}\n\nasync function loadTelegramConfig(accountDir: string): Promise<TelegramConfig | null> {\n try {\n const raw = await readFile(path.join(accountDir, 'telegram.json'), 'utf8')\n return JSON.parse(raw) as TelegramConfig\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return null\n throw error\n }\n}\n\nasync function saveTelegramConfig(accountDir: string, config: TelegramConfig): Promise<void> {\n await writeFile(\n path.join(accountDir, 'telegram.json'),\n `${JSON.stringify(config, null, 2)}\\n`,\n 'utf8',\n )\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n message: string,\n): Promise<T> {\n let timer: NodeJS.Timeout | undefined\n\n try {\n return await Promise.race([\n promise,\n new Promise<T>((_, reject) => {\n timer = setTimeout(() => {\n reject(new Error(message))\n }, timeoutMs)\n }),\n ])\n } finally {\n if (timer) {\n clearTimeout(timer)\n }\n }\n}\n","import type {\n AuthStatus,\n MessageContextBundle,\n MessageListItem,\n SavedDialogSummary,\n SearchResultPage,\n SyncResult,\n ThreadInspectNode,\n ThreadInspectResult,\n} from '@tgsm/core'\n\nexport function formatSyncResult(result: SyncResult): string {\n return [\n `sync backend=${result.backend}`,\n `synced_at=${result.synced_at}`,\n `dialogs=${result.synced_dialogs}`,\n `messages=${result.synced_messages}`,\n ].join('\\n')\n}\n\nexport function formatAuthStatus(status: AuthStatus): string {\n if (!status.authenticated || !status.user) {\n return 'authenticated: false'\n }\n\n return [`authenticated: true`, `user: ${status.user.display_name}`, `id: ${status.user.id}`].join('\\n')\n}\n\nexport function formatSavedDialogs(dialogs: SavedDialogSummary[]): string {\n if (dialogs.length === 0) return 'No saved dialogs found.'\n\n return dialogs\n .map((dialog) =>\n [\n `${dialog.saved_peer_id} (${dialog.kind})`,\n `title: ${dialog.title}`,\n `messages: ${dialog.message_count}`,\n `top_message_id: ${dialog.top_message_id ?? 'n/a'}`,\n `top_text: ${dialog.top_text_preview ?? '(none)'}`,\n ].join('\\n'),\n )\n .join('\\n\\n')\n}\n\nexport function formatMessagesPage(page: SearchResultPage<MessageListItem>): string {\n if (page.items.length === 0) return 'No messages found.'\n\n const header =\n page.scope === 'saved_dialog'\n ? `messages scope=${page.saved_peer_id} total=${page.result_count}`\n : `messages scope=all_saved_dialogs total=${page.result_count}`\n\n const blocks = page.items.map((item) =>\n [\n `#${item.message_id} ${item.date}`,\n `dialog: ${item.saved_peer_id} (${item.dialog_title})`,\n `from_self: ${item.from_self} forwarded: ${item.forwarded}`,\n `reply_to: ${item.reply_to_message_id ?? 'none'} backreplies: ${item.direct_backreply_count}`,\n `text: ${item.text_preview}`,\n ].join('\\n'),\n )\n\n return [header, ...blocks, page.next_cursor ? `next_cursor: ${page.next_cursor}` : ''].filter(Boolean).join('\\n\\n')\n}\n\nexport function formatContextBundle(bundle: MessageContextBundle): string {\n const lines: string[] = [\n `MESSAGE #${bundle.target.message_id}`,\n `dialog: ${bundle.dialog.saved_peer_id} (${bundle.dialog.title})`,\n `date: ${bundle.target.date}`,\n `from_self: ${bundle.target.from_self}`,\n `thread: direct_backreplies=${bundle.target.thread.direct_backreply_count} descendant_hint=${bundle.target.thread.descendant_count_hint ?? 0}`,\n '',\n 'text:',\n bundle.target.text || '(no text)',\n ]\n\n const replySection = bundle.target.reply.exists\n ? bundle.target.reply.target\n ? [``, 'reply_to:', `- #${bundle.target.reply.target.message_id} ${bundle.target.reply.target.text_preview}`]\n : [``, 'reply_to:', '- (missing from cache)']\n : []\n\n const backreplySection =\n bundle.target.backreplies.length > 0\n ? [\n '',\n 'backreplies:',\n ...bundle.target.backreplies.map(\n (item) => `- #${item.message.message_id} ${item.message.text_preview}`,\n ),\n ]\n : []\n\n const before = bundle.context_messages.filter((item) => item.context_roles.includes('chronology_before'))\n const after = bundle.context_messages.filter((item) => item.context_roles.includes('chronology_after'))\n\n if (before.length > 0) {\n lines.push('', 'chronology_before:')\n for (const item of before) lines.push(`- #${item.message.message_id} ${item.message.text_preview}`)\n }\n\n if (after.length > 0) {\n lines.push('', 'chronology_after:')\n for (const item of after) lines.push(`- #${item.message.message_id} ${item.message.text_preview}`)\n }\n\n lines.push(...replySection, ...backreplySection)\n\n if (bundle.notes.length > 0) {\n lines.push('', 'notes:')\n for (const note of bundle.notes) lines.push(`- ${note}`)\n }\n\n return lines.join('\\n')\n}\n\nexport function formatThread(result: ThreadInspectResult): string {\n const lines = [`THREAD #${result.root.message_id}`, `dialog: ${result.dialog.saved_peer_id} (${result.dialog.title})`, '']\n\n const root = result.nodes[0]\n if (!root) return lines.join('\\n')\n\n renderNode(root, '', true, lines)\n return lines.join('\\n')\n}\n\nfunction renderNode(node: ThreadInspectNode, prefix: string, isLast: boolean, lines: string[]): void {\n const branch = prefix ? `${prefix}${isLast ? '└── ' : '├── '}` : ''\n lines.push(`${branch}#${node.message.message_id} ${node.message.text_preview}`)\n\n const nextPrefix = prefix ? `${prefix}${isLast ? ' ' : '│ '}` : ''\n node.children.forEach((child, index) => {\n renderNode(child, nextPrefix, index === node.children.length - 1, lines)\n })\n}\n","{\n \"name\": \"@imadtg/tgsm\",\n \"version\": \"0.0.7\",\n \"type\": \"module\",\n \"description\": \"A retrieval-first CLI for navigating Telegram Saved Messages as structured, agent-readable context.\",\n \"license\": \"MIT\",\n \"homepage\": \"https://github.com/imadtg/tgsm\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/imadtg/tgsm.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/imadtg/tgsm/issues\"\n },\n \"keywords\": [\n \"telegram\",\n \"saved-messages\",\n \"cli\",\n \"agents\",\n \"mtproto\"\n ],\n \"engines\": {\n \"node\": \">=20\"\n },\n \"bin\": {\n \"tgsm\": \"dist/index.js\"\n },\n \"main\": \"./dist/index.js\",\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"test\": \"bun test\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"dependencies\": {\n \"@mtcute/node\": \"^0.28.2\",\n \"commander\": \"^14.0.1\"\n },\n \"devDependencies\": {\n \"@tgsm/core\": \"workspace:*\"\n }\n}\n"],"mappings":"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","names":["createInterface","process","readFile","readFile","path","path","path","readFile","writeFile","messages","previewText","path","readFile","writeFile","createInterface","process"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imadtg/tgsm",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "type": "module",
5
5
  "description": "A retrieval-first CLI for navigating Telegram Saved Messages as structured, agent-readable context.",
6
6
  "license": "MIT",
@@ -43,6 +43,6 @@
43
43
  "commander": "^14.0.1"
44
44
  },
45
45
  "devDependencies": {
46
- "@tgsm/core": "workspace:*"
46
+ "@tgsm/core": "0.0.1"
47
47
  }
48
48
  }