@imadtg/tgsm 0.0.2 → 0.0.4
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 +58 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -554,7 +554,12 @@ var TelegramSource = class {
|
|
|
554
554
|
try {
|
|
555
555
|
const user = await client.start({
|
|
556
556
|
phone: input.phone,
|
|
557
|
-
code: async () =>
|
|
557
|
+
code: async () => {
|
|
558
|
+
if (input.code && input.code.trim().length > 0) {
|
|
559
|
+
return input.code;
|
|
560
|
+
}
|
|
561
|
+
return rl.question("Code: ");
|
|
562
|
+
},
|
|
558
563
|
password: async () => input.password ?? await rl.question("2FA password (leave empty if not enabled): "),
|
|
559
564
|
codeSentCallback: async (sentCode) => {
|
|
560
565
|
const type = typeof sentCode.type === "string" ? sentCode.type : "unknown";
|
|
@@ -968,9 +973,59 @@ function renderNode(node, prefix, isLast, lines) {
|
|
|
968
973
|
});
|
|
969
974
|
}
|
|
970
975
|
|
|
976
|
+
// package.json
|
|
977
|
+
var package_default = {
|
|
978
|
+
name: "@imadtg/tgsm",
|
|
979
|
+
version: "0.0.4",
|
|
980
|
+
type: "module",
|
|
981
|
+
description: "A retrieval-first CLI for navigating Telegram Saved Messages as structured, agent-readable context.",
|
|
982
|
+
license: "MIT",
|
|
983
|
+
homepage: "https://github.com/imadtg/tgsm",
|
|
984
|
+
repository: {
|
|
985
|
+
type: "git",
|
|
986
|
+
url: "git+https://github.com/imadtg/tgsm.git"
|
|
987
|
+
},
|
|
988
|
+
bugs: {
|
|
989
|
+
url: "https://github.com/imadtg/tgsm/issues"
|
|
990
|
+
},
|
|
991
|
+
keywords: [
|
|
992
|
+
"telegram",
|
|
993
|
+
"saved-messages",
|
|
994
|
+
"cli",
|
|
995
|
+
"agents",
|
|
996
|
+
"mtproto"
|
|
997
|
+
],
|
|
998
|
+
engines: {
|
|
999
|
+
node: ">=20"
|
|
1000
|
+
},
|
|
1001
|
+
bin: {
|
|
1002
|
+
tgsm: "dist/index.js"
|
|
1003
|
+
},
|
|
1004
|
+
main: "./dist/index.js",
|
|
1005
|
+
files: [
|
|
1006
|
+
"dist",
|
|
1007
|
+
"README.md",
|
|
1008
|
+
"LICENSE"
|
|
1009
|
+
],
|
|
1010
|
+
scripts: {
|
|
1011
|
+
build: "tsup",
|
|
1012
|
+
test: "bun test"
|
|
1013
|
+
},
|
|
1014
|
+
publishConfig: {
|
|
1015
|
+
access: "public"
|
|
1016
|
+
},
|
|
1017
|
+
dependencies: {
|
|
1018
|
+
"@mtcute/node": "^0.28.2",
|
|
1019
|
+
commander: "^14.0.1"
|
|
1020
|
+
},
|
|
1021
|
+
devDependencies: {
|
|
1022
|
+
"@tgsm/core": "workspace:*"
|
|
1023
|
+
}
|
|
1024
|
+
};
|
|
1025
|
+
|
|
971
1026
|
// src/index.ts
|
|
972
1027
|
var program = new Command();
|
|
973
|
-
program.name("tgsm").description("Retrieval-first Telegram Saved Messages CLI").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");
|
|
1028
|
+
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");
|
|
974
1029
|
program.command("auth").description("Telegram auth commands").addCommand(
|
|
975
1030
|
new Command("login").action(async (_, command) => {
|
|
976
1031
|
await withService(command.optsWithGlobals(), async (service, options) => {
|
|
@@ -992,8 +1047,7 @@ program.command("auth").description("Telegram auth commands").addCommand(
|
|
|
992
1047
|
const result = await service.authLogin({
|
|
993
1048
|
apiId,
|
|
994
1049
|
apiHash,
|
|
995
|
-
phone
|
|
996
|
-
code: ""
|
|
1050
|
+
phone
|
|
997
1051
|
});
|
|
998
1052
|
emit(result, options);
|
|
999
1053
|
} finally {
|
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"],"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'\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 .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 code: '',\n })\n\n emit(result, options)\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 = new TelegramClient({\n apiId: config.apiId,\n apiHash: config.apiHash,\n storage: path.join(accountDir, 'mtcute-session'),\n })\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 () => input.code ?? (await rl.question('Code: ')),\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 // no-op: client storage/session is managed by mtcute\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 = new TelegramClient({\n apiId: config.apiId,\n apiHash: config.apiHash,\n storage: path.join(accountDir, 'mtcute-session'),\n })\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 // no-op: client storage/session is managed by mtcute\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 = new TelegramClient({\n apiId: config.apiId,\n apiHash: config.apiHash,\n storage: path.join(accountDir, 'mtcute-session'),\n })\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 // no-op: client storage/session is managed by mtcute\n }\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"],"mappings":";;;AAAA,SAAS,mBAAAA,wBAAuB;AAChC,OAAOC,cAAa;AACpB,SAAS,eAAe;;;ACAjB,IAAM,YAAN,cAAwB,MAAM;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,OAA4B;AACtC,UAAM,MAAM,OAAO;AACnB,SAAK,OAAO;AACZ,SAAK,OAAO,MAAM;AAClB,SAAK,YAAY,MAAM;AACvB,SAAK,aAAa,MAAM;AAAA,EAC1B;AAAA,EAEA,SAA8B;AAC5B,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,WAAW,KAAK;AAAA,MAChB,YAAY,KAAK;AAAA,IACnB;AAAA,EACF;AACF;;;ACvBA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,aAAa;AAOf,SAAS,WAAW,SAA0B;AACnD,SAAO,WAAW,QAAQ,IAAI,aAAa,KAAK,KAAK,GAAG,QAAQ,GAAG,OAAO;AAC5E;AAEO,SAAS,eAAe,SAA0B;AACvD,SAAO,WAAW;AACpB;AAEO,SAAS,cAAc,UAAuB,CAAC,GAAW;AAC/D,SAAO,KAAK,KAAK,WAAW,QAAQ,OAAO,GAAG,eAAe,QAAQ,OAAO,CAAC;AAC/E;AAEO,SAAS,aAAa,UAAuB,CAAC,GAAW;AAC9D,SAAO,KAAK,KAAK,cAAc,OAAO,GAAG,YAAY;AACvD;AAUA,eAAsB,iBAAiB,UAAuB,CAAC,GAAoB;AACjF,QAAM,aAAa,cAAc,OAAO;AACxC,QAAM,MAAM,YAAY,EAAE,WAAW,KAAK,CAAC;AAC3C,SAAO;AACT;;;ACrCA,SAAS,UAAU,iBAAiB;AAG7B,IAAM,cAA0B;AAAA,EACrC,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,WAAW;AAAA,EACX,SAAS,CAAC;AAAA,EACV,UAAU,CAAC;AACb;AAEA,eAAsB,UAAU,WAAwC;AACtE,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,WAAW,MAAM;AAC5C,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,UAAU;AACtD,aAAO;AAAA,IACT;AAEA,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,WAAW,WAAmB,UAAyC;AAC3F,QAAM,QAAoB;AAAA,IACxB,SAAS;AAAA,IACT,SAAS,SAAS;AAAA,IAClB,SAAS,SAAS;AAAA,IAClB,WAAW,SAAS;AAAA,IACpB,SAAS,SAAS;AAAA,IAClB,UAAU,SAAS;AAAA,EACrB;AAEA,QAAM,UAAU,WAAW,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AAC1E;;;ACpCA,SAAS,YAAAC,iBAAgB;AAUlB,IAAM,gBAAN,MAAiD;AAAA,EAGtD,YAA6B,aAAqB;AAArB;AAAA,EAAsB;AAAA,EAF1C,UAAU;AAAA,EAInB,MAAM,OAAgC;AACpC,UAAM,MAAM,MAAMC,UAAS,KAAK,aAAa,MAAM;AACnD,UAAM,SAAS,KAAK,MAAM,GAAG;AAE7B,QAAI,CAAC,MAAM,QAAQ,OAAO,OAAO,KAAK,CAAC,MAAM,QAAQ,OAAO,QAAQ,GAAG;AACrE,YAAM,IAAI,UAAU;AAAA,QAClB,MAAM;AAAA,QACN,SAAS,cAAc,KAAK,WAAW;AAAA,QACvC,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAEA,UAAM,YAAW,oBAAI,KAAK,GAAE,YAAY;AAExC,WAAO;AAAA,MACL,SAAS,KAAK;AAAA,MACd,SACE,OAAO,WACN;AAAA,QACC,IAAI;AAAA,QACJ,cAAc;AAAA,MAChB;AAAA,MACF,SAAS,OAAO,QAAQ,IAAI,CAAC,YAAY;AAAA,QACvC,GAAG;AAAA,QACH,gBAAgB;AAAA,MAClB,EAAE;AAAA,MACF,UAAU,OAAO;AAAA,MACjB,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EAEA,MAAM,aAAkC;AACtC,WAAO;AAAA,MACL,eAAe;AAAA,MACf,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,cAAc;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACF;;;ACvDA,OAAOC,WAAU;AAmCjB,IAAM,2BAA2B;AAE1B,IAAM,cAAN,MAAkB;AAAA,EACvB,YAA6B,SAA6B;AAA7B;AAAA,EAA8B;AAAA,EAE3D,MAAM,UAAU,OAAmE;AACjF,QAAI,CAAC,KAAK,QAAQ,QAAQ,WAAW;AACnC,YAAM,IAAI,UAAU;AAAA,QAClB,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAEA,WAAO,KAAK,QAAQ,OAAO,UAAU,KAAK,WAAW,GAAG,KAAK;AAAA,EAC/D;AAAA,EAEA,MAAM,aAAa;AACjB,QAAI,CAAC,KAAK,QAAQ,QAAQ,YAAY;AACpC,aAAO;AAAA,QACL,eAAe;AAAA,QACf,MAAM;AAAA,MACR;AAAA,IACF;AAEA,WAAO,KAAK,QAAQ,OAAO,WAAW,KAAK,WAAW,CAAC;AAAA,EACzD;AAAA,EAEA,MAAM,OAA4B;AAChC,QAAI,CAAC,KAAK,QAAQ,QAAQ;AACxB,YAAM,IAAI,UAAU;AAAA,QAClB,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAEA,UAAM,WAAW,MAAM,KAAK,QAAQ,OAAO,KAAK,KAAK,WAAW,CAAC;AACjE,UAAM,WAAW,KAAK,QAAQ,WAAW,QAAQ;AAEjD,WAAO;AAAA,MACL,SAAS,SAAS;AAAA,MAClB,WAAW,SAAS;AAAA,MACpB,gBAAgB,SAAS,QAAQ;AAAA,MACjC,iBAAiB,SAAS,SAAS;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,MAAM,mBAAkD;AACtD,UAAM,QAAQ,MAAM,KAAK,UAAU;AACnC,WAAO,CAAC,GAAG,MAAM,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AACvC,YAAM,OAAO,EAAE,kBAAkB;AACjC,YAAM,QAAQ,EAAE,kBAAkB;AAClC,aAAO,MAAM,cAAc,IAAI,KAAK,EAAE,cAAc,cAAc,EAAE,aAAa;AAAA,IACnF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,aAAa,UAA+B,CAAC,GAA+C;AAChG,UAAM,QAAQ,MAAM,KAAK,UAAU;AACnC,UAAM,UAAU,KAAK,aAAa,KAAK;AACvC,UAAM,WAAW,QAAQ,UAAU;AAEnC,QAAI,YAAY,CAAC,QAAQ,YAAY,IAAI,QAAQ,GAAG;AAClD,YAAM,IAAI,UAAU;AAAA,QAClB,MAAM;AAAA,QACN,SAAS,gBAAgB,QAAQ;AAAA,QACjC,WAAW;AAAA,QACX,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAEA,UAAM,SAAS,WACX,QAAQ,iBAAiB,IAAI,QAAQ,KAAK,CAAC,IAC3C,MAAM;AAEV,UAAM,WAAW,QAAQ,SACrB,OAAO,OAAO,CAAC,YAAgC,cAAc,SAAS,QAAQ,MAAO,CAAC,IACtF;AAEJ,UAAM,SAAS,CAAC,GAAG,QAAQ,EAAE,KAAK,iBAAiB;AACnD,UAAM,QAAQ,KAAK,IAAI,GAAG,QAAQ,SAAS,EAAE;AAC7C,UAAM,SAAS,aAAa,QAAQ,MAAM;AAC1C,UAAM,QAAQ,OAAO,MAAM,QAAQ,SAAS,KAAK;AAEjD,WAAO;AAAA,MACL,OAAO,MAAM,IAAI,CAAC,YAAY,KAAK,kBAAkB,SAAS,OAAO,CAAC;AAAA,MACtE,OAAO,WAAW,iBAAiB;AAAA,MACnC,eAAe;AAAA,MACf,aAAa,SAAS,QAAQ,OAAO,SAAS,aAAa,SAAS,KAAK,IAAI;AAAA,MAC7E,cAAc,SAAS;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,WAAmB,UAA6B,CAAC,GAAkC;AAClG,UAAM,QAAQ,MAAM,KAAK,UAAU;AACnC,UAAM,UAAU,KAAK,aAAa,KAAK;AACvC,UAAM,SAAS,KAAK,YAAY,SAAS,WAAW,QAAQ,MAAM;AAClE,WAAO,KAAK,mBAAmB,QAAQ,OAAO;AAAA,EAChD;AAAA,EAEA,MAAM,WAAW,WAAmB,UAA6B,CAAC,GAAkC;AAClG,WAAO,KAAK,WAAW,WAAW,OAAO;AAAA,EAC3C;AAAA,EAEA,MAAM,cAAc,WAAmB,UAA6B,CAAC,GAAiC;AACpG,UAAM,QAAQ,MAAM,KAAK,UAAU;AACnC,UAAM,UAAU,KAAK,aAAa,KAAK;AACvC,UAAM,SAAS,KAAK,YAAY,SAAS,WAAW,QAAQ,MAAM;AAClE,UAAM,OAAO,KAAK,eAAe,QAAQ,OAAO;AAChD,UAAM,SAAS,QAAQ,YAAY,IAAI,KAAK,aAAa;AAEzD,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,UAAU;AAAA,QAClB,MAAM;AAAA,QACN,SAAS,gBAAgB,KAAK,aAAa;AAAA,QAC3C,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL;AAAA,MACA,MAAM,KAAK,WAAW,MAAM,OAAO;AAAA,MACnC,OAAO,CAAC,KAAK,gBAAgB,MAAM,SAAS,CAAC,CAAC;AAAA,IAChD;AAAA,EACF;AAAA,EAEQ,aAAqB;AAC3B,WAAOC,MAAK,QAAQ,KAAK,QAAQ,SAAS;AAAA,EAC5C;AAAA,EAEA,MAAc,YAAiC;AAC7C,WAAO,UAAU,KAAK,QAAQ,SAAS;AAAA,EACzC;AAAA,EAEQ,aAAa,OAA4B;AAC/C,UAAM,cAAc,IAAI;AAAA,MACtB,MAAM,QAAQ,IAAI,CAAC,WAA+B,CAAC,OAAO,eAAe,MAAM,CAAC;AAAA,IAClF;AACA,UAAM,gBAAgB,oBAAI,IAAgC;AAC1D,UAAM,qBAAqB,oBAAI,IAAkC;AACjE,UAAM,mBAAmB,oBAAI,IAAkC;AAC/D,UAAM,iBAAiB,oBAAI,IAAkC;AAE7D,eAAW,WAAW,MAAM,UAAU;AACpC,oBAAc,IAAI,eAAe,QAAQ,eAAe,QAAQ,UAAU,GAAG,OAAO;AAEpF,YAAM,iBAAiB,mBAAmB,IAAI,QAAQ,UAAU,KAAK,CAAC;AACtE,qBAAe,KAAK,OAAO;AAC3B,yBAAmB,IAAI,QAAQ,YAAY,cAAc;AAEzD,YAAM,iBAAiB,iBAAiB,IAAI,QAAQ,aAAa,KAAK,CAAC;AACvE,qBAAe,KAAK,OAAO;AAC3B,uBAAiB,IAAI,QAAQ,eAAe,cAAc;AAE1D,UAAI,QAAQ,wBAAwB,MAAM;AACxC,cAAM,cAAc,QAAQ,0BAA0B,QAAQ;AAC9D,cAAM,MAAM,eAAe,aAAa,QAAQ,mBAAmB;AACnE,cAAM,WAAW,eAAe,IAAI,GAAG,KAAK,CAAC;AAC7C,iBAAS,KAAK,OAAO;AACrB,uBAAe,IAAI,KAAK,QAAQ;AAAA,MAClC;AAAA,IACF;AAEA,eAAW,WAAW,iBAAiB,OAAO,GAAG;AAC/C,cAAQ,KAAK,gBAAgB;AAAA,IAC/B;AAEA,eAAW,WAAW,eAAe,OAAO,GAAG;AAC7C,cAAQ,KAAK,gBAAgB;AAAA,IAC/B;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,YAAY,SAAkB,WAAmB,QAAqC;AAC5F,QAAI,QAAQ;AACV,YAAM,SAAS,QAAQ,cAAc,IAAI,eAAe,QAAQ,SAAS,CAAC;AAC1E,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,UAAU;AAAA,UAClB,MAAM;AAAA,UACN,SAAS,WAAW,SAAS,4BAA4B,MAAM;AAAA,UAC/D,WAAW;AAAA,UACX,YAAY;AAAA,QACd,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT;AAEA,UAAM,aAAa,QAAQ,mBAAmB,IAAI,SAAS,KAAK,CAAC;AAEjE,QAAI,WAAW,WAAW,GAAG;AAC3B,YAAM,IAAI,UAAU;AAAA,QAClB,MAAM;AAAA,QACN,SAAS,WAAW,SAAS;AAAA,QAC7B,WAAW;AAAA,QACX,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAEA,QAAI,WAAW,SAAS,GAAG;AACzB,YAAM,IAAI,UAAU;AAAA,QAClB,MAAM;AAAA,QACN,SAAS,cAAc,SAAS;AAAA,QAChC,WAAW;AAAA,QACX,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAEA,WAAO,WAAW,CAAC;AAAA,EACrB;AAAA,EAEQ,mBAAmB,QAA4B,SAAwC;AAC7F,UAAM,SAAS,QAAQ,YAAY,IAAI,OAAO,aAAa;AAE3D,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,UAAU;AAAA,QAClB,MAAM;AAAA,QACN,SAAS,gBAAgB,OAAO,aAAa;AAAA,QAC7C,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAEA,UAAM,gBAAgB,QAAQ,iBAAiB,IAAI,OAAO,aAAa,KAAK,CAAC;AAC7E,UAAM,cAAc,cAAc;AAAA,MAChC,CAAC,YAAY,QAAQ,eAAe,OAAO,cAAc,QAAQ,kBAAkB,OAAO;AAAA,IAC5F;AAEA,UAAM,cAAc,KAAK,MAAM,2BAA2B,CAAC;AAC3D,UAAM,SAAS,cAAc,MAAM,KAAK,IAAI,GAAG,cAAc,WAAW,GAAG,WAAW;AACtF,UAAM,QAAQ,cAAc,MAAM,cAAc,GAAG,cAAc,IAAI,WAAW;AAEhF,UAAM,cAAc,OAAO,sBACvB,QAAQ,cAAc;AAAA,MACpB,eAAe,OAAO,0BAA0B,OAAO,eAAe,OAAO,mBAAmB;AAAA,IAClG,KAAK,OACL;AAEJ,UAAM,oBACJ,QAAQ,eAAe,IAAI,eAAe,OAAO,eAAe,OAAO,UAAU,CAAC,KAAK,CAAC;AAE1F,UAAM,QAAkB,CAAC;AACzB,QAAI,OAAO,wBAAwB,QAAQ,CAAC,aAAa;AACvD,YAAM,KAAK,iBAAiB,OAAO,mBAAmB,kCAAkC;AAAA,IAC1F;AAEA,UAAM,WAAW,oBAAI,IAA4B;AACjD,UAAM,cAAc,CAClB,SACA,SACS;AACT,YAAM,MAAM,eAAe,QAAQ,eAAe,QAAQ,UAAU;AACpE,YAAM,WAAW,SAAS,IAAI,GAAG;AACjC,UAAI,UAAU;AACZ,YAAI,CAAC,SAAS,cAAc,SAAS,IAAI,GAAG;AAC1C,mBAAS,cAAc,KAAK,IAAI;AAAA,QAClC;AACA;AAAA,MACF;AAEA,eAAS,IAAI,KAAK;AAAA,QAChB,SAAS,KAAK,WAAW,SAAS,OAAO;AAAA,QACzC,eAAe,CAAC,IAAI;AAAA,MACtB,CAAC;AAAA,IACH;AAEA,eAAW,WAAW,OAAQ,aAAY,SAAS,mBAAmB;AACtE,QAAI,YAAa,aAAY,aAAa,cAAc;AACxD,gBAAY,QAAQ,QAAQ;AAC5B,eAAW,WAAW,kBAAmB,aAAY,SAAS,iBAAiB;AAC/E,eAAW,WAAW,MAAO,aAAY,SAAS,kBAAkB;AAEpE,UAAM,kBAAkB,CAAC,GAAG,SAAS,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,UAAU;AACnE,YAAM,OAAO,CAAC,UAAmD;AAC/D,YAAI,MAAM,SAAS,mBAAmB,EAAG,QAAO;AAChD,YAAI,MAAM,SAAS,cAAc,EAAG,QAAO;AAC3C,YAAI,MAAM,SAAS,QAAQ,EAAG,QAAO;AACrC,YAAI,MAAM,SAAS,iBAAiB,EAAG,QAAO;AAC9C,eAAO;AAAA,MACT;AAEA,aACE,KAAK,KAAK,aAAa,IAAI,KAAK,MAAM,aAAa,KACnD,KAAK,QAAQ,KAAK,cAAc,MAAM,QAAQ,IAAI,KAClD,KAAK,QAAQ,aAAa,MAAM,QAAQ;AAAA,IAE5C,CAAC;AAED,WAAO;AAAA,MACL,QAAQ,KAAK,WAAW,QAAQ,OAAO;AAAA,MACvC;AAAA,MACA,kBAAkB;AAAA,MAClB,QAAQ;AAAA,QACN,wBAAwB;AAAA,QACxB,yBAAyB,OAAO;AAAA,QAChC,wBAAwB,MAAM;AAAA,QAC9B,gCAAgC,QAAQ,WAAW;AAAA,QACnD,iCAAiC,kBAAkB;AAAA,MACrD;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,kBAAkB,SAA6B,SAAmC;AACxF,UAAM,SAAS,QAAQ,YAAY,IAAI,QAAQ,aAAa;AAC5D,UAAM,uBACJ,QAAQ,eAAe,IAAI,eAAe,QAAQ,eAAe,QAAQ,UAAU,CAAC,GAAG,UAAU;AAEnG,WAAO;AAAA,MACL,YAAY,QAAQ;AAAA,MACpB,eAAe,QAAQ;AAAA,MACvB,cAAc,QAAQ,SAAS,QAAQ;AAAA,MACvC,MAAM,QAAQ;AAAA,MACd,cAAc,YAAY,QAAQ,IAAI;AAAA,MACtC,WAAW,QAAQ;AAAA,MACnB,WAAW,QAAQ;AAAA,MACnB,qBAAqB,QAAQ;AAAA,MAC7B,wBAAwB;AAAA,MACxB,mBAAmB,QAAQ;AAAA,IAC7B;AAAA,EACF;AAAA,EAEQ,WAAW,SAA6B,SAAmC;AACjF,UAAM,cACJ,QAAQ,wBAAwB,OAC5B,QAAQ,cAAc;AAAA,MACpB,eAAe,QAAQ,0BAA0B,QAAQ,eAAe,QAAQ,mBAAmB;AAAA,IACrG,KAAK,OACL;AAEN,UAAM,oBACJ,QAAQ,eAAe,IAAI,eAAe,QAAQ,eAAe,QAAQ,UAAU,CAAC,KAAK,CAAC;AAE5F,UAAM,QACJ,QAAQ,wBAAwB,OAC5B;AAAA,MACE,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV,IACA;AAAA,MACE,QAAQ;AAAA,MACR,QAAQ,cACJ,KAAK,aAAa,aAAa,UAAU,IACzC;AAAA,QACE,YAAY,QAAQ;AAAA,QACpB,eAAe,QAAQ,0BAA0B,QAAQ;AAAA,QACzD,cAAc;AAAA,QACd,MAAM;AAAA,QACN,cAAc;AAAA,MAChB;AAAA,MACJ,QAAQ,cAAc,aAAa;AAAA,IACrC;AAEN,UAAM,cAAsC,kBAAkB,IAAI,CAAC,WAAW;AAAA,MAC5E,SAAS,KAAK,aAAa,OAAO,WAAW;AAAA,MAC7C,0BAA0B;AAAA,MAC1B,mBAAmB,KAAK,iBAAiB,OAAO,OAAO;AAAA,IACzD,EAAE;AAEF,WAAO;AAAA,MACL,YAAY,QAAQ;AAAA,MACpB,eAAe,QAAQ;AAAA,MACvB,MAAM,QAAQ;AAAA,MACd,WAAW,QAAQ;AAAA,MACnB,MAAM,QAAQ;AAAA,MACd,cAAc,YAAY,QAAQ,IAAI;AAAA,MACtC,WAAW,QAAQ;AAAA,MACnB,WAAW,QAAQ;AAAA,MACnB,gBAAgB,QAAQ;AAAA,MACxB;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,QACN,iBAAiB,KAAK,eAAe,SAAS,OAAO;AAAA,QACrD,wBAAwB,YAAY;AAAA,QACpC,uBAAuB,KAAK,iBAAiB,SAAS,OAAO;AAAA,QAC7D,iBAAiB,KAAK,SAAS,SAAS,OAAO;AAAA,MACjD;AAAA,MACA,OAAO,QAAQ;AAAA,MACf,eAAe,QAAQ;AAAA,MACvB,mBAAmB,QAAQ;AAAA,IAC7B;AAAA,EACF;AAAA,EAEQ,aACN,SACA,cACY;AACZ,WAAO;AAAA,MACL,YAAY,QAAQ;AAAA,MACpB,eAAe,QAAQ;AAAA,MACvB,cAAc,YAAY,QAAQ,IAAI;AAAA,MACtC,MAAM,QAAQ;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,eAAe,SAA6B,SAAsC;AACxF,QAAI,UAAU;AAEd,WAAO,QAAQ,wBAAwB,MAAM;AAC3C,YAAM,SAAS,QAAQ,cAAc;AAAA,QACnC,eAAe,QAAQ,0BAA0B,QAAQ,eAAe,QAAQ,mBAAmB;AAAA,MACrG;AACA,UAAI,CAAC,UAAU,OAAO,kBAAkB,QAAQ,eAAe;AAC7D;AAAA,MACF;AACA,gBAAU;AAAA,IACZ;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,gBACN,SACA,SACA,OACmB;AACnB,UAAM,WACJ,QAAQ,eAAe,IAAI,eAAe,QAAQ,eAAe,QAAQ,UAAU,CAAC,KAAK,CAAC;AAE5F,WAAO;AAAA,MACL,SAAS,KAAK,WAAW,SAAS,OAAO;AAAA,MACzC;AAAA,MACA,UAAU,SAAS,IAAI,CAAC,UAAU,KAAK,gBAAgB,OAAO,SAAS,QAAQ,CAAC,CAAC;AAAA,IACnF;AAAA,EACF;AAAA,EAEQ,eAAe,SAA6B,SAA0B;AAC5E,QAAI,QAAQ;AACZ,QAAI,UAAU;AAEd,WAAO,QAAQ,wBAAwB,MAAM;AAC3C,YAAM,SAAS,QAAQ,cAAc;AAAA,QACnC,eAAe,QAAQ,0BAA0B,QAAQ,eAAe,QAAQ,mBAAmB;AAAA,MACrG;AACA,UAAI,CAAC,OAAQ;AACb,eAAS;AACT,gBAAU;AAAA,IACZ;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAiB,SAA6B,SAA0B;AAC9E,UAAM,WACJ,QAAQ,eAAe,IAAI,eAAe,QAAQ,eAAe,QAAQ,UAAU,CAAC,KAAK,CAAC;AAE5F,WAAO,SAAS,OAAO,CAAC,OAAO,UAAU,QAAQ,IAAI,KAAK,iBAAiB,OAAO,OAAO,GAAG,CAAC;AAAA,EAC/F;AAAA,EAEQ,SAAS,SAA6B,SAA0B;AACtE,UAAM,WACJ,QAAQ,eAAe,IAAI,eAAe,QAAQ,eAAe,QAAQ,UAAU,CAAC,KAAK,CAAC;AAC5F,QAAI,SAAS,WAAW,EAAG,QAAO;AAClC,WAAO,IAAI,KAAK,IAAI,GAAG,SAAS,IAAI,CAAC,UAAU,KAAK,SAAS,OAAO,OAAO,CAAC,CAAC;AAAA,EAC/E;AACF;AAEA,SAAS,eAAe,aAAqB,WAA2B;AACtE,SAAO,GAAG,WAAW,IAAI,SAAS;AACpC;AAEA,SAAS,aAAa,QAAwB;AAC5C,SAAO,OAAO,KAAK,OAAO,MAAM,GAAG,MAAM,EAAE,SAAS,WAAW;AACjE;AAEA,SAAS,aAAa,QAAgC;AACpD,MAAI,CAAC,OAAQ,QAAO;AAEpB,MAAI;AACF,UAAM,QAAQ,OAAO,OAAO,KAAK,QAAQ,WAAW,EAAE,SAAS,MAAM,CAAC;AACtE,WAAO,OAAO,SAAS,KAAK,KAAK,SAAS,IAAI,QAAQ;AAAA,EACxD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,iBAAiB,MAA0B,OAAmC;AACrF,SAAO,KAAK,KAAK,cAAc,MAAM,IAAI,KAAK,KAAK,aAAa,MAAM;AACxE;AAEA,SAAS,kBAAkB,MAA0B,OAAmC;AACtF,SAAO,MAAM,KAAK,cAAc,KAAK,IAAI,KAAK,MAAM,aAAa,KAAK;AACxE;AAEA,SAAS,cAAc,SAA6B,OAAwB;AAC1E,QAAM,aAAa,MAAM,KAAK,EAAE,YAAY;AAC5C,MAAI,CAAC,WAAY,QAAO;AAExB,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ,gBAAgB,SAAS;AAAA,IACjC,QAAQ;AAAA,EACV,EACG,KAAK,IAAI,EACT,YAAY,EACZ,SAAS,UAAU;AACxB;AAEA,SAAS,YAAY,MAAc,QAAQ,IAAY;AACrD,QAAM,aAAa,KAAK,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAClD,MAAI,CAAC,WAAY,QAAO;AACxB,SAAO,WAAW,UAAU,QAAQ,aAAa,GAAG,WAAW,MAAM,GAAG,QAAQ,CAAC,CAAC;AACpF;;;AChiBA,OAAOC,WAAU;AACjB,SAAS,uBAAuB;AAChC,SAAS,YAAAC,WAAU,aAAAC,kBAAiB;AACpC,SAAS,gBAAgB,uBAAgC;AAyBlD,IAAM,iBAAN,MAAkD;AAAA,EAC9C,UAAU;AAAA,EAEnB,MAAM,UAAU,YAAoB,OAAgD;AAClF,UAAM,SAAyB;AAAA,MAC7B,OAAO,MAAM;AAAA,MACb,SAAS,MAAM;AAAA,MACf,OAAO,MAAM;AAAA,IACf;AAEA,UAAM,mBAAmB,YAAY,MAAM;AAC3C,UAAM,SAAS,IAAI,eAAe;AAAA,MAChC,OAAO,OAAO;AAAA,MACd,SAAS,OAAO;AAAA,MAChB,SAASC,MAAK,KAAK,YAAY,gBAAgB;AAAA,IACjD,CAAC;AACD,UAAM,KAAK,gBAAgB;AAAA,MACzB,OAAO,QAAQ;AAAA,MACf,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAED,QAAI;AACF,YAAM,OAAO,MAAM,OAAO,MAAM;AAAA,QAC9B,OAAO,MAAM;AAAA,QACb,MAAM,YAAY,MAAM,QAAS,MAAM,GAAG,SAAS,QAAQ;AAAA,QAC3D,UAAU,YACR,MAAM,YACL,MAAM,GAAG,SAAS,6CAA6C;AAAA,QAClE,kBAAkB,OAAO,aAAa;AACpC,gBAAM,OACJ,OAAO,SAAS,SAAS,WACrB,SAAS,OACT;AACN,kBAAQ,OAAO,MAAM,4BAA4B,IAAI;AAAA,CAAK;AAAA,QAC5D;AAAA,QACA,qBAAqB,OAAO,SAAS;AACnC,kBAAQ,OAAO,MAAM,WAAW,IAAI;AAAA,CAAuB;AAAA,QAC7D;AAAA,MACF,CAAC;AAED,aAAO;AAAA,QACL,eAAe;AAAA,QACf,MAAM;AAAA,UACJ,IAAI,OAAO,KAAK,EAAE;AAAA,UAClB,cAAc,KAAK;AAAA,QACrB;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,YAAM,IAAI,UAAU;AAAA,QAClB,MAAM;AAAA,QACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAClD,WAAW;AAAA,MACb,CAAC;AAAA,IACH,UAAE;AACA,SAAG,MAAM;AAAA,IAEX;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,YAAyC;AACxD,UAAM,SAAS,MAAM,mBAAmB,UAAU;AAClD,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,QACL,eAAe;AAAA,QACf,MAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,SAAS,IAAI,eAAe;AAAA,MAChC,OAAO,OAAO;AAAA,MACd,SAAS,OAAO;AAAA,MAChB,SAASA,MAAK,KAAK,YAAY,gBAAgB;AAAA,IACjD,CAAC;AAED,QAAI;AACF,YAAM,OAAO,MAAM,CAAC,CAAC;AACrB,YAAM,KAAK,MAAM,OAAO,MAAM;AAC9B,aAAO;AAAA,QACL,eAAe;AAAA,QACf,MAAM;AAAA,UACJ,IAAI,OAAO,GAAG,EAAE;AAAA,UAChB,cAAc,GAAG;AAAA,QACnB;AAAA,MACF;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,QACL,eAAe;AAAA,QACf,MAAM;AAAA,MACR;AAAA,IACF,UAAE;AAAA,IAEF;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,YAA6C;AACtD,UAAM,SAAS,MAAM,mBAAmB,UAAU;AAClD,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,UAAU;AAAA,QAClB,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW;AAAA,QACX,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAEA,UAAM,SAAS,IAAI,eAAe;AAAA,MAChC,OAAO,OAAO;AAAA,MACd,SAAS,OAAO;AAAA,MAChB,SAASA,MAAK,KAAK,YAAY,gBAAgB;AAAA,IACjD,CAAC;AAED,QAAI;AACF,YAAM,KAAK,MAAM,OAAO,MAAM,CAAC,CAAC;AAChC,YAAM,YAAW,oBAAI,KAAK,GAAE,YAAY;AACxC,YAAM,kBAAkB,MAAM,OAAO,KAAK;AAAA,QACxC,GAAG;AAAA,QACH,eAAe;AAAA,QACf,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,YAAY,EAAE,GAAG,iBAAiB;AAAA,QAClC,OAAO;AAAA,QACP,MAAM;AAAA,MACR,CAAC;AAED,UAAI,gBAAgB,MAAM,oCAAoC;AAC5D,eAAO;AAAA,UACL,SAAS,KAAK;AAAA,UACd,SAAS;AAAA,YACP,IAAI,OAAO,GAAG,EAAE;AAAA,YAChB,cAAc,GAAG;AAAA,UACnB;AAAA,UACA,SAAS,CAAC;AAAA,UACV,UAAU,CAAC;AAAA,UACX,WAAW;AAAA,QACb;AAAA,MACF;AAEA,YAAM,SAAuB;AAAA,QAC3B,OAAO,oBAAI,IAAI;AAAA,QACf,OAAO,oBAAI,IAAI;AAAA,QACf,YAAY,OAAO,GAAG,EAAE;AAAA,MAC1B;AAEA,qBAAe,QAAQ,gBAAgB,OAAO,gBAAgB,KAAK;AAEnE,YAAM,UAAgC,CAAC;AACvC,YAAM,gBAAgB,oBAAI,IAAgC;AAE1D,iBAAW,UAAU,gBAAgB,SAAS;AAC5C,YAAI,OAAO,MAAM,cAAe;AAEhC,cAAM,cAAc,oBAAoB,OAAO,MAAM,OAAO,UAAU;AACtE,cAAM,YAAY,MAAM,OAAO,YAAY,gBAAgB,OAAO,IAAI,CAAC;AACvE,cAAM,QAAQ,UAAU,OAAO,MAAM,MAAM;AAE3C,cAAMC,YAAW,MAAM,kBAAkB,QAAQ,WAAW,MAAM;AAClE,cAAM,aAAaA,UAAS,KAAK,CAAC,YAAY,QAAQ,eAAe,OAAO,UAAU,KAAKA,UAAS,CAAC,KAAK;AAE1G,gBAAQ,KAAK;AAAA,UACX,eAAe;AAAA,UACf,MAAM,iBAAiB,OAAO,MAAM,OAAO,UAAU;AAAA,UACrD;AAAA,UACA,gBAAgB,OAAO,cAAc,YAAY,cAAc;AAAA,UAC/D,kBAAkB,aAAaC,aAAY,WAAW,IAAI,IAAI;AAAA,UAC9D,eAAeD,UAAS;AAAA,UACxB,QAAQ,OAAO,UAAU;AAAA,UACzB,gBAAgB;AAAA,QAClB,CAAC;AAED,mBAAW,WAAWA,WAAU;AAC9B,wBAAc,IAAI,GAAG,QAAQ,aAAa,IAAI,QAAQ,UAAU,IAAI,OAAO;AAAA,QAC7E;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS,KAAK;AAAA,QACd,SAAS;AAAA,UACP,IAAI,OAAO,GAAG,EAAE;AAAA,UAChB,cAAc,GAAG;AAAA,QACnB;AAAA,QACA;AAAA,QACA,UAAU,CAAC,GAAG,cAAc,OAAO,CAAC,EAAE;AAAA,UAAK,CAAC,GAAG,MAC7C,EAAE,cAAc,cAAc,EAAE,aAAa,KAAK,EAAE,KAAK,cAAc,EAAE,IAAI,KAAK,EAAE,aAAa,EAAE;AAAA,QACrG;AAAA,QACA,WAAW;AAAA,MACb;AAAA,IACF,SAAS,OAAO;AACd,YAAM,IAAI,UAAU;AAAA,QAClB,MAAM;AAAA,QACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAClD,WAAW;AAAA,MACb,CAAC;AAAA,IACH,UAAE;AAAA,IAEF;AAAA,EACF;AACF;AAEA,eAAe,kBACb,QACA,MACA,QAC+B;AAC/B,MAAI,WAAW;AACf,MAAI,aAAa;AACjB,QAAM,UAAU,oBAAI,IAAgC;AAEpD,SAAO,MAAM;AACX,UAAM,UAAU,MAAM,OAAO,KAAK;AAAA,MAChC,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,MAAM;AAAA,IACR,CAAC;AAED,QAAI,EAAE,cAAc,UAAU;AAC5B;AAAA,IACF;AAEA,mBAAe,QAAQ,QAAQ,SAAS,CAAC,GAAG,QAAQ,SAAS,CAAC,CAAC;AAE/D,UAAM,cAAc,QAAQ,SAAS;AAAA,MACnC,CAAC,YACC,QAAQ,MAAM,aAAa,QAAQ,MAAM;AAAA,IAC7C;AAEA,QAAI,YAAY,WAAW,GAAG;AAC5B;AAAA,IACF;AAEA,eAAW,OAAO,aAAa;AAC7B,YAAM,SAAS,oBAAoB,KAAK,MAAM;AAC9C,cAAQ,IAAI,GAAG,OAAO,aAAa,IAAI,OAAO,UAAU,IAAI,MAAM;AAAA,IACpE;AAEA,UAAM,SAAS,YAAY,YAAY,SAAS,CAAC;AACjD,eAAW,OAAO;AAClB,iBAAa,OAAO;AAEpB,QAAI,YAAY,SAAS,KAAK;AAC5B;AAAA,IACF;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,QAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,KAAK,EAAE,aAAa,EAAE,UAAU;AACzG;AAEA,SAAS,oBAAoB,KAA2C,QAA0C;AAChH,QAAM,cAAc,oBAAoB,IAAI,QAAQ,OAAO,UAAU;AACrE,QAAM,cACJ,aAAa,OAAO,IAAI,WAAW,IAAI,QAAQ,MAAM,uBAAuB,IAAI,UAAU;AAC5F,QAAM,YAAY,aAAa,iBAAiB,IAAI;AACpD,QAAM,UAAU,aAAa,MAAM,IAAI,UAAU;AACjD,QAAM,WAAW,cAAc,MAAM,IAAI,WAAW;AACpD,QAAM,QAAQ,WAAW,MAAM,IAAI,QAAQ;AAC3C,QAAM,OAAO,aAAa,MAAM,IAAI,UAAU;AAE9C,SAAO;AAAA,IACL,YAAY,IAAI;AAAA,IAChB,eAAe;AAAA,IACf,MAAM,IAAI,KAAK,IAAI,OAAO,GAAI,EAAE,YAAY;AAAA,IAC5C,WAAW,WAAW,IAAI,KAAK,WAAW,GAAI,EAAE,YAAY,IAAI;AAAA,IAChE;AAAA,IACA,WAAW,WAAW,YAAY,MAAM,IAAI,SAAS,MAAM,OAAO,UAAU;AAAA,IAC5E,WAAW,QAAQ,OAAO;AAAA,IAC1B,gBAAgB,UAAU,wBAAwB,SAAS,MAAM,IAAI;AAAA,IACrE,qBAAqB,aAAa,gBAAgB;AAAA,IAClD,wBAAwB,aAAa,eACjC,oBAAoB,WAAW,OAAO,UAAU,IAChD;AAAA,IACJ,OAAO,aAAa,IAAI;AAAA,IACxB,eAAe,aAAa,KAAK;AAAA,IACjC,mBAAmB;AAAA,EACrB;AACF;AAEA,SAAS,wBACP,QACA,QACsB;AACtB,MAAI,OAAO,eAAe;AACxB,WAAO;AAAA,MACL,eAAe,oBAAoB,OAAO,eAAe,OAAO,UAAU;AAAA,MAC1E,OAAO,UAAU,OAAO,eAAe,MAAM;AAAA,MAC7C,YAAY,OAAO,kBAAkB;AAAA,IACvC;AAAA,EACF;AAEA,MAAI,OAAO,QAAQ;AACjB,WAAO;AAAA,MACL,eAAe,oBAAoB,OAAO,QAAQ,OAAO,UAAU;AAAA,MACnE,OAAO,OAAO,YAAY,UAAU,OAAO,QAAQ,MAAM;AAAA,MACzD,YAAY,OAAO,kBAAkB;AAAA,IACvC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,eAAe;AAAA,IACf,OAAO,OAAO,YAAY,OAAO,iBAAiB;AAAA,IAClD,YAAY,OAAO,kBAAkB;AAAA,EACvC;AACF;AAEA,SAAS,WAAW,MAAsC,YAA6B;AACrF,SAAO,QAAQ,QAAQ,KAAK,MAAM,cAAc,KAAK,WAAW,UAAU;AAC5E;AAEA,SAAS,iBAAiB,MAAmB,YAAgD;AAC3F,MAAI,KAAK,MAAM,cAAc,KAAK,WAAW,WAAY,QAAO;AAChE,MAAI,KAAK,MAAM,cAAc,KAAK,MAAM,WAAY,QAAO;AAC3D,MAAI,KAAK,MAAM,cAAe,QAAO;AACrC,SAAO;AACT;AAEO,SAAS,oBAAoB,MAAmB,YAA4B;AACjF,MAAI,KAAK,MAAM,cAAc,KAAK,WAAW,YAAY;AACvD,WAAO;AAAA,EACT;AAEA,MAAI,KAAK,MAAM,WAAY,QAAO,QAAQ,KAAK,MAAM;AACrD,MAAI,KAAK,MAAM,WAAY,QAAO,QAAQ,KAAK,MAAM;AACrD,MAAI,KAAK,MAAM,cAAe,QAAO,WAAW,KAAK,SAAS;AAC9D,SAAO,WAAW,gBAAgB,IAAI,CAAC;AACzC;AAEA,SAAS,UAAU,MAAmB,QAA8B;AAClE,MAAI,KAAK,MAAM,YAAY;AACzB,QAAI,KAAK,WAAW,OAAO,WAAY,QAAO;AAC9C,UAAM,OAAO,OAAO,MAAM,IAAI,KAAK,MAAM;AACzC,UAAM,YAAY,QAAQ,KAAK,MAAM,SAAS,KAAK,aAAa,KAAK;AACrE,UAAM,WAAW,QAAQ,KAAK,MAAM,SAAS,KAAK,YAAY,KAAK;AACnE,UAAM,WAAW,QAAQ,KAAK,MAAM,SAAS,KAAK,YAAY,KAAK;AACnE,UAAM,QAAQ,CAAC,WAAW,QAAQ,EAAE,OAAO,OAAO;AAClD,WAAO,MAAM,KAAK,GAAG,EAAE,KAAK,KAAK,YAAY,QAAQ,KAAK,MAAM;AAAA,EAClE;AAEA,QAAM,SAAS,OAAO,MAAM,IAAI,KAAK,MAAM,aAAa,KAAK,SAAS,KAAK,SAAS;AACpF,MAAI,UAAU,WAAW,QAAQ;AAC/B,WAAO,OAAO;AAAA,EAChB;AAEA,MAAI,KAAK,MAAM,WAAY,QAAO,QAAQ,KAAK,MAAM;AACrD,MAAI,KAAK,MAAM,cAAe,QAAO,WAAW,KAAK,SAAS;AAC9D,SAAO;AACT;AAEA,SAAS,eAAe,QAAsB,OAAsB,OAA4B;AAC9F,aAAW,QAAQ,OAAO;AACxB,QAAI,QAAQ,MAAM;AAChB,aAAO,MAAM,IAAI,OAAO,KAAK,EAAE,GAAG,IAAI;AAAA,IACxC;AAAA,EACF;AAEA,aAAW,QAAQ,OAAO;AACxB,QAAI,QAAQ,MAAM;AAChB,aAAO,MAAM,IAAI,OAAO,KAAK,EAAE,GAAG,IAAI;AAAA,IACxC;AAAA,EACF;AACF;AAEA,SAAS,aAAa,MAA6B;AACjD,QAAM,UAAU,KAAK,SAAS,qBAAqB;AACnD,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,QAAuB,CAAC;AAE9B,aAAW,SAAS,SAAS;AAC3B,UAAM,MAAM,MAAM,CAAC;AACnB,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AACZ,UAAM,KAAK,EAAE,IAAI,CAAC;AAAA,EACpB;AAEA,SAAO;AACT;AAEA,SAAS,aAAa,OAAuD;AAC3E,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,MAAM;AACf;AAEA,SAASC,aAAY,MAAc,QAAQ,IAAY;AACrD,QAAM,aAAa,KAAK,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAClD,MAAI,CAAC,WAAY,QAAO;AACxB,SAAO,WAAW,UAAU,QAAQ,aAAa,GAAG,WAAW,MAAM,GAAG,QAAQ,CAAC,CAAC;AACpF;AAEA,eAAe,mBAAmB,YAAoD;AACpF,MAAI;AACF,UAAM,MAAM,MAAMC,UAASH,MAAK,KAAK,YAAY,eAAe,GAAG,MAAM;AACzE,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,SAAU,QAAO;AAC/D,UAAM;AAAA,EACR;AACF;AAEA,eAAe,mBAAmB,YAAoB,QAAuC;AAC3F,QAAMI;AAAA,IACJJ,MAAK,KAAK,YAAY,eAAe;AAAA,IACrC,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA;AAAA,IAClC;AAAA,EACF;AACF;;;ACxaO,SAAS,iBAAiB,QAA4B;AAC3D,SAAO;AAAA,IACL,gBAAgB,OAAO,OAAO;AAAA,IAC9B,aAAa,OAAO,SAAS;AAAA,IAC7B,WAAW,OAAO,cAAc;AAAA,IAChC,YAAY,OAAO,eAAe;AAAA,EACpC,EAAE,KAAK,IAAI;AACb;AAEO,SAAS,iBAAiB,QAA4B;AAC3D,MAAI,CAAC,OAAO,iBAAiB,CAAC,OAAO,MAAM;AACzC,WAAO;AAAA,EACT;AAEA,SAAO,CAAC,uBAAuB,SAAS,OAAO,KAAK,YAAY,IAAI,OAAO,OAAO,KAAK,EAAE,EAAE,EAAE,KAAK,IAAI;AACxG;AAEO,SAAS,mBAAmB,SAAuC;AACxE,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,SAAO,QACJ;AAAA,IAAI,CAAC,WACJ;AAAA,MACE,GAAG,OAAO,aAAa,KAAK,OAAO,IAAI;AAAA,MACvC,UAAU,OAAO,KAAK;AAAA,MACtB,aAAa,OAAO,aAAa;AAAA,MACjC,mBAAmB,OAAO,kBAAkB,KAAK;AAAA,MACjD,aAAa,OAAO,oBAAoB,QAAQ;AAAA,IAClD,EAAE,KAAK,IAAI;AAAA,EACb,EACC,KAAK,MAAM;AAChB;AAEO,SAAS,mBAAmB,MAAiD;AAClF,MAAI,KAAK,MAAM,WAAW,EAAG,QAAO;AAEpC,QAAM,SACJ,KAAK,UAAU,iBACX,kBAAkB,KAAK,aAAa,UAAU,KAAK,YAAY,KAC/D,0CAA0C,KAAK,YAAY;AAEjE,QAAM,SAAS,KAAK,MAAM;AAAA,IAAI,CAAC,SAC7B;AAAA,MACE,IAAI,KAAK,UAAU,IAAI,KAAK,IAAI;AAAA,MAChC,WAAW,KAAK,aAAa,KAAK,KAAK,YAAY;AAAA,MACnD,cAAc,KAAK,SAAS,eAAe,KAAK,SAAS;AAAA,MACzD,aAAa,KAAK,uBAAuB,MAAM,iBAAiB,KAAK,sBAAsB;AAAA,MAC3F,SAAS,KAAK,YAAY;AAAA,IAC5B,EAAE,KAAK,IAAI;AAAA,EACb;AAEA,SAAO,CAAC,QAAQ,GAAG,QAAQ,KAAK,cAAc,gBAAgB,KAAK,WAAW,KAAK,EAAE,EAAE,OAAO,OAAO,EAAE,KAAK,MAAM;AACpH;AAEO,SAAS,oBAAoB,QAAsC;AACxE,QAAM,QAAkB;AAAA,IACtB,YAAY,OAAO,OAAO,UAAU;AAAA,IACpC,WAAW,OAAO,OAAO,aAAa,KAAK,OAAO,OAAO,KAAK;AAAA,IAC9D,SAAS,OAAO,OAAO,IAAI;AAAA,IAC3B,cAAc,OAAO,OAAO,SAAS;AAAA,IACrC,8BAA8B,OAAO,OAAO,OAAO,sBAAsB,oBAAoB,OAAO,OAAO,OAAO,yBAAyB,CAAC;AAAA,IAC5I;AAAA,IACA;AAAA,IACA,OAAO,OAAO,QAAQ;AAAA,EACxB;AAEA,QAAM,eAAe,OAAO,OAAO,MAAM,SACrC,OAAO,OAAO,MAAM,SAClB,CAAC,IAAI,aAAa,MAAM,OAAO,OAAO,MAAM,OAAO,UAAU,IAAI,OAAO,OAAO,MAAM,OAAO,YAAY,EAAE,IAC1G,CAAC,IAAI,aAAa,wBAAwB,IAC5C,CAAC;AAEL,QAAM,mBACJ,OAAO,OAAO,YAAY,SAAS,IAC/B;AAAA,IACE;AAAA,IACA;AAAA,IACA,GAAG,OAAO,OAAO,YAAY;AAAA,MAC3B,CAAC,SAAS,MAAM,KAAK,QAAQ,UAAU,IAAI,KAAK,QAAQ,YAAY;AAAA,IACtE;AAAA,EACF,IACA,CAAC;AAEP,QAAM,SAAS,OAAO,iBAAiB,OAAO,CAAC,SAAS,KAAK,cAAc,SAAS,mBAAmB,CAAC;AACxG,QAAM,QAAQ,OAAO,iBAAiB,OAAO,CAAC,SAAS,KAAK,cAAc,SAAS,kBAAkB,CAAC;AAEtG,MAAI,OAAO,SAAS,GAAG;AACrB,UAAM,KAAK,IAAI,oBAAoB;AACnC,eAAW,QAAQ,OAAQ,OAAM,KAAK,MAAM,KAAK,QAAQ,UAAU,IAAI,KAAK,QAAQ,YAAY,EAAE;AAAA,EACpG;AAEA,MAAI,MAAM,SAAS,GAAG;AACpB,UAAM,KAAK,IAAI,mBAAmB;AAClC,eAAW,QAAQ,MAAO,OAAM,KAAK,MAAM,KAAK,QAAQ,UAAU,IAAI,KAAK,QAAQ,YAAY,EAAE;AAAA,EACnG;AAEA,QAAM,KAAK,GAAG,cAAc,GAAG,gBAAgB;AAE/C,MAAI,OAAO,MAAM,SAAS,GAAG;AAC3B,UAAM,KAAK,IAAI,QAAQ;AACvB,eAAW,QAAQ,OAAO,MAAO,OAAM,KAAK,KAAK,IAAI,EAAE;AAAA,EACzD;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEO,SAAS,aAAa,QAAqC;AAChE,QAAM,QAAQ,CAAC,WAAW,OAAO,KAAK,UAAU,IAAI,WAAW,OAAO,OAAO,aAAa,KAAK,OAAO,OAAO,KAAK,KAAK,EAAE;AAEzH,QAAM,OAAO,OAAO,MAAM,CAAC;AAC3B,MAAI,CAAC,KAAM,QAAO,MAAM,KAAK,IAAI;AAEjC,aAAW,MAAM,IAAI,MAAM,KAAK;AAChC,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,WAAW,MAAyB,QAAgB,QAAiB,OAAuB;AACnG,QAAM,SAAS,SAAS,GAAG,MAAM,GAAG,SAAS,wBAAS,qBAAM,KAAK;AACjE,QAAM,KAAK,GAAG,MAAM,IAAI,KAAK,QAAQ,UAAU,IAAI,KAAK,QAAQ,YAAY,EAAE;AAE9E,QAAM,aAAa,SAAS,GAAG,MAAM,GAAG,SAAS,SAAS,WAAM,KAAK;AACrE,OAAK,SAAS,QAAQ,CAAC,OAAO,UAAU;AACtC,eAAW,OAAO,YAAY,UAAU,KAAK,SAAS,SAAS,GAAG,KAAK;AAAA,EACzE,CAAC;AACH;;;APxGA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,MAAM,EACX,YAAY,6CAA6C,EACzD,OAAO,UAAU,0CAA0C,EAC3D,OAAO,uBAAuB,uBAAuB,UAAU,EAC/D,OAAO,oBAAoB,sCAAsC,EACjE,OAAO,iBAAiB,8BAA8B,EACtD,OAAO,oBAAoB,qBAAqB,SAAS;AAE5D,QACG,QAAQ,MAAM,EACd,YAAY,wBAAwB,EACpC;AAAA,EACC,IAAI,QAAQ,OAAO,EAAE,OAAO,OAAO,GAAG,YAAY;AAChD,UAAM,YAAY,QAAQ,gBAAgB,GAAG,OAAO,SAAS,YAAY;AACvE,UAAI,QAAQ,YAAY,YAAY;AAClC,cAAM,IAAI,UAAU;AAAA,UAClB,MAAM;AAAA,UACN,SAAS;AAAA,UACT,WAAW;AAAA,QACb,CAAC;AAAA,MACH;AAEA,YAAM,KAAKK,iBAAgB;AAAA,QACzB,OAAOC,SAAQ;AAAA,QACf,QAAQA,SAAQ;AAAA,MAClB,CAAC;AAED,UAAI;AACF,cAAM,QAAQ,OAAO,MAAM,GAAG,SAAS,UAAU,CAAC;AAClD,cAAM,UAAU,MAAM,GAAG,SAAS,YAAY;AAC9C,cAAM,QAAQ,MAAM,GAAG,SAAS,SAAS;AAEzC,cAAM,SAAS,MAAM,QAAQ,UAAU;AAAA,UACrC;AAAA,UACA;AAAA,UACA;AAAA,UACA,MAAM;AAAA,QACR,CAAC;AAED,aAAK,QAAQ,OAAO;AAAA,MACtB,UAAE;AACA,WAAG,MAAM;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH,EACC;AAAA,EACC,IAAI,QAAQ,QAAQ,EAAE,OAAO,OAAO,GAAG,YAAY;AACjD,UAAM,YAAY,QAAQ,gBAAgB,GAAG,OAAO,SAAS,YAAY;AACvE,WAAK,MAAM,QAAQ,WAAW,GAAG,SAAS,gBAAgB;AAAA,IAC5D,CAAC;AAAA,EACH,CAAC;AACH;AAEF,QAAQ,QAAQ,MAAM,EAAE,OAAO,OAAO,GAAG,YAAY;AACnD,QAAM,YAAY,QAAQ,gBAAgB,GAAG,OAAO,SAAS,YAAY;AACvE,SAAK,MAAM,QAAQ,KAAK,GAAG,SAAS,gBAAgB;AAAA,EACtD,CAAC;AACH,CAAC;AAED,QACG,QAAQ,eAAe,EACvB,YAAY,uBAAuB,EACnC;AAAA,EACC,IAAI,QAAQ,MAAM,EAAE,OAAO,OAAO,GAAG,YAAY;AAC/C,UAAM,YAAY,QAAQ,gBAAgB,GAAG,OAAO,SAAS,YAAY;AACvE,WAAK,MAAM,QAAQ,iBAAiB,GAAG,SAAS,kBAAkB;AAAA,IACpE,CAAC;AAAA,EACH,CAAC;AACH;AAEF,IAAM,WAAW,QAAQ,QAAQ,UAAU,EAAE,YAAY,kBAAkB;AAE3E,SACG,QAAQ,MAAM,EACd,OAAO,wBAAwB,EAC/B,OAAO,kBAAkB,EACzB,OAAO,oBAAoB,aAAa,IAAI,EAC5C,OAAO,mBAAmB,EAC1B,OAAO,OAAO,gBAAgB,YAAY;AACzC,QAAM,YAAY,QAAQ,gBAAgB,GAAG,OAAO,SAAS,YAAY;AACvE,UAAM,SAAS,MAAM,QAAQ,aAAa;AAAA,MACxC,QAAQ,eAAe;AAAA,MACvB,QAAQ,eAAe;AAAA,MACvB,OAAO,OAAO,eAAe,KAAK;AAAA,MAClC,QAAQ,eAAe;AAAA,IACzB,CAA+B;AAC/B,SAAK,QAAQ,SAAS,kBAAkB;AAAA,EAC1C,CAAC;AACH,CAAC;AAEH,SACG,QAAQ,KAAK,EACb,SAAS,MAAM,EACf,OAAO,wBAAwB,EAC/B,OAAO,OAAO,IAAI,gBAAgB,YAAY;AAC7C,QAAM,YAAY,QAAQ,gBAAgB,GAAG,OAAO,SAAS,YAAY;AACvE,UAAM,SAAS,MAAM,QAAQ,WAAW,OAAO,EAAE,GAAG;AAAA,MAClD,QAAQ,eAAe;AAAA,IACzB,CAA6B;AAC7B,SAAK,QAAQ,SAAS,mBAAmB;AAAA,EAC3C,CAAC;AACH,CAAC;AAEH,SACG,QAAQ,SAAS,EACjB,SAAS,MAAM,EACf,OAAO,wBAAwB,EAC/B,OAAO,OAAO,IAAI,gBAAgB,YAAY;AAC7C,QAAM,YAAY,QAAQ,gBAAgB,GAAG,OAAO,SAAS,YAAY;AACvE,UAAM,SAAS,MAAM,QAAQ,WAAW,OAAO,EAAE,GAAG;AAAA,MAClD,QAAQ,eAAe;AAAA,IACzB,CAA6B;AAC7B,SAAK,QAAQ,SAAS,mBAAmB;AAAA,EAC3C,CAAC;AACH,CAAC;AAEH,QACG,QAAQ,SAAS,EACjB,YAAY,iBAAiB,EAC7B;AAAA,EACC,IAAI,QAAQ,SAAS,EAClB,SAAS,MAAM,EACf,OAAO,wBAAwB,EAC/B,OAAO,OAAO,IAAI,gBAAgB,YAAY;AAC7C,UAAM,YAAY,QAAQ,gBAAgB,GAAG,OAAO,SAAS,YAAY;AACvE,YAAM,SAAS,MAAM,QAAQ,cAAc,OAAO,EAAE,GAAG;AAAA,QACrD,QAAQ,eAAe;AAAA,MACzB,CAA6B;AAC7B,WAAK,QAAQ,SAAS,YAAY;AAAA,IACpC,CAAC;AAAA,EACH,CAAC;AACL;AAEF,QAAQ,WAAWA,SAAQ,IAAI,EAAE,MAAM,CAAC,UAAmB;AACzD,QAAM,YACJ,iBAAiB,YACb,QACA,IAAI,UAAU;AAAA,IACZ,MAAM;AAAA,IACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAClD,WAAW;AAAA,EACb,CAAC;AAEP,QAAM,UAAU,QAAQ,KAAoB;AAC5C,MAAI,QAAQ,MAAM;AAChB,IAAAA,SAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,UAAU,OAAO,GAAG,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,EACzE,OAAO;AACL,IAAAA,SAAQ,OAAO,MAAM,UAAU,UAAU,OAAO;AAAA,CAAI;AACpD,QAAI,UAAU,YAAY;AACxB,MAAAA,SAAQ,OAAO,MAAM,eAAe,UAAU,UAAU;AAAA,CAAI;AAAA,IAC9D;AAAA,EACF;AAEA,EAAAA,SAAQ,WAAW,UAAU,UAAU,IAAI;AAC7C,CAAC;AAED,eAAe,YACb,SACA,IACe;AACf,QAAM,aAAsC;AAAA,IAC1C,MAAM,QAAQ,QAAQ,IAAI;AAAA,IAC1B,SAAU,QAAQ,WAAW;AAAA,IAC7B,SAAS,QAAQ,WAAW;AAAA,IAC5B,MAAM,QAAQ,QAAQ;AAAA,IACtB,SAAS,QAAQ,WAAW;AAAA,EAC9B;AAEA,QAAM,iBAAiB;AAAA,IACrB,SAAS,WAAW,QAAQ;AAAA,IAC5B,SAAS,WAAW;AAAA,EACtB,CAAC;AAED,QAAM,YAAY,aAAa;AAAA,IAC7B,SAAS,WAAW,QAAQ;AAAA,IAC5B,SAAS,WAAW;AAAA,EACtB,CAAC;AAED,QAAM,SAAS,cAAc,UAAU;AACvC,QAAM,UAAU,IAAI,YAAY;AAAA,IAC9B;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,GAAG,SAAS,UAAU;AAC9B;AAEA,SAAS,cAAc,SAAqD;AAC1E,MAAI,QAAQ,YAAY,WAAW;AACjC,QAAI,CAAC,QAAQ,SAAS;AACpB,YAAM,IAAI,UAAU;AAAA,QAClB,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AACA,WAAO,IAAI,cAAc,QAAQ,OAAO;AAAA,EAC1C;AAEA,SAAO,IAAI,eAAe;AAC5B;AAEA,SAAS,KACP,OACA,SACA,QACM;AACN,MAAI,QAAQ,MAAM;AAChB,IAAAA,SAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,CAAI;AAC1D;AAAA,EACF;AAEA,EAAAA,SAAQ,OAAO,MAAM,GAAG,SAAS,OAAO,KAAK,IAAI,OAAO,KAAK,CAAC;AAAA,CAAI;AACpE;AAEA,SAAS,UAAU,MAAsB;AACvC,MAAI,KAAK,WAAW,MAAM,EAAG,QAAO;AACpC,MAAI,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,UAAU,EAAG,QAAO;AAC/D,SAAO;AACT;","names":["createInterface","process","readFile","readFile","path","path","path","readFile","writeFile","path","messages","previewText","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 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)\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 = new TelegramClient({\n apiId: config.apiId,\n apiHash: config.apiHash,\n storage: path.join(accountDir, 'mtcute-session'),\n })\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 // no-op: client storage/session is managed by mtcute\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 = new TelegramClient({\n apiId: config.apiId,\n apiHash: config.apiHash,\n storage: path.join(accountDir, 'mtcute-session'),\n })\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 // no-op: client storage/session is managed by mtcute\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 = new TelegramClient({\n apiId: config.apiId,\n apiHash: config.apiHash,\n storage: path.join(accountDir, 'mtcute-session'),\n })\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 // no-op: client storage/session is managed by mtcute\n }\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.4\",\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","path","messages","previewText","readFile","writeFile","createInterface","process"]}
|