@ih8e/express-cli 0.1.0 → 0.1.2

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.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/root.ts","../src/cli/auth.ts","../src/types/config.ts","../src/config/store.ts","../src/config/loader.ts","../src/auth/import.ts","../src/auth/keys.ts","../src/auth/apigw-signer.ts","../src/auth/device-login.ts","../src/auth/qr-login.ts","../src/auth/token-refresh.ts","../src/cli/api.ts","../src/api/client.ts","../src/cli/output.ts","../src/cli/config-cmd.ts","../src/cli/status.ts","../src/api/user.ts","../src/cli/contacts.ts","../src/api/websocket.ts","../src/api/chats.ts","../src/api/phonebook.ts","../src/cli/settings.ts","../src/api/settings.ts","../src/cli/chats.ts","../src/cli/send.ts","../src/api/messaging.ts","../src/api/messaging-ws.ts","../src/api/resolve.ts","../src/cli/avatar.ts","../src/api/uploads.ts","../src/cli/download.ts","../src/cli/messages.ts","../src/api/messages-read.ts","../src/api/decrypt.ts","../src/cli/listen.ts","../src/session/session.ts","../src/cli/tui.ts","../src/tui/index.tsx","../src/tui/app.tsx","../src/tui/image.ts","../src/cli/mcp.ts","../src/mcp/server.ts","../src/index.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { createAuthCommand } from \"./auth.js\";\nimport { createApiCommand } from \"./api.js\";\nimport { createConfigCommand } from \"./config-cmd.js\";\nimport { createStatusCommand } from \"./status.js\";\nimport { createContactsCommand } from \"./contacts.js\";\nimport { createSettingsCommand } from \"./settings.js\";\nimport { createChatsCommand } from \"./chats.js\";\nimport { createSendCommand } from \"./send.js\";\nimport { createAvatarCommand } from \"./avatar.js\";\nimport { createDownloadCommand } from \"./download.js\";\nimport { createMessagesCommand } from \"./messages.js\";\nimport { createListenCommand } from \"./listen.js\";\nimport { createTuiCommand } from \"./tui.js\";\nimport { createMcpCommand } from \"./mcp.js\";\n\nexport function createRootCommand(): Command {\n const program = new Command();\n\n program\n .name(\"express-cli\")\n .description(\"CLI client for eXpress Chat\")\n .version(\"0.1.0\")\n .option(\"--host <host>\", \"eXpress server host\");\n\n program.addCommand(createAuthCommand());\n program.addCommand(createApiCommand());\n program.addCommand(createConfigCommand());\n program.addCommand(createStatusCommand());\n program.addCommand(createContactsCommand());\n program.addCommand(createSettingsCommand());\n program.addCommand(createChatsCommand());\n program.addCommand(createSendCommand());\n program.addCommand(createAvatarCommand());\n program.addCommand(createDownloadCommand());\n program.addCommand(createMessagesCommand());\n program.addCommand(createListenCommand());\n program.addCommand(createTuiCommand());\n program.addCommand(createMcpCommand());\n\n return program;\n}\n","import { Command } from \"commander\";\nimport { importToken, logout, status, deviceLogin, qrLogin, loadApigwKeys, clearApigwKeys, importCtsKey } from \"../auth/index.js\";\nimport { getTokenExpiresAt, getRefreshToken, isTokenExpiringSoon } from \"../config/store.js\";\nimport { refreshToken } from \"../auth/token-refresh.js\";\n\nexport function createAuthCommand(): Command {\n const cmd = new Command(\"auth\");\n\n cmd.description(\"Authentication management\");\n\n cmd\n .command(\"import <token>\")\n .description(\"Import Bearer token from browser\")\n .option(\"--host <host>\", \"eXpress host\")\n .action(async (token: string, opts: { host?: string }) => {\n try {\n await importToken(token, opts.host ? { host: opts.host } : {});\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"login\")\n .description(\"Full device login (ed25519 signing for apigw endpoints)\")\n .option(\"--host <host>\", \"eXpress host\")\n .action(async (opts: { host?: string }) => {\n try {\n await deviceLogin(opts.host ? { host: opts.host } : {});\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"qr\")\n .description(\"QR-code login (scan with eXpress mobile app)\")\n .option(\"--host <host>\", \"eXpress host\")\n .action(async (opts: { host?: string }) => {\n try {\n await qrLogin(opts.host ? { host: opts.host } : {});\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"import-cts <private_key_b64> <key_id>\")\n .description(\"Import the account's shared CTS (E2E) key so the CLI decrypts like your phone/desktop. Get both values from the web client's IndexedDB (authState → encryptionKeys → user.privateKeys.cts: body + publicKeyId).\")\n .action((privateKeyB64: string, keyId: string) => {\n try {\n const ctsKey = importCtsKey(privateKeyB64, keyId);\n const pub = Buffer.from(ctsKey.publicKey).toString(\"base64\");\n console.log(`CTS key imported: ${keyId}`);\n console.log(` derived public key: ${pub}`);\n console.log(\" Verify this matches the KDC 'body' for this key_id. Do NOT run 'auth login/qr' with a different device now — it would re-register a new key and break sync.\");\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"logout\")\n .description(\"Remove stored authentication token and apigw keys\")\n .action(() => {\n clearApigwKeys();\n logout();\n });\n\n cmd\n .command(\"status\")\n .description(\"Show current authentication status\")\n .action(() => {\n status();\n const expiresAt = getTokenExpiresAt();\n const hasRefresh = !!getRefreshToken();\n if (expiresAt) {\n const remaining = Math.max(0, Math.floor((expiresAt - Date.now()) / 1000));\n const expired = remaining === 0;\n console.log(`Token: ${expired ? \"EXPIRED\" : `expires in ${remaining}s (~${(remaining / 60).toFixed(0)} min)`}`);\n console.log(`Refresh: ${hasRefresh ? \"available\" : \"not available\"}`);\n } else {\n console.log(\"Token: expiry unknown\");\n console.log(`Refresh: ${hasRefresh ? \"available\" : \"not available\"}`);\n }\n const keys = loadApigwKeys();\n if (keys) {\n console.log(`Apigw: enabled (signing: ${keys.signingKey.keyId.slice(0, 8)}..., encryption: ${keys.encryptionKey.keyId.slice(0, 8)}..., server: ${keys.serverPublicKeyId.slice(0, 8)}...)`);\n } else {\n console.log(\"Apigw: not configured. Run 'express auth login' or 'express auth qr' to enable.\");\n }\n });\n\n cmd\n .command(\"refresh\")\n .description(\"Refresh access token using refresh token\")\n .action(async () => {\n try {\n const refreshed = await refreshToken();\n if (refreshed) {\n const expiresAt = getTokenExpiresAt();\n const remaining = expiresAt ? Math.max(0, Math.floor((expiresAt - Date.now()) / 1000)) : 0;\n console.log(`Token refreshed successfully (expires in ${remaining}s)`);\n } else {\n console.error(\"Failed to refresh token. Re-authenticate with `express auth qr`.\");\n process.exit(1);\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { z } from \"zod\";\n\nexport const configSchema = z.object({\n host: z.string().min(1, \"host is required — set EXPRESS_HOST or configure via `express config set host <host>`\"),\n protocol: z.enum([\"https\", \"http\"]).default(\"https\"),\n token: z.string().optional(),\n locale: z.string().default(\"ru\"),\n platform: z.string().default(\"web\"),\n platform_package_id: z.string().default(\"ru.alfabank\"),\n app_version: z.string().default(\"3.66.47\"),\n output: z.enum([\"table\", \"json\"]).default(\"table\"),\n});\n\nexport type Config = z.infer<typeof configSchema>;\n\nexport const envSchema = z.object({\n EXPRESS_HOST: z.string().optional(),\n EXPRESS_TOKEN: z.string().optional(),\n EXPRESS_LOCALE: z.string().optional(),\n EXPRESS_OUTPUT: z.enum([\"table\", \"json\"]).optional(),\n});\n\nexport type EnvConfig = z.infer<typeof envSchema>;\n","import Conf from \"conf\";\nimport type { Config } from \"../types/index.js\";\n\ninterface StoredApigwKeys {\n signingKey: { keyId: string; privateKey: string; publicKey: string };\n rtsKeyId?: string;\n encryptionKeyId?: string;\n encryptionToken?: string;\n}\n\ninterface StoreSchema {\n config: Partial<Config>;\n authToken: string | null;\n refreshToken: string | null;\n rtsAuthToken: string | null;\n apigwKeys: string | null;\n tokenExpiresAt: number | null;\n etsAuthToken: string | null;\n}\n\nconst store = new Conf<StoreSchema>({\n projectName: \"express-cli\",\n defaults: {\n config: {},\n authToken: null,\n refreshToken: null,\n rtsAuthToken: null,\n apigwKeys: null,\n tokenExpiresAt: null,\n etsAuthToken: null,\n },\n});\n\nexport function getStoredConfig(): Partial<Config> {\n return store.get(\"config\") ?? {};\n}\n\nexport function setStoredConfig(partial: Partial<Config>): void {\n const current = getStoredConfig();\n store.set(\"config\", { ...current, ...partial });\n}\n\nexport function getAuthToken(): string | null {\n return store.get(\"authToken\") ?? null;\n}\n\nexport function setAuthToken(token: string | null): void {\n if (token === null) {\n store.delete(\"authToken\");\n } else {\n store.set(\"authToken\", token);\n }\n}\n\nexport function getRtsAuthToken(): string | null {\n return store.get(\"rtsAuthToken\") ?? null;\n}\n\nexport function setRtsAuthToken(token: string | null): void {\n if (token === null) {\n store.delete(\"rtsAuthToken\");\n } else {\n store.set(\"rtsAuthToken\", token);\n }\n}\n\nexport function getRefreshToken(): string | null {\n return store.get(\"refreshToken\") ?? null;\n}\n\nexport function setRefreshToken(token: string | null): void {\n if (token === null) {\n store.delete(\"refreshToken\");\n } else {\n store.set(\"refreshToken\", token);\n }\n}\n\nexport function getTokenExpiresAt(): number | null {\n return store.get(\"tokenExpiresAt\") ?? null;\n}\n\nexport function setTokenExpiresAt(expiresAt: number | null): void {\n if (expiresAt === null) {\n store.delete(\"tokenExpiresAt\");\n } else {\n store.set(\"tokenExpiresAt\", expiresAt);\n }\n}\n\nexport function calcTokenExpiresAt(expiresIn: number): number {\n return Date.now() + Math.floor(expiresIn / 2) * 1000;\n}\n\nexport function isTokenExpiringSoon(): boolean {\n const expiresAt = getTokenExpiresAt();\n if (!expiresAt) return true;\n return Date.now() >= expiresAt;\n}\n\nexport function getEtsAuthToken(): string | null {\n return store.get(\"etsAuthToken\") ?? null;\n}\n\nexport function setEtsAuthToken(token: string | null): void {\n if (token === null) {\n store.delete(\"etsAuthToken\");\n } else {\n store.set(\"etsAuthToken\", token);\n }\n}\n\nexport function getApigwKeysRaw(): string | null {\n return store.get(\"apigwKeys\") ?? null;\n}\n\nexport function setApigwKeysRaw(data: string | null): void {\n if (data === null) {\n store.delete(\"apigwKeys\");\n } else {\n store.set(\"apigwKeys\", data);\n }\n}\n\nexport function clearAll(): void {\n store.clear();\n}\n\nexport { store };\n","import { configSchema, type Config } from \"../types/index.js\";\nimport { getStoredConfig, getAuthToken } from \"./store.js\";\n\nexport function loadConfig(cliOverrides: Partial<Config> = {}): Config {\n const stored = getStoredConfig();\n const env: Partial<Config> = {};\n\n if (process.env.EXPRESS_HOST) env.host = process.env.EXPRESS_HOST;\n if (process.env.EXPRESS_TOKEN) env.token = process.env.EXPRESS_TOKEN;\n if (process.env.EXPRESS_LOCALE) env.locale = process.env.EXPRESS_LOCALE;\n if (process.env.EXPRESS_OUTPUT) env.output = process.env.EXPRESS_OUTPUT as \"table\" | \"json\";\n\n const merged = {\n ...stored,\n ...env,\n ...cliOverrides,\n };\n\n if (!merged.token) {\n const storedToken = getAuthToken();\n if (storedToken) merged.token = storedToken;\n }\n\n return configSchema.parse(merged);\n}\n\nexport function getBaseUrl(config: Config): string {\n return `${config.protocol}://${config.host}`;\n}\n\nfunction getDomain(ctsHost: string): string {\n const parts = ctsHost.split('.');\n return parts.length > 2 ? parts.slice(1).join('.') : ctsHost;\n}\n\nexport function getEtsBaseUrl(config: Config): string {\n return `https://ets.${getDomain(config.host)}`;\n}\n\nexport function getWebOrigin(config: Config): string {\n return `https://${getDomain(config.host)}`;\n}\n","import { setAuthToken, setStoredConfig, getAuthToken } from \"../config/index.js\";\nimport { getBaseUrl, loadConfig } from \"../config/loader.js\";\nimport type { Config } from \"../types/index.js\";\n\nexport async function importToken(token: string, cliOverrides: Partial<Config> = {}): Promise<void> {\n const config = loadConfig(cliOverrides);\n const baseUrl = getBaseUrl(config);\n\n const url = `${baseUrl}/api/v1/phonebook/profiles/self`;\n const res = await fetch(url, {\n headers: {\n Authorization: `Bearer ${token}`,\n Accept: \"application/json\",\n },\n });\n\n if (!res.ok) {\n throw new Error(`Token validation failed: ${res.status} ${res.statusText}`);\n }\n\n const body = await res.json() as { result?: { profile?: { name?: string; user_huid?: string } }; profile?: { name?: string; user_huid?: string } };\n setAuthToken(token);\n\n const profile = body.profile ?? body.result?.profile;\n if (profile?.name) {\n console.log(`Authenticated as: ${profile.name} (${profile.user_huid ?? \"unknown huid\"})`);\n } else {\n console.log(\"Token imported and validated successfully.\");\n }\n}\n\nexport function logout(): void {\n setAuthToken(null);\n console.log(\"Logged out. Token removed.\");\n}\n\nexport function status(): void {\n const token = getAuthToken();\n if (!token) {\n console.log(\"Not authenticated. Use `express auth import <token>` to login.\");\n return;\n }\n console.log(`Authenticated. Token: ${token.slice(0, 20)}...`);\n}\n","import { ed25519 } from \"@noble/curves/ed25519.js\";\nimport { randomBytes } from \"node:crypto\";\nimport { getApigwKeysRaw, setApigwKeysRaw } from \"../config/store.js\";\nimport nacl from \"tweetnacl\";\n\nexport interface SigningKeyPair {\n keyId: string;\n privateKey: Uint8Array;\n publicKey: Uint8Array;\n}\n\nexport interface EncryptionKeyPair {\n keyId: string;\n privateKey: Uint8Array;\n publicKey: Uint8Array;\n}\n\nexport interface ApigwKeys {\n signingKey: SigningKeyPair;\n encryptionKey: EncryptionKeyPair;\n ctsKey?: EncryptionKeyPair; // separate CTS key for E2E message encryption\n serverPublicKey: Uint8Array;\n serverPublicKeyId: string;\n}\n\nexport function generateSigningKeyPair(): SigningKeyPair {\n const privateKey = ed25519.utils.randomSecretKey();\n const publicKey = ed25519.getPublicKey(privateKey);\n const keyId = crypto.randomUUID();\n return { keyId, privateKey, publicKey };\n}\n\nexport function generateEncryptionKeyPair(): EncryptionKeyPair {\n const keyPair = nacl.box.keyPair();\n const keyId = crypto.randomUUID();\n return {\n keyId,\n privateKey: keyPair.secretKey,\n publicKey: keyPair.publicKey,\n };\n}\n\nexport function saveApigwKeys(keys: ApigwKeys): void {\n const data: Record<string, unknown> = {\n signingKey: {\n keyId: keys.signingKey.keyId,\n privateKey: Buffer.from(keys.signingKey.privateKey).toString(\"base64\"),\n publicKey: Buffer.from(keys.signingKey.publicKey).toString(\"base64\"),\n },\n encryptionKey: {\n keyId: keys.encryptionKey.keyId,\n privateKey: Buffer.from(keys.encryptionKey.privateKey).toString(\"base64\"),\n publicKey: Buffer.from(keys.encryptionKey.publicKey).toString(\"base64\"),\n },\n serverPublicKey: Buffer.from(keys.serverPublicKey).toString(\"base64\"),\n serverPublicKeyId: keys.serverPublicKeyId,\n };\n if (keys.ctsKey) {\n data.ctsKey = {\n keyId: keys.ctsKey.keyId,\n privateKey: Buffer.from(keys.ctsKey.privateKey).toString(\"base64\"),\n publicKey: Buffer.from(keys.ctsKey.publicKey).toString(\"base64\"),\n };\n }\n setApigwKeysRaw(JSON.stringify(data));\n}\n\nexport function loadApigwKeys(): ApigwKeys | null {\n const raw = getApigwKeysRaw();\n if (!raw) return null;\n\n try {\n const data = JSON.parse(raw) as {\n signingKey: { keyId: string; privateKey: string; publicKey: string };\n encryptionKey?: { keyId: string; privateKey: string; publicKey: string };\n ctsKey?: { keyId: string; privateKey: string; publicKey: string };\n serverPublicKey?: string;\n serverPublicKeyId?: string;\n rtsKeyId?: string;\n encryptionKeyId?: string;\n encryptionToken?: string;\n };\n\n if (!data.encryptionKey || !data.serverPublicKey) {\n return null;\n }\n\n return {\n signingKey: {\n keyId: data.signingKey.keyId,\n privateKey: new Uint8Array(Buffer.from(data.signingKey.privateKey, \"base64\")),\n publicKey: new Uint8Array(Buffer.from(data.signingKey.publicKey, \"base64\")),\n },\n encryptionKey: {\n keyId: data.encryptionKey.keyId,\n privateKey: new Uint8Array(Buffer.from(data.encryptionKey.privateKey, \"base64\")),\n publicKey: new Uint8Array(Buffer.from(data.encryptionKey.publicKey, \"base64\")),\n },\n ctsKey: data.ctsKey ? {\n keyId: data.ctsKey.keyId,\n privateKey: new Uint8Array(Buffer.from(data.ctsKey.privateKey, \"base64\")),\n publicKey: new Uint8Array(Buffer.from(data.ctsKey.publicKey, \"base64\")),\n } : undefined,\n serverPublicKey: new Uint8Array(Buffer.from(data.serverPublicKey, \"base64\")),\n serverPublicKeyId: data.serverPublicKeyId ?? data.rtsKeyId ?? data.encryptionKeyId ?? \"\",\n };\n } catch {\n return null;\n }\n}\n\nexport function getOrCreateApigwKeys(): ApigwKeys {\n const existing = loadApigwKeys();\n if (existing) return existing;\n\n const keys: ApigwKeys = {\n signingKey: generateSigningKeyPair(),\n encryptionKey: generateEncryptionKeyPair(),\n serverPublicKey: new Uint8Array(0),\n serverPublicKeyId: \"\",\n };\n saveApigwKeys(keys);\n return keys;\n}\n\nexport function signEd25519(privateKey: Uint8Array, message: Uint8Array): Uint8Array {\n return ed25519.sign(message, privateKey);\n}\n\nexport function encryptToken(token: string, serverPublicKey: Uint8Array, rtsPrivateKey: Uint8Array): string {\n const message = new TextEncoder().encode(token);\n const nonce = randomBytes(nacl.box.nonceLength);\n const encrypted = nacl.box(message, nonce, serverPublicKey, rtsPrivateKey);\n if (!encrypted) {\n throw new Error(\"crypto_box encryption failed\");\n }\n const combined = new Uint8Array(nonce.length + encrypted.length);\n combined.set(nonce, 0);\n combined.set(encrypted, nonce.length);\n return Buffer.from(combined).toString(\"base64\");\n}\n\nexport function generateNonce(): string {\n return Buffer.from(randomBytes(32)).toString(\"base64\");\n}\n\nexport function publicKeyToBase64(publicKey: Uint8Array): string {\n return Buffer.from(publicKey).toString(\"base64\");\n}\n\nexport function clearApigwKeys(): void {\n setApigwKeysRaw(null);\n}\n\n/**\n * Import an existing CTS (E2E) keypair so the CLI shares the account's key with\n * the official devices instead of minting its own. Public key is derived from\n * the private key; keyId must be the KDC-published id (e.g. from the web client).\n */\nexport function importCtsKey(privateKeyB64: string, keyId: string): EncryptionKeyPair {\n const existing = loadApigwKeys();\n if (!existing) {\n throw new Error(\"No apigw keys yet. Run 'express auth login' or 'express auth qr' first.\");\n }\n const privateKey = new Uint8Array(Buffer.from(privateKeyB64, \"base64\"));\n if (privateKey.length !== nacl.box.secretKeyLength) {\n throw new Error(`Invalid private key length: ${privateKey.length} bytes (expected ${nacl.box.secretKeyLength})`);\n }\n const publicKey = nacl.box.keyPair.fromSecretKey(privateKey).publicKey;\n const ctsKey: EncryptionKeyPair = { keyId, privateKey, publicKey };\n saveApigwKeys({ ...existing, ctsKey });\n return ctsKey;\n}\n\nexport function decryptRegistrationData(registrationDataB64: string, encryptionKey: Uint8Array): unknown {\n const raw = Uint8Array.from(Buffer.from(registrationDataB64, \"base64\"));\n const nonce = raw.slice(0, nacl.secretbox.nonceLength);\n const ciphertext = raw.slice(nacl.secretbox.nonceLength);\n const plaintext = nacl.secretbox.open(ciphertext, nonce, encryptionKey);\n if (!plaintext) {\n throw new Error(\"Failed to decrypt registration_data\");\n }\n const json = new TextDecoder().decode(plaintext);\n return JSON.parse(json);\n}\n\nexport function decryptRtsToken(encryptedRtsTokenB64: string, serverPublicKey: Uint8Array, rtsPrivateKey: Uint8Array): string {\n const raw = Uint8Array.from(Buffer.from(encryptedRtsTokenB64, \"base64\"));\n const nonce = raw.slice(0, nacl.box.nonceLength);\n const ciphertext = raw.slice(nacl.box.nonceLength);\n const plaintext = nacl.box.open(ciphertext, nonce, serverPublicKey, rtsPrivateKey);\n if (!plaintext) {\n throw new Error(\"Failed to decrypt encrypted_rts_token\");\n }\n return new TextDecoder().decode(plaintext);\n}\n\nexport function extractRtsKeyIdFromToken(token: string): string {\n const parts = token.split(\".\");\n if (parts.length < 2) return \"\";\n const bytes = Buffer.from(parts[1], \"base64\");\n const text = bytes.toString(\"latin1\");\n const uuidRegex = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/g;\n const uuids: string[] = [];\n let match;\n while ((match = uuidRegex.exec(text)) !== null) {\n uuids.push(match[0]);\n }\n return uuids.length >= 4 ? uuids[3] : \"\";\n}\n","import { signEd25519, generateNonce, loadApigwKeys, encryptToken, saveApigwKeys } from \"./keys.js\";\nimport { sha256 } from \"@noble/hashes/sha2.js\";\n\n\nexport interface ApigwSignedHeaders {\n Authorization: string;\n \"Express-Proxy-Authorization\": string;\n \"Express-Request-Nonce\": string;\n Digest?: string;\n Signature: string;\n \"Content-Type\"?: string;\n}\n\nexport function buildSigningInput(\n method: string,\n path: string,\n created: number,\n nonce: string,\n rtsAccessToken: string,\n digest?: string,\n): { signingString: string; signedHeaders: string } {\n return buildSigningInputInternal(method, path, created, nonce, rtsAccessToken, digest);\n}\n\nexport function buildQrSigningInput(\n method: string,\n path: string,\n created: number,\n nonce: string,\n digest?: string,\n): { signingString: string; signedHeaders: string } {\n return buildSigningInputInternal(method, path, created, nonce, undefined, digest);\n}\n\nfunction buildSigningInputInternal(\n method: string,\n path: string,\n created: number,\n nonce: string,\n rtsAccessToken: string | undefined,\n digest?: string,\n): { signingString: string; signedHeaders: string } {\n const lines: string[] = [];\n const headerNames: string[] = [];\n\n lines.push(`(request-target): ${method.toLowerCase()} ${path}`);\n headerNames.push(\"(request-target)\");\n\n lines.push(`(created): ${created}`);\n headerNames.push(\"(created)\");\n\n if (rtsAccessToken) {\n lines.push(`(rts-access-token): ${rtsAccessToken}`);\n headerNames.push(\"(rts-access-token)\");\n }\n\n lines.push(`express-request-nonce: ${nonce}`);\n headerNames.push(\"express-request-nonce\");\n\n if (digest) {\n lines.push(`digest: SHA-256=${digest}`);\n headerNames.push(\"digest\");\n }\n\n return {\n signingString: lines.join(\"\\n\"),\n signedHeaders: headerNames.join(\" \"),\n };\n}\n\nexport function computeDigest(body: string): string {\n const hash = sha256(new TextEncoder().encode(body));\n return Buffer.from(hash).toString(\"base64\");\n}\n\nexport async function signApigwRequest(params: {\n method: string;\n url: string;\n baseUrl: string;\n body?: string;\n ctsToken: string;\n rtsToken?: string;\n etsAuthToken?: string;\n}): Promise<ApigwSignedHeaders> {\n const keys = loadApigwKeys();\n if (!keys) {\n throw new Error(\"Apigw keys not initialized. Run 'express auth login' first.\");\n }\n\n const urlObj = new URL(params.url.startsWith(\"http\") ? params.url : `${params.baseUrl}${params.url}`);\n const path = urlObj.pathname + urlObj.search;\n const created = Math.floor(Date.now() / 1000);\n const nonce = generateNonce();\n\n let digest: string | undefined;\n if (params.body) {\n digest = computeDigest(params.body);\n }\n\n const tokenForSigning = params.etsAuthToken || params.rtsToken || params.ctsToken;\n const { signingString, signedHeaders } = buildSigningInput(\n params.method,\n path,\n created,\n nonce,\n tokenForSigning,\n digest,\n );\n\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] path: ${path}`);\n console.log(` [DEBUG] signedHeaders: ${signedHeaders}`);\n console.log(` [DEBUG] signingString:\\n${signingString}`);\n console.log(` [DEBUG] signingKey keyId: ${keys.signingKey.keyId}`);\n console.log(` [DEBUG] encryptionKey keyId: ${keys.encryptionKey.keyId}`);\n }\n\n const signature = signEd25519(keys.signingKey.privateKey, new TextEncoder().encode(signingString));\n const signatureBase64 = Buffer.from(signature).toString(\"base64\");\n\n let serverPublicKey = keys.serverPublicKey;\n try {\n const etsBaseUrl = params.baseUrl;\n const kdcStartRes = await fetch(`${etsBaseUrl}/api/v1/kdc/start`, {\n headers: {\n Accept: \"application/json\",\n },\n });\n if (kdcStartRes.ok) {\n const kdcStartData = await kdcStartRes.json() as { result?: string };\n if (kdcStartData.result) {\n serverPublicKey = new Uint8Array(Buffer.from(kdcStartData.result, \"base64\"));\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] ETS server public key (curve25519): ${kdcStartData.result}`);\n }\n keys.serverPublicKey = serverPublicKey;\n keys.serverPublicKeyId = \"kdc-start-ets\";\n saveApigwKeys(keys);\n }\n }\n } catch {\n // Fall back to cached key\n }\n\n const tokenToEncrypt = params.etsAuthToken || params.rtsToken || params.ctsToken;\n const encryptedToken = encryptToken(tokenToEncrypt, serverPublicKey, keys.encryptionKey.privateKey);\n\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] ctsToken length: ${params.ctsToken.length}`);\n console.log(` [DEBUG] rtsToken: ${params.rtsToken ? `present (${params.rtsToken.length} chars)` : \"not set\"}`);\n console.log(` [DEBUG] etsAuthToken: ${params.etsAuthToken ? `present (${params.etsAuthToken.length} chars)` : \"not set\"}`);\n console.log(` [DEBUG] tokenToEncrypt: ${tokenToEncrypt.length} chars (source: ${params.etsAuthToken ? 'etsAuthToken' : params.rtsToken ? 'rtsToken' : 'ctsToken'})`);\n console.log(` [DEBUG] serverPublicKey b64: ${Buffer.from(serverPublicKey).toString(\"base64\")}`);\n console.log(` [DEBUG] encryptionPrivateKey b64: ${Buffer.from(keys.encryptionKey.privateKey).toString(\"base64\")}`);\n console.log(` [DEBUG] encryptionPublicKey b64: ${Buffer.from(keys.encryptionKey.publicKey).toString(\"base64\")}`);\n console.log(` [DEBUG] encryptedToken length: ${encryptedToken.length}`);\n }\n\n return {\n Authorization: `keyId=\"${keys.encryptionKey.keyId}\",token=\"${encryptedToken}\"`,\n \"Express-Proxy-Authorization\": `Bearer ${params.ctsToken}`,\n \"Express-Request-Nonce\": nonce,\n ...(digest && { Digest: `SHA-256=${digest}` }),\n Signature: `keyId=\"${keys.signingKey.keyId}\",algorithm=\"ed25519\",headers=\"${signedHeaders}\",signature=\"${signatureBase64}\",created=${created}`,\n ...(params.body && { \"Content-Type\": \"application/json\" }),\n };\n}\n\nexport interface QrSignedHeaders {\n \"Express-Request-Nonce\": string;\n Digest: string;\n Signature: string;\n \"Content-Type\": string;\n}\n\nexport function signQrRequest(params: {\n method: string;\n url: string;\n body: string;\n registrationId: string;\n privateKey: Uint8Array;\n}): QrSignedHeaders {\n const urlObj = new URL(params.url);\n const path = urlObj.pathname + urlObj.search;\n const created = Math.floor(Date.now() / 1000);\n const nonce = generateNonce();\n const digest = computeDigest(params.body);\n\n const { signingString, signedHeaders } = buildQrSigningInput(\n params.method,\n path,\n created,\n nonce,\n digest,\n );\n\n const signature = signEd25519(params.privateKey, new TextEncoder().encode(signingString));\n const signatureBase64 = Buffer.from(signature).toString(\"base64\");\n\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG QR] path: ${path}`);\n console.log(` [DEBUG QR] signedHeaders: ${signedHeaders}`);\n console.log(` [DEBUG QR] signingString:\\n${signingString}`);\n }\n\n return {\n \"Express-Request-Nonce\": nonce,\n Digest: `SHA-256=${digest}`,\n Signature: `keyId=\"${params.registrationId}\",algorithm=\"ed25519\",headers=\"${signedHeaders}\",signature=\"${signatureBase64}\",created=${created}`,\n \"Content-Type\": \"application/json\",\n };\n}\n","import { generateSigningKeyPair, generateEncryptionKeyPair, loadApigwKeys, saveApigwKeys, clearApigwKeys, publicKeyToBase64, type ApigwKeys, type SigningKeyPair, type EncryptionKeyPair } from \"./keys.js\";\nimport { signApigwRequest } from \"./apigw-signer.js\";\nimport { setAuthToken, getAuthToken, getApigwKeysRaw, setApigwKeysRaw } from \"../config/store.js\";\nimport { loadConfig, getBaseUrl, getEtsBaseUrl, getWebOrigin } from \"../config/loader.js\";\nimport type { Config } from \"../types/index.js\";\nimport nacl from \"tweetnacl\";\nimport { randomUUID } from \"node:crypto\";\n\n/** Returns the account's current cts key_id in KDC, or null if none exists. */\nasync function fetchCurrentAccountCtsKey(baseUrl: string, token: string, userHuid: string, webOrigin: string): Promise<string | null> {\n try {\n const res = await fetch(`${baseUrl}/api/v1/kdc/keys/?user_huids=${userHuid}`, {\n headers: { Accept: \"application/json\", Authorization: `Bearer ${token}`, Origin: webOrigin },\n });\n if (!res.ok) return null;\n const data = await res.json() as { result?: Array<{ id: string; kind: string }> };\n return data.result?.find((k) => k.kind === \"cts\")?.id ?? null;\n } catch {\n return null;\n }\n}\n\ninterface ActivationResponse {\n result?: {\n access_token?: string;\n refresh_token?: string;\n user_huid?: string;\n };\n access_token?: string;\n refresh_token?: string;\n user_huid?: string;\n}\n\ninterface KdcKeysResponse {\n status?: string;\n result?: Array<{\n id: string;\n body: string;\n kind: string;\n user_huid: string;\n }>;\n}\n\nfunction extractResult<T>(data: T & { result?: T }): T {\n return (data.result ?? data) as T;\n}\n\nexport async function deviceLogin(cliOverrides: Partial<Config> = {}): Promise<void> {\n const config = loadConfig(cliOverrides);\n const baseUrl = getBaseUrl(config);\n const etsBaseUrl = getEtsBaseUrl(config);\n const webOrigin = getWebOrigin(config);\n const currentToken = config.token ?? getAuthToken();\n\n if (!currentToken) {\n throw new Error(\"No Bearer token. Run 'express auth import <token>' first, then 'express auth login'.\");\n }\n\n console.log(\"Step 1/5: Registering device with AD integration...\");\n\n const adBody = JSON.stringify({\n app_version: config.app_version,\n device: \"Chrome 149.0\",\n device_software: \"macOS 10.15.7\",\n manufacturer: \"Google\",\n platform: config.platform,\n locale: config.locale,\n platform_package_id: config.platform_package_id,\n device_meta: {\n pushes: false,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n permissions: { notifications: true },\n },\n device_hostname: null,\n });\n\n const adRes = await fetch(`${baseUrl}/api/v1/ad_integration/token`, {\n method: \"PUT\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\n \"Accept-Language\": \"ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7\",\n \"Cache-Control\": \"no-cache\",\n \"Pragma\": \"no-cache\",\n \"sec-ch-ua\": '\"Google Chrome\";v=\"149\", \"Chromium\";v=\"149\", \"Not)A;Brand\";v=\"24\"',\n \"sec-ch-ua-mobile\": \"?0\",\n \"sec-ch-ua-platform\": '\"macOS\"',\n },\n body: adBody,\n });\n\n const adText = await adRes.text();\n\n if (!adRes.ok) {\n throw new Error(`AD integration failed (${adRes.status}): ${adText.slice(0, 500)}`);\n }\n\n console.log(` AD integration: ${adText.slice(0, 200)}`);\n\n console.log(\"Step 2/5: Fetching user profile and server public key...\");\n\n const selfProfileRes = await fetch(`${baseUrl}/api/v1/phonebook/profiles/self`, {\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n },\n });\n let userHuid = \"\";\n let serverId = \"\";\n if (selfProfileRes.ok) {\n const selfData = await selfProfileRes.json() as { profile?: { user_huid?: string; server_id?: string } };\n userHuid = selfData.profile?.user_huid ?? \"\";\n serverId = selfData.profile?.server_id ?? userHuid;\n console.log(` User HUID: ${userHuid || \"unknown\"}`);\n }\n\n let serverPublicKey = new Uint8Array(0);\n let serverPublicKeyId = \"\";\n\n const existingKeys = loadApigwKeys();\n if (existingKeys?.serverPublicKey?.length) {\n serverPublicKey = existingKeys.serverPublicKey;\n serverPublicKeyId = existingKeys.serverPublicKeyId;\n console.log(` Server public key (cached): ${serverPublicKeyId || \"unknown\"}`);\n }\n\n if (!serverPublicKey.length) {\n try {\n const kdcStartRes = await fetch(`${etsBaseUrl}/api/v1/kdc/start`, {\n headers: { Accept: \"application/json\" },\n });\n if (kdcStartRes.ok) {\n const kdcStartData = await kdcStartRes.json() as { result?: string };\n if (kdcStartData.result) {\n serverPublicKey = new Uint8Array(Buffer.from(kdcStartData.result, \"base64\"));\n serverPublicKeyId = \"kdc-start-ets\";\n console.log(` Server public key (from ets): ${serverPublicKeyId}`);\n }\n }\n } catch {}\n }\n\n if (!serverPublicKey.length && serverId) {\n const kdcFetchUrl = `${baseUrl}/api/v1/kdc/keys/?ids=${serverId}`;\n const kdcFetchRes = await fetch(kdcFetchUrl, {\n headers: {\n \"Accept\": \"application/json\",\n \"Authorization\": `Bearer ${currentToken}`,\n },\n });\n\n if (kdcFetchRes.ok) {\n const kdcFetchData = JSON.parse(await kdcFetchRes.text()) as KdcKeysResponse;\n const kdcKeys = kdcFetchData.result ?? kdcFetchData as unknown as Array<{ id: string; body: string; kind: string; user_huid: string }>;\n const serverKey = Array.isArray(kdcKeys)\n ? kdcKeys.find((k) => (k.kind === \"rest\" || k.kind === \"rts\") && k.user_huid === serverId)\n : null;\n if (!serverKey && Array.isArray(kdcKeys) && kdcKeys.length > 0) {\n const first = kdcKeys[0];\n serverPublicKey = new Uint8Array(Buffer.from(first.body, \"base64\"));\n serverPublicKeyId = first.id;\n } else if (serverKey) {\n serverPublicKey = new Uint8Array(Buffer.from(serverKey.body, \"base64\"));\n serverPublicKeyId = serverKey.id;\n }\n console.log(` Server public key (from KDC): ${serverPublicKeyId || \"not found\"}`);\n }\n }\n\n if (!serverPublicKey.length) {\n throw new Error(\"Could not fetch server public key from KDC\");\n }\n\n console.log(\"Step 3/5: Registering keys with KDC...\");\n\n let apigwSigningKey: SigningKeyPair;\n let apigwEncryptionKey: EncryptionKeyPair;\n\n if (existingKeys?.signingKey && existingKeys?.encryptionKey) {\n apigwSigningKey = existingKeys.signingKey;\n apigwEncryptionKey = existingKeys.encryptionKey;\n console.log(` Reusing existing signing key: ${apigwSigningKey.keyId}`);\n console.log(` Reusing existing encryption key: ${apigwEncryptionKey.keyId}`);\n } else {\n apigwSigningKey = generateSigningKeyPair();\n apigwEncryptionKey = generateEncryptionKeyPair();\n\n const apigwKeyPublicBase64 = publicKeyToBase64(apigwSigningKey.publicKey);\n console.log(` Signing key: id=${apigwSigningKey.keyId} pub=${apigwKeyPublicBase64}`);\n\n const kdcUrl = `${baseUrl}/api/v2/kdc/keys/${userHuid}`;\n const kdcBody = JSON.stringify({\n key: apigwKeyPublicBase64,\n kind: \"ed25519\",\n algo: \"ed25519\",\n id: apigwSigningKey.keyId,\n });\n\n const [kdcRes, etsKdcRes] = await Promise.all([\n fetch(kdcUrl, {\n method: \"POST\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Content-Type\": \"application/json\",\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n },\n body: kdcBody,\n }),\n fetch(`${etsBaseUrl}/api/v2/kdc/keys/${userHuid}`, {\n method: \"POST\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Content-Type\": \"application/json\",\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n },\n body: kdcBody,\n }),\n ]);\n\n if (!kdcRes.ok) {\n const kdcErrText = await kdcRes.text().catch(() => \"\");\n console.log(` Warning: CTS KDC signing key registration failed (${kdcRes.status}): ${kdcErrText.slice(0, 200)}`);\n } else {\n console.log(` Signing key registered in CTS: ${apigwSigningKey.keyId}`);\n }\n\n if (!etsKdcRes.ok) {\n const etsErrText = await etsKdcRes.text().catch(() => \"\");\n console.log(` Warning: ETS KDC signing key registration failed (${etsKdcRes.status}): ${etsErrText.slice(0, 200)}`);\n } else {\n console.log(` Signing key registered in ETS: ${apigwSigningKey.keyId}`);\n }\n\n const encryptionKeyPublicBase64 = publicKeyToBase64(apigwEncryptionKey.publicKey);\n\n const kdcEncBody = JSON.stringify({\n key: encryptionKeyPublicBase64,\n kind: \"rts\",\n algo: \"xsalsa20\",\n id: apigwEncryptionKey.keyId,\n });\n\n const kdcEncRes = await fetch(kdcUrl, {\n method: \"POST\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Content-Type\": \"application/json\",\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n },\n body: kdcEncBody,\n });\n\n const etsKdcEncRes = await fetch(`${etsBaseUrl}/api/v2/kdc/keys/${userHuid}`, {\n method: \"POST\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Content-Type\": \"application/json\",\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n },\n body: kdcEncBody,\n });\n\n if (!kdcEncRes.ok) {\n const kdcErrText = await kdcEncRes.text().catch(() => \"\");\n console.log(` Warning: CTS KDC encryption key registration failed (${kdcEncRes.status}): ${kdcErrText.slice(0, 200)}`);\n } else {\n console.log(` Encryption key registered in CTS: ${apigwEncryptionKey.keyId}`);\n }\n\n if (!etsKdcEncRes.ok) {\n const etsErrText = await etsKdcEncRes.text().catch(() => \"\");\n console.log(` Warning: ETS KDC encryption key registration failed (${etsKdcEncRes.status}): ${etsErrText.slice(0, 200)}`);\n } else {\n console.log(` Encryption key registered in ETS: ${apigwEncryptionKey.keyId}`);\n }\n }\n\n let ctsKey: EncryptionKeyPair | undefined = existingKeys?.ctsKey;\n if (!ctsKey) {\n // Guard: never mint a cts key if the account already has one in KDC — the CLI\n // can't upload the private-key backup, so a new key would break other devices.\n const currentCts = await fetchCurrentAccountCtsKey(baseUrl, currentToken, userHuid, webOrigin);\n if (currentCts) {\n throw new Error(\n `Account already has a shared CTS key (${currentCts}) that this CLI doesn't hold.\\n` +\n `Minting a new one would break your other devices. Import the shared key instead:\\n` +\n ` express auth import-cts <private_key_b64> ${currentCts}\\n` +\n `(extract it from a logged-in web client: IndexedDB authState → encryptionKeys → user.privateKeys.cts)`,\n );\n }\n const ctsKeyPair = nacl.box.keyPair();\n const ctsKeyId = crypto.randomUUID();\n ctsKey = {\n keyId: ctsKeyId,\n privateKey: ctsKeyPair.secretKey,\n publicKey: ctsKeyPair.publicKey,\n };\n\n const ctsKeyPubB64 = Buffer.from(ctsKeyPair.publicKey).toString(\"base64\");\n const ctsKeyBody = JSON.stringify({ key: ctsKeyPubB64, kind: \"cts\", algo: \"xsalsa20\", id: ctsKeyId });\n\n const [ctsCtsRes, etsCtsRes] = await Promise.all([\n fetch(`${baseUrl}/api/v2/kdc/keys/${userHuid}`, {\n method: \"POST\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Content-Type\": \"application/json\",\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n },\n body: ctsKeyBody,\n }),\n fetch(`${etsBaseUrl}/api/v2/kdc/keys/${userHuid}`, {\n method: \"POST\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Content-Type\": \"application/json\",\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n },\n body: ctsKeyBody,\n }),\n ]);\n\n if (!ctsCtsRes.ok) {\n const errText = await ctsCtsRes.text().catch(() => \"\");\n console.log(` Warning: CTS encryption key registration failed (${ctsCtsRes.status}): ${errText.slice(0, 200)}`);\n } else {\n console.log(` CTS encryption key registered in CTS: ${ctsKeyId.slice(0, 8)}...`);\n }\n if (!etsCtsRes.ok) {\n const errText = await etsCtsRes.text().catch(() => \"\");\n console.log(` Warning: CTS encryption key registration in ETS failed (${etsCtsRes.status}): ${errText.slice(0, 200)}`);\n } else {\n console.log(` CTS encryption key registered in ETS: ${ctsKeyId.slice(0, 8)}...`);\n }\n }\n\n const apigwKeys: ApigwKeys = {\n signingKey: apigwSigningKey,\n encryptionKey: apigwEncryptionKey,\n serverPublicKey,\n serverPublicKeyId,\n ctsKey,\n };\n const previousKeysRaw = getApigwKeysRaw();\n saveApigwKeys(apigwKeys);\n\n console.log(\"Step 4/5: Activating device...\");\n\n const activationBody = JSON.stringify({\n app_version: config.app_version,\n locale: config.locale,\n device_meta: {\n pushes: false,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n permissions: { notifications: true },\n },\n device_hostname: null,\n });\n\n const activationUrl = `${etsBaseUrl}/api/v1/apigw/api/v1/authentication/activation`;\n const activationHeaders = await signApigwRequest({\n method: \"PUT\",\n url: activationUrl,\n baseUrl: etsBaseUrl,\n body: activationBody,\n ctsToken: currentToken,\n });\n\n const actRes = await fetch(activationUrl, {\n method: \"PUT\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n ...activationHeaders,\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\n \"Accept-Language\": \"ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7\",\n \"Cache-Control\": \"no-cache\",\n \"Pragma\": \"no-cache\",\n \"sec-ch-ua\": '\"Google Chrome\";v=\"149\", \"Chromium\";v=\"149\", \"Not)A;Brand\";v=\"24\"',\n \"sec-ch-ua-mobile\": \"?0\",\n \"sec-ch-ua-platform\": '\"macOS\"',\n },\n body: activationBody,\n });\n\n const actText = await actRes.text();\n\n if (!actRes.ok) {\n if (previousKeysRaw) {\n setApigwKeysRaw(previousKeysRaw);\n console.log(\" (Rolled back to previous apigw keys)\");\n } else {\n clearApigwKeys();\n }\n throw new Error(`Device activation failed (${actRes.status}): ${actText.slice(0, 500)}`);\n }\n\n console.log(` Activation response: ${actText.slice(0, 300)}`);\n\n let actData: ActivationResponse;\n try {\n actData = JSON.parse(actText) as ActivationResponse;\n } catch {\n console.log(\" (non-JSON activation response, continuing)\");\n actData = {};\n }\n\n const actResult = extractResult(actData);\n const newAccessToken = actResult.access_token;\n\n if (newAccessToken) {\n setAuthToken(newAccessToken);\n console.log(\" Device activated. Token refreshed.\");\n } else {\n console.log(\" Device activated (using existing token).\");\n }\n\n const effectiveToken = newAccessToken ?? currentToken;\n const udid = randomUUID();\n\n const pushBody = JSON.stringify({\n phone: null,\n token: null,\n platform: \"web_chrome\",\n user_huid: userHuid,\n locale: config.locale,\n udid,\n encryption_key: \"\",\n auth_key: \"\",\n platform_package_id: config.platform_package_id,\n });\n\n console.log(\"Step 5/5: Registering push token...\");\n\n const pushHeaders = await signApigwRequest({\n method: \"PUT\",\n url: `${etsBaseUrl}/api/v1/apigw/api/v1/push_service/protected/token`,\n baseUrl: etsBaseUrl,\n body: pushBody,\n ctsToken: effectiveToken,\n });\n\n const pushRes = await fetch(`${etsBaseUrl}/api/v1/apigw/api/v1/push_service/protected/token`, {\n method: \"PUT\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n ...pushHeaders,\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\n },\n body: pushBody,\n });\n\n const pushText = await pushRes.text();\n console.log(` Push token: ${pushRes.status} — ${pushText.slice(0, 200)}`);\n\n console.log(\"Login complete! Apigw endpoints are now available.\");\n}\n","import { generateSigningKeyPair, publicKeyToBase64, saveApigwKeys, loadApigwKeys, decryptRegistrationData, decryptRtsToken, extractRtsKeyIdFromToken, type ApigwKeys } from \"./keys.js\";\nimport { signQrRequest, signApigwRequest } from \"./apigw-signer.js\";\nimport { setAuthToken, setRtsAuthToken, setRefreshToken, setTokenExpiresAt, calcTokenExpiresAt, setEtsAuthToken } from \"../config/store.js\";\nimport { loadConfig, getBaseUrl, getEtsBaseUrl, getWebOrigin } from \"../config/loader.js\";\nimport type { Config } from \"../types/index.js\";\nimport { randomUUID, randomBytes } from \"node:crypto\";\nimport qrcode from \"qrcode-terminal\";\nimport nacl from \"tweetnacl\";\n\ninterface QrRequestResponse {\n status?: string;\n reason?: string;\n result?: {\n registration_id?: string;\n registration_data?: string;\n cts_registration_token?: string;\n rts_registration_token?: string;\n };\n registration_id?: string;\n registration_data?: string;\n cts_registration_token?: string;\n rts_registration_token?: string;\n}\n\ninterface RegisterConfirmResponse {\n status?: string;\n result?: {\n user_huid?: string;\n server_id?: string;\n expires_at?: string | null;\n auth_token?: string;\n };\n user_huid?: string;\n server_id?: string;\n auth_token?: string;\n}\n\ninterface AdIntegrationConfirmResponse {\n status?: string;\n result?: {\n active?: boolean;\n user_huid?: string;\n server_id?: string;\n access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n };\n access_token?: string;\n refresh_token?: string;\n}\n\ninterface KdcKeysResponse {\n status?: string;\n result?: Array<{\n id: string;\n body: string;\n kind: string;\n user_huid: string;\n }>;\n}\n\nfunction extractResult<T>(data: T & { result?: T }): T {\n return (data.result ?? data) as T;\n}\n\n/** Returns the account's current cts key_id in KDC, or null if none exists. */\nasync function fetchCurrentAccountCtsKey(baseUrl: string, accessToken: string, userHuid: string, webOrigin: string): Promise<string | null> {\n try {\n const res = await fetch(`${baseUrl}/api/v1/kdc/keys/?user_huids=${userHuid}`, {\n headers: { ...commonHeaders(webOrigin), Authorization: `Bearer ${accessToken}` },\n });\n if (!res.ok) return null;\n const data = await res.json() as { result?: Array<{ id: string; kind: string }> };\n return data.result?.find((k) => k.kind === \"cts\")?.id ?? null;\n } catch {\n return null;\n }\n}\n\nfunction commonHeaders(webOrigin: string): Record<string, string> {\n return {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Accept-Language\": \"ru-RU,ru;q=0.9\",\n \"Connection\": \"keep-alive\",\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n \"Sec-Fetch-Dest\": \"empty\",\n \"Sec-Fetch-Mode\": \"cors\",\n \"Sec-Fetch-Site\": \"same-site\",\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\n \"sec-ch-ua\": '\"Google Chrome\";v=\"149\", \"Chromium\";v=\"149\", \"Not)A;Brand\";v=\"24\"',\n \"sec-ch-ua-mobile\": \"?0\",\n \"sec-ch-ua-platform\": '\"macOS\"',\n };\n}\n\nexport async function qrLogin(cliOverrides: Partial<Config> = {}): Promise<void> {\n const config = loadConfig(cliOverrides);\n const etsBaseUrl = getEtsBaseUrl(config);\n const webOrigin = getWebOrigin(config);\n\n const qrSigningKey = generateSigningKeyPair();\n const registrationId = qrSigningKey.keyId;\n const registrationToken = Buffer.from(randomBytes(64)).toString(\"base64\");\n const signPubKey = publicKeyToBase64(qrSigningKey.publicKey);\n const udid = randomUUID();\n const encryptionKey = randomBytes(32);\n\n const qrBody = JSON.stringify({\n registration_id: registrationId,\n registration_token: registrationToken,\n sign_pub_key: signPubKey,\n udid,\n app_version: config.app_version,\n device: \"Chrome 149.0\",\n device_software: \"macOS 10.15.7\",\n device_hostname: null,\n device_meta: {\n pushes: false,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n permissions: { notifications: false },\n },\n locale: config.locale,\n manufacturer: \"Google\",\n platform: \"web\",\n platform_package_id: \"com.pyligrim.alphach\",\n });\n\n const qrPayload = JSON.stringify({\n registration_id: registrationId,\n registration_token: registrationToken,\n registration_key: Buffer.from(encryptionKey).toString(\"base64\"),\n version: 1,\n });\n\n console.log(\"Step 1/7: Scan this QR code with your eXpress app:\\n\");\n qrcode.generate(qrPayload, { small: true }, (qr: string) => {\n console.log(qr);\n });\n console.log(`\\n registration_id: ${registrationId}`);\n console.log(\" Waiting for scan (server long-polling)...\\n\");\n\n const etsUrl = `${etsBaseUrl}/api/v1/authentication/qr/mobile_to_web/request`;\n const qrHeaders = signQrRequest({\n method: \"POST\",\n url: etsUrl,\n body: qrBody,\n registrationId,\n privateKey: qrSigningKey.privateKey,\n });\n\n let qrRes: Response;\n try {\n qrRes = await fetch(etsUrl, {\n method: \"POST\",\n headers: { ...commonHeaders(webOrigin), ...qrHeaders },\n body: qrBody,\n });\n } catch (err) {\n throw new Error(`QR request network error: ${(err as Error).message}`);\n }\n\n const qrText = await qrRes.text();\n\n if (!qrRes.ok) {\n console.log(` Response (${qrRes.status}): ${qrText.slice(0, 500)}`);\n throw new Error(`QR request failed (${qrRes.status}): ${qrText.slice(0, 500)}`);\n }\n\n let qrData: QrRequestResponse;\n try {\n qrData = JSON.parse(qrText) as QrRequestResponse;\n } catch {\n throw new Error(`Invalid QR response: ${qrText.slice(0, 500)}`);\n }\n\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] QR full response: ${qrText.slice(0, 1000)}`);\n }\n\n const qrResult = extractResult(qrData);\n const ctsRegistrationToken = qrResult.cts_registration_token ?? \"\";\n const rtsRegistrationToken = qrResult.rts_registration_token ?? \"\";\n const registrationData = qrResult.registration_data ?? \"\";\n\n console.log(\" QR scanned! Got tokens from server.\");\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] registration_data length: ${registrationData.length}`);\n console.log(` [DEBUG] registration_data raw: ${registrationData.slice(0, 100)}...`);\n console.log(` [DEBUG] encryptionKey (registration_key) hex: ${Buffer.from(encryptionKey).toString(\"hex\")}`);\n }\n\n if (!ctsRegistrationToken && !rtsRegistrationToken) {\n throw new Error(`No tokens in QR response: ${qrText.slice(0, 500)}`);\n }\n\n let rtsPrivateKey: Uint8Array | null = null;\n let rtsPublicKeyId = \"\";\n // CTS (E2E) key transferred from the phone via the QR handshake — this is the\n // shared account key, so QR login alone yields a working E2E key (no import).\n let qrCtsPrivateKey: Uint8Array | null = null;\n let qrCtsKeyId = \"\";\n\n if (registrationData) {\n try {\n const raw = Uint8Array.from(Buffer.from(registrationData, \"base64\"));\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] registration_data decoded length: ${raw.length}`);\n console.log(` [DEBUG] first 40 bytes hex: ${Buffer.from(raw.slice(0, 40)).toString(\"hex\")}`);\n console.log(` [DEBUG] encryptionKey hex: ${Buffer.from(encryptionKey).toString(\"hex\")}`);\n console.log(` [DEBUG] encryptionKey length: ${encryptionKey.length}`);\n }\n const decrypted = decryptRegistrationData(registrationData, encryptionKey);\n if (process.env.EXPRESS_DEBUG) {\n console.log(\" Decrypted registration_data:\", JSON.stringify(decrypted).slice(0, 500));\n }\n\n if (decrypted && typeof decrypted === \"object\") {\n const data = decrypted as Record<string, unknown>;\n if (typeof data.rts_priv_key_body === \"string\") {\n rtsPrivateKey = new Uint8Array(Buffer.from(data.rts_priv_key_body as string, \"base64\"));\n }\n if (typeof data.rts_pub_key_id === \"string\") {\n rtsPublicKeyId = data.rts_pub_key_id as string;\n }\n // CTS/E2E key from the phone — key_id matches the account's current cts key\n if (typeof data.cts_priv_key_body === \"string\" && typeof data.cts_pub_key_id === \"string\") {\n qrCtsPrivateKey = new Uint8Array(Buffer.from(data.cts_priv_key_body as string, \"base64\"));\n qrCtsKeyId = data.cts_pub_key_id as string;\n }\n }\n } catch (err) {\n console.log(` Warning: could not decrypt registration_data: ${(err as Error).message}`);\n }\n }\n\n console.log(\"\\nStep 2/7: Confirming with ETS...\");\n\n const confirmUrl = `${etsBaseUrl}/api/v1/authentication/register_confirm/qr`;\n const confirmBody = JSON.stringify({\n registration_id: registrationId,\n temp_token: rtsRegistrationToken,\n });\n\n const confirmHeaders = signQrRequest({\n method: \"POST\",\n url: confirmUrl,\n body: confirmBody,\n registrationId,\n privateKey: qrSigningKey.privateKey,\n });\n\n const confirmRes = await fetch(confirmUrl, {\n method: \"POST\",\n headers: { ...commonHeaders(webOrigin), ...confirmHeaders },\n body: confirmBody,\n });\n\n const confirmText = await confirmRes.text();\n\n if (!confirmRes.ok) {\n throw new Error(`ETS register_confirm failed (${confirmRes.status}): ${confirmText.slice(0, 500)}`);\n }\n\n const confirmData = extractResult(JSON.parse(confirmText) as RegisterConfirmResponse);\n const userHuid = confirmData.user_huid ?? \"\";\n const etsAuthToken = confirmData.auth_token ?? \"\";\n\n console.log(` ETS confirmed. User: ${userHuid || \"unknown\"}`);\n if (etsAuthToken) {\n setEtsAuthToken(etsAuthToken);\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] ETS auth_token saved (${etsAuthToken.length} chars)`);\n }\n }\n\n if (!ctsRegistrationToken) {\n throw new Error(\"No cts_registration_token — cannot confirm with CTS\");\n }\n\n console.log(\"\\nStep 3/7: Confirming with CTS (AD integration)...\");\n\n const ctsUrl = `${getBaseUrl(config)}/api/v1/ad_integration/register_confirm/qr`;\n const adConfirmBody = JSON.stringify({\n rts_registration_id: registrationId,\n temp_token: ctsRegistrationToken,\n ets: true,\n });\n\n const adConfirmHeaders = signQrRequest({\n method: \"POST\",\n url: ctsUrl,\n body: adConfirmBody,\n registrationId,\n privateKey: qrSigningKey.privateKey,\n });\n\n const adRes = await fetch(ctsUrl, {\n method: \"POST\",\n headers: { ...commonHeaders(webOrigin), ...adConfirmHeaders },\n body: adConfirmBody,\n });\n\n const adText = await adRes.text();\n\n if (!adRes.ok) {\n throw new Error(`AD integration confirm failed (${adRes.status}): ${adText.slice(0, 500)}`);\n }\n\n const adData = extractResult(JSON.parse(adText) as AdIntegrationConfirmResponse);\n const accessToken = adData.access_token;\n const refreshToken = adData.refresh_token;\n const expiresIn = adData.expires_in;\n const serverId = adData.server_id ?? userHuid;\n const encryptedRtsToken = (adData as Record<string, unknown>).encrypted_rts_token as string | undefined;\n\n if (process.env.EXPRESS_DEBUG) {\n const adDataRaw = JSON.parse(adText);\n console.log(` [DEBUG] AD confirm full result keys: ${JSON.stringify(Object.keys(adDataRaw.result || adDataRaw))}`);\n if (encryptedRtsToken) {\n console.log(` [DEBUG] encrypted_rts_token found: ${encryptedRtsToken.slice(0, 60)}...`);\n } else {\n console.log(` [DEBUG] encrypted_rts_token NOT found in response`);\n }\n }\n\n if (!accessToken) {\n throw new Error(`No access_token in AD confirm response: ${adText.slice(0, 500)}`);\n }\n\n setAuthToken(accessToken);\n if (refreshToken) {\n setRefreshToken(refreshToken);\n }\n if (typeof expiresIn === \"number\") {\n setTokenExpiresAt(calcTokenExpiresAt(expiresIn));\n console.log(` Token expires in ${expiresIn}s (refresh after ${(expiresIn / 2 / 60).toFixed(0)} min)`);\n }\n\n console.log(` CTS confirmed. Access token: ${accessToken.slice(0, 40)}...`);\n\n console.log(\"\\nStep 4/7: Registering device token...\");\n\n const tokenUrl = `${getBaseUrl(config)}/api/v1/ad_integration/token`;\n const tokenBody = JSON.stringify({\n app_version: config.app_version,\n device: \"Chrome 149.0\",\n device_software: \"macOS 10.15.7\",\n manufacturer: \"Google\",\n platform: \"web\",\n locale: config.locale,\n platform_package_id: \"com.pyligrim.alphach\",\n device_meta: {\n pushes: false,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n permissions: { notifications: false },\n },\n device_hostname: null,\n });\n\n const tokenRes = await fetch(tokenUrl, {\n method: \"PUT\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: tokenBody,\n });\n\n if (!tokenRes.ok) {\n const tokenErrText = await tokenRes.text().catch(() => \"\");\n console.log(` Warning: device token registration failed (${tokenRes.status}): ${tokenErrText.slice(0, 200)}`);\n } else {\n console.log(\" Device token registered.\");\n }\n\n console.log(\"\\nStep 5/7: Registering signing key + fetching server key...\");\n\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] serverId: ${serverId}`);\n console.log(` [DEBUG] userHuid: ${userHuid}`);\n }\n\n const apigwSigningKey = generateSigningKeyPair();\n const apigwKeyPublicBase64 = publicKeyToBase64(apigwSigningKey.publicKey);\n\n const kdcSignUrl = `${getBaseUrl(config)}/api/v2/kdc/keys/${userHuid}`;\n const kdcSignBody = JSON.stringify({\n key: apigwKeyPublicBase64,\n kind: \"ed25519\",\n algo: \"ed25519\",\n id: apigwSigningKey.keyId,\n });\n\n const [kdcSignRes, etsKdcSignRes, etsKdcStartRes] = await Promise.all([\n fetch(kdcSignUrl, {\n method: \"POST\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: kdcSignBody,\n }),\n fetch(`${etsBaseUrl}/api/v2/kdc/keys/${userHuid}`, {\n method: \"POST\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${etsAuthToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: kdcSignBody,\n }),\n fetch(`${etsBaseUrl}/api/v1/kdc/start`, {\n headers: {\n ...commonHeaders(webOrigin),\n },\n }),\n ]);\n\n if (!kdcSignRes.ok) {\n const kdcErrText = await kdcSignRes.text().catch(() => \"\");\n console.log(` Warning: CTS KDC signing key registration failed (${kdcSignRes.status}): ${kdcErrText.slice(0, 200)}`);\n } else {\n const kdcSignData = await kdcSignRes.json().catch(() => null);\n console.log(` Signing key registered in CTS: ${apigwSigningKey.keyId}`, kdcSignData ? JSON.stringify(kdcSignData).slice(0, 200) : \"\");\n }\n\n if (!etsKdcSignRes.ok) {\n const etsErrText = await etsKdcSignRes.text().catch(() => \"\");\n console.log(` Warning: ETS KDC signing key registration failed (${etsKdcSignRes.status}): ${etsErrText.slice(0, 200)}`);\n } else {\n const etsSignData = await etsKdcSignRes.json().catch(() => null);\n console.log(` Signing key registered in ETS: ${apigwSigningKey.keyId}`, etsSignData ? JSON.stringify(etsSignData).slice(0, 200) : \"\");\n }\n\n let serverPublicKey = new Uint8Array(0);\n let serverPublicKeyId = \"\";\n\n if (etsKdcStartRes.ok) {\n const kdcStartText = await etsKdcStartRes.text();\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] ETS KDC start response: ${kdcStartText.slice(0, 500)}`);\n }\n try {\n const kdcStartData = JSON.parse(kdcStartText) as { result?: string; status?: string };\n const keyBody = kdcStartData.result ?? kdcStartText;\n serverPublicKey = new Uint8Array(Buffer.from(keyBody, \"base64\"));\n serverPublicKeyId = \"kdc-start-ets\";\n const rawB64 = Buffer.from(serverPublicKey).toString(\"base64\");\n console.log(` ETS server public key from /kdc/start: ${rawB64} (curve25519, used directly)`);\n } catch {\n try { serverPublicKey = new Uint8Array(Buffer.from(kdcStartText, \"base64\")); } catch {}\n }\n }\n\n if (!serverPublicKey.length) {\n if (process.env.EXPRESS_DEBUG && !etsKdcStartRes.ok) {\n console.log(` [DEBUG] ETS KDC start status: ${etsKdcStartRes.status}`);\n try { console.log(` [DEBUG] ETS KDC start body: ${(await etsKdcStartRes.text()).slice(0, 500)}`); } catch {}\n }\n throw new Error(\"Could not fetch server public key from ETS /kdc/start\");\n }\n\n if (rtsPrivateKey) {\n const rtsPubKeyB64 = Buffer.from(nacl.box.keyPair.fromSecretKey(rtsPrivateKey).publicKey).toString(\"base64\");\n const rtsKeyBody = JSON.stringify({ key: rtsPubKeyB64, kind: \"rts\", algo: \"xsalsa20\", id: rtsPublicKeyId });\n const [ctsRtsRes, etsRtsRes] = await Promise.all([\n fetch(kdcSignUrl, {\n method: \"POST\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: rtsKeyBody,\n }),\n fetch(`${etsBaseUrl}/api/v2/kdc/keys/${userHuid}`, {\n method: \"POST\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${etsAuthToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: rtsKeyBody,\n }),\n ]);\n if (!ctsRtsRes.ok) {\n const errText = await ctsRtsRes.text().catch(() => \"\");\n console.log(` Warning: CTS RTS key registration failed (${ctsRtsRes.status}): ${errText.slice(0, 200)}`);\n } else {\n console.log(` RTS key registered in CTS: ${rtsPublicKeyId}`);\n }\n if (!etsRtsRes.ok) {\n const errText = await etsRtsRes.text().catch(() => \"\");\n console.log(` Warning: ETS RTS key registration failed (${etsRtsRes.status}): ${errText.slice(0, 200)}`);\n } else {\n console.log(` RTS key registered in ETS: ${rtsPublicKeyId}`);\n }\n }\n\n if (!rtsPrivateKey) {\n const fallbackKeyPair = nacl.box.keyPair();\n rtsPrivateKey = fallbackKeyPair.secretKey;\n rtsPublicKeyId = crypto.randomUUID();\n\n const encPubB64 = Buffer.from(fallbackKeyPair.publicKey).toString(\"base64\");\n const rtsFallbackBody = JSON.stringify({ key: encPubB64, kind: \"rts\", algo: \"xsalsa20\", id: rtsPublicKeyId });\n const [ctsEncRes, etsEncRes] = await Promise.all([\n fetch(kdcSignUrl, {\n method: \"POST\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: rtsFallbackBody,\n }),\n fetch(`${etsBaseUrl}/api/v2/kdc/keys/${userHuid}`, {\n method: \"POST\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${etsAuthToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: rtsFallbackBody,\n }),\n ]);\n\n if (!ctsEncRes.ok) {\n const errText = await ctsEncRes.text().catch(() => \"\");\n console.log(` Warning: CTS fallback RTS key registration failed (${ctsEncRes.status}): ${errText.slice(0, 200)}`);\n } else {\n console.log(` Fallback encryption key registered in CTS: ${rtsPublicKeyId}`);\n }\n if (!etsEncRes.ok) {\n const errText = await etsEncRes.text().catch(() => \"\");\n console.log(` Warning: ETS fallback RTS key registration failed (${etsEncRes.status}): ${errText.slice(0, 200)}`);\n } else {\n console.log(` Fallback encryption key registered in ETS: ${rtsPublicKeyId}`);\n }\n }\n\n const rtsPublicKey = nacl.box.keyPair.fromSecretKey(rtsPrivateKey).publicKey;\n\n let rtsAuthToken = \"\";\n if (encryptedRtsToken && rtsPrivateKey && serverPublicKey.length) {\n try {\n rtsAuthToken = decryptRtsToken(encryptedRtsToken, serverPublicKey, rtsPrivateKey);\n setRtsAuthToken(rtsAuthToken);\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] Decrypted RTS auth token: ${rtsAuthToken.slice(0, 60)}...`);\n }\n console.log(` RTS auth token decrypted from encrypted_rts_token`);\n } catch (err) {\n console.log(` Warning: could not decrypt encrypted_rts_token: ${(err as Error).message}`);\n }\n }\n\n const rtsIdFromToken = extractRtsKeyIdFromToken(accessToken);\n if (rtsIdFromToken && process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] rts_id from CTS token: ${rtsIdFromToken}`);\n }\n\n // CTS encryption key for E2E messages. eXpress keeps ONE active cts key per\n // user (shared across devices via the QR handshake / key backup). Priority:\n // 1. the cts key the phone sent through registration_data (the shared account\n // key) — this makes QR login self-sufficient, no import needed;\n // 2. the stored ctsKey (already-shared key from a prior import/login);\n // 3. mint a new one — only when the account genuinely has no cts key yet.\n const existingCts = loadApigwKeys()?.ctsKey;\n let ctsKey: ApigwKeys[\"ctsKey\"];\n\n if (qrCtsPrivateKey && qrCtsKeyId) {\n ctsKey = {\n keyId: qrCtsKeyId,\n privateKey: qrCtsPrivateKey,\n publicKey: nacl.box.keyPair.fromSecretKey(qrCtsPrivateKey).publicKey,\n };\n console.log(` Using CTS key from QR handshake: ${qrCtsKeyId.slice(0, 8)}... (shared account key)`);\n } else if (existingCts) {\n ctsKey = existingCts;\n console.log(` Reusing existing CTS key: ${existingCts.keyId.slice(0, 8)}... (not re-registering)`);\n } else {\n // Guard: if the account already has a current cts key in KDC, DO NOT mint a\n // new one — it would supersede the shared key and, since the CLI can't upload\n // the private-key backup, permanently break your phone/desktop/web.\n const currentCts = await fetchCurrentAccountCtsKey(getBaseUrl(config), accessToken, userHuid, webOrigin);\n if (currentCts) {\n throw new Error(\n `Account already has a shared CTS key (${currentCts}) that this CLI doesn't hold.\\n` +\n `Minting a new one would break your other devices (they can't fetch its private key).\\n` +\n `Instead, extract the key from a logged-in web client (IndexedDB authState → encryptionKeys → user.privateKeys.cts) and run:\\n` +\n ` express auth import-cts <private_key_b64> ${currentCts}\\n` +\n `Then re-run login, or just use 'auth refresh' for tokens.`,\n );\n }\n console.log(\" No existing account CTS key found — minting a new one (first device).\");\n const ctsKeyPair = nacl.box.keyPair();\n const ctsKeyId = crypto.randomUUID();\n const ctsKeyPubB64 = Buffer.from(ctsKeyPair.publicKey).toString(\"base64\");\n const ctsKeyBody = JSON.stringify({ key: ctsKeyPubB64, kind: \"cts\", algo: \"xsalsa20\", id: ctsKeyId });\n\n const ctsCtsKeyRes = await fetch(kdcSignUrl, {\n method: \"POST\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: ctsKeyBody,\n });\n\n if (!ctsCtsKeyRes.ok) {\n const errText = await ctsCtsKeyRes.text().catch(() => \"\");\n console.log(` Warning: CTS encryption key registration failed (${ctsCtsKeyRes.status}): ${errText.slice(0, 200)}`);\n } else {\n console.log(` CTS encryption key registered: ${ctsKeyId.slice(0, 8)}...`);\n }\n\n ctsKey = {\n keyId: ctsKeyId,\n privateKey: ctsKeyPair.secretKey,\n publicKey: ctsKeyPair.publicKey,\n };\n }\n\n const apigwKeys: ApigwKeys = {\n signingKey: apigwSigningKey,\n encryptionKey: {\n keyId: rtsPublicKeyId,\n privateKey: rtsPrivateKey,\n publicKey: rtsPublicKey,\n },\n ctsKey,\n serverPublicKey,\n serverPublicKeyId,\n };\n saveApigwKeys(apigwKeys);\n\n console.log(\"\\nStep 6/7: Activating apigw via ETS...\");\n\n const activationUrl = `${etsBaseUrl}/api/v1/apigw/api/v1/authentication/activation`;\n const activationBody = JSON.stringify({\n app_version: config.app_version,\n locale: config.locale,\n device_meta: {\n pushes: false,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n permissions: { notifications: false },\n },\n device_hostname: null,\n });\n\n const activationHeaders = await signApigwRequest({\n method: \"PUT\",\n url: activationUrl,\n baseUrl: etsBaseUrl,\n body: activationBody,\n ctsToken: accessToken,\n rtsToken: rtsAuthToken || undefined,\n etsAuthToken: etsAuthToken || undefined,\n });\n\n const activationRes = await fetch(activationUrl, {\n method: \"PUT\",\n headers: { ...commonHeaders(webOrigin), ...activationHeaders },\n body: activationBody,\n });\n\n if (!activationRes.ok) {\n const actErrText = await activationRes.text().catch(() => \"\");\n console.log(` Warning: apigw activation failed (${activationRes.status}): ${actErrText.slice(0, 200)}`);\n } else {\n console.log(\" Apigw activated.\");\n }\n\n console.log(`\\n User HUID: ${userHuid || \"unknown\"}`);\n console.log(` Signing key: ${apigwSigningKey.keyId.slice(0, 8)}...`);\n console.log(` Encryption key: ${rtsPublicKeyId.slice(0, 8)}...`);\n console.log(` Server key: ${serverPublicKeyId.slice(0, 8)}...`);\n\n console.log(\"\\nQR login complete! You are now authenticated.\");\n}\n","import { getAuthToken, getRefreshToken, setAuthToken, setRefreshToken, setTokenExpiresAt, calcTokenExpiresAt } from \"../config/store.js\";\nimport { getBaseUrl, getWebOrigin } from \"../config/loader.js\";\nimport { loadConfig } from \"../config/index.js\";\nimport type { Config } from \"../types/index.js\";\n\ninterface RefreshResponse {\n status?: string;\n result?: {\n cts_access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n };\n cts_access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n}\n\nlet refreshPromise: Promise<boolean> | null = null;\n\nexport async function refreshToken(cliOverrides: Partial<Config> = {}): Promise<boolean> {\n if (refreshPromise) return refreshPromise;\n\n refreshPromise = doRefresh(cliOverrides);\n try {\n return await refreshPromise;\n } finally {\n refreshPromise = null;\n }\n}\n\nasync function doRefresh(cliOverrides: Partial<Config> = {}): Promise<boolean> {\n const currentToken = getAuthToken();\n const rt = getRefreshToken();\n\n if (!currentToken || !rt) return false;\n\n const config = loadConfig(cliOverrides);\n const baseUrl = getBaseUrl(config);\n const webOrigin = getWebOrigin(config);\n\n try {\n const res = await fetch(`${baseUrl}/api/v1/ad_integration/token/refresh`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/plain, */*\",\n \"Accept-Language\": \"ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n Origin: webOrigin,\n Pragma: \"no-cache\",\n Referer: `${webOrigin}/`,\n \"Sec-Fetch-Dest\": \"empty\",\n \"Sec-Fetch-Mode\": \"cors\",\n \"Sec-Fetch-Site\": \"same-site\",\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\n Authorization: `Bearer ${currentToken}`,\n },\n body: JSON.stringify({ refresh_token: rt }),\n });\n\n if (!res.ok) {\n return false;\n }\n\n const text = await res.text();\n const data = JSON.parse(text) as RefreshResponse;\n const result = data.result ?? data;\n\n const newAccessToken = result.cts_access_token;\n const newRefreshToken = result.refresh_token;\n const expiresIn = result.expires_in;\n\n if (!newAccessToken) return false;\n\n setAuthToken(newAccessToken);\n if (newRefreshToken) setRefreshToken(newRefreshToken);\n if (typeof expiresIn === \"number\") {\n setTokenExpiresAt(calcTokenExpiresAt(expiresIn));\n }\n\n return true;\n } catch {\n return false;\n }\n}\n","import { Command } from \"commander\";\nimport { ApiClient } from \"../api/client.js\";\nimport { loadConfig } from \"../config/index.js\";\nimport { formatOutput, type OutputFormat } from \"./output.js\";\n\nexport function createApiCommand(): Command {\n const cmd = new Command(\"api\");\n\n cmd\n .description(\"Make arbitrary API request\")\n .argument(\"<path>\", \"API path (e.g. /api/v1/phonebook/profiles/self)\")\n .option(\"-X, --method <method>\", \"HTTP method\", \"GET\")\n .option(\"-d, --data <data>\", \"Request body (JSON)\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (path: string, opts: { method: string; data?: string; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n\n let body: unknown;\n if (opts.data) {\n try {\n body = JSON.parse(opts.data);\n } catch {\n throw new Error(\"Invalid JSON in --data\");\n }\n }\n\n const method = opts.method.toUpperCase();\n const res = await client.rawRequest(path, {\n method,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n const text = await res.text();\n console.log(`Response: status=${res.status}, content-type=${res.headers.get(\"content-type\")}, body=${text.length} chars`);\n if (!text) {\n return;\n }\n let data: unknown;\n try {\n data = JSON.parse(text);\n } catch {\n console.log(`Response: status=${res.status}, non-JSON body (${text.length} chars): ${text.slice(0, 500)}`);\n return;\n }\n\n if (!res.ok) {\n console.error(`API error ${res.status}:`, JSON.stringify(data, null, 2));\n process.exit(1);\n }\n\n console.log(formatOutput(data, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { loadConfig, getBaseUrl, getEtsBaseUrl, getWebOrigin } from \"../config/index.js\";\nimport { getAuthToken, getRtsAuthToken, setAuthToken, isTokenExpiringSoon, getEtsAuthToken } from \"../config/store.js\";\nimport { signApigwRequest } from \"../auth/apigw-signer.js\";\nimport { loadApigwKeys } from \"../auth/keys.js\";\nimport { refreshToken } from \"../auth/token-refresh.js\";\nimport type { Config, ApiResponse } from \"../types/index.js\";\n\nexport class ApiClient {\n private config: Config;\n private baseUrl: string;\n private etsBaseUrl: string;\n private webOrigin: string;\n\n constructor(cliOverrides: Partial<Config> = {}) {\n this.config = loadConfig(cliOverrides);\n this.baseUrl = getBaseUrl(this.config);\n this.etsBaseUrl = getEtsBaseUrl(this.config);\n this.webOrigin = getWebOrigin(this.config);\n }\n\n private getToken(): string {\n const token = this.config.token ?? getAuthToken();\n if (!token) {\n throw new Error(\"Not authenticated. Use `express auth import <token>` to login.\");\n }\n return token;\n }\n\n private isApigwPath(path: string): boolean {\n return path.includes(\"/apigw/\");\n }\n\n private resolveUrl(path: string): string {\n if (path.startsWith(\"http\")) return path;\n if (this.isApigwPath(path)) {\n return `${this.etsBaseUrl}${path}`;\n }\n return `${this.baseUrl}${path}`;\n }\n\n private async request<T>(\n path: string,\n options: RequestInit = {},\n retry = true,\n ): Promise<T> {\n if (retry && isTokenExpiringSoon()) {\n await refreshToken(this.config);\n }\n\n let token = this.getToken();\n const url = this.resolveUrl(path);\n\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n ...(this.isApigwPath(path)\n ? await this.buildApigwHeaders(options.method ?? \"GET\", path, token, options.body as string | undefined)\n : { Authorization: `Bearer ${token}` }),\n Origin: this.webOrigin,\n ...((options.headers as Record<string, string>) ?? {}),\n };\n\n if (options.body && !headers[\"Content-Type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const res = await fetch(url, {\n ...options,\n headers,\n });\n\n if (res.status === 401 && retry) {\n const text = await res.text().catch(() => \"\");\n const isExpired = text.includes(\"token_expired\");\n if (isExpired) {\n const refreshed = await refreshToken(this.config);\n if (refreshed) {\n const newToken = this.getToken();\n const newHeaders: Record<string, string> = {\n Accept: \"application/json\",\n ...(this.isApigwPath(path)\n ? await this.buildApigwHeaders(options.method ?? \"GET\", path, newToken, options.body as string | undefined)\n : { Authorization: `Bearer ${newToken}` }),\n Origin: this.webOrigin,\n ...((options.headers as Record<string, string>) ?? {}),\n };\n if (options.body && !newHeaders[\"Content-Type\"]) {\n newHeaders[\"Content-Type\"] = \"application/json\";\n }\n const retryRes = await fetch(url, { ...options, headers: newHeaders });\n return this.handleResponse<T>(retryRes);\n }\n }\n throw new Error(\"Token expired and refresh failed. Please re-authenticate with `express auth qr`.\");\n }\n\n return this.handleResponse<T>(res);\n }\n\n private async handleResponse<T>(res: Response): Promise<T> {\n if (res.status === 204) {\n return undefined as T;\n }\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`API error ${res.status}: ${res.statusText}${text ? ` — ${text.slice(0, 200)}` : \"\"}`);\n }\n\n const text = await res.text();\n if (!text) {\n return undefined as T;\n }\n\n const data = JSON.parse(text);\n if (data && typeof data === \"object\" && \"result\" in data) {\n return (data as ApiResponse<T>).result as T;\n }\n return data as T;\n }\n\n private async buildApigwHeaders(\n method: string,\n path: string,\n ctsToken: string,\n body?: string,\n ): Promise<Record<string, string>> {\n const rtsToken = getRtsAuthToken() ?? undefined;\n const etsAuthToken = getEtsAuthToken() ?? undefined;\n const etsBaseUrl = this.etsBaseUrl;\n const signed = await signApigwRequest({\n method,\n url: path.startsWith(\"http\") ? path : `${etsBaseUrl}${path}`,\n baseUrl: etsBaseUrl,\n body,\n ctsToken,\n rtsToken,\n etsAuthToken,\n });\n return {\n Authorization: signed.Authorization,\n \"Express-Proxy-Authorization\": signed[\"Express-Proxy-Authorization\"],\n \"Express-Request-Nonce\": signed[\"Express-Request-Nonce\"],\n ...(signed.Digest && { Digest: signed.Digest }),\n Signature: signed.Signature,\n };\n }\n\n async get<T>(path: string): Promise<T> {\n return this.request<T>(path, { method: \"GET\" });\n }\n\n async post<T>(path: string, body?: unknown): Promise<T> {\n const jsonBody = body ? JSON.stringify(body) : undefined;\n return this.request<T>(path, {\n method: \"POST\",\n body: jsonBody,\n });\n }\n\n async put<T>(path: string, body?: unknown): Promise<T> {\n const jsonBody = body ? JSON.stringify(body) : undefined;\n return this.request<T>(path, {\n method: \"PUT\",\n body: jsonBody,\n });\n }\n\n async delete<T>(path: string): Promise<T> {\n return this.request<T>(path, { method: \"DELETE\" });\n }\n\n async rawRequest(path: string, options: RequestInit = {}): Promise<Response> {\n const token = this.getToken();\n const url = this.resolveUrl(path);\n\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n ...(this.isApigwPath(path)\n ? await this.buildApigwHeaders(options.method ?? \"GET\", path, token, options.body as string | undefined)\n : { Authorization: `Bearer ${token}` }),\n Origin: this.webOrigin,\n ...((options.headers as Record<string, string>) ?? {}),\n };\n\n if (options.body && !headers[\"Content-Type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n return fetch(url, { ...options, headers });\n }\n\n async downloadFile(url: string): Promise<Response> {\n const token = this.getToken();\n const fullUrl = url.startsWith(\"http\") ? url : `${this.baseUrl}${url}`;\n\n return fetch(fullUrl, {\n headers: {\n Authorization: `Bearer ${token}`,\n Referer: `${this.webOrigin}/`,\n Accept: \"*/*\",\n },\n });\n }\n\n isApigwReady(): boolean {\n return loadApigwKeys() !== null;\n }\n}\n","import chalk from \"chalk\";\nimport Table from \"cli-table3\";\nimport type { ExpressProfile, ExpressUserStatus } from \"../types/index.js\";\n\nexport type OutputFormat = \"table\" | \"json\";\n\nexport function formatOutput(data: unknown, format: OutputFormat): string {\n if (format === \"json\") {\n return JSON.stringify(data, null, 2);\n }\n if (typeof data === \"string\") return data;\n if (typeof data === \"number\" || typeof data === \"boolean\") return String(data);\n return JSON.stringify(data, null, 2);\n}\n\nexport function formatProfileTable(profiles: ExpressProfile[]): string {\n const table = new Table({\n head: [\"Name\", \"Email\", \"AD Login\", \"Department\", \"Position\", \"HUID\"],\n style: { head: [\"cyan\"] },\n });\n\n for (const p of profiles) {\n table.push([\n p.name ?? \"-\",\n p.email ?? \"-\",\n p.ad_login ?? \"-\",\n p.department ?? \"-\",\n p.company_position ?? \"-\",\n p.user_huid ? p.user_huid.slice(0, 8) + \"...\" : \"-\",\n ]);\n }\n\n return table.toString();\n}\n\nexport function formatStatusTable(statuses: ExpressUserStatus[]): string {\n const table = new Table({\n head: [\"HUID\", \"Status\", \"Last Seen\"],\n style: { head: [\"cyan\"] },\n });\n\n const statusColors: Record<string, typeof chalk.green> = {\n online: chalk.green,\n offline: chalk.gray,\n away: chalk.yellow,\n dnd: chalk.red,\n invisible: chalk.gray,\n };\n\n for (const s of statuses) {\n const color = statusColors[s.status] ?? chalk.white;\n table.push([\n s.huid ? s.huid.slice(0, 8) + \"...\" : \"-\",\n color(s.status),\n s.last_seen ?? \"-\",\n ]);\n }\n\n return table.toString();\n}\n","import { Command } from \"commander\";\nimport { getStoredConfig, setStoredConfig, clearAll } from \"../config/index.js\";\nimport { formatOutput, type OutputFormat } from \"./output.js\";\n\nexport function createConfigCommand(): Command {\n const cmd = new Command(\"config\");\n\n cmd.description(\"Configuration management\");\n\n cmd\n .command(\"get [key]\")\n .description(\"Get config value(s)\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action((key?: string, opts?: { output: OutputFormat }) => {\n const config = getStoredConfig();\n const data = key ? { [key]: (config as Record<string, unknown>)[key] } : config;\n console.log(formatOutput(data, opts?.output ?? \"json\"));\n });\n\n cmd\n .command(\"set <key> <value>\")\n .description(\"Set config value\")\n .action((key: string, value: string) => {\n const current = getStoredConfig();\n let parsed: unknown = value;\n try {\n parsed = JSON.parse(value);\n } catch {}\n setStoredConfig({ ...current, [key]: parsed });\n console.log(`Set ${key} = ${JSON.stringify(parsed)}`);\n });\n\n cmd\n .command(\"list\")\n .description(\"List all config values\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action((opts: { output: OutputFormat }) => {\n console.log(formatOutput(getStoredConfig(), opts.output));\n });\n\n cmd\n .command(\"reset\")\n .description(\"Reset all configuration and tokens\")\n .action(() => {\n clearAll();\n console.log(\"All configuration and tokens cleared.\");\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport { UserApi } from \"../api/user.js\";\nimport { ApiClient } from \"../api/client.js\";\nimport { formatStatusTable, formatOutput, type OutputFormat } from \"./output.js\";\n\nexport function createStatusCommand(): Command {\n const cmd = new Command(\"status\");\n\n cmd.description(\"Get user statuses\");\n\n cmd\n .command(\"self\")\n .description(\"Get own status\")\n .option(\"-s, --short\", \"Short format\", false)\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (opts: { short: boolean; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new UserApi(client);\n const profile = await api.getSelfProfile();\n const result = await api.getUserStatuses([profile.user_huid], opts.short);\n if (opts.output === \"json\") {\n console.log(formatOutput(result, \"json\"));\n } else {\n console.log(formatStatusTable(result.user_statuses));\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"get <huids...>\")\n .description(\"Get statuses for users by HUID\")\n .option(\"-s, --short\", \"Short format\", false)\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (huids: string[], opts: { short: boolean; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new UserApi(client);\n const result = await api.getUserStatuses(huids, opts.short);\n\n if (opts.output === \"json\") {\n console.log(formatOutput(result, \"json\"));\n } else {\n console.log(formatStatusTable(result.user_statuses));\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"history\")\n .description(\"Get status history\")\n .option(\"--since <iso-date>\", \"Since date (ISO 8601)\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (opts: { since?: string; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new UserApi(client);\n const history = await api.getUserStatusHistory(opts.since);\n console.log(formatOutput(history, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { ApiClient } from \"./client.js\";\nimport type { ExpressProfile, ExpressSelfProfileResponse, ExpressUserStatus } from \"../types/index.js\";\nimport { loadApigwKeys } from \"../auth/keys.js\";\n\nexport class UserApi {\n constructor(private client: ApiClient) {}\n\n async getSelfProfile(): Promise<ExpressProfile> {\n const data = await this.client.get<ExpressSelfProfileResponse>(\"/api/v1/phonebook/profiles/self\");\n return data.profile;\n }\n\n async getProfilesByHuid(huids: string[]): Promise<ExpressProfile[]> {\n const data = await this.client.post<unknown>(\"/api/v1/phonebook/cts_profiles/query\", { huids });\n if (!data) return [];\n const entries = Array.isArray(data) ? data : [];\n const profiles: ExpressProfile[] = [];\n for (const entry of entries) {\n const obj = entry as Record<string, unknown>;\n if (Array.isArray(obj.cts_profiles)) {\n profiles.push(...(obj.cts_profiles as ExpressProfile[]));\n }\n }\n return profiles;\n }\n\n async getUserStatuses(userHuids: string[], short = false): Promise<{ user_statuses: ExpressUserStatus[]; failed: string[] }> {\n const keys = loadApigwKeys();\n const keyId = (keys?.ctsKey ?? keys?.encryptionKey)?.keyId ?? \"\";\n return this.client.post(\"/api/v1/user_statuses/get\", {\n user_huids: userHuids,\n short,\n key_id: keyId,\n });\n }\n\n async getUserStatusHistory(since?: string): Promise<ExpressUserStatus[]> {\n return this.client.post<ExpressUserStatus[]>(\"/api/v1/user_statuses/history\", {\n since: since ?? null,\n });\n }\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { UserApi } from \"../api/user.js\";\nimport { ChatsApi } from \"../api/chats.js\";\nimport { PhonebookApi } from \"../api/phonebook.js\";\nimport { ApiClient } from \"../api/client.js\";\nimport { formatProfileTable, formatOutput, type OutputFormat } from \"./output.js\";\n\nexport function createContactsCommand(): Command {\n const cmd = new Command(\"contacts\");\n\n cmd.description(\"Contacts and phonebook\");\n\n cmd\n .command(\"self\")\n .description(\"Get own profile\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (opts: { host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new UserApi(client);\n const profile = await api.getSelfProfile();\n\n if (opts.output === \"json\") {\n console.log(formatOutput(profile, \"json\"));\n } else {\n console.log(formatProfileTable([profile]));\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"query <huids...>\")\n .description(\"Query profiles by HUIDs\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (huids: string[], opts: { host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new UserApi(client);\n const profiles = await api.getProfilesByHuid(huids);\n\n if (opts.output === \"json\") {\n console.log(formatOutput(profiles, \"json\"));\n } else {\n console.log(formatProfileTable(profiles));\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"search <query>\")\n .description(\"Search users by name/email/department (apigw or directory)\")\n .option(\"-l, --limit <n>\", \"Max results\", \"20\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (query: string, opts: { limit: string; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const limit = parseInt(opts.limit, 10);\n const phonebook = new PhonebookApi(client);\n let profiles = await phonebook.searchUsers(query, limit);\n\n // Fallback: search across all chat members (works even when apigw phonebook is empty)\n if (profiles.length === 0) {\n try {\n const userApi = new UserApi(client);\n const chatsApi = new ChatsApi(client);\n const [allChats, self] = await Promise.all([chatsApi.listChats(), userApi.getSelfProfile()]);\n const myHuid = self.user_huid;\n const allMemberHuids = [...new Set(\n allChats.flatMap((c) => c.member_huids ?? []).filter((h) => h !== myHuid),\n )];\n if (allMemberHuids.length > 0) {\n const allProfiles = await userApi.getProfilesByHuid(allMemberHuids);\n const lowerQuery = query.toLowerCase();\n profiles = allProfiles\n .filter((p) =>\n [p.name, p.email, p.ad_login, p.department, p.company_position]\n .filter(Boolean).join(\" \").toLowerCase().includes(lowerQuery),\n )\n .slice(0, limit);\n }\n } catch (err) {\n if (process.env.EXPRESS_DEBUG) {\n console.error(` [DEBUG] Chat member search failed: ${(err as Error).message}`);\n }\n }\n }\n\n if (profiles.length === 0) {\n console.log(chalk.yellow(\"No users found.\"));\n return;\n }\n\n if (opts.output === \"json\") {\n console.log(formatOutput(profiles, \"json\"));\n } else {\n console.log(formatProfileTable(profiles));\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"list\")\n .description(\"List all contacts (requires 'express auth login')\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (opts: { host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n\n if (!client.isApigwReady()) {\n console.error(chalk.yellow(\"Error: This command requires apigw auth. Run 'express auth login' first.\"));\n process.exit(1);\n }\n\n const api = new PhonebookApi(client);\n const contacts = await api.getContacts();\n if (!contacts || contacts.length === 0) {\n console.log(chalk.yellow(\"No contacts found. The apigw phonebook endpoint may not have synced contacts yet.\"));\n console.log(chalk.yellow(\"Use 'express contacts search <query>' to search via corporate directory.\"));\n return;\n }\n console.log(formatOutput(contacts, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"directory\")\n .description(\"Corporate directory entries\")\n .option(\"--since <iso-date>\", \"Since date (ISO 8601)\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (opts: { since?: string; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new PhonebookApi(client);\n const entries = await api.getCorporateDirectory(opts.since);\n console.log(formatOutput(entries, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import type { ExpressChat } from \"../types/index.js\";\nimport { randomUUID } from \"node:crypto\";\n\ninterface PhxMessage {\n topic: string;\n event: string;\n payload: Record<string, unknown>;\n ref: number;\n}\n\ninterface PhxReply {\n ref: number;\n event: string;\n topic: string;\n payload: {\n status: \"ok\" | \"error\";\n response: Record<string, unknown>;\n };\n}\n\nexport async function fetchChatListViaWebSocket(params: {\n host: string;\n ctsToken: string;\n encryptionKeyId: string;\n timeoutMs?: number;\n}): Promise<ExpressChat[]> {\n const { host, ctsToken, encryptionKeyId, timeoutMs = 15000 } = params;\n const instanceId = randomUUID();\n\n const wsUrl = `wss://${host}/socket/user/websocket?vsn=1.0.0&auto_join=true&key_id=${encryptionKeyId}&version=6&background=false&voex_unencrypted=true&voex_multistream=true&voex_audio_bridge=true&instance_id=${instanceId}`;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const done = (fn: () => void) => {\n if (!settled) { settled = true; fn(); }\n };\n\n const timer = setTimeout(() => {\n try { ws.close(); } catch {}\n done(() => reject(new Error(\"WebSocket timeout: no chat_list response\")));\n }, timeoutMs);\n\n const hostParts = host.split('.');\n const webOrigin = `https://${hostParts.length > 2 ? hostParts.slice(1).join('.') : host}`;\n\n const ws = new WebSocket(wsUrl, {\n headers: {\n Origin: webOrigin,\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\n },\n } as ConstructorParameters<typeof WebSocket>[1]);\n\n const authRef = 0;\n const chatListRef = 1;\n\n const send = (msg: PhxMessage) => {\n ws.send(JSON.stringify(msg));\n };\n\n ws.addEventListener(\"open\", () => {\n send({ topic: \"phoenix\", event: \"authenticate\", payload: { token: ctsToken }, ref: authRef });\n });\n\n ws.addEventListener(\"message\", (event) => {\n let msg: PhxReply;\n try {\n msg = JSON.parse(event.data as string) as PhxReply;\n } catch {\n return;\n }\n\n if (msg.ref === authRef && msg.topic === \"phoenix\" && msg.event === \"phx_reply\") {\n if (msg.payload.status !== \"ok\") {\n clearTimeout(timer);\n ws.close();\n done(() => reject(new Error(`WebSocket auth failed: ${JSON.stringify(msg.payload.response)}`)));\n return;\n }\n send({ topic: \"system\", event: \"chat_list\", payload: { since: null, request_version: 6 }, ref: chatListRef });\n return;\n }\n\n if (msg.ref === chatListRef && msg.topic === \"system\" && msg.event === \"phx_reply\") {\n if (msg.payload.status !== \"ok\") {\n clearTimeout(timer);\n ws.close();\n done(() => reject(new Error(`WebSocket chat_list failed: ${JSON.stringify(msg.payload.response)}`)));\n return;\n }\n const response = msg.payload.response as { chat_list?: ExpressChat[] };\n if (Array.isArray(response.chat_list)) {\n clearTimeout(timer);\n ws.close();\n done(() => resolve(response.chat_list!));\n }\n }\n });\n\n ws.addEventListener(\"error\", (err) => {\n clearTimeout(timer);\n done(() => reject(new Error(`WebSocket connection error: ${String(err)}`)));\n });\n\n ws.addEventListener(\"close\", (event) => {\n clearTimeout(timer);\n done(() => reject(new Error(`WebSocket closed before completion (code=${event.code})`)));\n });\n });\n}\n","import { ApiClient } from \"./client.js\";\nimport { fetchChatListViaWebSocket } from \"./websocket.js\";\nimport { getAuthToken } from \"../config/store.js\";\nimport { loadApigwKeys } from \"../auth/keys.js\";\nimport { loadConfig, getBaseUrl } from \"../config/index.js\";\nimport type { ExpressChat } from \"../types/index.js\";\n\ninterface DirectoryEntry {\n position: number;\n entry_type: \"user\" | \"bot\" | \"chat\";\n entry_id: string;\n is_info_updated: boolean;\n deleted: boolean;\n}\n\ninterface OpenChatsResponse {\n generated_at: string;\n open_chats: ExpressChat[];\n}\n\nexport class ChatsApi {\n constructor(private client: ApiClient) {}\n\n async listChats(): Promise<ExpressChat[]> {\n const config = loadConfig();\n const host = new URL(getBaseUrl(config)).hostname;\n const ctsToken = getAuthToken();\n const keys = loadApigwKeys();\n\n const ctsKeyId = (keys?.ctsKey ?? keys?.encryptionKey)?.keyId;\n if (ctsToken && ctsKeyId) {\n try {\n return await fetchChatListViaWebSocket({\n host,\n ctsToken,\n encryptionKeyId: ctsKeyId,\n });\n } catch (err) {\n if (process.env.EXPRESS_DEBUG) {\n console.error(` [DEBUG] WebSocket failed, falling back to directory: ${(err as Error).message}`);\n }\n }\n }\n\n return this.listChatsViaDirectory();\n }\n\n private async listChatsViaDirectory(): Promise<ExpressChat[]> {\n const data = await this.client.get<{ entries: DirectoryEntry[] }>(\"/api/v1/corporate_directory/entries\");\n const entries = data?.entries ?? [];\n const chatIds = entries\n .filter((e) => e.entry_type === \"chat\" && !e.deleted)\n .map((e) => e.entry_id);\n if (chatIds.length === 0) return [];\n const result = await this.client.post<OpenChatsResponse>(\"/api/v1/messaging/chats/open_chats_list\", {\n chat_ids: chatIds,\n });\n return result?.open_chats ?? [];\n }\n\n async getChatInfo(chatId: string): Promise<ExpressChat | null> {\n const data = await this.client.post<OpenChatsResponse>(\"/api/v1/messaging/chats/open_chats_list\", {\n chat_ids: [chatId],\n });\n return data?.open_chats?.[0] ?? null;\n }\n}\n","import { ApiClient } from \"./client.js\";\nimport type { ExpressProfile } from \"../types/index.js\";\n\ninterface DirectoryEntry {\n position: number;\n entry_type: \"user\" | \"bot\" | \"chat\";\n entry_id: string;\n is_info_updated: boolean;\n deleted: boolean;\n}\n\ninterface DirectoryResponse {\n entries: DirectoryEntry[];\n}\n\ninterface CtsProfileEntry {\n cts_profiles?: ExpressProfile[];\n}\n\ninterface CtsProfilesResponse {\n result?: CtsProfileEntry[];\n}\n\ninterface ApigwContact {\n huid?: string;\n name?: string;\n email?: string;\n ad_login?: string;\n department?: string;\n company_position?: string;\n phone?: string;\n ip_phone?: string;\n [key: string]: unknown;\n}\n\nexport class PhonebookApi {\n constructor(private client: ApiClient) {}\n\n async getContacts(): Promise<ApigwContact[]> {\n const data = await this.client.get<unknown>(\"/api/v1/apigw/api/v1/phonebook/contacts\");\n if (!data) return [];\n if (Array.isArray(data)) return data as ApigwContact[];\n if (typeof data === \"object\" && data !== null) {\n const obj = data as Record<string, unknown>;\n if (Array.isArray(obj.contacts)) return obj.contacts as ApigwContact[];\n if (Array.isArray(obj.users)) return obj.users as ApigwContact[];\n if (Array.isArray(obj.result)) return obj.result as ApigwContact[];\n }\n return [];\n }\n\n async getContactChanges(since: string, udid = \"latest_mobile\"): Promise<unknown> {\n return this.client.get(\n `/api/v1/apigw/api/v4/phonebook/user_contacts_changes?since=${encodeURIComponent(since)}&udid=${udid}`,\n );\n }\n\n async getEncryptedEntries(since: string, udid = \"latest_mobile\"): Promise<unknown> {\n return this.client.get(\n `/api/v1/apigw/api/v4/phonebook/encrypted_entries?since=${encodeURIComponent(since)}&udid=${udid}`,\n );\n }\n\n async getCorporateDirectory(since?: string): Promise<unknown> {\n const params = since ? `?since=${encodeURIComponent(since)}` : \"\";\n const data = await this.client.get<unknown>(`/api/v1/corporate_directory/entries${params}`);\n if (!data) return { entries: [] };\n if (typeof data === \"object\" && data !== null && \"entries\" in data) return data;\n return data;\n }\n\n async searchUsers(query: string, limit = 20): Promise<ExpressProfile[]> {\n return this.searchUsersPhonebook(query, limit);\n }\n\n async searchUsersPhonebook(query: string, limit: number): Promise<ExpressProfile[]> {\n const data = await this.client.get<unknown>(\n `/api/v3/phonebook/search?query=${encodeURIComponent(query)}&active=true&disable_fuzzy_search=false`,\n );\n if (!data || typeof data !== \"object\") return [];\n const obj = data as Record<string, unknown>;\n const result = obj.result as Record<string, unknown> | undefined;\n const phonebook = (result?.phonebook ?? []) as Array<{ name?: string; contacts?: Array<{ user_huid?: string }> }>;\n const huids = [\n ...new Set(\n phonebook\n .flatMap((entry) => entry.contacts ?? [])\n .map((c) => c.user_huid)\n .filter(Boolean) as string[],\n ),\n ].slice(0, limit);\n if (huids.length === 0) return [];\n const raw = await this.client.rawRequest(\"/api/v1/phonebook/cts_profiles/query\", {\n method: \"POST\",\n body: JSON.stringify({ huids }),\n });\n const profileData = (await raw.json()) as { result?: Array<{ cts_profiles?: ExpressProfile[] }> };\n const entries = profileData.result ?? [];\n const profiles: ExpressProfile[] = [];\n for (const entry of entries) {\n profiles.push(...(entry.cts_profiles ?? []));\n }\n return profiles.slice(0, limit);\n }\n\n private async searchUsersApigw(query: string, limit: number, contacts: ApigwContact[]): Promise<ExpressProfile[]> {\n const lowerQuery = query.toLowerCase();\n const matched = contacts.filter((c) => {\n const searchable = [c.name, c.email, c.ad_login, c.department, c.company_position, c.phone, c.ip_phone]\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n return searchable.includes(lowerQuery);\n }).slice(0, limit);\n\n if (matched.length > 0) {\n const huids = matched.map((c) => c.huid).filter(Boolean) as string[];\n if (huids.length > 0) {\n const raw = await this.client.rawRequest(\"/api/v1/phonebook/cts_profiles/query\", {\n method: \"POST\",\n body: JSON.stringify({ huids }),\n });\n const data = (await raw.json()) as CtsProfilesResponse;\n const entries = data.result ?? (Array.isArray(data) ? data : []);\n const profiles: ExpressProfile[] = [];\n for (const entry of entries) {\n profiles.push(...(entry.cts_profiles ?? []));\n }\n return profiles.slice(0, limit);\n }\n }\n\n return [];\n }\n\n private async searchUsersDirectory(query: string, limit: number): Promise<ExpressProfile[]> {\n const dirData = await this.getCorporateDirectory() as DirectoryResponse;\n const entries = dirData?.entries ?? [];\n const userIds = entries\n .filter((e) => e.entry_type === \"user\" && !e.deleted)\n .map((e) => e.entry_id);\n\n if (userIds.length === 0) {\n return [];\n }\n\n const batchSize = 100;\n const allProfiles: ExpressProfile[] = [];\n const lowerQuery = query.toLowerCase();\n\n for (let i = 0; i < userIds.length && allProfiles.length < limit; i += batchSize) {\n const batch = userIds.slice(i, i + batchSize);\n const raw = await this.client.rawRequest(\"/api/v1/phonebook/cts_profiles/query\", {\n method: \"POST\",\n body: JSON.stringify({ huids: batch }),\n });\n const data = (await raw.json()) as CtsProfilesResponse;\n const entries = data.result ?? (Array.isArray(data) ? data : []);\n\n for (const entry of entries) {\n for (const p of entry.cts_profiles ?? []) {\n const searchable = [\n p.name,\n p.email,\n p.ad_login,\n p.department,\n p.company_position,\n p.phone,\n p.ip_phone,\n ]\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n\n if (searchable.includes(lowerQuery)) {\n allProfiles.push(p);\n if (allProfiles.length >= limit) return allProfiles;\n }\n }\n }\n }\n\n return allProfiles;\n }\n}\n","import { Command } from \"commander\";\nimport { SettingsApi } from \"../api/settings.js\";\nimport { ApiClient } from \"../api/client.js\";\nimport { formatOutput, type OutputFormat } from \"./output.js\";\n\nexport function createSettingsCommand(): Command {\n const cmd = new Command(\"settings\");\n\n cmd.description(\"Server settings and meta\");\n\n cmd\n .command(\"meta\")\n .description(\"Get server metadata\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (opts: { host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new SettingsApi(client);\n const meta = await api.getServerMeta();\n console.log(formatOutput(meta, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"get\")\n .description(\"Get settings\")\n .option(\"--since <iso-date>\", \"Since date (ISO 8601)\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (opts: { since?: string; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new SettingsApi(client);\n const settings = await api.getSettings(opts.since);\n console.log(formatOutput(settings, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { ApiClient } from \"./client.js\";\nimport type { ServerMeta } from \"../types/index.js\";\n\nexport class SettingsApi {\n constructor(private client: ApiClient) {}\n\n async getServerMeta(): Promise<ServerMeta> {\n return this.client.get<ServerMeta>(\"/api/v1/settings/server/meta/\");\n }\n\n async getSettings(since?: string): Promise<unknown> {\n const params = since ? `?since=${encodeURIComponent(since)}` : \"\";\n return this.client.get(`/api/v2/settings/${params}`);\n }\n\n async getRoles(deviceHash: string): Promise<unknown> {\n return this.client.get(`/api/v1/roles/rules?device_hash=${encodeURIComponent(deviceHash)}`);\n }\n}\n","import { Command } from \"commander\";\nimport { ChatsApi } from \"../api/chats.js\";\nimport { UserApi } from \"../api/user.js\";\nimport { ApiClient } from \"../api/client.js\";\nimport { formatOutput, type OutputFormat } from \"./output.js\";\nimport type { ExpressChat } from \"../types/index.js\";\nimport Table from \"cli-table3\";\nimport chalk from \"chalk\";\n\nasync function resolveDmNames(chats: ExpressChat[], client: ApiClient): Promise<void> {\n const dmChats = chats.filter((c) => c.chat_type === \"chat\" && c.member_huids?.length);\n if (dmChats.length === 0) return;\n try {\n const userApi = new UserApi(client);\n const self = await userApi.getSelfProfile();\n const myHuid = self.user_huid;\n const otherHuids = [...new Set(\n dmChats.flatMap((c) => (c.member_huids ?? []).filter((h) => h !== myHuid)),\n )];\n if (otherHuids.length === 0) return;\n const profiles = await userApi.getProfilesByHuid(otherHuids);\n const nameMap = new Map(profiles.map((p) => [p.user_huid, p.name]));\n for (const chat of chats) {\n if (chat.chat_type === \"chat\" && chat.member_huids) {\n const otherHuid = chat.member_huids.find((h) => h !== myHuid);\n if (otherHuid) chat.name = nameMap.get(otherHuid) ?? chat.name;\n }\n }\n } catch (err) {\n if (process.env.EXPRESS_DEBUG) {\n console.error(` [DEBUG] Failed to resolve DM names: ${(err as Error).message}`);\n }\n }\n}\n\nfunction typeLabel(chatType: string): string {\n if (chatType === \"channel\" || chatType === \"global\") return chalk.magenta(chatType);\n if (chatType === \"group_chat\") return chalk.blue(\"group\");\n if (chatType === \"chat\") return chalk.green(\"dm\");\n return chalk.gray(chatType);\n}\n\nfunction memberCount(c: ExpressChat): string {\n return c.members_count != null ? String(c.members_count) :\n c.member_huids?.length != null ? String(c.member_huids.length) : \"-\";\n}\n\nexport function createChatsCommand(): Command {\n const cmd = new Command(\"chats\");\n\n cmd.description(\"Chat management\");\n\n cmd\n .command(\"list\")\n .description(\"List all chats (uses WebSocket for full list)\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"--type <type>\", \"Filter by type: dm, group, channel, all\", \"all\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (opts: { host?: string; type: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new ChatsApi(client);\n let chats = await api.listChats();\n\n await resolveDmNames(chats, client);\n\n if (opts.type !== \"all\") {\n const typeMap: Record<string, string[]> = {\n dm: [\"chat\"],\n group: [\"group_chat\"],\n channel: [\"channel\", \"global\"],\n };\n const allowed = typeMap[opts.type] ?? [];\n chats = chats.filter((c) => allowed.includes(c.chat_type));\n }\n\n if (opts.output === \"json\") {\n console.log(formatOutput(chats, \"json\"));\n return;\n }\n\n const table = new Table({\n head: [\"Name\", \"Type\", \"Members\", \"Chat ID\"],\n style: { head: [\"cyan\"] },\n });\n\n for (const c of chats) {\n table.push([c.name ?? \"-\", typeLabel(c.chat_type), memberCount(c), c.group_chat_id.slice(0, 8) + \"...\"]);\n }\n\n console.log(table.toString());\n console.log(chalk.gray(` ${chats.length} chats`));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"find <query>\")\n .description(\"Find chats by name (case-insensitive), shows full IDs\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"--type <type>\", \"Filter by type: dm, group, channel, all\", \"all\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (query: string, opts: { host?: string; type: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new ChatsApi(client);\n let chats = await api.listChats();\n\n await resolveDmNames(chats, client);\n\n const lowerQuery = query.toLowerCase();\n chats = chats.filter((c) => (c.name ?? \"\").toLowerCase().includes(lowerQuery));\n\n if (opts.type !== \"all\") {\n const typeMap: Record<string, string[]> = {\n dm: [\"chat\"],\n group: [\"group_chat\"],\n channel: [\"channel\", \"global\"],\n };\n const allowed = typeMap[opts.type] ?? [];\n chats = chats.filter((c) => allowed.includes(c.chat_type));\n }\n\n if (chats.length === 0) {\n console.log(chalk.yellow(`No chats matching \"${query}\".`));\n return;\n }\n\n if (opts.output === \"json\") {\n console.log(formatOutput(chats, \"json\"));\n return;\n }\n\n const table = new Table({\n head: [\"Name\", \"Type\", \"Members\", \"Chat ID (full)\"],\n style: { head: [\"cyan\"] },\n });\n\n for (const c of chats) {\n table.push([c.name ?? \"-\", typeLabel(c.chat_type), memberCount(c), c.group_chat_id]);\n }\n\n console.log(table.toString());\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"info <chat-id>\")\n .description(\"Get chat details\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (chatId: string, opts: { host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new ChatsApi(client);\n const chat = await api.getChatInfo(chatId);\n if (!chat) {\n console.error(`Chat not found: ${chatId}`);\n process.exit(1);\n }\n console.log(formatOutput(chat, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport { MessagingApi } from \"../api/messaging.js\";\nimport { sendMessageViaWebSocket } from \"../api/messaging-ws.js\";\nimport { ApiClient } from \"../api/client.js\";\nimport { resolveChatId } from \"../api/resolve.js\";\nimport { formatOutput, type OutputFormat } from \"./output.js\";\nimport { readFileSync } from \"node:fs\";\n\nexport function createSendCommand(): Command {\n const cmd = new Command(\"send\");\n\n cmd.description(\"Send messages and files\");\n\n cmd\n .command(\"message <chat-id-or-name> <text>\")\n .description(\"Send a text message to a chat (chat ID or partial name)\")\n .option(\"--stealth\", \"Send in stealth mode\", false)\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (chatIdOrName: string, text: string, opts: { stealth: boolean; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const chatId = await resolveChatId(client, chatIdOrName);\n const result = await sendMessageViaWebSocket({ client, chatId, body: text });\n console.log(formatOutput(result, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"file <chat-id> <file-path>\")\n .description(\"Send a file to a chat\")\n .option(\"--caption <caption>\", \"File caption\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (chatId: string, filePath: string, opts: { caption?: string; host?: string; output: OutputFormat }) => {\n try {\n const data = readFileSync(filePath);\n const fileName = filePath.split(\"/\").pop() ?? \"file\";\n const mimeMap: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".pdf\": \"application/pdf\",\n \".txt\": \"text/plain\",\n \".json\": \"application/json\",\n \".csv\": \"text/csv\",\n \".zip\": \"application/zip\",\n };\n const ext = fileName.includes(\".\") ? \".\" + fileName.split(\".\").pop()!.toLowerCase() : \"\";\n const mime = mimeMap[ext] ?? \"application/octet-stream\";\n const base64 = data.toString(\"base64\");\n const dataUri = `data:${mime};base64,${base64}`;\n\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new MessagingApi(client);\n const result = await api.sendFile({\n groupChatId: chatId,\n fileName,\n fileData: dataUri,\n caption: opts.caption,\n });\n console.log(formatOutput(result, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { ApiClient } from \"./client.js\";\n\nexport interface SendMessagePayload {\n group_chat_id: string;\n notification: {\n status: \"ok\" | \"error\";\n body: string;\n metadata?: Record<string, unknown>;\n mentions?: Record<string, unknown>;\n opts?: {\n stealth_mode?: boolean;\n notification_opts?: {\n send?: boolean;\n force_dnd?: boolean;\n };\n };\n };\n file?: {\n file_name: string;\n data: string;\n };\n}\n\nexport class MessagingApi {\n constructor(private client: ApiClient) {}\n\n async sendMessage(params: {\n groupChatId: string;\n body: string;\n metadata?: Record<string, unknown>;\n mentions?: Record<string, unknown>;\n stealthMode?: boolean;\n }): Promise<unknown> {\n const payload: SendMessagePayload = {\n group_chat_id: params.groupChatId,\n notification: {\n status: \"ok\",\n body: params.body,\n ...(params.metadata && { metadata: params.metadata }),\n ...(params.mentions && { mentions: params.mentions }),\n ...(params.stealthMode && {\n opts: { stealth_mode: true },\n }),\n },\n };\n\n return this.client.post(\"/api/v4/botx/notifications/direct\", payload);\n }\n\n async sendFile(params: {\n groupChatId: string;\n fileName: string;\n fileData: string;\n caption?: string;\n }): Promise<unknown> {\n const payload: SendMessagePayload = {\n group_chat_id: params.groupChatId,\n notification: {\n status: \"ok\",\n body: params.caption ?? \"\",\n },\n file: {\n file_name: params.fileName,\n data: params.fileData,\n },\n };\n\n return this.client.post(\"/api/v4/botx/notifications/direct\", payload);\n }\n}\n","import { randomBytes, randomUUID } from \"node:crypto\";\nimport nacl from \"tweetnacl\";\nimport sodium from \"libsodium-wrappers-sumo\";\nimport type { ApiClient } from \"./client.js\";\nimport { UserApi } from \"./user.js\";\nimport { loadApigwKeys, signEd25519 } from \"../auth/keys.js\";\nimport { getAuthToken } from \"../config/store.js\";\nimport { loadConfig, getBaseUrl, getWebOrigin } from \"../config/index.js\";\n\n/**\n * Build the wire plaintext for a text message. Shape reverse-engineered from the\n * eXpress web client (`encryptMessagePayload` in app.js): a flat snake_case\n * object with `body` (plain text) — the client generates the markdown AST from\n * `body` on receipt, so no bodyAstTree on the wire. A bare `{body}` makes\n * recipients show \"Can't decrypt\".\n */\nfunction buildTextPayload(text: string, fromHuid: string, chatId: string): string {\n return JSON.stringify({\n type: \"text\",\n msg_id: randomUUID(),\n from: fromHuid,\n timestamp: new Date().toISOString(),\n group_chat_id: chatId,\n lat: 0,\n lng: 0,\n link_meta_disabled: false,\n stealth_forwarding: false,\n body: text,\n });\n}\n\n/** AEAD additional data — must match the client: `${groupChatId}:${syncId}`. */\nfunction payloadAad(chatId: string, syncId: string): Uint8Array {\n return new Uint8Array(Buffer.from(`${chatId}:${syncId}`));\n}\n\ninterface KdcKey {\n id: string;\n body: string; // base64 Curve25519 public key\n algo: string;\n kind: string;\n user_huid: string;\n}\n\ninterface EncryptedKey {\n key_id: string;\n key: string; // base64 nonce+ciphertext\n algo: string;\n}\n\nexport async function sendMessageViaWebSocket(params: {\n client: ApiClient;\n chatId: string;\n body: string;\n timeoutMs?: number;\n}): Promise<{ sync_id: string }> {\n const { client, chatId, body, timeoutMs = 20000 } = params;\n\n await sodium.ready;\n\n const apigwKeys = loadApigwKeys();\n if (!apigwKeys) throw new Error(\"No apigw keys. Run 'express auth login' first.\");\n\n const config = loadConfig();\n const host = new URL(getBaseUrl(config)).hostname;\n const webOrigin = getWebOrigin(config);\n const ctsToken = getAuthToken();\n const ctsKey = apigwKeys.ctsKey ?? apigwKeys.encryptionKey;\n const encKeyId = ctsKey.keyId;\n\n // Step 1: get participant key_ids via WebSocket chat_info.\n // The server rejects message_new with `invalid_keys` unless keys[] matches this\n // set exactly — no extra/superseded key_ids allowed, so encrypt for these only.\n const participantKeyIds = await getChatKeyIds(host, webOrigin, ctsToken, encKeyId, chatId);\n\n // Step 2: fetch public keys from KDC (only cts keys are usable for E2E)\n const kdcKeys = await client.get<KdcKey[]>(\n `/api/v1/kdc/keys/?ids=${participantKeyIds.join(\",\")}`,\n ) ?? [];\n const publicKeys = kdcKeys.filter((k) => k.kind === \"cts\");\n\n // Step 3: generate symmetric key + sync_id (sync_id is part of the body AAD)\n const symmetricKey = randomBytes(32);\n const syncId = randomUUID();\n\n // Step 4: encrypt symmetric key for each participant\n const encryptedKeys: EncryptedKey[] = publicKeys.map((kdcKey) => {\n const recipientPubKey = new Uint8Array(Buffer.from(kdcKey.body, \"base64\"));\n const nonce = randomBytes(nacl.box.nonceLength);\n const ciphertext = nacl.box(\n symmetricKey,\n nonce,\n recipientPubKey,\n ctsKey.privateKey,\n );\n if (!ciphertext) throw new Error(`Failed to encrypt key for ${kdcKey.id}`);\n const combined = Buffer.concat([nonce, Buffer.from(ciphertext)]);\n return {\n key_id: kdcKey.id,\n key: combined.toString(\"base64\"),\n algo: \"xsalsa20:xchacha20_aead_ietf\",\n };\n });\n\n // Step 5: encrypt message body with XChaCha20-Poly1305 IETF.\n // AAD = `${group_chat_id}:${sync_id}` — recipients authenticate against it, so\n // it must match or they get \"Can't decrypt\".\n const selfHuid = (await new UserApi(client).getSelfProfile()).user_huid;\n const plaintext = new Uint8Array(Buffer.from(buildTextPayload(body, selfHuid, chatId)));\n const msgNonce = randomBytes(sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);\n const ciphertext = sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(\n plaintext, payloadAad(chatId, syncId), null,\n new Uint8Array(msgNonce),\n new Uint8Array(symmetricKey),\n );\n const encryptedPayload = Buffer.concat([msgNonce, Buffer.from(ciphertext)]).toString(\"base64\");\n\n // Step 6: send via WebSocket (no signature required for DMs)\n // Sign the base64 payload string with ed25519 (browser requires this to decrypt)\n const signingKey = apigwKeys.signingKey;\n const signBytes = signEd25519(\n signingKey.privateKey,\n new Uint8Array(Buffer.from(encryptedPayload, \"utf8\")),\n );\n const signature = {\n sign: Buffer.from(signBytes).toString(\"base64\"),\n sign_key_id: signingKey.keyId,\n sign_algo: \"ed25519\",\n };\n\n return sendMessageNew({\n host,\n webOrigin,\n ctsToken,\n encKeyId,\n chatId,\n syncId,\n encryptedKeys,\n encryptedPayload,\n signature,\n timeoutMs,\n });\n}\n\nasync function getChatKeyIds(\n host: string,\n webOrigin: string,\n ctsToken: string,\n encKeyId: string,\n chatId: string,\n): Promise<string[]> {\n const wsUrl = `wss://${host}/socket/user/websocket?vsn=1.0.0&auto_join=true&key_id=${encKeyId}&version=6&background=false&voex_unencrypted=true&instance_id=${randomUUID()}`;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const done = (fn: () => void) => { if (!settled) { settled = true; fn(); } };\n const timer = setTimeout(() => {\n try { ws.close(); } catch {}\n done(() => reject(new Error(\"Timeout getting chat key_ids\")));\n }, 10000);\n\n const ws = new WebSocket(wsUrl, {\n headers: { Origin: webOrigin, \"User-Agent\": \"Mozilla/5.0\" },\n } as ConstructorParameters<typeof WebSocket>[1]);\n\n let ref = 0;\n const authRef = ref++;\n let chatInfoRef: number;\n\n const send = (msg: object) => ws.send(JSON.stringify(msg));\n\n ws.addEventListener(\"open\", () => {\n send({ topic: \"phoenix\", event: \"authenticate\", payload: { token: ctsToken }, ref: authRef });\n });\n\n ws.addEventListener(\"message\", (e) => {\n const msg = JSON.parse(e.data as string) as {\n ref: number; event: string; topic: string;\n payload: { status: string; response: Record<string, unknown> };\n };\n\n if (msg.ref === authRef && msg.event === \"phx_reply\" && msg.payload?.status === \"ok\") {\n chatInfoRef = ref++;\n send({ topic: \"system\", event: \"chat_info\", payload: { group_chat_id: chatId, request_version: 6 }, ref: chatInfoRef });\n return;\n }\n\n if (msg.ref === chatInfoRef && msg.event === \"phx_reply\") {\n clearTimeout(timer);\n ws.close();\n const chatInfo = (msg.payload?.response?.chat_info ?? msg.payload?.response) as Record<string, unknown>;\n const keys = (chatInfo?.keys as string[]) ?? [];\n done(() => resolve(keys));\n }\n });\n\n ws.addEventListener(\"error\", (err) => {\n clearTimeout(timer);\n done(() => reject(new Error(`WS error: ${String(err)}`)));\n });\n\n ws.addEventListener(\"close\", () => {\n clearTimeout(timer);\n done(() => reject(new Error(\"WS closed before chat_info\")));\n });\n });\n}\n\nasync function sendMessageNew(params: {\n host: string;\n webOrigin: string;\n ctsToken: string;\n encKeyId: string;\n chatId: string;\n syncId: string;\n encryptedKeys: EncryptedKey[];\n encryptedPayload: string;\n signature: { sign: string; sign_key_id: string; sign_algo: string };\n timeoutMs: number;\n}): Promise<{ sync_id: string }> {\n const { host, webOrigin, ctsToken, encKeyId, chatId, syncId, encryptedKeys, encryptedPayload, signature, timeoutMs } = params;\n const wsUrl = `wss://${host}/socket/user/websocket?vsn=1.0.0&auto_join=true&key_id=${encKeyId}&version=6&background=false&voex_unencrypted=true&instance_id=${randomUUID()}`;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const done = (fn: () => void) => { if (!settled) { settled = true; fn(); } };\n const timer = setTimeout(() => {\n try { ws.close(); } catch {}\n done(() => reject(new Error(\"Timeout sending message\")));\n }, timeoutMs);\n\n const ws = new WebSocket(wsUrl, {\n headers: { Origin: webOrigin, \"User-Agent\": \"Mozilla/5.0\" },\n } as ConstructorParameters<typeof WebSocket>[1]);\n\n let ref = 0;\n const authRef = ref++;\n let msgRef: number;\n\n const send = (msg: object) => ws.send(JSON.stringify(msg));\n\n ws.addEventListener(\"open\", () => {\n send({ topic: \"phoenix\", event: \"authenticate\", payload: { token: ctsToken }, ref: authRef });\n });\n\n ws.addEventListener(\"message\", (e) => {\n const msg = JSON.parse(e.data as string) as {\n ref: number; event: string; topic: string;\n payload: { status: string; response: Record<string, unknown> };\n };\n\n if (msg.ref === authRef && msg.event === \"phx_reply\" && msg.payload?.status === \"ok\") {\n msgRef = ref++;\n send({\n topic: `groupchat:${chatId}`,\n event: \"message_new\",\n payload: {\n keys: encryptedKeys,\n group_chat_id: chatId,\n sync_id: syncId,\n payload: encryptedPayload,\n signature,\n },\n ref: msgRef,\n });\n return;\n }\n\n if (msg.ref === msgRef && msg.event === \"phx_reply\") {\n clearTimeout(timer);\n ws.close();\n if (msg.payload?.status === \"ok\") {\n done(() => resolve({ sync_id: syncId }));\n } else {\n done(() => reject(new Error(`message_new failed: ${JSON.stringify(msg.payload?.response)}`)));\n }\n }\n });\n\n ws.addEventListener(\"error\", (err) => {\n clearTimeout(timer);\n done(() => reject(new Error(`WS error: ${String(err)}`)));\n });\n\n ws.addEventListener(\"close\", () => {\n clearTimeout(timer);\n done(() => reject(new Error(\"WS closed before message_new reply\")));\n });\n });\n}\n","import { ApiClient } from \"./client.js\";\nimport { ChatsApi } from \"./chats.js\";\nimport { UserApi } from \"./user.js\";\nimport type { ExpressChat } from \"../types/index.js\";\n\n/** List chats with DM display names resolved to the other participant's full name. */\nexport async function listChatsWithNames(client: ApiClient): Promise<ExpressChat[]> {\n const chats = await new ChatsApi(client).listChats();\n const dmChats = chats.filter((c) => c.chat_type === \"chat\" && c.member_huids?.length);\n if (dmChats.length === 0) return chats;\n\n const userApi = new UserApi(client);\n const myHuid = (await userApi.getSelfProfile()).user_huid;\n const otherHuids = [...new Set(dmChats.flatMap((c) => (c.member_huids ?? []).filter((h) => h !== myHuid)))];\n if (otherHuids.length === 0) return chats;\n\n const nameMap = new Map((await userApi.getProfilesByHuid(otherHuids)).map((p) => [p.user_huid, p.name]));\n for (const chat of chats) {\n if (chat.chat_type === \"chat\" && chat.member_huids) {\n const other = chat.member_huids.find((h) => h !== myHuid);\n if (other) chat.name = nameMap.get(other) ?? chat.name;\n }\n }\n return chats;\n}\n\n/** Resolve a chat name (partial match) or UUID to a full chat_id. Throws on 0/many matches. */\nexport async function resolveChatId(client: ApiClient, chatIdOrName: string): Promise<string> {\n if (/^[0-9a-f-]{36}$/i.test(chatIdOrName)) return chatIdOrName;\n\n const chats = await listChatsWithNames(client);\n const lower = chatIdOrName.toLowerCase();\n const matches = chats.filter((c) => (c.name ?? \"\").toLowerCase().includes(lower));\n if (matches.length === 0) throw new Error(`No chat found matching \"${chatIdOrName}\"`);\n if (matches.length > 1) {\n const names = matches.map((c) => ` ${c.name} (${c.group_chat_id})`).join(\"\\n\");\n throw new Error(`Multiple chats match \"${chatIdOrName}\":\\n${names}\\nUse the full chat ID.`);\n }\n return matches[0].group_chat_id;\n}\n","import { Command } from \"commander\";\nimport { ApiClient } from \"../api/client.js\";\nimport { UserApi } from \"../api/user.js\";\nimport { UploadsApi } from \"../api/uploads.js\";\nimport { formatProfileTable, formatOutput, type OutputFormat } from \"./output.js\";\nimport { writeFileSync } from \"node:fs\";\n\nexport function createAvatarCommand(): Command {\n const cmd = new Command(\"avatar\");\n\n cmd.description(\"Download user avatars\");\n\n cmd\n .command(\"get <huid>\")\n .description(\"Download avatar for a user by HUID\")\n .option(\"-o, --output <path>\", \"Output file path (default: <huid>.png)\")\n .option(\"--host <host>\", \"eXpress host\")\n .action(async (huid: string, opts: { output?: string; host?: string }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const userApi = new UserApi(client);\n const uploadsApi = new UploadsApi(client);\n\n const profiles = await userApi.getProfilesByHuid([huid]);\n const profile = profiles?.[0];\n const avatarUrl = profile?.custom_avatar ?? profile?.avatar;\n\n if (!avatarUrl) {\n console.log(\"No avatar found for this user.\");\n return;\n }\n\n const { data, contentType } = await uploadsApi.download(avatarUrl);\n const ext = contentType?.includes(\"jpeg\") ? \".jpg\" : contentType?.includes(\"png\") ? \".png\" : \".png\";\n const outputPath = opts.output ?? `${huid}${ext}`;\n\n writeFileSync(outputPath, Buffer.from(data));\n console.log(`Avatar saved to ${outputPath}`);\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"self\")\n .description(\"Download your own avatar\")\n .option(\"-o, --output <path>\", \"Output file path (default: self_avatar.png)\")\n .option(\"--host <host>\", \"eXpress host\")\n .action(async (opts: { output?: string; host?: string }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const userApi = new UserApi(client);\n const uploadsApi = new UploadsApi(client);\n\n const profile = await userApi.getSelfProfile();\n const avatarUrl = profile.custom_avatar ?? profile.avatar;\n\n if (!avatarUrl) {\n console.log(\"No avatar found for your profile.\");\n return;\n }\n\n const { data, contentType } = await uploadsApi.download(avatarUrl);\n const ext = contentType?.includes(\"jpeg\") ? \".jpg\" : contentType?.includes(\"png\") ? \".png\" : \".png\";\n const outputPath = opts.output ?? `self_avatar${ext}`;\n\n writeFileSync(outputPath, Buffer.from(data));\n console.log(`Avatar saved to ${outputPath}`);\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { ApiClient } from \"./client.js\";\n\nexport class UploadsApi {\n constructor(private client: ApiClient) {}\n\n async downloadAvatar(huid: string): Promise<{ data: ArrayBuffer; contentType: string | null } | null> {\n const profile = await this.client.get<{ custom_avatar?: string; avatar?: string }>(\n `/api/v1/phonebook/cts_profiles/query`,\n );\n return null;\n }\n\n async download(url: string): Promise<{ data: ArrayBuffer; contentType: string | null }> {\n const res = await this.client.downloadFile(url);\n if (!res.ok) {\n throw new Error(`Download failed: ${res.status} ${res.statusText}`);\n }\n const data = await res.arrayBuffer();\n const contentType = res.headers.get(\"content-type\");\n return { data, contentType };\n }\n}\n","import { Command } from \"commander\";\nimport { ApiClient } from \"../api/client.js\";\nimport { UploadsApi } from \"../api/uploads.js\";\nimport { writeFileSync } from \"node:fs\";\n\nexport function createDownloadCommand(): Command {\n const cmd = new Command(\"download\");\n\n cmd\n .description(\"Download a file from eXpress uploads\")\n .argument(\"<url>\", \"Full URL or path (e.g. /uploads/files/...)\")\n .option(\"-o, --output <path>\", \"Output file path (default: auto from URL)\")\n .option(\"--host <host>\", \"eXpress host\")\n .action(async (url: string, opts: { output?: string; host?: string }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const uploadsApi = new UploadsApi(client);\n\n const { data, contentType } = await uploadsApi.download(url);\n const urlPath = new URL(url.startsWith(\"http\") ? url : `https://x${url}`).pathname;\n const baseName = urlPath.split(\"/\").pop() ?? \"download\";\n const outputPath = opts.output ?? baseName;\n\n writeFileSync(outputPath, Buffer.from(data));\n console.log(`Downloaded to ${outputPath} (${contentType ?? \"unknown\"}, ${data.byteLength} bytes)`);\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport { readMessages } from \"../api/messages-read.js\";\nimport { formatOutput, type OutputFormat } from \"./output.js\";\n\nexport function createMessagesCommand(): Command {\n const cmd = new Command(\"messages\");\n\n cmd.description(\"Read and decrypt chat messages\");\n\n cmd\n .command(\"list <chat-id>\")\n .description(\"List recent messages from a chat\")\n .option(\"-n, --limit <number>\", \"Number of messages\", \"20\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (chatId: string, opts: { limit: string; host?: string; output: OutputFormat }) => {\n try {\n const messages = await readMessages({\n chatId,\n limit: parseInt(opts.limit, 10) || 20,\n });\n\n if (opts.output === \"json\") {\n console.log(formatOutput(messages, opts.output));\n return;\n }\n\n for (const msg of messages) {\n const time = msg.inserted_at ? new Date(msg.inserted_at).toLocaleString(\"ru-RU\") : \"?\";\n const sender = msg.sender ? msg.sender.slice(0, 8) + \"...\" : \"unknown\";\n if (msg.decrypted) {\n console.log(`[${time}] ${sender}: ${msg.body}`);\n } else {\n console.log(`[${time}] ${sender}: [DECRYPT FAILED: ${msg.error}]`);\n }\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { randomUUID } from \"node:crypto\";\nimport { loadApigwKeys } from \"../auth/keys.js\";\nimport { getAuthToken } from \"../config/store.js\";\nimport { loadConfig, getBaseUrl, getWebOrigin } from \"../config/index.js\";\nimport { decryptMessages, type HistoryMessage, type DecryptedMessage } from \"./decrypt.js\";\n\nexport async function readMessages(params: {\n chatId: string;\n limit?: number;\n timeoutMs?: number;\n direction?: \"backward\" | \"forward\";\n}): Promise<DecryptedMessage[]> {\n const { chatId, limit = 20, timeoutMs = 20000, direction = \"backward\" } = params;\n\n const apigwKeys = loadApigwKeys();\n if (!apigwKeys) throw new Error(\"No apigw keys. Run 'express auth login' first.\");\n\n const config = loadConfig();\n const host = new URL(getBaseUrl(config)).hostname;\n const webOrigin = getWebOrigin(config);\n const ctsToken = getAuthToken();\n const ctsKey = apigwKeys.ctsKey ?? apigwKeys.encryptionKey;\n\n const history = await fetchEventsHistory(host, webOrigin, ctsToken, ctsKey.keyId, chatId, limit, timeoutMs, direction);\n return decryptMessages(history, apigwKeys);\n}\n\nasync function fetchEventsHistory(\n host: string,\n webOrigin: string,\n ctsToken: string,\n encKeyId: string,\n chatId: string,\n limit: number,\n timeoutMs: number,\n direction: \"backward\" | \"forward\" = \"backward\",\n): Promise<HistoryMessage[]> {\n const wsUrl = `wss://${host}/socket/user/websocket?vsn=1.0.0&auto_join=true&key_id=${encKeyId}&version=6&background=false&voex_unencrypted=true&instance_id=${randomUUID()}`;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const done = (fn: () => void) => { if (!settled) { settled = true; fn(); } };\n const timer = setTimeout(() => {\n try { ws.close(); } catch {}\n done(() => reject(new Error(\"Timeout fetching messages\")));\n }, timeoutMs);\n\n const ws = new WebSocket(wsUrl, {\n headers: { Origin: webOrigin, \"User-Agent\": \"Mozilla/5.0\" },\n } as ConstructorParameters<typeof WebSocket>[1]);\n\n let ref = 0;\n const authRef = ref++;\n let subRef = 0;\n let histRef = 0;\n\n const send = (msg: object) => ws.send(JSON.stringify(msg));\n\n ws.addEventListener(\"open\", () => {\n send({ topic: \"phoenix\", event: \"authenticate\", payload: { token: ctsToken }, ref: authRef });\n });\n\n ws.addEventListener(\"message\", (e) => {\n const msg = JSON.parse(e.data as string) as {\n ref: number | string; event: string; topic: string;\n payload: Record<string, unknown>;\n };\n\n const msgRef = typeof msg.ref === \"string\" ? parseInt(msg.ref, 10) : msg.ref;\n\n if (msgRef === authRef && msg.event === \"phx_reply\" && msg.payload?.status === \"ok\") {\n subRef = ref++;\n send({ topic: `groupchat:${chatId}`, event: \"subscribe_to_chat_activities\", payload: { group_chat_id: chatId }, ref: subRef });\n return;\n }\n\n if (msgRef === subRef && msg.event === \"phx_reply\") {\n histRef = ref++;\n send({\n topic: `groupchat:${chatId}`,\n event: \"events_history\",\n payload: {\n direction,\n group_chat_id: chatId,\n limit,\n skip_non_affecting_rc: true,\n skip_to_sync_id_event: true,\n last_ignore_messages_at: null,\n },\n ref: histRef,\n });\n return;\n }\n\n if (msgRef === histRef && msg.event === \"phx_reply\") {\n clearTimeout(timer);\n ws.close();\n const response = (msg.payload?.response ?? msg.payload) as Record<string, unknown>;\n const history = (response?.history ?? []) as HistoryMessage[];\n done(() => resolve(Array.isArray(history) ? history : []));\n return;\n }\n });\n\n ws.addEventListener(\"error\", (err) => {\n clearTimeout(timer);\n done(() => reject(new Error(`WS error: ${String(err)}`)));\n });\n\n ws.addEventListener(\"close\", () => {\n clearTimeout(timer);\n done(() => reject(new Error(\"WS closed before messages received\")));\n });\n });\n}\n","import nacl from \"tweetnacl\";\nimport sodium from \"libsodium-wrappers-sumo\";\nimport { loadApigwKeys } from \"../auth/keys.js\";\nimport { ApiClient } from \"./client.js\";\n\nexport interface HistoryMessage {\n sync_id: string;\n payload: string;\n key: { algo: string; key: string; key_id: string };\n sender: string;\n sender_key_id: string;\n group_chat_id: string;\n inserted_at: string;\n event_type: string;\n}\n\nexport interface ImageAttachment {\n fileName: string;\n mimeType?: string;\n /** Inline base64 data-URI (blur_preview_file) — renderable without download/decryption. */\n previewDataUri?: string;\n width?: number;\n height?: number;\n}\n\nexport interface DecryptedMessage {\n sync_id: string;\n body: string;\n sender: string;\n inserted_at: string;\n decrypted: boolean;\n error?: string;\n type?: string;\n image?: ImageAttachment;\n}\n\ntype KdcKeyMap = Map<string, { id: string; body: string; user_huid: string }>;\ntype ApigwKeys = NonNullable<ReturnType<typeof loadApigwKeys>>;\n\n/**\n * Decrypt a single history/message_new event.\n * E2E: nacl.box.open(encrypted symmetric key) → XChaCha20-Poly1305 IETF body,\n * with AAD `${group_chat_id}:${sync_id}` (must match the sender).\n */\nfunction decryptMessage(\n msg: HistoryMessage,\n ctsPrivateKey: Uint8Array,\n myKeyId: string,\n keyMap: KdcKeyMap,\n apigwKeys: ApigwKeys,\n): DecryptedPayload {\n const encKey = msg.key;\n if (encKey.key_id !== myKeyId) {\n throw new Error(`key not for us (key_id=${encKey.key_id}, myKeyId=${myKeyId})`);\n }\n\n const keyRaw = Uint8Array.from(Buffer.from(encKey.key, \"base64\"));\n const nonce = keyRaw.slice(0, nacl.box.nonceLength);\n const ciphertext = keyRaw.slice(nacl.box.nonceLength);\n\n const senderPubKey = getSenderPublicKey(msg, keyMap, apigwKeys);\n if (!senderPubKey) throw new Error(\"cannot determine sender public key\");\n\n const symmetricKey = nacl.box.open(ciphertext, nonce, senderPubKey, ctsPrivateKey);\n if (!symmetricKey) throw new Error(\"nacl.box.open failed — wrong key pair\");\n\n const payloadRaw = Uint8Array.from(Buffer.from(msg.payload, \"base64\"));\n const msgNonce = payloadRaw.slice(0, sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);\n const msgCiphertext = payloadRaw.slice(sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);\n\n const aad = new Uint8Array(Buffer.from(`${msg.group_chat_id}:${msg.sync_id}`));\n const plaintext = sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(null, msgCiphertext, aad, msgNonce, symmetricKey);\n\n return JSON.parse(new TextDecoder().decode(plaintext)) as DecryptedPayload;\n}\n\n/** Shape of the decrypted wire payload (text or image message). */\ninterface DecryptedPayload {\n type?: string;\n body?: string;\n payload?: {\n file_name?: string;\n file_mime_type?: string;\n blur_preview_file?: string;\n file_preview_width?: number;\n file_preview_height?: number;\n };\n}\n\nfunction toDecrypted(msg: HistoryMessage, payload: DecryptedPayload): DecryptedMessage {\n const base = { sync_id: msg.sync_id, sender: msg.sender ?? \"\", inserted_at: msg.inserted_at, decrypted: true, type: payload.type };\n if (payload.type === \"image\" && payload.payload) {\n const p = payload.payload;\n return {\n ...base,\n body: payload.body ?? \"\",\n image: {\n fileName: p.file_name ?? \"image\",\n mimeType: p.file_mime_type,\n previewDataUri: p.blur_preview_file,\n width: p.file_preview_width,\n height: p.file_preview_height,\n },\n };\n }\n return { ...base, body: payload.body ?? \"\" };\n}\n\nexport function getSenderPublicKey(\n msg: HistoryMessage,\n keyMap: KdcKeyMap,\n apigwKeys: ApigwKeys,\n): Uint8Array | null {\n const senderKeyId = msg.sender_key_id;\n if (!senderKeyId) return null;\n\n if (senderKeyId === apigwKeys.ctsKey?.keyId) return apigwKeys.ctsKey.publicKey;\n if (senderKeyId === apigwKeys.encryptionKey?.keyId) return apigwKeys.encryptionKey.publicKey;\n\n const kdcKey = keyMap.get(senderKeyId);\n if (kdcKey) return new Uint8Array(Buffer.from(kdcKey.body, \"base64\"));\n return null;\n}\n\n/**\n * Fetch the sender public keys from KDC and decrypt a batch of message events.\n * Shared by `messages list` and the live session layer.\n */\nexport async function decryptMessages(\n events: HistoryMessage[],\n apigwKeys: ApigwKeys,\n client: ApiClient = new ApiClient(),\n): Promise<DecryptedMessage[]> {\n await sodium.ready;\n const ctsKey = apigwKeys.ctsKey ?? apigwKeys.encryptionKey;\n const messages = events.filter((e) => e.event_type === \"message_new\" && e.payload && e.key);\n if (messages.length === 0) return [];\n\n const keyIds = [...new Set([\n ...messages.map((m) => m.sender_key_id).filter(Boolean),\n ...messages.map((m) => m.key.key_id),\n ])];\n const kdcKeys = await client.get<Array<{ id: string; body: string; user_huid: string }>>(\n `/api/v1/kdc/keys/?ids=${keyIds.join(\",\")}`,\n ) ?? [];\n const keyMap: KdcKeyMap = new Map(kdcKeys.map((k) => [k.id, k]));\n\n return messages.map((msg) => {\n try {\n return toDecrypted(msg, decryptMessage(msg, ctsKey.privateKey, ctsKey.keyId, keyMap, apigwKeys));\n } catch (err) {\n return { sync_id: msg.sync_id, body: \"\", sender: msg.sender ?? \"\", inserted_at: msg.inserted_at, decrypted: false, error: (err as Error).message };\n }\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { ExpressSession, type SessionMessage, type SessionActivity } from \"../session/session.js\";\nimport type { ExpressChat } from \"../types/index.js\";\n\nexport function createListenCommand(): Command {\n const cmd = new Command(\"listen\");\n\n cmd\n .description(\"Open a persistent session and stream incoming messages/notifications\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"--activity\", \"Also print raw activity events (before decryption)\", false)\n .action(async (opts: { host?: string; activity?: boolean }) => {\n let session: ExpressSession;\n try {\n session = new ExpressSession();\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n\n const names = new Map<string, string>();\n const label = (chatId: string) => names.get(chatId) ?? chatId.slice(0, 8);\n const ts = (iso: string) => (iso ? new Date(iso).toLocaleTimeString(\"ru-RU\") : new Date().toLocaleTimeString(\"ru-RU\"));\n\n session.on(\"connected\", () => console.log(chalk.green(\"● connected\")));\n\n session.on(\"chats\", (chats: ExpressChat[]) => {\n for (const c of chats) {\n const id = (c as { group_chat_id?: string; id?: string }).group_chat_id ?? (c as { id?: string }).id;\n const name = (c as { name?: string }).name;\n if (id) names.set(id, name || id.slice(0, 8));\n }\n console.log(chalk.dim(` ${chats.length} chats loaded, subscribing to activity…`));\n });\n\n if (opts.activity) {\n session.on(\"activity\", (a: SessionActivity) => {\n console.log(chalk.dim(` · activity in ${label(a.chatId)} (${a.syncId.slice(0, 8)})`));\n });\n }\n\n session.on(\"message\", (m: SessionMessage) => {\n const who = m.sender.slice(0, 8);\n if (m.decrypted) {\n console.log(`${chalk.dim(`[${ts(m.insertedAt)}]`)} ${chalk.cyan(label(m.chatId))} ${chalk.yellow(who)}: ${m.body}`);\n } else {\n console.log(`${chalk.dim(`[${ts(m.insertedAt)}]`)} ${chalk.cyan(label(m.chatId))} ${chalk.yellow(who)}: ${chalk.red(`[decrypt failed: ${m.error}]`)}`);\n }\n });\n\n session.on(\"reconnecting\", ({ attempt, delayMs }: { attempt: number; delayMs: number }) => {\n console.log(chalk.yellow(`○ reconnecting (attempt ${attempt}) in ${Math.round(delayMs / 1000)}s…`));\n });\n session.on(\"disconnected\", ({ code }: { code: number }) => console.log(chalk.yellow(`○ disconnected (code=${code})`)));\n session.on(\"error\", (err: Error) => console.error(chalk.red(`! ${err.message}`)));\n\n const shutdown = () => { console.log(chalk.dim(\"\\nclosing…\")); session.close(); process.exit(0); };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n try {\n await session.connect();\n console.log(chalk.dim(\"Listening. Press Ctrl+C to stop.\"));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n session.close();\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { EventEmitter } from \"node:events\";\nimport { randomUUID } from \"node:crypto\";\nimport { loadApigwKeys, type ApigwKeys } from \"../auth/keys.js\";\nimport { getAuthToken } from \"../config/store.js\";\nimport { loadConfig, getBaseUrl, getWebOrigin } from \"../config/index.js\";\nimport { refreshToken } from \"../auth/token-refresh.js\";\nimport { decryptMessages, type HistoryMessage, type ImageAttachment } from \"../api/decrypt.js\";\nimport type { ExpressChat } from \"../types/index.js\";\n\nexport interface SessionMessage {\n chatId: string;\n syncId: string;\n sender: string;\n body: string;\n decrypted: boolean;\n error?: string;\n insertedAt: string;\n type?: string;\n image?: ImageAttachment;\n}\n\nexport interface SessionActivity {\n chatId: string;\n syncId: string;\n sender: string;\n senderKeyId: string;\n}\n\n/** A discussion/thread — a chat-like entity keyed by thread_id under a parent chat. */\nexport interface ThreadSummary {\n thread_id: string;\n group_chat_id: string;\n counter?: number;\n last_event_inserted_at?: string | null;\n}\n\ninterface PhxFrame {\n ref: number | string | null;\n topic: string;\n event: string;\n payload: Record<string, unknown> & { status?: string; response?: Record<string, unknown> };\n}\n\ninterface Pending {\n resolve: (response: Record<string, unknown>) => void;\n reject: (err: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\nconst HEARTBEAT_MS = 25_000;\nconst REQUEST_TIMEOUT_MS = 15_000;\nconst MAX_RECONNECT_DELAY_MS = 30_000;\n\n/**\n * Persistent, stateful eXpress connection. One WebSocket stays open: it holds the\n * chat list, subscribes to every chat's activities, decrypts incoming messages\n * (live pushes carry no key, so we pull `events_history` which returns it), and\n * re-connects with backoff + token refresh. Reused by the TUI and MCP layers.\n *\n * Events: `connected`, `chats` (ExpressChat[]), `activity` (SessionActivity),\n * `message` (SessionMessage), `disconnected` ({code}), `reconnecting`\n * ({attempt, delayMs}), `error` (Error).\n */\nexport class ExpressSession extends EventEmitter {\n private ws: WebSocket | null = null;\n private ref = 0;\n private pending = new Map<number, Pending>();\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private chats: ExpressChat[] = [];\n private threads: ThreadSummary[] = [];\n private subscribed = new Set<string>();\n private closing = false;\n private connecting = false;\n private reconnectAttempt = 0;\n private readonly host: string;\n private readonly webOrigin: string;\n private readonly keyId: string;\n private readonly apigwKeys: ApigwKeys;\n\n constructor() {\n super();\n const config = loadConfig();\n this.host = new URL(getBaseUrl(config)).hostname;\n this.webOrigin = getWebOrigin(config);\n const keys = loadApigwKeys();\n if (!keys) throw new Error(\"No apigw keys. Run 'express auth qr' first.\");\n this.apigwKeys = keys;\n this.keyId = (keys.ctsKey ?? keys.encryptionKey).keyId;\n }\n\n getChats(): ExpressChat[] {\n return this.chats;\n }\n\n getThreads(): ThreadSummary[] {\n return this.threads;\n }\n\n /** Initial connect (awaited by the caller). Reconnection afterwards is driven\n * solely by `handleClose` → `scheduleReconnect`. */\n async connect(): Promise<void> {\n this.closing = false;\n await this.openSocket();\n }\n\n private async openSocket(): Promise<void> {\n if (this.closing) return;\n // Never run two sockets at once — overlapping connections with the same\n // key_id make the server kill each other (observed as a 1006 storm).\n if (this.connecting || (this.ws && this.ws.readyState === this.ws.OPEN)) return;\n this.connecting = true;\n\n const token = getAuthToken();\n if (!token) { this.connecting = false; throw new Error(\"Not authenticated. Run 'express auth qr'.\"); }\n\n const url = `wss://${this.host}/socket/user/websocket?vsn=1.0.0&auto_join=true&key_id=${this.keyId}`\n + `&version=6&background=false&voex_unencrypted=true&voex_multistream=true&voex_audio_bridge=true&instance_id=${randomUUID()}`;\n const ws = new WebSocket(url, {\n headers: { Origin: this.webOrigin, \"User-Agent\": \"Mozilla/5.0\" },\n } as ConstructorParameters<typeof WebSocket>[1]);\n this.ws = ws;\n\n // Only the currently-active socket's events matter; ignore stale ones.\n ws.addEventListener(\"message\", (e) => { if (this.ws === ws) this.onMessage(e.data as string); });\n ws.addEventListener(\"close\", () => this.handleClose(ws));\n ws.addEventListener(\"error\", () => { /* a close event always follows; reconnect is handled there */ });\n\n try {\n await new Promise<void>((resolve, reject) => {\n const openTimer = setTimeout(() => { try { ws.close(); } catch { /* ignore */ } reject(new Error(\"WebSocket open timeout\")); }, REQUEST_TIMEOUT_MS);\n ws.addEventListener(\"open\", () => {\n clearTimeout(openTimer);\n this.request(\"phoenix\", \"authenticate\", { token }).then(() => resolve()).catch(reject);\n });\n ws.addEventListener(\"close\", () => { clearTimeout(openTimer); reject(new Error(\"closed during connect\")); });\n });\n } catch (err) {\n if (this.ws === ws) { this.connecting = false; try { ws.close(); } catch { /* ignore */ } }\n throw err; // handleClose (fired by the close event) drives the reconnect\n }\n\n if (this.ws !== ws) return; // a newer socket superseded us — abandon this one\n this.connecting = false;\n this.reconnectAttempt = 0;\n this.startHeartbeat();\n this.emit(\"connected\");\n await this.loadChats(ws);\n }\n\n close(): void {\n this.closing = true;\n this.connecting = false;\n if (this.reconnectTimer) { clearTimeout(this.reconnectTimer); this.reconnectTimer = null; }\n this.stopHeartbeat();\n const ws = this.ws;\n this.ws = null;\n try { ws?.close(); } catch { /* ignore */ }\n }\n\n /** chat_type values that accept `subscribe_to_chat_activities` (others like\n * \"global\"/\"voex_call\" reply \"unmatched topic\"). */\n private static readonly SUBSCRIBABLE = new Set([\"chat\", \"group_chat\", \"channel\", \"notes\"]);\n\n /** Load the chat list and subscribe to each real chat's live activities.\n * Bails if the socket changes/closes mid-way (avoids error spam on teardown). */\n private async loadChats(ws: WebSocket): Promise<void> {\n const response = await this.request(\"system\", \"chat_list\", { since: null, request_version: 6 });\n const chats = (response.chat_list ?? []) as ExpressChat[];\n this.chats = Array.isArray(chats) ? chats : [];\n this.emit(\"chats\", this.chats);\n\n const ids = this.chats\n .filter((c) => !c.chat_type || ExpressSession.SUBSCRIBABLE.has(c.chat_type))\n .map((c) => c.group_chat_id)\n .filter((id): id is string => Boolean(id));\n\n await Promise.allSettled(ids.map((id) => this.subscribe(id, ws)));\n\n // Discussions (threads) — chat-like entities read via events_history by thread_id.\n // Thread messages carry group_chat_id = thread_id, so subscribing routes their\n // live pushes through the same message pipeline (chatId === thread_id).\n try {\n const tl = await this.request(\"system\", \"thread_list\", { group_chat_id: null, limit: 200, request_version: 2 });\n this.threads = (tl.thread_list ?? []) as ThreadSummary[];\n this.emit(\"threads\", this.threads);\n const threadIds = this.threads.map((t) => t.thread_id).filter(Boolean);\n await Promise.allSettled(threadIds.map((id) => this.subscribe(id, ws)));\n } catch { /* threads are optional; ignore on failure */ }\n }\n\n private async subscribe(chatId: string, ws: WebSocket): Promise<void> {\n if (this.subscribed.has(chatId) || this.ws !== ws) return;\n try {\n await this.request(`groupchat:${chatId}`, \"subscribe_to_chat_activities\", { group_chat_id: chatId });\n this.subscribed.add(chatId);\n } catch {\n // Transient (socket closing / server hiccup) — next reconnect re-subscribes. Stay quiet.\n }\n }\n\n private onMessage(data: string): void {\n let frame: PhxFrame;\n try { frame = JSON.parse(data) as PhxFrame; } catch { return; }\n\n const ref = frame.ref == null ? null : (typeof frame.ref === \"string\" ? parseInt(frame.ref, 10) : frame.ref);\n\n // Reply to one of our requests\n if (ref != null && this.pending.has(ref) && frame.event === \"phx_reply\") {\n const p = this.pending.get(ref)!;\n this.pending.delete(ref);\n clearTimeout(p.timer);\n if (frame.payload?.status === \"ok\") p.resolve(frame.payload.response ?? {});\n else p.reject(new Error(`${frame.event} failed: ${JSON.stringify(frame.payload?.response)}`));\n return;\n }\n\n // Live push: a new message in a subscribed chat (carries no decryption key)\n if (ref == null && frame.event === \"message_new\") {\n const p = frame.payload as Record<string, unknown>;\n const chatId = (p.group_chat_id as string) ?? frame.topic.replace(\"groupchat:\", \"\");\n const activity: SessionActivity = {\n chatId,\n syncId: (p.sync_id as string) ?? \"\",\n sender: (p.sender as string) ?? \"\",\n senderKeyId: (p.sender_key_id as string) ?? \"\",\n };\n this.emit(\"activity\", activity);\n void this.resolveMessage(activity);\n }\n }\n\n /** Pushes have `key: null`; pull recent history (which includes our key) and decrypt. */\n private async resolveMessage(activity: SessionActivity): Promise<void> {\n try {\n const response = await this.request(`groupchat:${activity.chatId}`, \"events_history\", {\n direction: \"backward\",\n group_chat_id: activity.chatId,\n limit: 5,\n skip_non_affecting_rc: true,\n skip_to_sync_id_event: true,\n last_ignore_messages_at: null,\n });\n const history = (response.history ?? []) as HistoryMessage[];\n const decrypted = await decryptMessages(history, this.apigwKeys);\n const match = decrypted.find((m) => m.sync_id === activity.syncId) ?? decrypted[0];\n if (!match) return;\n const msg: SessionMessage = {\n chatId: activity.chatId,\n syncId: match.sync_id,\n sender: match.sender,\n body: match.body,\n decrypted: match.decrypted,\n error: match.error,\n insertedAt: match.inserted_at,\n type: match.type,\n image: match.image,\n };\n this.emit(\"message\", msg);\n } catch (err) {\n this.emit(\"error\", new Error(`decrypt push failed: ${(err as Error).message}`));\n }\n }\n\n private request(topic: string, event: string, payload: Record<string, unknown>): Promise<Record<string, unknown>> {\n const ws = this.ws;\n if (!ws || ws.readyState !== ws.OPEN) return Promise.reject(new Error(\"WebSocket not open\"));\n const ref = this.ref++;\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pending.delete(ref);\n reject(new Error(`request timeout: ${event}`));\n }, REQUEST_TIMEOUT_MS);\n this.pending.set(ref, { resolve, reject, timer });\n ws.send(JSON.stringify({ topic, event, payload, ref }));\n });\n }\n\n private startHeartbeat(): void {\n this.stopHeartbeat();\n this.heartbeatTimer = setInterval(() => {\n const ws = this.ws;\n if (ws && ws.readyState === ws.OPEN) {\n ws.send(JSON.stringify({ topic: \"phoenix\", event: \"heartbeat\", payload: {}, ref: this.ref++ }));\n }\n }, HEARTBEAT_MS);\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) { clearInterval(this.heartbeatTimer); this.heartbeatTimer = null; }\n }\n\n /** Sole reconnect trigger. Ignores events from stale sockets. */\n private handleClose(ws: WebSocket): void {\n if (this.ws !== ws) return; // stale socket from a previous connection\n this.ws = null;\n this.connecting = false;\n this.stopHeartbeat();\n for (const [, p] of this.pending) { clearTimeout(p.timer); p.reject(new Error(\"WebSocket closed\")); }\n this.pending.clear();\n this.subscribed.clear();\n this.emit(\"disconnected\", { code: 1006 });\n if (!this.closing) this.scheduleReconnect();\n }\n\n private scheduleReconnect(): void {\n if (this.closing || this.reconnectTimer) return; // single pending timer\n this.reconnectAttempt += 1;\n const delayMs = Math.min(1000 * 2 ** (this.reconnectAttempt - 1), MAX_RECONNECT_DELAY_MS);\n this.emit(\"reconnecting\", { attempt: this.reconnectAttempt, delayMs });\n this.reconnectTimer = setTimeout(async () => {\n this.reconnectTimer = null;\n if (this.closing) return;\n await refreshToken().catch(() => false); // best-effort; keep a valid token across reconnects\n // Failure closes the socket → handleClose reschedules; don't schedule here (avoids storms).\n this.openSocket().catch(() => { /* handled via handleClose */ });\n }, delayMs);\n }\n}\n","import { Command } from \"commander\";\nimport { runTui } from \"../tui/index.js\";\n\nexport function createTuiCommand(): Command {\n const cmd = new Command(\"tui\");\n\n cmd\n .description(\"Interactive terminal UI: chat list + live message thread\")\n .option(\"--host <host>\", \"eXpress host\")\n .action(async () => {\n try {\n await runTui();\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { render } from \"ink\";\nimport { App } from \"./app.js\";\n\nexport async function runTui(): Promise<void> {\n const { waitUntilExit } = render(<App />);\n await waitUntilExit();\n}\n","import { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Box, Text, useApp, useInput, useStdin, useStdout } from \"ink\";\nimport TextInput from \"ink-text-input\";\nimport { ExpressSession, type SessionMessage, type ThreadSummary } from \"../session/session.js\";\nimport { readMessages } from \"../api/messages-read.js\";\nimport { sendMessageViaWebSocket } from \"../api/messaging-ws.js\";\nimport { UserApi } from \"../api/user.js\";\nimport { ApiClient } from \"../api/client.js\";\nimport { renderImage } from \"./image.js\";\nimport type { ImageAttachment } from \"../api/decrypt.js\";\nimport type { ExpressChat } from \"../types/index.js\";\n\ninterface DisplayMsg {\n syncId: string;\n sender: string;\n body: string;\n decrypted: boolean;\n error?: string;\n insertedAt: string;\n type?: string;\n image?: ImageAttachment;\n}\n\ntype Focus = \"chats\" | \"thread\" | \"input\" | \"discussions\";\n\nconst LIST_TYPES = new Set([\"chat\", \"group_chat\", \"channel\", \"notes\"]);\nconst shortHuid = (h: string) => (h ? h.slice(0, 8) : \"unknown\");\nconst clock = (iso: string) => {\n const d = iso ? new Date(iso) : new Date();\n return Number.isNaN(d.getTime()) ? \"--:--\" : d.toLocaleTimeString(\"ru-RU\", { hour: \"2-digit\", minute: \"2-digit\" });\n};\n\nconst MENTION_RE = /@\\{mention:([0-9a-fA-F-]{36})\\}/g;\ntype Seg = { mention?: string; text?: string };\nfunction parseBody(body: string): Seg[] {\n const out: Seg[] = [];\n let last = 0;\n let m: RegExpExecArray | null;\n MENTION_RE.lastIndex = 0;\n while ((m = MENTION_RE.exec(body))) {\n if (m.index > last) out.push({ text: body.slice(last, m.index) });\n out.push({ mention: m[1] });\n last = m.index + m[0].length;\n }\n if (last < body.length) out.push({ text: body.slice(last) });\n return out.length ? out : [{ text: body }];\n}\n\nconst toDisplay = (m: { sync_id: string; sender: string; body: string; decrypted: boolean; error?: string; inserted_at: string; type?: string; image?: ImageAttachment }): DisplayMsg =>\n ({ syncId: m.sync_id, sender: m.sender, body: m.body, decrypted: m.decrypted, error: m.error, insertedAt: m.inserted_at, type: m.type, image: m.image });\n\nexport function App() {\n const { exit } = useApp();\n const { stdout } = useStdout();\n const { isRawModeSupported } = useStdin();\n const rows = stdout?.rows ?? 24;\n const cols = stdout?.columns ?? 80;\n\n const sessionRef = useRef<ExpressSession | null>(null);\n const [chats, setChats] = useState<ExpressChat[]>([]);\n const [threads, setThreads] = useState<ThreadSummary[]>([]);\n const [selected, setSelected] = useState(0);\n const [messages, setMessages] = useState<Record<string, DisplayMsg[]>>({});\n const [status, setStatus] = useState<{ text: string; color: string }>({ text: \"connecting…\", color: \"yellow\" });\n const [focus, setFocus] = useState<Focus>(\"chats\");\n const [draft, setDraft] = useState(\"\");\n const [selfHuid, setSelfHuid] = useState(\"\");\n const [names, setNames] = useState<Record<string, string>>({});\n const [unread, setUnread] = useState<Record<string, number>>({});\n const [msgCursor, setMsgCursor] = useState(0);\n const [discussionsOpen, setDiscussionsOpen] = useState(false);\n const [threadCursor, setThreadCursor] = useState(0);\n const [openThreadId, setOpenThreadId] = useState<string | null>(null);\n const [threadTitles, setThreadTitles] = useState<Record<string, string>>({});\n const [renderedImages, setRenderedImages] = useState<Record<string, string>>({});\n const requested = useRef<Set<string>>(new Set());\n const titleRequested = useRef<Set<string>>(new Set());\n const imgRequested = useRef<Set<string>>(new Set());\n const currentIdRef = useRef<string | undefined>(undefined);\n\n const visibleChats = useMemo(\n () =>\n chats\n .filter((c) => LIST_TYPES.has(c.chat_type) && !c.left)\n .sort((a, b) => (b.last_event_inserted_at ?? \"\").localeCompare(a.last_event_inserted_at ?? \"\")),\n [chats],\n );\n\n const current = visibleChats[selected];\n const currentId = current?.group_chat_id;\n currentIdRef.current = currentId;\n\n const threadsForChat = useMemo(\n () => threads.filter((t) => t.group_chat_id === currentId).sort((a, b) => (b.last_event_inserted_at ?? \"\").localeCompare(a.last_event_inserted_at ?? \"\")),\n [threads, currentId],\n );\n const activeMessages = openThreadId ? messages[openThreadId] : (currentId ? messages[currentId] : undefined);\n\n const resolveHuids = (huids: string[]) => {\n const need = [...new Set(huids)].filter((h) => h && h.length >= 30 && !requested.current.has(h));\n if (need.length === 0) return;\n need.forEach((h) => requested.current.add(h));\n new UserApi(new ApiClient()).getProfilesByHuid(need)\n .then((profiles) => setNames((prev) => {\n const next = { ...prev };\n for (const p of profiles) if (p.name) next[p.user_huid] = p.name;\n return next;\n }))\n .catch(() => need.forEach((h) => requested.current.delete(h)));\n };\n\n const displayChatName = (c: ExpressChat): string => {\n if (c.chat_type === \"chat\" && c.member_huids && selfHuid) {\n const other = c.member_huids.find((h) => h !== selfHuid);\n if (other && names[other]) return names[other];\n }\n return c.name?.trim() || c.group_chat_id.slice(0, 8);\n };\n\n const senderLabel = (huid: string): string =>\n huid === selfHuid || huid === \"me\" ? \"you\" : names[huid] || shortHuid(huid);\n\n // A thread's title = its root (oldest) message\n const fetchThreadTitle = (threadId: string) => {\n if (threadTitles[threadId] || titleRequested.current.has(threadId)) return;\n titleRequested.current.add(threadId);\n readMessages({ chatId: threadId, limit: 1, direction: \"forward\" })\n .then((h) => {\n const root = h.find((m) => m.decrypted && m.body);\n if (root) setThreadTitles((p) => ({ ...p, [threadId]: root.body.replace(/\\s+/g, \" \").trim() }));\n })\n .catch(() => titleRequested.current.delete(threadId));\n };\n const threadTitle = (threadId: string) => threadTitles[threadId];\n\n // Session lifecycle\n useEffect(() => {\n let session: ExpressSession;\n try {\n session = new ExpressSession();\n } catch (err) {\n setStatus({ text: (err as Error).message, color: \"red\" });\n return;\n }\n sessionRef.current = session;\n\n session.on(\"connected\", () => setStatus({ text: \"connected\", color: \"green\" }));\n session.on(\"chats\", (list: ExpressChat[]) => setChats(list));\n session.on(\"threads\", (list: ThreadSummary[]) => setThreads(list));\n session.on(\"message\", (m: SessionMessage) => {\n setMessages((prev) => {\n const list = prev[m.chatId] ?? [];\n if (list.some((x) => x.syncId === m.syncId)) return prev;\n const next: DisplayMsg = { syncId: m.syncId, sender: m.sender, body: m.body, decrypted: m.decrypted, error: m.error, insertedAt: m.insertedAt, type: m.type, image: m.image };\n return { ...prev, [m.chatId]: [...list, next].slice(-200) };\n });\n if (m.chatId !== currentIdRef.current) setUnread((u) => ({ ...u, [m.chatId]: (u[m.chatId] ?? 0) + 1 }));\n });\n session.on(\"reconnecting\", ({ attempt }: { attempt: number }) => setStatus({ text: `reconnecting (#${attempt})…`, color: \"yellow\" }));\n session.on(\"disconnected\", () => setStatus({ text: \"disconnected\", color: \"yellow\" }));\n session.on(\"error\", () => { /* status reflects it on disconnect */ });\n\n session.connect().catch((err) => setStatus({ text: (err as Error).message, color: \"red\" }));\n new UserApi(new ApiClient()).getSelfProfile().then((p) => setSelfHuid(p.user_huid)).catch(() => {});\n return () => session.close();\n }, []);\n\n const send = async (text: string) => {\n const body = text.trim();\n setDraft(\"\");\n const target = openThreadId ?? currentId;\n if (!body || !target) return;\n const localId = `local-${Date.now()}`;\n const optimistic: DisplayMsg = { syncId: localId, sender: selfHuid || \"me\", body, decrypted: true, insertedAt: new Date().toISOString() };\n setMessages((prev) => ({ ...prev, [target]: [...(prev[target] ?? []), optimistic].slice(-200) }));\n try {\n await sendMessageViaWebSocket({ client: new ApiClient(), chatId: target, body });\n } catch (err) {\n setMessages((prev) => ({\n ...prev,\n [target]: (prev[target] ?? []).map((m) => (m.syncId === localId ? { ...m, decrypted: false, error: (err as Error).message } : m)),\n }));\n }\n };\n\n // Load history for a chat / thread when first opened (threads read the same way)\n const loadHistory = (id: string) => {\n if (messages[id]) return;\n readMessages({ chatId: id, limit: 40 })\n .then((h) => setMessages((prev) => (prev[id] ? prev : { ...prev, [id]: h.map(toDisplay) })))\n .catch(() => setMessages((prev) => (prev[id] ? prev : { ...prev, [id]: [] })));\n };\n useEffect(() => { if (currentId) loadHistory(currentId); }, [currentId]);\n useEffect(() => { if (openThreadId) { loadHistory(openThreadId); fetchThreadTitle(openThreadId); setMsgCursor((messages[openThreadId]?.length ?? 1) - 1); } }, [openThreadId]);\n\n // Resolve DM partner names\n useEffect(() => {\n if (!selfHuid) return;\n resolveHuids(visibleChats.filter((c) => c.chat_type === \"chat\").flatMap((c) => (c.member_huids ?? []).filter((h) => h !== selfHuid)));\n }, [chats, selfHuid]);\n\n // Resolve sender + mention names for the active message view\n useEffect(() => {\n if (!activeMessages) return;\n resolveHuids(activeMessages.flatMap((m) => [m.sender, ...parseBody(m.body).filter((s) => s.mention).map((s) => s.mention!)]));\n }, [activeMessages]);\n\n // Reset per-chat view state on chat change\n useEffect(() => {\n setDiscussionsOpen(false);\n setOpenThreadId(null);\n if (currentId) setUnread((u) => (u[currentId] ? { ...u, [currentId]: 0 } : u));\n }, [currentId]);\n\n // Fetch thread titles (root messages) when the discussions panel is open\n useEffect(() => {\n if (!discussionsOpen) return;\n threadsForChat.forEach((t) => fetchThreadTitle(t.thread_id));\n }, [discussionsOpen, threadsForChat]);\n\n // Render the inline preview of the currently-selected image message\n useEffect(() => {\n const m = focus === \"thread\" ? activeMessages?.[msgCursor] : undefined;\n const uri = m?.image?.previewDataUri;\n if (!m || !uri || renderedImages[m.syncId] || imgRequested.current.has(m.syncId)) return;\n imgRequested.current.add(m.syncId);\n const w = Math.min(40, Math.max(10, cols - 36));\n renderImage(uri, w)\n .then((s) => setRenderedImages((p) => ({ ...p, [m.syncId]: s })))\n .catch(() => imgRequested.current.delete(m.syncId));\n }, [focus, msgCursor, activeMessages]);\n\n useInput((input, key) => {\n if (focus === \"input\") { if (key.escape) setFocus(openThreadId ? \"thread\" : \"chats\"); return; }\n if (input === \"q\" || (key.ctrl && input === \"c\")) { sessionRef.current?.close(); exit(); return; }\n\n // Toggle discussions panel for the current chat\n if (input === \"t\" && currentId && !openThreadId) {\n if (discussionsOpen) { setDiscussionsOpen(false); setFocus(\"chats\"); }\n else { setDiscussionsOpen(true); setThreadCursor(0); setFocus(\"discussions\"); }\n return;\n }\n\n if (focus === \"chats\") {\n if (key.upArrow || input === \"k\") setSelected((i) => Math.max(0, i - 1));\n else if (key.downArrow || input === \"j\") setSelected((i) => Math.min(visibleChats.length - 1, i + 1));\n else if ((key.rightArrow || key.tab) && currentId) { setMsgCursor((activeMessages?.length ?? 1) - 1); setFocus(\"thread\"); }\n else if (key.return && currentId) setFocus(\"input\");\n } else if (focus === \"discussions\") {\n if (key.upArrow || input === \"k\") setThreadCursor((c) => Math.max(0, c - 1));\n else if (key.downArrow || input === \"j\") setThreadCursor((c) => Math.min(threadsForChat.length - 1, c + 1));\n else if (key.return && threadsForChat[threadCursor]) { setOpenThreadId(threadsForChat[threadCursor].thread_id); setFocus(\"thread\"); }\n else if (key.leftArrow || key.escape) { setDiscussionsOpen(false); setFocus(\"chats\"); }\n } else if (focus === \"thread\") {\n const len = activeMessages?.length ?? 0;\n if (key.upArrow || input === \"k\") setMsgCursor((c) => Math.max(0, c - 1));\n else if (key.downArrow || input === \"j\") setMsgCursor((c) => Math.min(len - 1, c + 1));\n else if (key.leftArrow || key.escape) {\n if (openThreadId) { setOpenThreadId(null); setFocus(\"discussions\"); }\n else setFocus(\"chats\");\n }\n else if (key.return) setFocus(\"input\");\n }\n }, { isActive: isRawModeSupported });\n\n // --- Layout / viewport ---\n const bodyHeight = Math.max(4, rows - 4);\n const rightWidth = Math.max(20, cols - 34);\n const listWindow = windowAround(selected, visibleChats.length, bodyHeight);\n const showDiscussions = discussionsOpen && !openThreadId;\n\n const estLines = (m: DisplayMsg): number => {\n let n = 9 + senderLabel(m.sender).length + 2;\n for (const seg of parseBody(m.body)) n += seg.mention ? 1 + (names[seg.mention]?.length ?? 8) : (seg.text?.length ?? 0);\n return Math.max(1, Math.ceil(n / rightWidth));\n };\n let threadStart = activeMessages ? activeMessages.length : 0;\n if (activeMessages) {\n let used = 0;\n while (threadStart > 0 && used < bodyHeight) { used += estLines(activeMessages[threadStart - 1]); threadStart--; }\n if (focus === \"thread\" && msgCursor < threadStart) threadStart = msgCursor;\n }\n const threadView = activeMessages ? activeMessages.slice(threadStart) : undefined;\n\n const renderBody = (m: DisplayMsg) =>\n parseBody(m.body).map((seg, i) =>\n seg.mention\n ? <Text key={i} color=\"magenta\">@{names[seg.mention] || shortHuid(seg.mention)}</Text>\n : <Text key={i}>{seg.text}</Text>,\n );\n\n const rightBorder = focus === \"input\" ? \"green\" : (focus === \"thread\" || focus === \"discussions\") ? \"cyan\" : \"gray\";\n const rightTitle = openThreadId\n ? `💬 ${threadTitle(openThreadId) ?? \"Обсуждение\"}`\n : (current ? displayChatName(current) : \"—\") + (threadsForChat.length ? ` 💬 ${threadsForChat.length}` : \"\");\n\n return (\n <Box flexDirection=\"column\" height={rows}>\n <Box>\n <Text> </Text>\n <Text color={status.color}>●</Text>\n <Text> eXpress TUI — </Text>\n <Text color={status.color}>{status.text}</Text>\n <Text dimColor> ({visibleChats.length} chats)</Text>\n </Box>\n\n <Box flexGrow={1}>\n <Box flexDirection=\"column\" width={32} borderStyle=\"single\" borderColor={focus === \"chats\" ? \"cyan\" : \"gray\"} paddingX={1}>\n {visibleChats.length === 0 && <Text dimColor>loading…</Text>}\n {visibleChats.slice(listWindow.start, listWindow.end).map((c, i) => {\n const idx = listWindow.start + i;\n const active = idx === selected;\n const n = unread[c.group_chat_id] ?? 0;\n return (\n <Text key={c.group_chat_id} color={active ? \"black\" : n > 0 ? \"cyan\" : undefined} backgroundColor={active ? \"cyan\" : undefined} bold={n > 0 && !active} wrap=\"truncate\">\n {active ? \"› \" : \" \"}{displayChatName(c)}{n > 0 ? ` (${n})` : \"\"}\n </Text>\n );\n })}\n </Box>\n\n <Box flexDirection=\"column\" flexGrow={1} borderStyle=\"single\" borderColor={rightBorder} paddingX={1}>\n <Text bold wrap=\"truncate\">{rightTitle}</Text>\n <Box flexDirection=\"column\" flexGrow={1}>\n {showDiscussions ? (\n <>\n {threadsForChat.length === 0 && <Text dimColor>no discussions</Text>}\n {threadsForChat.map((t, i) => {\n const on = focus === \"discussions\" && i === threadCursor;\n const title = threadTitle(t.thread_id) ?? t.thread_id.slice(0, 8);\n return (\n <Text key={t.thread_id} color={on ? \"black\" : undefined} backgroundColor={on ? \"cyan\" : undefined} wrap=\"truncate\">\n {on ? \"› \" : \" \"}💬 {title} <Text dimColor={!on}>· {t.counter ?? 0} · {clock(t.last_event_inserted_at ?? \"\")}</Text>\n </Text>\n );\n })}\n </>\n ) : (\n <>\n {!current && <Text dimColor>select a chat</Text>}\n {current && !threadView && <Text dimColor>loading messages…</Text>}\n {threadView && threadView.length === 0 && <Text dimColor>no messages</Text>}\n {threadView?.map((m, i) => {\n const idx = threadStart + i;\n const mine = m.sender === selfHuid || m.sender === \"me\";\n const onCursor = focus === \"thread\" && idx === msgCursor;\n const img = renderedImages[m.syncId];\n return (\n <Box key={m.syncId} flexDirection=\"column\">\n <Text wrap=\"wrap\">\n <Text color={onCursor ? \"cyan\" : undefined}>{onCursor ? \"▍\" : \" \"}</Text>\n <Text dimColor>[{clock(m.insertedAt)}] </Text>\n <Text color={mine ? \"green\" : \"yellow\"}>{senderLabel(m.sender)}</Text>\n <Text>: </Text>\n {!m.decrypted\n ? <Text color=\"red\">[{m.error ? \"send failed\" : \"decrypt failed\"}]</Text>\n : m.image\n ? <Text color=\"cyan\">🖼 {m.image.fileName}{m.body ? ` — ${m.body}` : \"\"}</Text>\n : renderBody(m)}\n </Text>\n {onCursor && m.image?.previewDataUri && (img ? <Text>{img}</Text> : <Text dimColor> rendering preview…</Text>)}\n </Box>\n );\n })}\n </>\n )}\n </Box>\n {current && !showDiscussions && (\n <Box>\n <Text color={focus === \"input\" ? \"green\" : \"gray\"}>{focus === \"input\" ? \"› \" : \" \"}</Text>\n <TextInput value={draft} onChange={setDraft} onSubmit={send} focus={focus === \"input\"} placeholder={focus === \"input\" ? \"type a message…\" : \"Enter to write\"} />\n </Box>\n )}\n </Box>\n </Box>\n\n <Box>\n <Text dimColor> {footerHint(focus, openThreadId != null)}</Text>\n </Box>\n </Box>\n );\n}\n\nfunction footerHint(focus: Focus, inThread: boolean): string {\n if (focus === \"input\") return \"Enter send · Esc cancel\";\n if (focus === \"discussions\") return \"↑/↓ discussions · Enter open · Esc back\";\n if (focus === \"thread\") return `↑/↓ messages · ← ${inThread ? \"discussions\" : \"chats\"} · Enter write · q quit`;\n return \"↑/↓ chats · → open thread · t discussions · Enter write · q quit\";\n}\n\n/** Scrolling window that keeps `selected` visible within `size` rows. */\nfunction windowAround(selected: number, total: number, size: number): { start: number; end: number } {\n if (total <= size) return { start: 0, end: total };\n let start = selected - Math.floor(size / 2);\n start = Math.max(0, Math.min(start, total - size));\n return { start, end: start + size };\n}\n","import terminalImage from \"terminal-image\";\n\n/**\n * Render a base64 image (raw or `data:*;base64,` URI) as Ink-compatible ANSI\n * half-block art. `preferNativeRender: false` forces the block fallback (colored\n * Unicode half-blocks) instead of iTerm2/Kitty escapes, which break Ink layout.\n */\nexport async function renderImage(data: string, cols: number, rows?: number): Promise<string> {\n const b64 = data.includes(\",\") ? data.slice(data.indexOf(\",\") + 1) : data;\n const buf = Buffer.from(b64, \"base64\");\n const out = await terminalImage.buffer(buf, {\n width: Math.max(4, cols),\n ...(rows ? { height: rows } : {}),\n preserveAspectRatio: true,\n preferNativeRender: false,\n });\n return out.replace(/\\n$/, \"\");\n}\n","import { Command } from \"commander\";\nimport { runMcpServer } from \"../mcp/server.js\";\n\nexport function createMcpCommand(): Command {\n const cmd = new Command(\"mcp\");\n\n cmd\n .description(\"Run as an MCP server (stdio): exposes chats/messages/contacts tools to MCP hosts\")\n .action(async () => {\n try {\n await runMcpServer();\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { ApiClient } from \"../api/client.js\";\nimport { PhonebookApi } from \"../api/phonebook.js\";\nimport { UserApi } from \"../api/user.js\";\nimport { readMessages } from \"../api/messages-read.js\";\nimport { sendMessageViaWebSocket } from \"../api/messaging-ws.js\";\nimport { resolveChatId, listChatsWithNames } from \"../api/resolve.js\";\nimport { getAuthToken, getTokenExpiresAt } from \"../config/store.js\";\nimport { ExpressSession, type SessionMessage } from \"../session/session.js\";\nimport type { ExpressChat } from \"../types/index.js\";\n\nconst ok = (data: unknown) => ({\n content: [{ type: \"text\" as const, text: typeof data === \"string\" ? data : JSON.stringify(data, null, 2) }],\n});\n\ninterface Incoming { seq: number; chatId: string; sender: string; body: string; time: string; decrypted: boolean; image?: string }\n\n/** Buffers incoming messages so `wait_for_messages` can hand an agent everything\n * new since its last call, blocking up to a timeout when nothing is pending. */\nclass Inbox {\n private buf: Incoming[] = [];\n private seq = 0;\n private cursor = 0;\n private waiters: Array<() => void> = [];\n\n add(m: SessionMessage): void {\n this.buf.push({ seq: ++this.seq, chatId: m.chatId, sender: m.sender, body: m.body, time: m.insertedAt, decrypted: m.decrypted, image: m.image?.fileName });\n if (this.buf.length > 500) this.buf.splice(0, this.buf.length - 500);\n const woken = this.waiters; this.waiters = []; woken.forEach((fn) => fn());\n }\n\n private pending(): Incoming[] { return this.buf.filter((x) => x.seq > this.cursor); }\n\n /** Return (and consume) messages arrived since the last take, waiting up to timeoutMs. */\n async take(timeoutMs: number): Promise<Incoming[]> {\n if (this.pending().length === 0) {\n await new Promise<void>((resolve) => {\n const fn = () => { clearTimeout(t); resolve(); };\n const t = setTimeout(() => { this.waiters = this.waiters.filter((w) => w !== fn); resolve(); }, timeoutMs);\n this.waiters.push(fn);\n });\n }\n const items = this.pending();\n if (this.buf.length) this.cursor = this.buf[this.buf.length - 1].seq;\n return items;\n }\n}\n\n/**\n * MCP server (stdio) exposing eXpress chat over the existing api layer. Reuses the\n * same E2E send/read code as the CLI, so nothing is duplicated. stdout carries only\n * the MCP protocol (the request/refresh path is free of stdout logging).\n */\nexport async function runMcpServer(): Promise<void> {\n const server = new McpServer({ name: \"express-cli\", version: \"0.1.0\" });\n\n // Persistent session that buffers incoming messages for wait_for_messages.\n const inbox = new Inbox();\n const chatNames = new Map<string, string>();\n const senderNames = new Map<string, string>();\n let sessionReady = false;\n let session: ExpressSession | null = null;\n try {\n session = new ExpressSession();\n session.on(\"connected\", () => { sessionReady = true; });\n session.on(\"chats\", (list: ExpressChat[]) => { for (const c of list) chatNames.set(c.group_chat_id, c.name?.trim() || c.group_chat_id.slice(0, 8)); });\n session.on(\"message\", (m: SessionMessage) => inbox.add(m));\n session.connect().catch((err) => { process.stderr.write(`[mcp] session connect failed: ${(err as Error).message}\\n`); });\n // Resolve DM names in the background for nicer chat labels\n listChatsWithNames(new ApiClient()).then((chats) => { for (const c of chats) chatNames.set(c.group_chat_id, c.name ?? c.group_chat_id.slice(0, 8)); }).catch(() => {});\n } catch (err) {\n process.stderr.write(`[mcp] session unavailable: ${(err as Error).message}\\n`);\n }\n\n const enrich = async (items: Incoming[]) => {\n const unknown = [...new Set(items.map((i) => i.sender))].filter((h) => h && h.length >= 30 && !senderNames.has(h));\n if (unknown.length) {\n try {\n const profiles = await new UserApi(new ApiClient()).getProfilesByHuid(unknown);\n for (const p of profiles) if (p.name) senderNames.set(p.user_huid, p.name);\n } catch { /* names are best-effort */ }\n }\n return items.map((i) => ({\n time: i.time,\n chat: chatNames.get(i.chatId) ?? i.chatId.slice(0, 8),\n chat_id: i.chatId,\n sender: senderNames.get(i.sender) ?? i.sender.slice(0, 8),\n message: i.decrypted ? (i.image ? `🖼 ${i.image}` : i.body) : \"[decrypt failed]\",\n }));\n };\n\n server.registerTool(\"chats_list\", {\n title: \"List chats\",\n description: \"List chats (DMs, groups, channels) with names and full chat IDs. DM names are resolved to the person's full name.\",\n inputSchema: { type: z.enum([\"all\", \"dm\", \"group\", \"channel\"]).optional().describe(\"Filter by chat type (default all)\") },\n }, async ({ type }) => {\n const chats = await listChatsWithNames(new ApiClient());\n const kind: Record<string, string> = { dm: \"chat\", group: \"group_chat\", channel: \"channel\" };\n const filtered = !type || type === \"all\" ? chats : chats.filter((c) => c.chat_type === kind[type]);\n return ok(filtered.map((c) => ({ name: c.name, chat_id: c.group_chat_id, type: c.chat_type, members: c.members_count })));\n });\n\n server.registerTool(\"chats_find\", {\n title: \"Find a chat by name\",\n description: \"Find chats whose name (person or group) contains the query. Returns name + full chat_id to use with other tools.\",\n inputSchema: { query: z.string().describe(\"Part of the chat or person name\") },\n }, async ({ query }) => {\n const chats = await listChatsWithNames(new ApiClient());\n const q = query.toLowerCase();\n return ok(chats.filter((c) => (c.name ?? \"\").toLowerCase().includes(q)).map((c) => ({ name: c.name, chat_id: c.group_chat_id, type: c.chat_type })));\n });\n\n server.registerTool(\"messages_list\", {\n title: \"Read messages\",\n description: \"Read and decrypt recent messages from a chat, identified by name or chat_id.\",\n inputSchema: {\n chat: z.string().describe(\"Chat name (partial ok) or full chat_id\"),\n limit: z.number().int().min(1).max(200).optional().describe(\"How many recent messages (default 20)\"),\n },\n }, async ({ chat, limit }) => {\n const client = new ApiClient();\n const chatId = await resolveChatId(client, chat);\n const msgs = await readMessages({ chatId, limit: limit ?? 20 });\n return ok(msgs.map((m) => ({\n time: m.inserted_at,\n sender: m.sender,\n body: m.decrypted ? (m.image ? `🖼 ${m.image.fileName}${m.body ? ` — ${m.body}` : \"\"}` : m.body) : `[decrypt failed: ${m.error}]`,\n })));\n });\n\n server.registerTool(\"send_message\", {\n title: \"Send a message\",\n description: \"Send a text message to a chat, identified by name (partial ok) or chat_id. Returns the sync_id.\",\n inputSchema: { chat: z.string().describe(\"Chat name or full chat_id\"), text: z.string().describe(\"Message text\") },\n }, async ({ chat, text }) => {\n const client = new ApiClient();\n const chatId = await resolveChatId(client, chat);\n const res = await sendMessageViaWebSocket({ client, chatId, body: text });\n return ok({ sent: true, chat_id: chatId, sync_id: res.sync_id });\n });\n\n server.registerTool(\"contacts_search\", {\n title: \"Search employees\",\n description: \"Global company phonebook search across all employees by name.\",\n inputSchema: { query: z.string().describe(\"Name to search\"), limit: z.number().int().min(1).max(50).optional() },\n }, async ({ query, limit }) => {\n const profiles = await new PhonebookApi(new ApiClient()).searchUsers(query, limit ?? 20);\n return ok(profiles.map((p) => ({ name: p.name, huid: p.user_huid, email: p.email, position: p.company_position, department: p.department })));\n });\n\n server.registerTool(\"contacts_self\", {\n title: \"My profile\",\n description: \"Get the authenticated user's own profile.\",\n inputSchema: {},\n }, async () => ok(await new UserApi(new ApiClient()).getSelfProfile()));\n\n server.registerTool(\"wait_for_messages\", {\n title: \"Wait for incoming messages\",\n description: \"Block until new incoming messages arrive (from any chat/discussion), then return them. Returns messages received since the previous call to this tool; if none are pending, waits up to timeout_seconds. Your own sent messages are not included. Use this to react to new messages instead of polling.\",\n inputSchema: { timeout_seconds: z.number().int().min(1).max(120).optional().describe(\"Max seconds to wait when nothing is pending (default 30)\") },\n }, async ({ timeout_seconds }) => {\n if (!session) return ok({ error: \"Session unavailable — run 'express auth qr' to authenticate.\" });\n const items = await inbox.take((timeout_seconds ?? 30) * 1000);\n return ok({ connected: sessionReady, count: items.length, messages: await enrich(items) });\n });\n\n server.registerTool(\"status\", {\n title: \"Auth status\",\n description: \"Check authentication and access-token status.\",\n inputSchema: {},\n }, async () => {\n const exp = getTokenExpiresAt();\n return ok({\n authenticated: !!getAuthToken(),\n token_expires_in_seconds: exp ? Math.max(0, Math.floor((exp - Date.now()) / 1000)) : null,\n });\n });\n\n await server.connect(new StdioServerTransport());\n}\n","import { createRootCommand } from \"./cli/root.js\";\n\nconst program = createRootCommand();\nprogram.parse();\n"],"mappings":"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","names":["Command","nacl","randomUUID","randomBytes","nacl","extractResult","fetchCurrentAccountCtsKey","refreshToken","Command","text","Command","Command","Command","Command","Command","Command","chalk","randomUUID","entries","Command","chalk","Command","Command","Command","Table","chalk","Command","Command","randomBytes","randomUUID","nacl","randomUUID","randomBytes","nacl","ciphertext","Command","Command","Command","Command","writeFileSync","Command","Command","randomUUID","nacl","sodium","nacl","sodium","randomUUID","Command","Command","chalk","randomUUID","randomUUID","Command","chalk","Command","status","jsx","Command","Command","z","z","Command","program","Command"]}
1
+ {"version":3,"sources":["../src/cli/root.ts","../src/cli/auth.ts","../src/types/config.ts","../src/config/store.ts","../src/config/loader.ts","../src/auth/import.ts","../src/auth/keys.ts","../src/auth/apigw-signer.ts","../src/auth/device-login.ts","../src/auth/qr-login.ts","../src/auth/token-refresh.ts","../src/cli/api.ts","../src/api/client.ts","../src/cli/output.ts","../src/cli/config-cmd.ts","../src/cli/status.ts","../src/api/user.ts","../src/cli/contacts.ts","../src/api/websocket.ts","../src/api/chats.ts","../src/api/phonebook.ts","../src/cli/settings.ts","../src/api/settings.ts","../src/cli/chats.ts","../src/cli/send.ts","../src/api/messaging.ts","../src/api/messaging-ws.ts","../src/api/resolve.ts","../src/cli/avatar.ts","../src/api/uploads.ts","../src/cli/download.ts","../src/cli/messages.ts","../src/api/messages-read.ts","../src/api/decrypt.ts","../src/cli/listen.ts","../src/session/session.ts","../src/cli/tui.ts","../src/tui/index.tsx","../src/tui/app.tsx","../src/tui/image.ts","../src/cli/mcp.ts","../src/mcp/server.ts","../src/index.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { createAuthCommand } from \"./auth.js\";\nimport { createApiCommand } from \"./api.js\";\nimport { createConfigCommand } from \"./config-cmd.js\";\nimport { createStatusCommand } from \"./status.js\";\nimport { createContactsCommand } from \"./contacts.js\";\nimport { createSettingsCommand } from \"./settings.js\";\nimport { createChatsCommand } from \"./chats.js\";\nimport { createSendCommand } from \"./send.js\";\nimport { createAvatarCommand } from \"./avatar.js\";\nimport { createDownloadCommand } from \"./download.js\";\nimport { createMessagesCommand } from \"./messages.js\";\nimport { createListenCommand } from \"./listen.js\";\nimport { createTuiCommand } from \"./tui.js\";\nimport { createMcpCommand } from \"./mcp.js\";\n\nexport function createRootCommand(): Command {\n const program = new Command();\n\n program\n .name(\"express-cli\")\n .description(\"CLI client for eXpress Chat\")\n .version(\"0.1.2\");\n\n program.addCommand(createAuthCommand());\n program.addCommand(createApiCommand());\n program.addCommand(createConfigCommand());\n program.addCommand(createStatusCommand());\n program.addCommand(createContactsCommand());\n program.addCommand(createSettingsCommand());\n program.addCommand(createChatsCommand());\n program.addCommand(createSendCommand());\n program.addCommand(createAvatarCommand());\n program.addCommand(createDownloadCommand());\n program.addCommand(createMessagesCommand());\n program.addCommand(createListenCommand());\n program.addCommand(createTuiCommand());\n program.addCommand(createMcpCommand());\n\n return program;\n}\n","import { Command } from \"commander\";\nimport { importToken, logout, status, deviceLogin, qrLogin, loadApigwKeys, clearApigwKeys, importCtsKey } from \"../auth/index.js\";\nimport { getTokenExpiresAt, getRefreshToken, isTokenExpiringSoon } from \"../config/store.js\";\nimport { refreshToken } from \"../auth/token-refresh.js\";\n\nexport function createAuthCommand(): Command {\n const cmd = new Command(\"auth\");\n\n cmd.description(\"Authentication management\");\n\n cmd\n .command(\"import <token>\")\n .description(\"Import Bearer token from browser\")\n .option(\"--host <host>\", \"eXpress host\")\n .action(async (token: string, opts: { host?: string }) => {\n try {\n await importToken(token, opts.host ? { host: opts.host } : {});\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"login\")\n .description(\"Full device login (ed25519 signing for apigw endpoints)\")\n .option(\"--host <host>\", \"eXpress host\")\n .action(async (opts: { host?: string }) => {\n try {\n await deviceLogin(opts.host ? { host: opts.host } : {});\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"qr\")\n .description(\"QR-code login (scan with eXpress mobile app)\")\n .option(\"--host <host>\", \"eXpress host\")\n .action(async (opts: { host?: string }) => {\n try {\n await qrLogin(opts.host ? { host: opts.host } : {});\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"import-cts <private_key_b64> <key_id>\")\n .description(\"Import the account's shared CTS (E2E) key so the CLI decrypts like your phone/desktop. Get both values from the web client's IndexedDB (authState → encryptionKeys → user.privateKeys.cts: body + publicKeyId).\")\n .action((privateKeyB64: string, keyId: string) => {\n try {\n const ctsKey = importCtsKey(privateKeyB64, keyId);\n const pub = Buffer.from(ctsKey.publicKey).toString(\"base64\");\n console.log(`CTS key imported: ${keyId}`);\n console.log(` derived public key: ${pub}`);\n console.log(\" Verify this matches the KDC 'body' for this key_id. Do NOT run 'auth login/qr' with a different device now — it would re-register a new key and break sync.\");\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"logout\")\n .description(\"Remove stored authentication token and apigw keys\")\n .action(() => {\n clearApigwKeys();\n logout();\n });\n\n cmd\n .command(\"status\")\n .description(\"Show current authentication status\")\n .action(() => {\n status();\n const expiresAt = getTokenExpiresAt();\n const hasRefresh = !!getRefreshToken();\n if (expiresAt) {\n const remaining = Math.max(0, Math.floor((expiresAt - Date.now()) / 1000));\n const expired = remaining === 0;\n console.log(`Token: ${expired ? \"EXPIRED\" : `expires in ${remaining}s (~${(remaining / 60).toFixed(0)} min)`}`);\n console.log(`Refresh: ${hasRefresh ? \"available\" : \"not available\"}`);\n } else {\n console.log(\"Token: expiry unknown\");\n console.log(`Refresh: ${hasRefresh ? \"available\" : \"not available\"}`);\n }\n const keys = loadApigwKeys();\n if (keys) {\n console.log(`Apigw: enabled (signing: ${keys.signingKey.keyId.slice(0, 8)}..., encryption: ${keys.encryptionKey.keyId.slice(0, 8)}..., server: ${keys.serverPublicKeyId.slice(0, 8)}...)`);\n } else {\n console.log(\"Apigw: not configured. Run 'express auth login' or 'express auth qr' to enable.\");\n }\n });\n\n cmd\n .command(\"refresh\")\n .description(\"Refresh access token using refresh token\")\n .action(async () => {\n try {\n const refreshed = await refreshToken();\n if (refreshed) {\n const expiresAt = getTokenExpiresAt();\n const remaining = expiresAt ? Math.max(0, Math.floor((expiresAt - Date.now()) / 1000)) : 0;\n console.log(`Token refreshed successfully (expires in ${remaining}s)`);\n } else {\n console.error(\"Failed to refresh token. Re-authenticate with `express auth qr`.\");\n process.exit(1);\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { z } from \"zod\";\n\nexport const configSchema = z.object({\n host: z.string().min(1, \"host is required — set EXPRESS_HOST or configure via `express config set host <host>`\"),\n protocol: z.enum([\"https\", \"http\"]).default(\"https\"),\n token: z.string().optional(),\n locale: z.string().default(\"ru\"),\n platform: z.string().default(\"web\"),\n platform_package_id: z.string().default(\"ru.alfabank\"),\n app_version: z.string().default(\"3.66.47\"),\n output: z.enum([\"table\", \"json\"]).default(\"table\"),\n});\n\nexport type Config = z.infer<typeof configSchema>;\n\nexport const envSchema = z.object({\n EXPRESS_HOST: z.string().optional(),\n EXPRESS_TOKEN: z.string().optional(),\n EXPRESS_LOCALE: z.string().optional(),\n EXPRESS_OUTPUT: z.enum([\"table\", \"json\"]).optional(),\n});\n\nexport type EnvConfig = z.infer<typeof envSchema>;\n","import Conf from \"conf\";\nimport type { Config } from \"../types/index.js\";\n\ninterface StoredApigwKeys {\n signingKey: { keyId: string; privateKey: string; publicKey: string };\n rtsKeyId?: string;\n encryptionKeyId?: string;\n encryptionToken?: string;\n}\n\ninterface StoreSchema {\n config: Partial<Config>;\n authToken: string | null;\n refreshToken: string | null;\n rtsAuthToken: string | null;\n apigwKeys: string | null;\n tokenExpiresAt: number | null;\n etsAuthToken: string | null;\n}\n\nconst store = new Conf<StoreSchema>({\n projectName: \"express-cli\",\n defaults: {\n config: {},\n authToken: null,\n refreshToken: null,\n rtsAuthToken: null,\n apigwKeys: null,\n tokenExpiresAt: null,\n etsAuthToken: null,\n },\n});\n\nexport function getStoredConfig(): Partial<Config> {\n return store.get(\"config\") ?? {};\n}\n\nexport function setStoredConfig(partial: Partial<Config>): void {\n const current = getStoredConfig();\n store.set(\"config\", { ...current, ...partial });\n}\n\nexport function getAuthToken(): string | null {\n return store.get(\"authToken\") ?? null;\n}\n\nexport function setAuthToken(token: string | null): void {\n if (token === null) {\n store.delete(\"authToken\");\n } else {\n store.set(\"authToken\", token);\n }\n}\n\nexport function getRtsAuthToken(): string | null {\n return store.get(\"rtsAuthToken\") ?? null;\n}\n\nexport function setRtsAuthToken(token: string | null): void {\n if (token === null) {\n store.delete(\"rtsAuthToken\");\n } else {\n store.set(\"rtsAuthToken\", token);\n }\n}\n\nexport function getRefreshToken(): string | null {\n return store.get(\"refreshToken\") ?? null;\n}\n\nexport function setRefreshToken(token: string | null): void {\n if (token === null) {\n store.delete(\"refreshToken\");\n } else {\n store.set(\"refreshToken\", token);\n }\n}\n\nexport function getTokenExpiresAt(): number | null {\n return store.get(\"tokenExpiresAt\") ?? null;\n}\n\nexport function setTokenExpiresAt(expiresAt: number | null): void {\n if (expiresAt === null) {\n store.delete(\"tokenExpiresAt\");\n } else {\n store.set(\"tokenExpiresAt\", expiresAt);\n }\n}\n\nexport function calcTokenExpiresAt(expiresIn: number): number {\n return Date.now() + Math.floor(expiresIn / 2) * 1000;\n}\n\nexport function isTokenExpiringSoon(): boolean {\n const expiresAt = getTokenExpiresAt();\n if (!expiresAt) return true;\n return Date.now() >= expiresAt;\n}\n\nexport function getEtsAuthToken(): string | null {\n return store.get(\"etsAuthToken\") ?? null;\n}\n\nexport function setEtsAuthToken(token: string | null): void {\n if (token === null) {\n store.delete(\"etsAuthToken\");\n } else {\n store.set(\"etsAuthToken\", token);\n }\n}\n\nexport function getApigwKeysRaw(): string | null {\n return store.get(\"apigwKeys\") ?? null;\n}\n\nexport function setApigwKeysRaw(data: string | null): void {\n if (data === null) {\n store.delete(\"apigwKeys\");\n } else {\n store.set(\"apigwKeys\", data);\n }\n}\n\nexport function clearAll(): void {\n store.clear();\n}\n\nexport { store };\n","import { configSchema, type Config } from \"../types/index.js\";\nimport { getStoredConfig, getAuthToken } from \"./store.js\";\n\nexport function loadConfig(cliOverrides: Partial<Config> = {}): Config {\n const stored = getStoredConfig();\n const env: Partial<Config> = {};\n\n if (process.env.EXPRESS_HOST) env.host = process.env.EXPRESS_HOST;\n if (process.env.EXPRESS_TOKEN) env.token = process.env.EXPRESS_TOKEN;\n if (process.env.EXPRESS_LOCALE) env.locale = process.env.EXPRESS_LOCALE;\n if (process.env.EXPRESS_OUTPUT) env.output = process.env.EXPRESS_OUTPUT as \"table\" | \"json\";\n\n const merged = {\n ...stored,\n ...env,\n ...cliOverrides,\n };\n\n if (!merged.token) {\n const storedToken = getAuthToken();\n if (storedToken) merged.token = storedToken;\n }\n\n return configSchema.parse(merged);\n}\n\nexport function getBaseUrl(config: Config): string {\n return `${config.protocol}://${config.host}`;\n}\n\nfunction getDomain(ctsHost: string): string {\n const parts = ctsHost.split('.');\n return parts.length > 2 ? parts.slice(1).join('.') : ctsHost;\n}\n\nexport function getEtsBaseUrl(config: Config): string {\n return `https://ets.${getDomain(config.host)}`;\n}\n\nexport function getWebOrigin(config: Config): string {\n return `https://${getDomain(config.host)}`;\n}\n","import { setAuthToken, setStoredConfig, getAuthToken } from \"../config/index.js\";\nimport { getBaseUrl, loadConfig } from \"../config/loader.js\";\nimport type { Config } from \"../types/index.js\";\n\nexport async function importToken(token: string, cliOverrides: Partial<Config> = {}): Promise<void> {\n const config = loadConfig(cliOverrides);\n const baseUrl = getBaseUrl(config);\n\n const url = `${baseUrl}/api/v1/phonebook/profiles/self`;\n const res = await fetch(url, {\n headers: {\n Authorization: `Bearer ${token}`,\n Accept: \"application/json\",\n },\n });\n\n if (!res.ok) {\n throw new Error(`Token validation failed: ${res.status} ${res.statusText}`);\n }\n\n const body = await res.json() as { result?: { profile?: { name?: string; user_huid?: string } }; profile?: { name?: string; user_huid?: string } };\n setAuthToken(token);\n\n const profile = body.profile ?? body.result?.profile;\n if (profile?.name) {\n console.log(`Authenticated as: ${profile.name} (${profile.user_huid ?? \"unknown huid\"})`);\n } else {\n console.log(\"Token imported and validated successfully.\");\n }\n}\n\nexport function logout(): void {\n setAuthToken(null);\n console.log(\"Logged out. Token removed.\");\n}\n\nexport function status(): void {\n const token = getAuthToken();\n if (!token) {\n console.log(\"Not authenticated. Use `express auth import <token>` to login.\");\n return;\n }\n console.log(`Authenticated. Token: ${token.slice(0, 20)}...`);\n}\n","import { ed25519 } from \"@noble/curves/ed25519.js\";\nimport { randomBytes } from \"node:crypto\";\nimport { getApigwKeysRaw, setApigwKeysRaw } from \"../config/store.js\";\nimport nacl from \"tweetnacl\";\n\nexport interface SigningKeyPair {\n keyId: string;\n privateKey: Uint8Array;\n publicKey: Uint8Array;\n}\n\nexport interface EncryptionKeyPair {\n keyId: string;\n privateKey: Uint8Array;\n publicKey: Uint8Array;\n}\n\nexport interface ApigwKeys {\n signingKey: SigningKeyPair;\n encryptionKey: EncryptionKeyPair;\n ctsKey?: EncryptionKeyPair; // separate CTS key for E2E message encryption\n serverPublicKey: Uint8Array;\n serverPublicKeyId: string;\n}\n\nexport function generateSigningKeyPair(): SigningKeyPair {\n const privateKey = ed25519.utils.randomSecretKey();\n const publicKey = ed25519.getPublicKey(privateKey);\n const keyId = crypto.randomUUID();\n return { keyId, privateKey, publicKey };\n}\n\nexport function generateEncryptionKeyPair(): EncryptionKeyPair {\n const keyPair = nacl.box.keyPair();\n const keyId = crypto.randomUUID();\n return {\n keyId,\n privateKey: keyPair.secretKey,\n publicKey: keyPair.publicKey,\n };\n}\n\nexport function saveApigwKeys(keys: ApigwKeys): void {\n const data: Record<string, unknown> = {\n signingKey: {\n keyId: keys.signingKey.keyId,\n privateKey: Buffer.from(keys.signingKey.privateKey).toString(\"base64\"),\n publicKey: Buffer.from(keys.signingKey.publicKey).toString(\"base64\"),\n },\n encryptionKey: {\n keyId: keys.encryptionKey.keyId,\n privateKey: Buffer.from(keys.encryptionKey.privateKey).toString(\"base64\"),\n publicKey: Buffer.from(keys.encryptionKey.publicKey).toString(\"base64\"),\n },\n serverPublicKey: Buffer.from(keys.serverPublicKey).toString(\"base64\"),\n serverPublicKeyId: keys.serverPublicKeyId,\n };\n if (keys.ctsKey) {\n data.ctsKey = {\n keyId: keys.ctsKey.keyId,\n privateKey: Buffer.from(keys.ctsKey.privateKey).toString(\"base64\"),\n publicKey: Buffer.from(keys.ctsKey.publicKey).toString(\"base64\"),\n };\n }\n setApigwKeysRaw(JSON.stringify(data));\n}\n\nexport function loadApigwKeys(): ApigwKeys | null {\n const raw = getApigwKeysRaw();\n if (!raw) return null;\n\n try {\n const data = JSON.parse(raw) as {\n signingKey: { keyId: string; privateKey: string; publicKey: string };\n encryptionKey?: { keyId: string; privateKey: string; publicKey: string };\n ctsKey?: { keyId: string; privateKey: string; publicKey: string };\n serverPublicKey?: string;\n serverPublicKeyId?: string;\n rtsKeyId?: string;\n encryptionKeyId?: string;\n encryptionToken?: string;\n };\n\n if (!data.encryptionKey || !data.serverPublicKey) {\n return null;\n }\n\n return {\n signingKey: {\n keyId: data.signingKey.keyId,\n privateKey: new Uint8Array(Buffer.from(data.signingKey.privateKey, \"base64\")),\n publicKey: new Uint8Array(Buffer.from(data.signingKey.publicKey, \"base64\")),\n },\n encryptionKey: {\n keyId: data.encryptionKey.keyId,\n privateKey: new Uint8Array(Buffer.from(data.encryptionKey.privateKey, \"base64\")),\n publicKey: new Uint8Array(Buffer.from(data.encryptionKey.publicKey, \"base64\")),\n },\n ctsKey: data.ctsKey ? {\n keyId: data.ctsKey.keyId,\n privateKey: new Uint8Array(Buffer.from(data.ctsKey.privateKey, \"base64\")),\n publicKey: new Uint8Array(Buffer.from(data.ctsKey.publicKey, \"base64\")),\n } : undefined,\n serverPublicKey: new Uint8Array(Buffer.from(data.serverPublicKey, \"base64\")),\n serverPublicKeyId: data.serverPublicKeyId ?? data.rtsKeyId ?? data.encryptionKeyId ?? \"\",\n };\n } catch {\n return null;\n }\n}\n\nexport function getOrCreateApigwKeys(): ApigwKeys {\n const existing = loadApigwKeys();\n if (existing) return existing;\n\n const keys: ApigwKeys = {\n signingKey: generateSigningKeyPair(),\n encryptionKey: generateEncryptionKeyPair(),\n serverPublicKey: new Uint8Array(0),\n serverPublicKeyId: \"\",\n };\n saveApigwKeys(keys);\n return keys;\n}\n\nexport function signEd25519(privateKey: Uint8Array, message: Uint8Array): Uint8Array {\n return ed25519.sign(message, privateKey);\n}\n\nexport function encryptToken(token: string, serverPublicKey: Uint8Array, rtsPrivateKey: Uint8Array): string {\n const message = new TextEncoder().encode(token);\n const nonce = randomBytes(nacl.box.nonceLength);\n const encrypted = nacl.box(message, nonce, serverPublicKey, rtsPrivateKey);\n if (!encrypted) {\n throw new Error(\"crypto_box encryption failed\");\n }\n const combined = new Uint8Array(nonce.length + encrypted.length);\n combined.set(nonce, 0);\n combined.set(encrypted, nonce.length);\n return Buffer.from(combined).toString(\"base64\");\n}\n\nexport function generateNonce(): string {\n return Buffer.from(randomBytes(32)).toString(\"base64\");\n}\n\nexport function publicKeyToBase64(publicKey: Uint8Array): string {\n return Buffer.from(publicKey).toString(\"base64\");\n}\n\nexport function clearApigwKeys(): void {\n setApigwKeysRaw(null);\n}\n\n/**\n * Import an existing CTS (E2E) keypair so the CLI shares the account's key with\n * the official devices instead of minting its own. Public key is derived from\n * the private key; keyId must be the KDC-published id (e.g. from the web client).\n */\nexport function importCtsKey(privateKeyB64: string, keyId: string): EncryptionKeyPair {\n const existing = loadApigwKeys();\n if (!existing) {\n throw new Error(\"No apigw keys yet. Run 'express auth login' or 'express auth qr' first.\");\n }\n const privateKey = new Uint8Array(Buffer.from(privateKeyB64, \"base64\"));\n if (privateKey.length !== nacl.box.secretKeyLength) {\n throw new Error(`Invalid private key length: ${privateKey.length} bytes (expected ${nacl.box.secretKeyLength})`);\n }\n const publicKey = nacl.box.keyPair.fromSecretKey(privateKey).publicKey;\n const ctsKey: EncryptionKeyPair = { keyId, privateKey, publicKey };\n saveApigwKeys({ ...existing, ctsKey });\n return ctsKey;\n}\n\nexport function decryptRegistrationData(registrationDataB64: string, encryptionKey: Uint8Array): unknown {\n const raw = Uint8Array.from(Buffer.from(registrationDataB64, \"base64\"));\n const nonce = raw.slice(0, nacl.secretbox.nonceLength);\n const ciphertext = raw.slice(nacl.secretbox.nonceLength);\n const plaintext = nacl.secretbox.open(ciphertext, nonce, encryptionKey);\n if (!plaintext) {\n throw new Error(\"Failed to decrypt registration_data\");\n }\n const json = new TextDecoder().decode(plaintext);\n return JSON.parse(json);\n}\n\nexport function decryptRtsToken(encryptedRtsTokenB64: string, serverPublicKey: Uint8Array, rtsPrivateKey: Uint8Array): string {\n const raw = Uint8Array.from(Buffer.from(encryptedRtsTokenB64, \"base64\"));\n const nonce = raw.slice(0, nacl.box.nonceLength);\n const ciphertext = raw.slice(nacl.box.nonceLength);\n const plaintext = nacl.box.open(ciphertext, nonce, serverPublicKey, rtsPrivateKey);\n if (!plaintext) {\n throw new Error(\"Failed to decrypt encrypted_rts_token\");\n }\n return new TextDecoder().decode(plaintext);\n}\n\nexport function extractRtsKeyIdFromToken(token: string): string {\n const parts = token.split(\".\");\n if (parts.length < 2) return \"\";\n const bytes = Buffer.from(parts[1], \"base64\");\n const text = bytes.toString(\"latin1\");\n const uuidRegex = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/g;\n const uuids: string[] = [];\n let match;\n while ((match = uuidRegex.exec(text)) !== null) {\n uuids.push(match[0]);\n }\n return uuids.length >= 4 ? uuids[3] : \"\";\n}\n","import { signEd25519, generateNonce, loadApigwKeys, encryptToken, saveApigwKeys } from \"./keys.js\";\nimport { sha256 } from \"@noble/hashes/sha2.js\";\n\n\nexport interface ApigwSignedHeaders {\n Authorization: string;\n \"Express-Proxy-Authorization\": string;\n \"Express-Request-Nonce\": string;\n Digest?: string;\n Signature: string;\n \"Content-Type\"?: string;\n}\n\nexport function buildSigningInput(\n method: string,\n path: string,\n created: number,\n nonce: string,\n rtsAccessToken: string,\n digest?: string,\n): { signingString: string; signedHeaders: string } {\n return buildSigningInputInternal(method, path, created, nonce, rtsAccessToken, digest);\n}\n\nexport function buildQrSigningInput(\n method: string,\n path: string,\n created: number,\n nonce: string,\n digest?: string,\n): { signingString: string; signedHeaders: string } {\n return buildSigningInputInternal(method, path, created, nonce, undefined, digest);\n}\n\nfunction buildSigningInputInternal(\n method: string,\n path: string,\n created: number,\n nonce: string,\n rtsAccessToken: string | undefined,\n digest?: string,\n): { signingString: string; signedHeaders: string } {\n const lines: string[] = [];\n const headerNames: string[] = [];\n\n lines.push(`(request-target): ${method.toLowerCase()} ${path}`);\n headerNames.push(\"(request-target)\");\n\n lines.push(`(created): ${created}`);\n headerNames.push(\"(created)\");\n\n if (rtsAccessToken) {\n lines.push(`(rts-access-token): ${rtsAccessToken}`);\n headerNames.push(\"(rts-access-token)\");\n }\n\n lines.push(`express-request-nonce: ${nonce}`);\n headerNames.push(\"express-request-nonce\");\n\n if (digest) {\n lines.push(`digest: SHA-256=${digest}`);\n headerNames.push(\"digest\");\n }\n\n return {\n signingString: lines.join(\"\\n\"),\n signedHeaders: headerNames.join(\" \"),\n };\n}\n\nexport function computeDigest(body: string): string {\n const hash = sha256(new TextEncoder().encode(body));\n return Buffer.from(hash).toString(\"base64\");\n}\n\nexport async function signApigwRequest(params: {\n method: string;\n url: string;\n baseUrl: string;\n body?: string;\n ctsToken: string;\n rtsToken?: string;\n etsAuthToken?: string;\n}): Promise<ApigwSignedHeaders> {\n const keys = loadApigwKeys();\n if (!keys) {\n throw new Error(\"Apigw keys not initialized. Run 'express auth login' first.\");\n }\n\n const urlObj = new URL(params.url.startsWith(\"http\") ? params.url : `${params.baseUrl}${params.url}`);\n const path = urlObj.pathname + urlObj.search;\n const created = Math.floor(Date.now() / 1000);\n const nonce = generateNonce();\n\n let digest: string | undefined;\n if (params.body) {\n digest = computeDigest(params.body);\n }\n\n const tokenForSigning = params.etsAuthToken || params.rtsToken || params.ctsToken;\n const { signingString, signedHeaders } = buildSigningInput(\n params.method,\n path,\n created,\n nonce,\n tokenForSigning,\n digest,\n );\n\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] path: ${path}`);\n console.log(` [DEBUG] signedHeaders: ${signedHeaders}`);\n console.log(` [DEBUG] signingString:\\n${signingString}`);\n console.log(` [DEBUG] signingKey keyId: ${keys.signingKey.keyId}`);\n console.log(` [DEBUG] encryptionKey keyId: ${keys.encryptionKey.keyId}`);\n }\n\n const signature = signEd25519(keys.signingKey.privateKey, new TextEncoder().encode(signingString));\n const signatureBase64 = Buffer.from(signature).toString(\"base64\");\n\n let serverPublicKey = keys.serverPublicKey;\n try {\n const etsBaseUrl = params.baseUrl;\n const kdcStartRes = await fetch(`${etsBaseUrl}/api/v1/kdc/start`, {\n headers: {\n Accept: \"application/json\",\n },\n });\n if (kdcStartRes.ok) {\n const kdcStartData = await kdcStartRes.json() as { result?: string };\n if (kdcStartData.result) {\n serverPublicKey = new Uint8Array(Buffer.from(kdcStartData.result, \"base64\"));\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] ETS server public key (curve25519): ${kdcStartData.result}`);\n }\n keys.serverPublicKey = serverPublicKey;\n keys.serverPublicKeyId = \"kdc-start-ets\";\n saveApigwKeys(keys);\n }\n }\n } catch {\n // Fall back to cached key\n }\n\n const tokenToEncrypt = params.etsAuthToken || params.rtsToken || params.ctsToken;\n const encryptedToken = encryptToken(tokenToEncrypt, serverPublicKey, keys.encryptionKey.privateKey);\n\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] ctsToken length: ${params.ctsToken.length}`);\n console.log(` [DEBUG] rtsToken: ${params.rtsToken ? `present (${params.rtsToken.length} chars)` : \"not set\"}`);\n console.log(` [DEBUG] etsAuthToken: ${params.etsAuthToken ? `present (${params.etsAuthToken.length} chars)` : \"not set\"}`);\n console.log(` [DEBUG] tokenToEncrypt: ${tokenToEncrypt.length} chars (source: ${params.etsAuthToken ? 'etsAuthToken' : params.rtsToken ? 'rtsToken' : 'ctsToken'})`);\n console.log(` [DEBUG] serverPublicKey b64: ${Buffer.from(serverPublicKey).toString(\"base64\")}`);\n console.log(` [DEBUG] encryptionPrivateKey b64: ${Buffer.from(keys.encryptionKey.privateKey).toString(\"base64\")}`);\n console.log(` [DEBUG] encryptionPublicKey b64: ${Buffer.from(keys.encryptionKey.publicKey).toString(\"base64\")}`);\n console.log(` [DEBUG] encryptedToken length: ${encryptedToken.length}`);\n }\n\n return {\n Authorization: `keyId=\"${keys.encryptionKey.keyId}\",token=\"${encryptedToken}\"`,\n \"Express-Proxy-Authorization\": `Bearer ${params.ctsToken}`,\n \"Express-Request-Nonce\": nonce,\n ...(digest && { Digest: `SHA-256=${digest}` }),\n Signature: `keyId=\"${keys.signingKey.keyId}\",algorithm=\"ed25519\",headers=\"${signedHeaders}\",signature=\"${signatureBase64}\",created=${created}`,\n ...(params.body && { \"Content-Type\": \"application/json\" }),\n };\n}\n\nexport interface QrSignedHeaders {\n \"Express-Request-Nonce\": string;\n Digest: string;\n Signature: string;\n \"Content-Type\": string;\n}\n\nexport function signQrRequest(params: {\n method: string;\n url: string;\n body: string;\n registrationId: string;\n privateKey: Uint8Array;\n}): QrSignedHeaders {\n const urlObj = new URL(params.url);\n const path = urlObj.pathname + urlObj.search;\n const created = Math.floor(Date.now() / 1000);\n const nonce = generateNonce();\n const digest = computeDigest(params.body);\n\n const { signingString, signedHeaders } = buildQrSigningInput(\n params.method,\n path,\n created,\n nonce,\n digest,\n );\n\n const signature = signEd25519(params.privateKey, new TextEncoder().encode(signingString));\n const signatureBase64 = Buffer.from(signature).toString(\"base64\");\n\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG QR] path: ${path}`);\n console.log(` [DEBUG QR] signedHeaders: ${signedHeaders}`);\n console.log(` [DEBUG QR] signingString:\\n${signingString}`);\n }\n\n return {\n \"Express-Request-Nonce\": nonce,\n Digest: `SHA-256=${digest}`,\n Signature: `keyId=\"${params.registrationId}\",algorithm=\"ed25519\",headers=\"${signedHeaders}\",signature=\"${signatureBase64}\",created=${created}`,\n \"Content-Type\": \"application/json\",\n };\n}\n","import { generateSigningKeyPair, generateEncryptionKeyPair, loadApigwKeys, saveApigwKeys, clearApigwKeys, publicKeyToBase64, type ApigwKeys, type SigningKeyPair, type EncryptionKeyPair } from \"./keys.js\";\nimport { signApigwRequest } from \"./apigw-signer.js\";\nimport { setAuthToken, getAuthToken, getApigwKeysRaw, setApigwKeysRaw } from \"../config/store.js\";\nimport { loadConfig, getBaseUrl, getEtsBaseUrl, getWebOrigin } from \"../config/loader.js\";\nimport type { Config } from \"../types/index.js\";\nimport nacl from \"tweetnacl\";\nimport { randomUUID } from \"node:crypto\";\n\n/** Returns the account's current cts key_id in KDC, or null if none exists. */\nasync function fetchCurrentAccountCtsKey(baseUrl: string, token: string, userHuid: string, webOrigin: string): Promise<string | null> {\n try {\n const res = await fetch(`${baseUrl}/api/v1/kdc/keys/?user_huids=${userHuid}`, {\n headers: { Accept: \"application/json\", Authorization: `Bearer ${token}`, Origin: webOrigin },\n });\n if (!res.ok) return null;\n const data = await res.json() as { result?: Array<{ id: string; kind: string }> };\n return data.result?.find((k) => k.kind === \"cts\")?.id ?? null;\n } catch {\n return null;\n }\n}\n\ninterface ActivationResponse {\n result?: {\n access_token?: string;\n refresh_token?: string;\n user_huid?: string;\n };\n access_token?: string;\n refresh_token?: string;\n user_huid?: string;\n}\n\ninterface KdcKeysResponse {\n status?: string;\n result?: Array<{\n id: string;\n body: string;\n kind: string;\n user_huid: string;\n }>;\n}\n\nfunction extractResult<T>(data: T & { result?: T }): T {\n return (data.result ?? data) as T;\n}\n\nexport async function deviceLogin(cliOverrides: Partial<Config> = {}): Promise<void> {\n const config = loadConfig(cliOverrides);\n const baseUrl = getBaseUrl(config);\n const etsBaseUrl = getEtsBaseUrl(config);\n const webOrigin = getWebOrigin(config);\n const currentToken = config.token ?? getAuthToken();\n\n if (!currentToken) {\n throw new Error(\"No Bearer token. Run 'express auth import <token>' first, then 'express auth login'.\");\n }\n\n console.log(\"Step 1/5: Registering device with AD integration...\");\n\n const adBody = JSON.stringify({\n app_version: config.app_version,\n device: \"Chrome 149.0\",\n device_software: \"macOS 10.15.7\",\n manufacturer: \"Google\",\n platform: config.platform,\n locale: config.locale,\n platform_package_id: config.platform_package_id,\n device_meta: {\n pushes: false,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n permissions: { notifications: true },\n },\n device_hostname: null,\n });\n\n const adRes = await fetch(`${baseUrl}/api/v1/ad_integration/token`, {\n method: \"PUT\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\n \"Accept-Language\": \"ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7\",\n \"Cache-Control\": \"no-cache\",\n \"Pragma\": \"no-cache\",\n \"sec-ch-ua\": '\"Google Chrome\";v=\"149\", \"Chromium\";v=\"149\", \"Not)A;Brand\";v=\"24\"',\n \"sec-ch-ua-mobile\": \"?0\",\n \"sec-ch-ua-platform\": '\"macOS\"',\n },\n body: adBody,\n });\n\n const adText = await adRes.text();\n\n if (!adRes.ok) {\n throw new Error(`AD integration failed (${adRes.status}): ${adText.slice(0, 500)}`);\n }\n\n console.log(` AD integration: ${adText.slice(0, 200)}`);\n\n console.log(\"Step 2/5: Fetching user profile and server public key...\");\n\n const selfProfileRes = await fetch(`${baseUrl}/api/v1/phonebook/profiles/self`, {\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n },\n });\n let userHuid = \"\";\n let serverId = \"\";\n if (selfProfileRes.ok) {\n const selfData = await selfProfileRes.json() as { profile?: { user_huid?: string; server_id?: string } };\n userHuid = selfData.profile?.user_huid ?? \"\";\n serverId = selfData.profile?.server_id ?? userHuid;\n console.log(` User HUID: ${userHuid || \"unknown\"}`);\n }\n\n let serverPublicKey = new Uint8Array(0);\n let serverPublicKeyId = \"\";\n\n const existingKeys = loadApigwKeys();\n if (existingKeys?.serverPublicKey?.length) {\n serverPublicKey = existingKeys.serverPublicKey;\n serverPublicKeyId = existingKeys.serverPublicKeyId;\n console.log(` Server public key (cached): ${serverPublicKeyId || \"unknown\"}`);\n }\n\n if (!serverPublicKey.length) {\n try {\n const kdcStartRes = await fetch(`${etsBaseUrl}/api/v1/kdc/start`, {\n headers: { Accept: \"application/json\" },\n });\n if (kdcStartRes.ok) {\n const kdcStartData = await kdcStartRes.json() as { result?: string };\n if (kdcStartData.result) {\n serverPublicKey = new Uint8Array(Buffer.from(kdcStartData.result, \"base64\"));\n serverPublicKeyId = \"kdc-start-ets\";\n console.log(` Server public key (from ets): ${serverPublicKeyId}`);\n }\n }\n } catch {}\n }\n\n if (!serverPublicKey.length && serverId) {\n const kdcFetchUrl = `${baseUrl}/api/v1/kdc/keys/?ids=${serverId}`;\n const kdcFetchRes = await fetch(kdcFetchUrl, {\n headers: {\n \"Accept\": \"application/json\",\n \"Authorization\": `Bearer ${currentToken}`,\n },\n });\n\n if (kdcFetchRes.ok) {\n const kdcFetchData = JSON.parse(await kdcFetchRes.text()) as KdcKeysResponse;\n const kdcKeys = kdcFetchData.result ?? kdcFetchData as unknown as Array<{ id: string; body: string; kind: string; user_huid: string }>;\n const serverKey = Array.isArray(kdcKeys)\n ? kdcKeys.find((k) => (k.kind === \"rest\" || k.kind === \"rts\") && k.user_huid === serverId)\n : null;\n if (!serverKey && Array.isArray(kdcKeys) && kdcKeys.length > 0) {\n const first = kdcKeys[0];\n serverPublicKey = new Uint8Array(Buffer.from(first.body, \"base64\"));\n serverPublicKeyId = first.id;\n } else if (serverKey) {\n serverPublicKey = new Uint8Array(Buffer.from(serverKey.body, \"base64\"));\n serverPublicKeyId = serverKey.id;\n }\n console.log(` Server public key (from KDC): ${serverPublicKeyId || \"not found\"}`);\n }\n }\n\n if (!serverPublicKey.length) {\n throw new Error(\"Could not fetch server public key from KDC\");\n }\n\n console.log(\"Step 3/5: Registering keys with KDC...\");\n\n let apigwSigningKey: SigningKeyPair;\n let apigwEncryptionKey: EncryptionKeyPair;\n\n if (existingKeys?.signingKey && existingKeys?.encryptionKey) {\n apigwSigningKey = existingKeys.signingKey;\n apigwEncryptionKey = existingKeys.encryptionKey;\n console.log(` Reusing existing signing key: ${apigwSigningKey.keyId}`);\n console.log(` Reusing existing encryption key: ${apigwEncryptionKey.keyId}`);\n } else {\n apigwSigningKey = generateSigningKeyPair();\n apigwEncryptionKey = generateEncryptionKeyPair();\n\n const apigwKeyPublicBase64 = publicKeyToBase64(apigwSigningKey.publicKey);\n console.log(` Signing key: id=${apigwSigningKey.keyId} pub=${apigwKeyPublicBase64}`);\n\n const kdcUrl = `${baseUrl}/api/v2/kdc/keys/${userHuid}`;\n const kdcBody = JSON.stringify({\n key: apigwKeyPublicBase64,\n kind: \"ed25519\",\n algo: \"ed25519\",\n id: apigwSigningKey.keyId,\n });\n\n const [kdcRes, etsKdcRes] = await Promise.all([\n fetch(kdcUrl, {\n method: \"POST\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Content-Type\": \"application/json\",\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n },\n body: kdcBody,\n }),\n fetch(`${etsBaseUrl}/api/v2/kdc/keys/${userHuid}`, {\n method: \"POST\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Content-Type\": \"application/json\",\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n },\n body: kdcBody,\n }),\n ]);\n\n if (!kdcRes.ok) {\n const kdcErrText = await kdcRes.text().catch(() => \"\");\n console.log(` Warning: CTS KDC signing key registration failed (${kdcRes.status}): ${kdcErrText.slice(0, 200)}`);\n } else {\n console.log(` Signing key registered in CTS: ${apigwSigningKey.keyId}`);\n }\n\n if (!etsKdcRes.ok) {\n const etsErrText = await etsKdcRes.text().catch(() => \"\");\n console.log(` Warning: ETS KDC signing key registration failed (${etsKdcRes.status}): ${etsErrText.slice(0, 200)}`);\n } else {\n console.log(` Signing key registered in ETS: ${apigwSigningKey.keyId}`);\n }\n\n const encryptionKeyPublicBase64 = publicKeyToBase64(apigwEncryptionKey.publicKey);\n\n const kdcEncBody = JSON.stringify({\n key: encryptionKeyPublicBase64,\n kind: \"rts\",\n algo: \"xsalsa20\",\n id: apigwEncryptionKey.keyId,\n });\n\n const kdcEncRes = await fetch(kdcUrl, {\n method: \"POST\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Content-Type\": \"application/json\",\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n },\n body: kdcEncBody,\n });\n\n const etsKdcEncRes = await fetch(`${etsBaseUrl}/api/v2/kdc/keys/${userHuid}`, {\n method: \"POST\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Content-Type\": \"application/json\",\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n },\n body: kdcEncBody,\n });\n\n if (!kdcEncRes.ok) {\n const kdcErrText = await kdcEncRes.text().catch(() => \"\");\n console.log(` Warning: CTS KDC encryption key registration failed (${kdcEncRes.status}): ${kdcErrText.slice(0, 200)}`);\n } else {\n console.log(` Encryption key registered in CTS: ${apigwEncryptionKey.keyId}`);\n }\n\n if (!etsKdcEncRes.ok) {\n const etsErrText = await etsKdcEncRes.text().catch(() => \"\");\n console.log(` Warning: ETS KDC encryption key registration failed (${etsKdcEncRes.status}): ${etsErrText.slice(0, 200)}`);\n } else {\n console.log(` Encryption key registered in ETS: ${apigwEncryptionKey.keyId}`);\n }\n }\n\n let ctsKey: EncryptionKeyPair | undefined = existingKeys?.ctsKey;\n if (!ctsKey) {\n // Guard: never mint a cts key if the account already has one in KDC — the CLI\n // can't upload the private-key backup, so a new key would break other devices.\n const currentCts = await fetchCurrentAccountCtsKey(baseUrl, currentToken, userHuid, webOrigin);\n if (currentCts) {\n throw new Error(\n `Account already has a shared CTS key (${currentCts}) that this CLI doesn't hold.\\n` +\n `Minting a new one would break your other devices. Import the shared key instead:\\n` +\n ` express auth import-cts <private_key_b64> ${currentCts}\\n` +\n `(extract it from a logged-in web client: IndexedDB authState → encryptionKeys → user.privateKeys.cts)`,\n );\n }\n const ctsKeyPair = nacl.box.keyPair();\n const ctsKeyId = crypto.randomUUID();\n ctsKey = {\n keyId: ctsKeyId,\n privateKey: ctsKeyPair.secretKey,\n publicKey: ctsKeyPair.publicKey,\n };\n\n const ctsKeyPubB64 = Buffer.from(ctsKeyPair.publicKey).toString(\"base64\");\n const ctsKeyBody = JSON.stringify({ key: ctsKeyPubB64, kind: \"cts\", algo: \"xsalsa20\", id: ctsKeyId });\n\n const [ctsCtsRes, etsCtsRes] = await Promise.all([\n fetch(`${baseUrl}/api/v2/kdc/keys/${userHuid}`, {\n method: \"POST\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Content-Type\": \"application/json\",\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n },\n body: ctsKeyBody,\n }),\n fetch(`${etsBaseUrl}/api/v2/kdc/keys/${userHuid}`, {\n method: \"POST\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Authorization\": `Bearer ${currentToken}`,\n \"Content-Type\": \"application/json\",\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n },\n body: ctsKeyBody,\n }),\n ]);\n\n if (!ctsCtsRes.ok) {\n const errText = await ctsCtsRes.text().catch(() => \"\");\n console.log(` Warning: CTS encryption key registration failed (${ctsCtsRes.status}): ${errText.slice(0, 200)}`);\n } else {\n console.log(` CTS encryption key registered in CTS: ${ctsKeyId.slice(0, 8)}...`);\n }\n if (!etsCtsRes.ok) {\n const errText = await etsCtsRes.text().catch(() => \"\");\n console.log(` Warning: CTS encryption key registration in ETS failed (${etsCtsRes.status}): ${errText.slice(0, 200)}`);\n } else {\n console.log(` CTS encryption key registered in ETS: ${ctsKeyId.slice(0, 8)}...`);\n }\n }\n\n const apigwKeys: ApigwKeys = {\n signingKey: apigwSigningKey,\n encryptionKey: apigwEncryptionKey,\n serverPublicKey,\n serverPublicKeyId,\n ctsKey,\n };\n const previousKeysRaw = getApigwKeysRaw();\n saveApigwKeys(apigwKeys);\n\n console.log(\"Step 4/5: Activating device...\");\n\n const activationBody = JSON.stringify({\n app_version: config.app_version,\n locale: config.locale,\n device_meta: {\n pushes: false,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n permissions: { notifications: true },\n },\n device_hostname: null,\n });\n\n const activationUrl = `${etsBaseUrl}/api/v1/apigw/api/v1/authentication/activation`;\n const activationHeaders = await signApigwRequest({\n method: \"PUT\",\n url: activationUrl,\n baseUrl: etsBaseUrl,\n body: activationBody,\n ctsToken: currentToken,\n });\n\n const actRes = await fetch(activationUrl, {\n method: \"PUT\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n ...activationHeaders,\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\n \"Accept-Language\": \"ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7\",\n \"Cache-Control\": \"no-cache\",\n \"Pragma\": \"no-cache\",\n \"sec-ch-ua\": '\"Google Chrome\";v=\"149\", \"Chromium\";v=\"149\", \"Not)A;Brand\";v=\"24\"',\n \"sec-ch-ua-mobile\": \"?0\",\n \"sec-ch-ua-platform\": '\"macOS\"',\n },\n body: activationBody,\n });\n\n const actText = await actRes.text();\n\n if (!actRes.ok) {\n if (previousKeysRaw) {\n setApigwKeysRaw(previousKeysRaw);\n console.log(\" (Rolled back to previous apigw keys)\");\n } else {\n clearApigwKeys();\n }\n throw new Error(`Device activation failed (${actRes.status}): ${actText.slice(0, 500)}`);\n }\n\n console.log(` Activation response: ${actText.slice(0, 300)}`);\n\n let actData: ActivationResponse;\n try {\n actData = JSON.parse(actText) as ActivationResponse;\n } catch {\n console.log(\" (non-JSON activation response, continuing)\");\n actData = {};\n }\n\n const actResult = extractResult(actData);\n const newAccessToken = actResult.access_token;\n\n if (newAccessToken) {\n setAuthToken(newAccessToken);\n console.log(\" Device activated. Token refreshed.\");\n } else {\n console.log(\" Device activated (using existing token).\");\n }\n\n const effectiveToken = newAccessToken ?? currentToken;\n const udid = randomUUID();\n\n const pushBody = JSON.stringify({\n phone: null,\n token: null,\n platform: \"web_chrome\",\n user_huid: userHuid,\n locale: config.locale,\n udid,\n encryption_key: \"\",\n auth_key: \"\",\n platform_package_id: config.platform_package_id,\n });\n\n console.log(\"Step 5/5: Registering push token...\");\n\n const pushHeaders = await signApigwRequest({\n method: \"PUT\",\n url: `${etsBaseUrl}/api/v1/apigw/api/v1/push_service/protected/token`,\n baseUrl: etsBaseUrl,\n body: pushBody,\n ctsToken: effectiveToken,\n });\n\n const pushRes = await fetch(`${etsBaseUrl}/api/v1/apigw/api/v1/push_service/protected/token`, {\n method: \"PUT\",\n headers: {\n \"Accept\": \"application/json, text/plain, */*\",\n ...pushHeaders,\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\n },\n body: pushBody,\n });\n\n const pushText = await pushRes.text();\n console.log(` Push token: ${pushRes.status} — ${pushText.slice(0, 200)}`);\n\n console.log(\"Login complete! Apigw endpoints are now available.\");\n}\n","import { generateSigningKeyPair, publicKeyToBase64, saveApigwKeys, loadApigwKeys, decryptRegistrationData, decryptRtsToken, extractRtsKeyIdFromToken, type ApigwKeys } from \"./keys.js\";\nimport { signQrRequest, signApigwRequest } from \"./apigw-signer.js\";\nimport { setAuthToken, setRtsAuthToken, setRefreshToken, setTokenExpiresAt, calcTokenExpiresAt, setEtsAuthToken } from \"../config/store.js\";\nimport { loadConfig, getBaseUrl, getEtsBaseUrl, getWebOrigin } from \"../config/loader.js\";\nimport type { Config } from \"../types/index.js\";\nimport { randomUUID, randomBytes } from \"node:crypto\";\nimport qrcode from \"qrcode-terminal\";\nimport nacl from \"tweetnacl\";\n\ninterface QrRequestResponse {\n status?: string;\n reason?: string;\n result?: {\n registration_id?: string;\n registration_data?: string;\n cts_registration_token?: string;\n rts_registration_token?: string;\n };\n registration_id?: string;\n registration_data?: string;\n cts_registration_token?: string;\n rts_registration_token?: string;\n}\n\ninterface RegisterConfirmResponse {\n status?: string;\n result?: {\n user_huid?: string;\n server_id?: string;\n expires_at?: string | null;\n auth_token?: string;\n };\n user_huid?: string;\n server_id?: string;\n auth_token?: string;\n}\n\ninterface AdIntegrationConfirmResponse {\n status?: string;\n result?: {\n active?: boolean;\n user_huid?: string;\n server_id?: string;\n access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n };\n access_token?: string;\n refresh_token?: string;\n}\n\ninterface KdcKeysResponse {\n status?: string;\n result?: Array<{\n id: string;\n body: string;\n kind: string;\n user_huid: string;\n }>;\n}\n\nfunction extractResult<T>(data: T & { result?: T }): T {\n return (data.result ?? data) as T;\n}\n\n/** Returns the account's current cts key_id in KDC, or null if none exists. */\nasync function fetchCurrentAccountCtsKey(baseUrl: string, accessToken: string, userHuid: string, webOrigin: string): Promise<string | null> {\n try {\n const res = await fetch(`${baseUrl}/api/v1/kdc/keys/?user_huids=${userHuid}`, {\n headers: { ...commonHeaders(webOrigin), Authorization: `Bearer ${accessToken}` },\n });\n if (!res.ok) return null;\n const data = await res.json() as { result?: Array<{ id: string; kind: string }> };\n return data.result?.find((k) => k.kind === \"cts\")?.id ?? null;\n } catch {\n return null;\n }\n}\n\nfunction commonHeaders(webOrigin: string): Record<string, string> {\n return {\n \"Accept\": \"application/json, text/plain, */*\",\n \"Accept-Language\": \"ru-RU,ru;q=0.9\",\n \"Connection\": \"keep-alive\",\n \"Origin\": webOrigin,\n \"Referer\": `${webOrigin}/`,\n \"Sec-Fetch-Dest\": \"empty\",\n \"Sec-Fetch-Mode\": \"cors\",\n \"Sec-Fetch-Site\": \"same-site\",\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\n \"sec-ch-ua\": '\"Google Chrome\";v=\"149\", \"Chromium\";v=\"149\", \"Not)A;Brand\";v=\"24\"',\n \"sec-ch-ua-mobile\": \"?0\",\n \"sec-ch-ua-platform\": '\"macOS\"',\n };\n}\n\nexport async function qrLogin(cliOverrides: Partial<Config> = {}): Promise<void> {\n const config = loadConfig(cliOverrides);\n const etsBaseUrl = getEtsBaseUrl(config);\n const webOrigin = getWebOrigin(config);\n\n const qrSigningKey = generateSigningKeyPair();\n const registrationId = qrSigningKey.keyId;\n const registrationToken = Buffer.from(randomBytes(64)).toString(\"base64\");\n const signPubKey = publicKeyToBase64(qrSigningKey.publicKey);\n const udid = randomUUID();\n const encryptionKey = randomBytes(32);\n\n const qrBody = JSON.stringify({\n registration_id: registrationId,\n registration_token: registrationToken,\n sign_pub_key: signPubKey,\n udid,\n app_version: config.app_version,\n device: \"Chrome 149.0\",\n device_software: \"macOS 10.15.7\",\n device_hostname: null,\n device_meta: {\n pushes: false,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n permissions: { notifications: false },\n },\n locale: config.locale,\n manufacturer: \"Google\",\n platform: \"web\",\n platform_package_id: \"com.pyligrim.alphach\",\n });\n\n const qrPayload = JSON.stringify({\n registration_id: registrationId,\n registration_token: registrationToken,\n registration_key: Buffer.from(encryptionKey).toString(\"base64\"),\n version: 1,\n });\n\n console.log(\"Step 1/7: Scan this QR code with your eXpress app:\\n\");\n qrcode.generate(qrPayload, { small: true }, (qr: string) => {\n console.log(qr);\n });\n console.log(`\\n registration_id: ${registrationId}`);\n console.log(\" Waiting for scan (server long-polling)...\\n\");\n\n const etsUrl = `${etsBaseUrl}/api/v1/authentication/qr/mobile_to_web/request`;\n const qrHeaders = signQrRequest({\n method: \"POST\",\n url: etsUrl,\n body: qrBody,\n registrationId,\n privateKey: qrSigningKey.privateKey,\n });\n\n let qrRes: Response;\n try {\n qrRes = await fetch(etsUrl, {\n method: \"POST\",\n headers: { ...commonHeaders(webOrigin), ...qrHeaders },\n body: qrBody,\n });\n } catch (err) {\n throw new Error(`QR request network error: ${(err as Error).message}`);\n }\n\n const qrText = await qrRes.text();\n\n if (!qrRes.ok) {\n console.log(` Response (${qrRes.status}): ${qrText.slice(0, 500)}`);\n throw new Error(`QR request failed (${qrRes.status}): ${qrText.slice(0, 500)}`);\n }\n\n let qrData: QrRequestResponse;\n try {\n qrData = JSON.parse(qrText) as QrRequestResponse;\n } catch {\n throw new Error(`Invalid QR response: ${qrText.slice(0, 500)}`);\n }\n\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] QR full response: ${qrText.slice(0, 1000)}`);\n }\n\n const qrResult = extractResult(qrData);\n const ctsRegistrationToken = qrResult.cts_registration_token ?? \"\";\n const rtsRegistrationToken = qrResult.rts_registration_token ?? \"\";\n const registrationData = qrResult.registration_data ?? \"\";\n\n console.log(\" QR scanned! Got tokens from server.\");\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] registration_data length: ${registrationData.length}`);\n console.log(` [DEBUG] registration_data raw: ${registrationData.slice(0, 100)}...`);\n console.log(` [DEBUG] encryptionKey (registration_key) hex: ${Buffer.from(encryptionKey).toString(\"hex\")}`);\n }\n\n if (!ctsRegistrationToken && !rtsRegistrationToken) {\n throw new Error(`No tokens in QR response: ${qrText.slice(0, 500)}`);\n }\n\n let rtsPrivateKey: Uint8Array | null = null;\n let rtsPublicKeyId = \"\";\n // CTS (E2E) key transferred from the phone via the QR handshake — this is the\n // shared account key, so QR login alone yields a working E2E key (no import).\n let qrCtsPrivateKey: Uint8Array | null = null;\n let qrCtsKeyId = \"\";\n\n if (registrationData) {\n try {\n const raw = Uint8Array.from(Buffer.from(registrationData, \"base64\"));\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] registration_data decoded length: ${raw.length}`);\n console.log(` [DEBUG] first 40 bytes hex: ${Buffer.from(raw.slice(0, 40)).toString(\"hex\")}`);\n console.log(` [DEBUG] encryptionKey hex: ${Buffer.from(encryptionKey).toString(\"hex\")}`);\n console.log(` [DEBUG] encryptionKey length: ${encryptionKey.length}`);\n }\n const decrypted = decryptRegistrationData(registrationData, encryptionKey);\n if (process.env.EXPRESS_DEBUG) {\n console.log(\" Decrypted registration_data:\", JSON.stringify(decrypted).slice(0, 500));\n }\n\n if (decrypted && typeof decrypted === \"object\") {\n const data = decrypted as Record<string, unknown>;\n if (typeof data.rts_priv_key_body === \"string\") {\n rtsPrivateKey = new Uint8Array(Buffer.from(data.rts_priv_key_body as string, \"base64\"));\n }\n if (typeof data.rts_pub_key_id === \"string\") {\n rtsPublicKeyId = data.rts_pub_key_id as string;\n }\n // CTS/E2E key from the phone — key_id matches the account's current cts key\n if (typeof data.cts_priv_key_body === \"string\" && typeof data.cts_pub_key_id === \"string\") {\n qrCtsPrivateKey = new Uint8Array(Buffer.from(data.cts_priv_key_body as string, \"base64\"));\n qrCtsKeyId = data.cts_pub_key_id as string;\n }\n }\n } catch (err) {\n console.log(` Warning: could not decrypt registration_data: ${(err as Error).message}`);\n }\n }\n\n console.log(\"\\nStep 2/7: Confirming with ETS...\");\n\n const confirmUrl = `${etsBaseUrl}/api/v1/authentication/register_confirm/qr`;\n const confirmBody = JSON.stringify({\n registration_id: registrationId,\n temp_token: rtsRegistrationToken,\n });\n\n const confirmHeaders = signQrRequest({\n method: \"POST\",\n url: confirmUrl,\n body: confirmBody,\n registrationId,\n privateKey: qrSigningKey.privateKey,\n });\n\n const confirmRes = await fetch(confirmUrl, {\n method: \"POST\",\n headers: { ...commonHeaders(webOrigin), ...confirmHeaders },\n body: confirmBody,\n });\n\n const confirmText = await confirmRes.text();\n\n if (!confirmRes.ok) {\n throw new Error(`ETS register_confirm failed (${confirmRes.status}): ${confirmText.slice(0, 500)}`);\n }\n\n const confirmData = extractResult(JSON.parse(confirmText) as RegisterConfirmResponse);\n const userHuid = confirmData.user_huid ?? \"\";\n const etsAuthToken = confirmData.auth_token ?? \"\";\n\n console.log(` ETS confirmed. User: ${userHuid || \"unknown\"}`);\n if (etsAuthToken) {\n setEtsAuthToken(etsAuthToken);\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] ETS auth_token saved (${etsAuthToken.length} chars)`);\n }\n }\n\n if (!ctsRegistrationToken) {\n throw new Error(\"No cts_registration_token — cannot confirm with CTS\");\n }\n\n console.log(\"\\nStep 3/7: Confirming with CTS (AD integration)...\");\n\n const ctsUrl = `${getBaseUrl(config)}/api/v1/ad_integration/register_confirm/qr`;\n const adConfirmBody = JSON.stringify({\n rts_registration_id: registrationId,\n temp_token: ctsRegistrationToken,\n ets: true,\n });\n\n const adConfirmHeaders = signQrRequest({\n method: \"POST\",\n url: ctsUrl,\n body: adConfirmBody,\n registrationId,\n privateKey: qrSigningKey.privateKey,\n });\n\n const adRes = await fetch(ctsUrl, {\n method: \"POST\",\n headers: { ...commonHeaders(webOrigin), ...adConfirmHeaders },\n body: adConfirmBody,\n });\n\n const adText = await adRes.text();\n\n if (!adRes.ok) {\n throw new Error(`AD integration confirm failed (${adRes.status}): ${adText.slice(0, 500)}`);\n }\n\n const adData = extractResult(JSON.parse(adText) as AdIntegrationConfirmResponse);\n const accessToken = adData.access_token;\n const refreshToken = adData.refresh_token;\n const expiresIn = adData.expires_in;\n const serverId = adData.server_id ?? userHuid;\n const encryptedRtsToken = (adData as Record<string, unknown>).encrypted_rts_token as string | undefined;\n\n if (process.env.EXPRESS_DEBUG) {\n const adDataRaw = JSON.parse(adText);\n console.log(` [DEBUG] AD confirm full result keys: ${JSON.stringify(Object.keys(adDataRaw.result || adDataRaw))}`);\n if (encryptedRtsToken) {\n console.log(` [DEBUG] encrypted_rts_token found: ${encryptedRtsToken.slice(0, 60)}...`);\n } else {\n console.log(` [DEBUG] encrypted_rts_token NOT found in response`);\n }\n }\n\n if (!accessToken) {\n throw new Error(`No access_token in AD confirm response: ${adText.slice(0, 500)}`);\n }\n\n setAuthToken(accessToken);\n if (refreshToken) {\n setRefreshToken(refreshToken);\n }\n if (typeof expiresIn === \"number\") {\n setTokenExpiresAt(calcTokenExpiresAt(expiresIn));\n console.log(` Token expires in ${expiresIn}s (refresh after ${(expiresIn / 2 / 60).toFixed(0)} min)`);\n }\n\n console.log(` CTS confirmed. Access token: ${accessToken.slice(0, 40)}...`);\n\n console.log(\"\\nStep 4/7: Registering device token...\");\n\n const tokenUrl = `${getBaseUrl(config)}/api/v1/ad_integration/token`;\n const tokenBody = JSON.stringify({\n app_version: config.app_version,\n device: \"Chrome 149.0\",\n device_software: \"macOS 10.15.7\",\n manufacturer: \"Google\",\n platform: \"web\",\n locale: config.locale,\n platform_package_id: \"com.pyligrim.alphach\",\n device_meta: {\n pushes: false,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n permissions: { notifications: false },\n },\n device_hostname: null,\n });\n\n const tokenRes = await fetch(tokenUrl, {\n method: \"PUT\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: tokenBody,\n });\n\n if (!tokenRes.ok) {\n const tokenErrText = await tokenRes.text().catch(() => \"\");\n console.log(` Warning: device token registration failed (${tokenRes.status}): ${tokenErrText.slice(0, 200)}`);\n } else {\n console.log(\" Device token registered.\");\n }\n\n console.log(\"\\nStep 5/7: Registering signing key + fetching server key...\");\n\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] serverId: ${serverId}`);\n console.log(` [DEBUG] userHuid: ${userHuid}`);\n }\n\n const apigwSigningKey = generateSigningKeyPair();\n const apigwKeyPublicBase64 = publicKeyToBase64(apigwSigningKey.publicKey);\n\n const kdcSignUrl = `${getBaseUrl(config)}/api/v2/kdc/keys/${userHuid}`;\n const kdcSignBody = JSON.stringify({\n key: apigwKeyPublicBase64,\n kind: \"ed25519\",\n algo: \"ed25519\",\n id: apigwSigningKey.keyId,\n });\n\n const [kdcSignRes, etsKdcSignRes, etsKdcStartRes] = await Promise.all([\n fetch(kdcSignUrl, {\n method: \"POST\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: kdcSignBody,\n }),\n fetch(`${etsBaseUrl}/api/v2/kdc/keys/${userHuid}`, {\n method: \"POST\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${etsAuthToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: kdcSignBody,\n }),\n fetch(`${etsBaseUrl}/api/v1/kdc/start`, {\n headers: {\n ...commonHeaders(webOrigin),\n },\n }),\n ]);\n\n if (!kdcSignRes.ok) {\n const kdcErrText = await kdcSignRes.text().catch(() => \"\");\n console.log(` Warning: CTS KDC signing key registration failed (${kdcSignRes.status}): ${kdcErrText.slice(0, 200)}`);\n } else {\n const kdcSignData = await kdcSignRes.json().catch(() => null);\n console.log(` Signing key registered in CTS: ${apigwSigningKey.keyId}`, kdcSignData ? JSON.stringify(kdcSignData).slice(0, 200) : \"\");\n }\n\n if (!etsKdcSignRes.ok) {\n const etsErrText = await etsKdcSignRes.text().catch(() => \"\");\n console.log(` Warning: ETS KDC signing key registration failed (${etsKdcSignRes.status}): ${etsErrText.slice(0, 200)}`);\n } else {\n const etsSignData = await etsKdcSignRes.json().catch(() => null);\n console.log(` Signing key registered in ETS: ${apigwSigningKey.keyId}`, etsSignData ? JSON.stringify(etsSignData).slice(0, 200) : \"\");\n }\n\n let serverPublicKey = new Uint8Array(0);\n let serverPublicKeyId = \"\";\n\n if (etsKdcStartRes.ok) {\n const kdcStartText = await etsKdcStartRes.text();\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] ETS KDC start response: ${kdcStartText.slice(0, 500)}`);\n }\n try {\n const kdcStartData = JSON.parse(kdcStartText) as { result?: string; status?: string };\n const keyBody = kdcStartData.result ?? kdcStartText;\n serverPublicKey = new Uint8Array(Buffer.from(keyBody, \"base64\"));\n serverPublicKeyId = \"kdc-start-ets\";\n const rawB64 = Buffer.from(serverPublicKey).toString(\"base64\");\n console.log(` ETS server public key from /kdc/start: ${rawB64} (curve25519, used directly)`);\n } catch {\n try { serverPublicKey = new Uint8Array(Buffer.from(kdcStartText, \"base64\")); } catch {}\n }\n }\n\n if (!serverPublicKey.length) {\n if (process.env.EXPRESS_DEBUG && !etsKdcStartRes.ok) {\n console.log(` [DEBUG] ETS KDC start status: ${etsKdcStartRes.status}`);\n try { console.log(` [DEBUG] ETS KDC start body: ${(await etsKdcStartRes.text()).slice(0, 500)}`); } catch {}\n }\n throw new Error(\"Could not fetch server public key from ETS /kdc/start\");\n }\n\n if (rtsPrivateKey) {\n const rtsPubKeyB64 = Buffer.from(nacl.box.keyPair.fromSecretKey(rtsPrivateKey).publicKey).toString(\"base64\");\n const rtsKeyBody = JSON.stringify({ key: rtsPubKeyB64, kind: \"rts\", algo: \"xsalsa20\", id: rtsPublicKeyId });\n const [ctsRtsRes, etsRtsRes] = await Promise.all([\n fetch(kdcSignUrl, {\n method: \"POST\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: rtsKeyBody,\n }),\n fetch(`${etsBaseUrl}/api/v2/kdc/keys/${userHuid}`, {\n method: \"POST\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${etsAuthToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: rtsKeyBody,\n }),\n ]);\n if (!ctsRtsRes.ok) {\n const errText = await ctsRtsRes.text().catch(() => \"\");\n console.log(` Warning: CTS RTS key registration failed (${ctsRtsRes.status}): ${errText.slice(0, 200)}`);\n } else {\n console.log(` RTS key registered in CTS: ${rtsPublicKeyId}`);\n }\n if (!etsRtsRes.ok) {\n const errText = await etsRtsRes.text().catch(() => \"\");\n console.log(` Warning: ETS RTS key registration failed (${etsRtsRes.status}): ${errText.slice(0, 200)}`);\n } else {\n console.log(` RTS key registered in ETS: ${rtsPublicKeyId}`);\n }\n }\n\n if (!rtsPrivateKey) {\n const fallbackKeyPair = nacl.box.keyPair();\n rtsPrivateKey = fallbackKeyPair.secretKey;\n rtsPublicKeyId = crypto.randomUUID();\n\n const encPubB64 = Buffer.from(fallbackKeyPair.publicKey).toString(\"base64\");\n const rtsFallbackBody = JSON.stringify({ key: encPubB64, kind: \"rts\", algo: \"xsalsa20\", id: rtsPublicKeyId });\n const [ctsEncRes, etsEncRes] = await Promise.all([\n fetch(kdcSignUrl, {\n method: \"POST\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: rtsFallbackBody,\n }),\n fetch(`${etsBaseUrl}/api/v2/kdc/keys/${userHuid}`, {\n method: \"POST\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${etsAuthToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: rtsFallbackBody,\n }),\n ]);\n\n if (!ctsEncRes.ok) {\n const errText = await ctsEncRes.text().catch(() => \"\");\n console.log(` Warning: CTS fallback RTS key registration failed (${ctsEncRes.status}): ${errText.slice(0, 200)}`);\n } else {\n console.log(` Fallback encryption key registered in CTS: ${rtsPublicKeyId}`);\n }\n if (!etsEncRes.ok) {\n const errText = await etsEncRes.text().catch(() => \"\");\n console.log(` Warning: ETS fallback RTS key registration failed (${etsEncRes.status}): ${errText.slice(0, 200)}`);\n } else {\n console.log(` Fallback encryption key registered in ETS: ${rtsPublicKeyId}`);\n }\n }\n\n const rtsPublicKey = nacl.box.keyPair.fromSecretKey(rtsPrivateKey).publicKey;\n\n let rtsAuthToken = \"\";\n if (encryptedRtsToken && rtsPrivateKey && serverPublicKey.length) {\n try {\n rtsAuthToken = decryptRtsToken(encryptedRtsToken, serverPublicKey, rtsPrivateKey);\n setRtsAuthToken(rtsAuthToken);\n if (process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] Decrypted RTS auth token: ${rtsAuthToken.slice(0, 60)}...`);\n }\n console.log(` RTS auth token decrypted from encrypted_rts_token`);\n } catch (err) {\n console.log(` Warning: could not decrypt encrypted_rts_token: ${(err as Error).message}`);\n }\n }\n\n const rtsIdFromToken = extractRtsKeyIdFromToken(accessToken);\n if (rtsIdFromToken && process.env.EXPRESS_DEBUG) {\n console.log(` [DEBUG] rts_id from CTS token: ${rtsIdFromToken}`);\n }\n\n // CTS encryption key for E2E messages. eXpress keeps ONE active cts key per\n // user (shared across devices via the QR handshake / key backup). Priority:\n // 1. the cts key the phone sent through registration_data (the shared account\n // key) — this makes QR login self-sufficient, no import needed;\n // 2. the stored ctsKey (already-shared key from a prior import/login);\n // 3. mint a new one — only when the account genuinely has no cts key yet.\n const existingCts = loadApigwKeys()?.ctsKey;\n let ctsKey: ApigwKeys[\"ctsKey\"];\n\n if (qrCtsPrivateKey && qrCtsKeyId) {\n ctsKey = {\n keyId: qrCtsKeyId,\n privateKey: qrCtsPrivateKey,\n publicKey: nacl.box.keyPair.fromSecretKey(qrCtsPrivateKey).publicKey,\n };\n console.log(` Using CTS key from QR handshake: ${qrCtsKeyId.slice(0, 8)}... (shared account key)`);\n } else if (existingCts) {\n ctsKey = existingCts;\n console.log(` Reusing existing CTS key: ${existingCts.keyId.slice(0, 8)}... (not re-registering)`);\n } else {\n // Guard: if the account already has a current cts key in KDC, DO NOT mint a\n // new one — it would supersede the shared key and, since the CLI can't upload\n // the private-key backup, permanently break your phone/desktop/web.\n const currentCts = await fetchCurrentAccountCtsKey(getBaseUrl(config), accessToken, userHuid, webOrigin);\n if (currentCts) {\n throw new Error(\n `Account already has a shared CTS key (${currentCts}) that this CLI doesn't hold.\\n` +\n `Minting a new one would break your other devices (they can't fetch its private key).\\n` +\n `Instead, extract the key from a logged-in web client (IndexedDB authState → encryptionKeys → user.privateKeys.cts) and run:\\n` +\n ` express auth import-cts <private_key_b64> ${currentCts}\\n` +\n `Then re-run login, or just use 'auth refresh' for tokens.`,\n );\n }\n console.log(\" No existing account CTS key found — minting a new one (first device).\");\n const ctsKeyPair = nacl.box.keyPair();\n const ctsKeyId = crypto.randomUUID();\n const ctsKeyPubB64 = Buffer.from(ctsKeyPair.publicKey).toString(\"base64\");\n const ctsKeyBody = JSON.stringify({ key: ctsKeyPubB64, kind: \"cts\", algo: \"xsalsa20\", id: ctsKeyId });\n\n const ctsCtsKeyRes = await fetch(kdcSignUrl, {\n method: \"POST\",\n headers: {\n ...commonHeaders(webOrigin),\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: ctsKeyBody,\n });\n\n if (!ctsCtsKeyRes.ok) {\n const errText = await ctsCtsKeyRes.text().catch(() => \"\");\n console.log(` Warning: CTS encryption key registration failed (${ctsCtsKeyRes.status}): ${errText.slice(0, 200)}`);\n } else {\n console.log(` CTS encryption key registered: ${ctsKeyId.slice(0, 8)}...`);\n }\n\n ctsKey = {\n keyId: ctsKeyId,\n privateKey: ctsKeyPair.secretKey,\n publicKey: ctsKeyPair.publicKey,\n };\n }\n\n const apigwKeys: ApigwKeys = {\n signingKey: apigwSigningKey,\n encryptionKey: {\n keyId: rtsPublicKeyId,\n privateKey: rtsPrivateKey,\n publicKey: rtsPublicKey,\n },\n ctsKey,\n serverPublicKey,\n serverPublicKeyId,\n };\n saveApigwKeys(apigwKeys);\n\n console.log(\"\\nStep 6/7: Activating apigw via ETS...\");\n\n const activationUrl = `${etsBaseUrl}/api/v1/apigw/api/v1/authentication/activation`;\n const activationBody = JSON.stringify({\n app_version: config.app_version,\n locale: config.locale,\n device_meta: {\n pushes: false,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n permissions: { notifications: false },\n },\n device_hostname: null,\n });\n\n const activationHeaders = await signApigwRequest({\n method: \"PUT\",\n url: activationUrl,\n baseUrl: etsBaseUrl,\n body: activationBody,\n ctsToken: accessToken,\n rtsToken: rtsAuthToken || undefined,\n etsAuthToken: etsAuthToken || undefined,\n });\n\n const activationRes = await fetch(activationUrl, {\n method: \"PUT\",\n headers: { ...commonHeaders(webOrigin), ...activationHeaders },\n body: activationBody,\n });\n\n if (!activationRes.ok) {\n const actErrText = await activationRes.text().catch(() => \"\");\n console.log(` Warning: apigw activation failed (${activationRes.status}): ${actErrText.slice(0, 200)}`);\n } else {\n console.log(\" Apigw activated.\");\n }\n\n console.log(`\\n User HUID: ${userHuid || \"unknown\"}`);\n console.log(` Signing key: ${apigwSigningKey.keyId.slice(0, 8)}...`);\n console.log(` Encryption key: ${rtsPublicKeyId.slice(0, 8)}...`);\n console.log(` Server key: ${serverPublicKeyId.slice(0, 8)}...`);\n\n console.log(\"\\nQR login complete! You are now authenticated.\");\n}\n","import { getAuthToken, getRefreshToken, setAuthToken, setRefreshToken, setTokenExpiresAt, calcTokenExpiresAt } from \"../config/store.js\";\nimport { getBaseUrl, getWebOrigin } from \"../config/loader.js\";\nimport { loadConfig } from \"../config/index.js\";\nimport type { Config } from \"../types/index.js\";\n\ninterface RefreshResponse {\n status?: string;\n result?: {\n cts_access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n };\n cts_access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n}\n\nlet refreshPromise: Promise<boolean> | null = null;\n\nexport async function refreshToken(cliOverrides: Partial<Config> = {}): Promise<boolean> {\n if (refreshPromise) return refreshPromise;\n\n refreshPromise = doRefresh(cliOverrides);\n try {\n return await refreshPromise;\n } finally {\n refreshPromise = null;\n }\n}\n\nasync function doRefresh(cliOverrides: Partial<Config> = {}): Promise<boolean> {\n const currentToken = getAuthToken();\n const rt = getRefreshToken();\n\n if (!currentToken || !rt) return false;\n\n const config = loadConfig(cliOverrides);\n const baseUrl = getBaseUrl(config);\n const webOrigin = getWebOrigin(config);\n\n try {\n const res = await fetch(`${baseUrl}/api/v1/ad_integration/token/refresh`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/plain, */*\",\n \"Accept-Language\": \"ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n Origin: webOrigin,\n Pragma: \"no-cache\",\n Referer: `${webOrigin}/`,\n \"Sec-Fetch-Dest\": \"empty\",\n \"Sec-Fetch-Mode\": \"cors\",\n \"Sec-Fetch-Site\": \"same-site\",\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\n Authorization: `Bearer ${currentToken}`,\n },\n body: JSON.stringify({ refresh_token: rt }),\n });\n\n if (!res.ok) {\n return false;\n }\n\n const text = await res.text();\n const data = JSON.parse(text) as RefreshResponse;\n const result = data.result ?? data;\n\n const newAccessToken = result.cts_access_token;\n const newRefreshToken = result.refresh_token;\n const expiresIn = result.expires_in;\n\n if (!newAccessToken) return false;\n\n setAuthToken(newAccessToken);\n if (newRefreshToken) setRefreshToken(newRefreshToken);\n if (typeof expiresIn === \"number\") {\n setTokenExpiresAt(calcTokenExpiresAt(expiresIn));\n }\n\n return true;\n } catch {\n return false;\n }\n}\n","import { Command } from \"commander\";\nimport { ApiClient } from \"../api/client.js\";\nimport { loadConfig } from \"../config/index.js\";\nimport { formatOutput, type OutputFormat } from \"./output.js\";\n\nexport function createApiCommand(): Command {\n const cmd = new Command(\"api\");\n\n cmd\n .description(\"Make arbitrary API request\")\n .argument(\"<path>\", \"API path (e.g. /api/v1/phonebook/profiles/self)\")\n .option(\"-X, --method <method>\", \"HTTP method\", \"GET\")\n .option(\"-d, --data <data>\", \"Request body (JSON)\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (path: string, opts: { method: string; data?: string; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n\n let body: unknown;\n if (opts.data) {\n try {\n body = JSON.parse(opts.data);\n } catch {\n throw new Error(\"Invalid JSON in --data\");\n }\n }\n\n const method = opts.method.toUpperCase();\n const res = await client.rawRequest(path, {\n method,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n const text = await res.text();\n console.log(`Response: status=${res.status}, content-type=${res.headers.get(\"content-type\")}, body=${text.length} chars`);\n if (!text) {\n return;\n }\n let data: unknown;\n try {\n data = JSON.parse(text);\n } catch {\n console.log(`Response: status=${res.status}, non-JSON body (${text.length} chars): ${text.slice(0, 500)}`);\n return;\n }\n\n if (!res.ok) {\n console.error(`API error ${res.status}:`, JSON.stringify(data, null, 2));\n process.exit(1);\n }\n\n console.log(formatOutput(data, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { loadConfig, getBaseUrl, getEtsBaseUrl, getWebOrigin } from \"../config/index.js\";\nimport { getAuthToken, getRtsAuthToken, setAuthToken, isTokenExpiringSoon, getEtsAuthToken } from \"../config/store.js\";\nimport { signApigwRequest } from \"../auth/apigw-signer.js\";\nimport { loadApigwKeys } from \"../auth/keys.js\";\nimport { refreshToken } from \"../auth/token-refresh.js\";\nimport type { Config, ApiResponse } from \"../types/index.js\";\n\nexport class ApiClient {\n private config: Config;\n private baseUrl: string;\n private etsBaseUrl: string;\n private webOrigin: string;\n\n constructor(cliOverrides: Partial<Config> = {}) {\n this.config = loadConfig(cliOverrides);\n this.baseUrl = getBaseUrl(this.config);\n this.etsBaseUrl = getEtsBaseUrl(this.config);\n this.webOrigin = getWebOrigin(this.config);\n }\n\n private getToken(): string {\n const token = this.config.token ?? getAuthToken();\n if (!token) {\n throw new Error(\"Not authenticated. Use `express auth import <token>` to login.\");\n }\n return token;\n }\n\n private isApigwPath(path: string): boolean {\n return path.includes(\"/apigw/\");\n }\n\n private resolveUrl(path: string): string {\n if (path.startsWith(\"http\")) return path;\n if (this.isApigwPath(path)) {\n return `${this.etsBaseUrl}${path}`;\n }\n return `${this.baseUrl}${path}`;\n }\n\n private async request<T>(\n path: string,\n options: RequestInit = {},\n retry = true,\n ): Promise<T> {\n if (retry && isTokenExpiringSoon()) {\n await refreshToken(this.config);\n }\n\n let token = this.getToken();\n const url = this.resolveUrl(path);\n\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n ...(this.isApigwPath(path)\n ? await this.buildApigwHeaders(options.method ?? \"GET\", path, token, options.body as string | undefined)\n : { Authorization: `Bearer ${token}` }),\n Origin: this.webOrigin,\n ...((options.headers as Record<string, string>) ?? {}),\n };\n\n if (options.body && !headers[\"Content-Type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const res = await fetch(url, {\n ...options,\n headers,\n });\n\n if (res.status === 401 && retry) {\n const text = await res.text().catch(() => \"\");\n const isExpired = text.includes(\"token_expired\");\n if (isExpired) {\n const refreshed = await refreshToken(this.config);\n if (refreshed) {\n const newToken = this.getToken();\n const newHeaders: Record<string, string> = {\n Accept: \"application/json\",\n ...(this.isApigwPath(path)\n ? await this.buildApigwHeaders(options.method ?? \"GET\", path, newToken, options.body as string | undefined)\n : { Authorization: `Bearer ${newToken}` }),\n Origin: this.webOrigin,\n ...((options.headers as Record<string, string>) ?? {}),\n };\n if (options.body && !newHeaders[\"Content-Type\"]) {\n newHeaders[\"Content-Type\"] = \"application/json\";\n }\n const retryRes = await fetch(url, { ...options, headers: newHeaders });\n return this.handleResponse<T>(retryRes);\n }\n }\n throw new Error(\"Token expired and refresh failed. Please re-authenticate with `express auth qr`.\");\n }\n\n return this.handleResponse<T>(res);\n }\n\n private async handleResponse<T>(res: Response): Promise<T> {\n if (res.status === 204) {\n return undefined as T;\n }\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`API error ${res.status}: ${res.statusText}${text ? ` — ${text.slice(0, 200)}` : \"\"}`);\n }\n\n const text = await res.text();\n if (!text) {\n return undefined as T;\n }\n\n const data = JSON.parse(text);\n if (data && typeof data === \"object\" && \"result\" in data) {\n return (data as ApiResponse<T>).result as T;\n }\n return data as T;\n }\n\n private async buildApigwHeaders(\n method: string,\n path: string,\n ctsToken: string,\n body?: string,\n ): Promise<Record<string, string>> {\n const rtsToken = getRtsAuthToken() ?? undefined;\n const etsAuthToken = getEtsAuthToken() ?? undefined;\n const etsBaseUrl = this.etsBaseUrl;\n const signed = await signApigwRequest({\n method,\n url: path.startsWith(\"http\") ? path : `${etsBaseUrl}${path}`,\n baseUrl: etsBaseUrl,\n body,\n ctsToken,\n rtsToken,\n etsAuthToken,\n });\n return {\n Authorization: signed.Authorization,\n \"Express-Proxy-Authorization\": signed[\"Express-Proxy-Authorization\"],\n \"Express-Request-Nonce\": signed[\"Express-Request-Nonce\"],\n ...(signed.Digest && { Digest: signed.Digest }),\n Signature: signed.Signature,\n };\n }\n\n async get<T>(path: string): Promise<T> {\n return this.request<T>(path, { method: \"GET\" });\n }\n\n async post<T>(path: string, body?: unknown): Promise<T> {\n const jsonBody = body ? JSON.stringify(body) : undefined;\n return this.request<T>(path, {\n method: \"POST\",\n body: jsonBody,\n });\n }\n\n async put<T>(path: string, body?: unknown): Promise<T> {\n const jsonBody = body ? JSON.stringify(body) : undefined;\n return this.request<T>(path, {\n method: \"PUT\",\n body: jsonBody,\n });\n }\n\n async delete<T>(path: string): Promise<T> {\n return this.request<T>(path, { method: \"DELETE\" });\n }\n\n async rawRequest(path: string, options: RequestInit = {}): Promise<Response> {\n const token = this.getToken();\n const url = this.resolveUrl(path);\n\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n ...(this.isApigwPath(path)\n ? await this.buildApigwHeaders(options.method ?? \"GET\", path, token, options.body as string | undefined)\n : { Authorization: `Bearer ${token}` }),\n Origin: this.webOrigin,\n ...((options.headers as Record<string, string>) ?? {}),\n };\n\n if (options.body && !headers[\"Content-Type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n return fetch(url, { ...options, headers });\n }\n\n async downloadFile(url: string): Promise<Response> {\n const token = this.getToken();\n const fullUrl = url.startsWith(\"http\") ? url : `${this.baseUrl}${url}`;\n\n return fetch(fullUrl, {\n headers: {\n Authorization: `Bearer ${token}`,\n Referer: `${this.webOrigin}/`,\n Accept: \"*/*\",\n },\n });\n }\n\n isApigwReady(): boolean {\n return loadApigwKeys() !== null;\n }\n}\n","import chalk from \"chalk\";\nimport Table from \"cli-table3\";\nimport type { ExpressProfile, ExpressUserStatus } from \"../types/index.js\";\n\nexport type OutputFormat = \"table\" | \"json\";\n\nexport function formatOutput(data: unknown, format: OutputFormat): string {\n if (format === \"json\") {\n return JSON.stringify(data, null, 2);\n }\n if (typeof data === \"string\") return data;\n if (typeof data === \"number\" || typeof data === \"boolean\") return String(data);\n return JSON.stringify(data, null, 2);\n}\n\nexport function formatProfileTable(profiles: ExpressProfile[]): string {\n const table = new Table({\n head: [\"Name\", \"Email\", \"AD Login\", \"Department\", \"Position\", \"HUID\"],\n style: { head: [\"cyan\"] },\n });\n\n for (const p of profiles) {\n table.push([\n p.name ?? \"-\",\n p.email ?? \"-\",\n p.ad_login ?? \"-\",\n p.department ?? \"-\",\n p.company_position ?? \"-\",\n p.user_huid ? p.user_huid.slice(0, 8) + \"...\" : \"-\",\n ]);\n }\n\n return table.toString();\n}\n\nexport function formatStatusTable(statuses: ExpressUserStatus[]): string {\n const table = new Table({\n head: [\"HUID\", \"Status\", \"Last Seen\"],\n style: { head: [\"cyan\"] },\n });\n\n const statusColors: Record<string, typeof chalk.green> = {\n online: chalk.green,\n offline: chalk.gray,\n away: chalk.yellow,\n dnd: chalk.red,\n invisible: chalk.gray,\n };\n\n for (const s of statuses) {\n const color = statusColors[s.status] ?? chalk.white;\n table.push([\n s.huid ? s.huid.slice(0, 8) + \"...\" : \"-\",\n color(s.status),\n s.last_seen ?? \"-\",\n ]);\n }\n\n return table.toString();\n}\n","import { Command } from \"commander\";\nimport { getStoredConfig, setStoredConfig, clearAll } from \"../config/index.js\";\nimport { formatOutput, type OutputFormat } from \"./output.js\";\n\nexport function createConfigCommand(): Command {\n const cmd = new Command(\"config\");\n\n cmd.description(\"Configuration management\");\n\n cmd\n .command(\"get [key]\")\n .description(\"Get config value(s)\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action((key?: string, opts?: { output: OutputFormat }) => {\n const config = getStoredConfig();\n const data = key ? { [key]: (config as Record<string, unknown>)[key] } : config;\n console.log(formatOutput(data, opts?.output ?? \"json\"));\n });\n\n cmd\n .command(\"set <key> <value>\")\n .description(\"Set config value\")\n .action((key: string, value: string) => {\n const current = getStoredConfig();\n let parsed: unknown = value;\n try {\n parsed = JSON.parse(value);\n } catch {}\n setStoredConfig({ ...current, [key]: parsed });\n console.log(`Set ${key} = ${JSON.stringify(parsed)}`);\n });\n\n cmd\n .command(\"list\")\n .description(\"List all config values\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action((opts: { output: OutputFormat }) => {\n console.log(formatOutput(getStoredConfig(), opts.output));\n });\n\n cmd\n .command(\"reset\")\n .description(\"Reset all configuration and tokens\")\n .action(() => {\n clearAll();\n console.log(\"All configuration and tokens cleared.\");\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport { UserApi } from \"../api/user.js\";\nimport { ApiClient } from \"../api/client.js\";\nimport { formatStatusTable, formatOutput, type OutputFormat } from \"./output.js\";\n\nexport function createStatusCommand(): Command {\n const cmd = new Command(\"status\");\n\n cmd.description(\"Get user statuses\");\n\n cmd\n .command(\"self\")\n .description(\"Get own status\")\n .option(\"-s, --short\", \"Short format\", false)\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (opts: { short: boolean; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new UserApi(client);\n const profile = await api.getSelfProfile();\n const result = await api.getUserStatuses([profile.user_huid], opts.short);\n if (opts.output === \"json\") {\n console.log(formatOutput(result, \"json\"));\n } else {\n console.log(formatStatusTable(result.user_statuses));\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"get <huids...>\")\n .description(\"Get statuses for users by HUID\")\n .option(\"-s, --short\", \"Short format\", false)\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (huids: string[], opts: { short: boolean; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new UserApi(client);\n const result = await api.getUserStatuses(huids, opts.short);\n\n if (opts.output === \"json\") {\n console.log(formatOutput(result, \"json\"));\n } else {\n console.log(formatStatusTable(result.user_statuses));\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"history\")\n .description(\"Get status history\")\n .option(\"--since <iso-date>\", \"Since date (ISO 8601)\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (opts: { since?: string; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new UserApi(client);\n const history = await api.getUserStatusHistory(opts.since);\n console.log(formatOutput(history, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { ApiClient } from \"./client.js\";\nimport type { ExpressProfile, ExpressSelfProfileResponse, ExpressUserStatus } from \"../types/index.js\";\nimport { loadApigwKeys } from \"../auth/keys.js\";\n\nexport class UserApi {\n constructor(private client: ApiClient) {}\n\n async getSelfProfile(): Promise<ExpressProfile> {\n const data = await this.client.get<ExpressSelfProfileResponse>(\"/api/v1/phonebook/profiles/self\");\n return data.profile;\n }\n\n async getProfilesByHuid(huids: string[]): Promise<ExpressProfile[]> {\n const data = await this.client.post<unknown>(\"/api/v1/phonebook/cts_profiles/query\", { huids });\n if (!data) return [];\n const entries = Array.isArray(data) ? data : [];\n const profiles: ExpressProfile[] = [];\n for (const entry of entries) {\n const obj = entry as Record<string, unknown>;\n if (Array.isArray(obj.cts_profiles)) {\n profiles.push(...(obj.cts_profiles as ExpressProfile[]));\n }\n }\n return profiles;\n }\n\n async getUserStatuses(userHuids: string[], short = false): Promise<{ user_statuses: ExpressUserStatus[]; failed: string[] }> {\n const keys = loadApigwKeys();\n const keyId = (keys?.ctsKey ?? keys?.encryptionKey)?.keyId ?? \"\";\n return this.client.post(\"/api/v1/user_statuses/get\", {\n user_huids: userHuids,\n short,\n key_id: keyId,\n });\n }\n\n async getUserStatusHistory(since?: string): Promise<ExpressUserStatus[]> {\n return this.client.post<ExpressUserStatus[]>(\"/api/v1/user_statuses/history\", {\n since: since ?? null,\n });\n }\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { UserApi } from \"../api/user.js\";\nimport { ChatsApi } from \"../api/chats.js\";\nimport { PhonebookApi } from \"../api/phonebook.js\";\nimport { ApiClient } from \"../api/client.js\";\nimport { formatProfileTable, formatOutput, type OutputFormat } from \"./output.js\";\n\nexport function createContactsCommand(): Command {\n const cmd = new Command(\"contacts\");\n\n cmd.description(\"Contacts and phonebook\");\n\n cmd\n .command(\"self\")\n .description(\"Get own profile\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (opts: { host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new UserApi(client);\n const profile = await api.getSelfProfile();\n\n if (opts.output === \"json\") {\n console.log(formatOutput(profile, \"json\"));\n } else {\n console.log(formatProfileTable([profile]));\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"query <huids...>\")\n .description(\"Query profiles by HUIDs\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (huids: string[], opts: { host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new UserApi(client);\n const profiles = await api.getProfilesByHuid(huids);\n\n if (opts.output === \"json\") {\n console.log(formatOutput(profiles, \"json\"));\n } else {\n console.log(formatProfileTable(profiles));\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"search <query>\")\n .description(\"Search users by name/email/department (apigw or directory)\")\n .option(\"-l, --limit <n>\", \"Max results\", \"20\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (query: string, opts: { limit: string; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const limit = parseInt(opts.limit, 10);\n const phonebook = new PhonebookApi(client);\n let profiles = await phonebook.searchUsers(query, limit);\n\n // Fallback: search across all chat members (works even when apigw phonebook is empty)\n if (profiles.length === 0) {\n try {\n const userApi = new UserApi(client);\n const chatsApi = new ChatsApi(client);\n const [allChats, self] = await Promise.all([chatsApi.listChats(), userApi.getSelfProfile()]);\n const myHuid = self.user_huid;\n const allMemberHuids = [...new Set(\n allChats.flatMap((c) => c.member_huids ?? []).filter((h) => h !== myHuid),\n )];\n if (allMemberHuids.length > 0) {\n const allProfiles = await userApi.getProfilesByHuid(allMemberHuids);\n const lowerQuery = query.toLowerCase();\n profiles = allProfiles\n .filter((p) =>\n [p.name, p.email, p.ad_login, p.department, p.company_position]\n .filter(Boolean).join(\" \").toLowerCase().includes(lowerQuery),\n )\n .slice(0, limit);\n }\n } catch (err) {\n if (process.env.EXPRESS_DEBUG) {\n console.error(` [DEBUG] Chat member search failed: ${(err as Error).message}`);\n }\n }\n }\n\n if (profiles.length === 0) {\n console.log(chalk.yellow(\"No users found.\"));\n return;\n }\n\n if (opts.output === \"json\") {\n console.log(formatOutput(profiles, \"json\"));\n } else {\n console.log(formatProfileTable(profiles));\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"list\")\n .description(\"List all contacts (requires 'express auth login')\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (opts: { host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n\n if (!client.isApigwReady()) {\n console.error(chalk.yellow(\"Error: This command requires apigw auth. Run 'express auth login' first.\"));\n process.exit(1);\n }\n\n const api = new PhonebookApi(client);\n const contacts = await api.getContacts();\n if (!contacts || contacts.length === 0) {\n console.log(chalk.yellow(\"No contacts found. The apigw phonebook endpoint may not have synced contacts yet.\"));\n console.log(chalk.yellow(\"Use 'express contacts search <query>' to search via corporate directory.\"));\n return;\n }\n console.log(formatOutput(contacts, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"directory\")\n .description(\"Corporate directory entries\")\n .option(\"--since <iso-date>\", \"Since date (ISO 8601)\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (opts: { since?: string; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new PhonebookApi(client);\n const entries = await api.getCorporateDirectory(opts.since);\n console.log(formatOutput(entries, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import type { ExpressChat } from \"../types/index.js\";\nimport { randomUUID } from \"node:crypto\";\n\ninterface PhxMessage {\n topic: string;\n event: string;\n payload: Record<string, unknown>;\n ref: number;\n}\n\ninterface PhxReply {\n ref: number;\n event: string;\n topic: string;\n payload: {\n status: \"ok\" | \"error\";\n response: Record<string, unknown>;\n };\n}\n\nexport async function fetchChatListViaWebSocket(params: {\n host: string;\n ctsToken: string;\n encryptionKeyId: string;\n timeoutMs?: number;\n}): Promise<ExpressChat[]> {\n const { host, ctsToken, encryptionKeyId, timeoutMs = 15000 } = params;\n const instanceId = randomUUID();\n\n const wsUrl = `wss://${host}/socket/user/websocket?vsn=1.0.0&auto_join=true&key_id=${encryptionKeyId}&version=6&background=false&voex_unencrypted=true&voex_multistream=true&voex_audio_bridge=true&instance_id=${instanceId}`;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const done = (fn: () => void) => {\n if (!settled) { settled = true; fn(); }\n };\n\n const timer = setTimeout(() => {\n try { ws.close(); } catch {}\n done(() => reject(new Error(\"WebSocket timeout: no chat_list response\")));\n }, timeoutMs);\n\n const hostParts = host.split('.');\n const webOrigin = `https://${hostParts.length > 2 ? hostParts.slice(1).join('.') : host}`;\n\n const ws = new WebSocket(wsUrl, {\n headers: {\n Origin: webOrigin,\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\n },\n } as ConstructorParameters<typeof WebSocket>[1]);\n\n const authRef = 0;\n const chatListRef = 1;\n\n const send = (msg: PhxMessage) => {\n ws.send(JSON.stringify(msg));\n };\n\n ws.addEventListener(\"open\", () => {\n send({ topic: \"phoenix\", event: \"authenticate\", payload: { token: ctsToken }, ref: authRef });\n });\n\n ws.addEventListener(\"message\", (event) => {\n let msg: PhxReply;\n try {\n msg = JSON.parse(event.data as string) as PhxReply;\n } catch {\n return;\n }\n\n if (msg.ref === authRef && msg.topic === \"phoenix\" && msg.event === \"phx_reply\") {\n if (msg.payload.status !== \"ok\") {\n clearTimeout(timer);\n ws.close();\n done(() => reject(new Error(`WebSocket auth failed: ${JSON.stringify(msg.payload.response)}`)));\n return;\n }\n send({ topic: \"system\", event: \"chat_list\", payload: { since: null, request_version: 6 }, ref: chatListRef });\n return;\n }\n\n if (msg.ref === chatListRef && msg.topic === \"system\" && msg.event === \"phx_reply\") {\n if (msg.payload.status !== \"ok\") {\n clearTimeout(timer);\n ws.close();\n done(() => reject(new Error(`WebSocket chat_list failed: ${JSON.stringify(msg.payload.response)}`)));\n return;\n }\n const response = msg.payload.response as { chat_list?: ExpressChat[] };\n if (Array.isArray(response.chat_list)) {\n clearTimeout(timer);\n ws.close();\n done(() => resolve(response.chat_list!));\n }\n }\n });\n\n ws.addEventListener(\"error\", (err) => {\n clearTimeout(timer);\n done(() => reject(new Error(`WebSocket connection error: ${String(err)}`)));\n });\n\n ws.addEventListener(\"close\", (event) => {\n clearTimeout(timer);\n done(() => reject(new Error(`WebSocket closed before completion (code=${event.code})`)));\n });\n });\n}\n","import { ApiClient } from \"./client.js\";\nimport { fetchChatListViaWebSocket } from \"./websocket.js\";\nimport { getAuthToken } from \"../config/store.js\";\nimport { loadApigwKeys } from \"../auth/keys.js\";\nimport { loadConfig, getBaseUrl } from \"../config/index.js\";\nimport type { ExpressChat } from \"../types/index.js\";\n\ninterface DirectoryEntry {\n position: number;\n entry_type: \"user\" | \"bot\" | \"chat\";\n entry_id: string;\n is_info_updated: boolean;\n deleted: boolean;\n}\n\ninterface OpenChatsResponse {\n generated_at: string;\n open_chats: ExpressChat[];\n}\n\nexport class ChatsApi {\n constructor(private client: ApiClient) {}\n\n async listChats(): Promise<ExpressChat[]> {\n const config = loadConfig();\n const host = new URL(getBaseUrl(config)).hostname;\n const ctsToken = getAuthToken();\n const keys = loadApigwKeys();\n\n const ctsKeyId = (keys?.ctsKey ?? keys?.encryptionKey)?.keyId;\n if (ctsToken && ctsKeyId) {\n try {\n return await fetchChatListViaWebSocket({\n host,\n ctsToken,\n encryptionKeyId: ctsKeyId,\n });\n } catch (err) {\n if (process.env.EXPRESS_DEBUG) {\n console.error(` [DEBUG] WebSocket failed, falling back to directory: ${(err as Error).message}`);\n }\n }\n }\n\n return this.listChatsViaDirectory();\n }\n\n private async listChatsViaDirectory(): Promise<ExpressChat[]> {\n const data = await this.client.get<{ entries: DirectoryEntry[] }>(\"/api/v1/corporate_directory/entries\");\n const entries = data?.entries ?? [];\n const chatIds = entries\n .filter((e) => e.entry_type === \"chat\" && !e.deleted)\n .map((e) => e.entry_id);\n if (chatIds.length === 0) return [];\n const result = await this.client.post<OpenChatsResponse>(\"/api/v1/messaging/chats/open_chats_list\", {\n chat_ids: chatIds,\n });\n return result?.open_chats ?? [];\n }\n\n async getChatInfo(chatId: string): Promise<ExpressChat | null> {\n const data = await this.client.post<OpenChatsResponse>(\"/api/v1/messaging/chats/open_chats_list\", {\n chat_ids: [chatId],\n });\n return data?.open_chats?.[0] ?? null;\n }\n}\n","import { ApiClient } from \"./client.js\";\nimport type { ExpressProfile } from \"../types/index.js\";\n\ninterface DirectoryEntry {\n position: number;\n entry_type: \"user\" | \"bot\" | \"chat\";\n entry_id: string;\n is_info_updated: boolean;\n deleted: boolean;\n}\n\ninterface DirectoryResponse {\n entries: DirectoryEntry[];\n}\n\ninterface CtsProfileEntry {\n cts_profiles?: ExpressProfile[];\n}\n\ninterface CtsProfilesResponse {\n result?: CtsProfileEntry[];\n}\n\ninterface ApigwContact {\n huid?: string;\n name?: string;\n email?: string;\n ad_login?: string;\n department?: string;\n company_position?: string;\n phone?: string;\n ip_phone?: string;\n [key: string]: unknown;\n}\n\nexport class PhonebookApi {\n constructor(private client: ApiClient) {}\n\n async getContacts(): Promise<ApigwContact[]> {\n const data = await this.client.get<unknown>(\"/api/v1/apigw/api/v1/phonebook/contacts\");\n if (!data) return [];\n if (Array.isArray(data)) return data as ApigwContact[];\n if (typeof data === \"object\" && data !== null) {\n const obj = data as Record<string, unknown>;\n if (Array.isArray(obj.contacts)) return obj.contacts as ApigwContact[];\n if (Array.isArray(obj.users)) return obj.users as ApigwContact[];\n if (Array.isArray(obj.result)) return obj.result as ApigwContact[];\n }\n return [];\n }\n\n async getContactChanges(since: string, udid = \"latest_mobile\"): Promise<unknown> {\n return this.client.get(\n `/api/v1/apigw/api/v4/phonebook/user_contacts_changes?since=${encodeURIComponent(since)}&udid=${udid}`,\n );\n }\n\n async getEncryptedEntries(since: string, udid = \"latest_mobile\"): Promise<unknown> {\n return this.client.get(\n `/api/v1/apigw/api/v4/phonebook/encrypted_entries?since=${encodeURIComponent(since)}&udid=${udid}`,\n );\n }\n\n async getCorporateDirectory(since?: string): Promise<unknown> {\n const params = since ? `?since=${encodeURIComponent(since)}` : \"\";\n const data = await this.client.get<unknown>(`/api/v1/corporate_directory/entries${params}`);\n if (!data) return { entries: [] };\n if (typeof data === \"object\" && data !== null && \"entries\" in data) return data;\n return data;\n }\n\n async searchUsers(query: string, limit = 20): Promise<ExpressProfile[]> {\n return this.searchUsersPhonebook(query, limit);\n }\n\n async searchUsersPhonebook(query: string, limit: number): Promise<ExpressProfile[]> {\n const data = await this.client.get<unknown>(\n `/api/v3/phonebook/search?query=${encodeURIComponent(query)}&active=true&disable_fuzzy_search=false`,\n );\n if (!data || typeof data !== \"object\") return [];\n const obj = data as Record<string, unknown>;\n const result = obj.result as Record<string, unknown> | undefined;\n const phonebook = (result?.phonebook ?? []) as Array<{ name?: string; contacts?: Array<{ user_huid?: string }> }>;\n const huids = [\n ...new Set(\n phonebook\n .flatMap((entry) => entry.contacts ?? [])\n .map((c) => c.user_huid)\n .filter(Boolean) as string[],\n ),\n ].slice(0, limit);\n if (huids.length === 0) return [];\n const raw = await this.client.rawRequest(\"/api/v1/phonebook/cts_profiles/query\", {\n method: \"POST\",\n body: JSON.stringify({ huids }),\n });\n const profileData = (await raw.json()) as { result?: Array<{ cts_profiles?: ExpressProfile[] }> };\n const entries = profileData.result ?? [];\n const profiles: ExpressProfile[] = [];\n for (const entry of entries) {\n profiles.push(...(entry.cts_profiles ?? []));\n }\n return profiles.slice(0, limit);\n }\n\n private async searchUsersApigw(query: string, limit: number, contacts: ApigwContact[]): Promise<ExpressProfile[]> {\n const lowerQuery = query.toLowerCase();\n const matched = contacts.filter((c) => {\n const searchable = [c.name, c.email, c.ad_login, c.department, c.company_position, c.phone, c.ip_phone]\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n return searchable.includes(lowerQuery);\n }).slice(0, limit);\n\n if (matched.length > 0) {\n const huids = matched.map((c) => c.huid).filter(Boolean) as string[];\n if (huids.length > 0) {\n const raw = await this.client.rawRequest(\"/api/v1/phonebook/cts_profiles/query\", {\n method: \"POST\",\n body: JSON.stringify({ huids }),\n });\n const data = (await raw.json()) as CtsProfilesResponse;\n const entries = data.result ?? (Array.isArray(data) ? data : []);\n const profiles: ExpressProfile[] = [];\n for (const entry of entries) {\n profiles.push(...(entry.cts_profiles ?? []));\n }\n return profiles.slice(0, limit);\n }\n }\n\n return [];\n }\n\n private async searchUsersDirectory(query: string, limit: number): Promise<ExpressProfile[]> {\n const dirData = await this.getCorporateDirectory() as DirectoryResponse;\n const entries = dirData?.entries ?? [];\n const userIds = entries\n .filter((e) => e.entry_type === \"user\" && !e.deleted)\n .map((e) => e.entry_id);\n\n if (userIds.length === 0) {\n return [];\n }\n\n const batchSize = 100;\n const allProfiles: ExpressProfile[] = [];\n const lowerQuery = query.toLowerCase();\n\n for (let i = 0; i < userIds.length && allProfiles.length < limit; i += batchSize) {\n const batch = userIds.slice(i, i + batchSize);\n const raw = await this.client.rawRequest(\"/api/v1/phonebook/cts_profiles/query\", {\n method: \"POST\",\n body: JSON.stringify({ huids: batch }),\n });\n const data = (await raw.json()) as CtsProfilesResponse;\n const entries = data.result ?? (Array.isArray(data) ? data : []);\n\n for (const entry of entries) {\n for (const p of entry.cts_profiles ?? []) {\n const searchable = [\n p.name,\n p.email,\n p.ad_login,\n p.department,\n p.company_position,\n p.phone,\n p.ip_phone,\n ]\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n\n if (searchable.includes(lowerQuery)) {\n allProfiles.push(p);\n if (allProfiles.length >= limit) return allProfiles;\n }\n }\n }\n }\n\n return allProfiles;\n }\n}\n","import { Command } from \"commander\";\nimport { SettingsApi } from \"../api/settings.js\";\nimport { ApiClient } from \"../api/client.js\";\nimport { formatOutput, type OutputFormat } from \"./output.js\";\n\nexport function createSettingsCommand(): Command {\n const cmd = new Command(\"settings\");\n\n cmd.description(\"Server settings and meta\");\n\n cmd\n .command(\"meta\")\n .description(\"Get server metadata\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (opts: { host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new SettingsApi(client);\n const meta = await api.getServerMeta();\n console.log(formatOutput(meta, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"get\")\n .description(\"Get settings\")\n .option(\"--since <iso-date>\", \"Since date (ISO 8601)\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (opts: { since?: string; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new SettingsApi(client);\n const settings = await api.getSettings(opts.since);\n console.log(formatOutput(settings, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { ApiClient } from \"./client.js\";\nimport type { ServerMeta } from \"../types/index.js\";\n\nexport class SettingsApi {\n constructor(private client: ApiClient) {}\n\n async getServerMeta(): Promise<ServerMeta> {\n return this.client.get<ServerMeta>(\"/api/v1/settings/server/meta/\");\n }\n\n async getSettings(since?: string): Promise<unknown> {\n const params = since ? `?since=${encodeURIComponent(since)}` : \"\";\n return this.client.get(`/api/v2/settings/${params}`);\n }\n\n async getRoles(deviceHash: string): Promise<unknown> {\n return this.client.get(`/api/v1/roles/rules?device_hash=${encodeURIComponent(deviceHash)}`);\n }\n}\n","import { Command } from \"commander\";\nimport { ChatsApi } from \"../api/chats.js\";\nimport { UserApi } from \"../api/user.js\";\nimport { ApiClient } from \"../api/client.js\";\nimport { formatOutput, type OutputFormat } from \"./output.js\";\nimport type { ExpressChat } from \"../types/index.js\";\nimport Table from \"cli-table3\";\nimport chalk from \"chalk\";\n\nasync function resolveDmNames(chats: ExpressChat[], client: ApiClient): Promise<void> {\n const dmChats = chats.filter((c) => c.chat_type === \"chat\" && c.member_huids?.length);\n if (dmChats.length === 0) return;\n try {\n const userApi = new UserApi(client);\n const self = await userApi.getSelfProfile();\n const myHuid = self.user_huid;\n const otherHuids = [...new Set(\n dmChats.flatMap((c) => (c.member_huids ?? []).filter((h) => h !== myHuid)),\n )];\n if (otherHuids.length === 0) return;\n const profiles = await userApi.getProfilesByHuid(otherHuids);\n const nameMap = new Map(profiles.map((p) => [p.user_huid, p.name]));\n for (const chat of chats) {\n if (chat.chat_type === \"chat\" && chat.member_huids) {\n const otherHuid = chat.member_huids.find((h) => h !== myHuid);\n if (otherHuid) chat.name = nameMap.get(otherHuid) ?? chat.name;\n }\n }\n } catch (err) {\n if (process.env.EXPRESS_DEBUG) {\n console.error(` [DEBUG] Failed to resolve DM names: ${(err as Error).message}`);\n }\n }\n}\n\nfunction typeLabel(chatType: string): string {\n if (chatType === \"channel\" || chatType === \"global\") return chalk.magenta(chatType);\n if (chatType === \"group_chat\") return chalk.blue(\"group\");\n if (chatType === \"chat\") return chalk.green(\"dm\");\n return chalk.gray(chatType);\n}\n\nfunction memberCount(c: ExpressChat): string {\n return c.members_count != null ? String(c.members_count) :\n c.member_huids?.length != null ? String(c.member_huids.length) : \"-\";\n}\n\nexport function createChatsCommand(): Command {\n const cmd = new Command(\"chats\");\n\n cmd.description(\"Chat management\");\n\n cmd\n .command(\"list\")\n .description(\"List all chats (uses WebSocket for full list)\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"--type <type>\", \"Filter by type: dm, group, channel, all\", \"all\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (opts: { host?: string; type: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new ChatsApi(client);\n let chats = await api.listChats();\n\n await resolveDmNames(chats, client);\n\n if (opts.type !== \"all\") {\n const typeMap: Record<string, string[]> = {\n dm: [\"chat\"],\n group: [\"group_chat\"],\n channel: [\"channel\", \"global\"],\n };\n const allowed = typeMap[opts.type] ?? [];\n chats = chats.filter((c) => allowed.includes(c.chat_type));\n }\n\n if (opts.output === \"json\") {\n console.log(formatOutput(chats, \"json\"));\n return;\n }\n\n const table = new Table({\n head: [\"Name\", \"Type\", \"Members\", \"Chat ID\"],\n style: { head: [\"cyan\"] },\n });\n\n for (const c of chats) {\n table.push([c.name ?? \"-\", typeLabel(c.chat_type), memberCount(c), c.group_chat_id.slice(0, 8) + \"...\"]);\n }\n\n console.log(table.toString());\n console.log(chalk.gray(` ${chats.length} chats`));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"find <query>\")\n .description(\"Find chats by name (case-insensitive), shows full IDs\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"--type <type>\", \"Filter by type: dm, group, channel, all\", \"all\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (query: string, opts: { host?: string; type: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new ChatsApi(client);\n let chats = await api.listChats();\n\n await resolveDmNames(chats, client);\n\n const lowerQuery = query.toLowerCase();\n chats = chats.filter((c) => (c.name ?? \"\").toLowerCase().includes(lowerQuery));\n\n if (opts.type !== \"all\") {\n const typeMap: Record<string, string[]> = {\n dm: [\"chat\"],\n group: [\"group_chat\"],\n channel: [\"channel\", \"global\"],\n };\n const allowed = typeMap[opts.type] ?? [];\n chats = chats.filter((c) => allowed.includes(c.chat_type));\n }\n\n if (chats.length === 0) {\n console.log(chalk.yellow(`No chats matching \"${query}\".`));\n return;\n }\n\n if (opts.output === \"json\") {\n console.log(formatOutput(chats, \"json\"));\n return;\n }\n\n const table = new Table({\n head: [\"Name\", \"Type\", \"Members\", \"Chat ID (full)\"],\n style: { head: [\"cyan\"] },\n });\n\n for (const c of chats) {\n table.push([c.name ?? \"-\", typeLabel(c.chat_type), memberCount(c), c.group_chat_id]);\n }\n\n console.log(table.toString());\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"info <chat-id>\")\n .description(\"Get chat details\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (chatId: string, opts: { host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new ChatsApi(client);\n const chat = await api.getChatInfo(chatId);\n if (!chat) {\n console.error(`Chat not found: ${chatId}`);\n process.exit(1);\n }\n console.log(formatOutput(chat, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport { MessagingApi } from \"../api/messaging.js\";\nimport { sendMessageViaWebSocket } from \"../api/messaging-ws.js\";\nimport { ApiClient } from \"../api/client.js\";\nimport { resolveChatId } from \"../api/resolve.js\";\nimport { formatOutput, type OutputFormat } from \"./output.js\";\nimport { readFileSync } from \"node:fs\";\n\nexport function createSendCommand(): Command {\n const cmd = new Command(\"send\");\n\n cmd.description(\"Send messages and files\");\n\n cmd\n .command(\"message <chat-id-or-name> <text>\")\n .description(\"Send a text message to a chat (chat ID or partial name)\")\n .option(\"--stealth\", \"Send in stealth mode\", false)\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (chatIdOrName: string, text: string, opts: { stealth: boolean; host?: string; output: OutputFormat }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const chatId = await resolveChatId(client, chatIdOrName);\n const result = await sendMessageViaWebSocket({ client, chatId, body: text });\n console.log(formatOutput(result, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"file <chat-id> <file-path>\")\n .description(\"Send a file to a chat\")\n .option(\"--caption <caption>\", \"File caption\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"json\")\n .action(async (chatId: string, filePath: string, opts: { caption?: string; host?: string; output: OutputFormat }) => {\n try {\n const data = readFileSync(filePath);\n const fileName = filePath.split(\"/\").pop() ?? \"file\";\n const mimeMap: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".pdf\": \"application/pdf\",\n \".txt\": \"text/plain\",\n \".json\": \"application/json\",\n \".csv\": \"text/csv\",\n \".zip\": \"application/zip\",\n };\n const ext = fileName.includes(\".\") ? \".\" + fileName.split(\".\").pop()!.toLowerCase() : \"\";\n const mime = mimeMap[ext] ?? \"application/octet-stream\";\n const base64 = data.toString(\"base64\");\n const dataUri = `data:${mime};base64,${base64}`;\n\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const api = new MessagingApi(client);\n const result = await api.sendFile({\n groupChatId: chatId,\n fileName,\n fileData: dataUri,\n caption: opts.caption,\n });\n console.log(formatOutput(result, opts.output));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { ApiClient } from \"./client.js\";\n\nexport interface SendMessagePayload {\n group_chat_id: string;\n notification: {\n status: \"ok\" | \"error\";\n body: string;\n metadata?: Record<string, unknown>;\n mentions?: Record<string, unknown>;\n opts?: {\n stealth_mode?: boolean;\n notification_opts?: {\n send?: boolean;\n force_dnd?: boolean;\n };\n };\n };\n file?: {\n file_name: string;\n data: string;\n };\n}\n\nexport class MessagingApi {\n constructor(private client: ApiClient) {}\n\n async sendMessage(params: {\n groupChatId: string;\n body: string;\n metadata?: Record<string, unknown>;\n mentions?: Record<string, unknown>;\n stealthMode?: boolean;\n }): Promise<unknown> {\n const payload: SendMessagePayload = {\n group_chat_id: params.groupChatId,\n notification: {\n status: \"ok\",\n body: params.body,\n ...(params.metadata && { metadata: params.metadata }),\n ...(params.mentions && { mentions: params.mentions }),\n ...(params.stealthMode && {\n opts: { stealth_mode: true },\n }),\n },\n };\n\n return this.client.post(\"/api/v4/botx/notifications/direct\", payload);\n }\n\n async sendFile(params: {\n groupChatId: string;\n fileName: string;\n fileData: string;\n caption?: string;\n }): Promise<unknown> {\n const payload: SendMessagePayload = {\n group_chat_id: params.groupChatId,\n notification: {\n status: \"ok\",\n body: params.caption ?? \"\",\n },\n file: {\n file_name: params.fileName,\n data: params.fileData,\n },\n };\n\n return this.client.post(\"/api/v4/botx/notifications/direct\", payload);\n }\n}\n","import { randomBytes, randomUUID } from \"node:crypto\";\nimport nacl from \"tweetnacl\";\nimport sodium from \"libsodium-wrappers-sumo\";\nimport type { ApiClient } from \"./client.js\";\nimport { UserApi } from \"./user.js\";\nimport { loadApigwKeys, signEd25519 } from \"../auth/keys.js\";\nimport { getAuthToken } from \"../config/store.js\";\nimport { loadConfig, getBaseUrl, getWebOrigin } from \"../config/index.js\";\n\n/**\n * Build the wire plaintext for a text message. Shape reverse-engineered from the\n * eXpress web client (`encryptMessagePayload` in app.js): a flat snake_case\n * object with `body` (plain text) — the client generates the markdown AST from\n * `body` on receipt, so no bodyAstTree on the wire. A bare `{body}` makes\n * recipients show \"Can't decrypt\".\n */\nfunction buildTextPayload(text: string, fromHuid: string, chatId: string): string {\n return JSON.stringify({\n type: \"text\",\n msg_id: randomUUID(),\n from: fromHuid,\n timestamp: new Date().toISOString(),\n group_chat_id: chatId,\n lat: 0,\n lng: 0,\n link_meta_disabled: false,\n stealth_forwarding: false,\n body: text,\n });\n}\n\n/** AEAD additional data — must match the client: `${groupChatId}:${syncId}`. */\nfunction payloadAad(chatId: string, syncId: string): Uint8Array {\n return new Uint8Array(Buffer.from(`${chatId}:${syncId}`));\n}\n\ninterface KdcKey {\n id: string;\n body: string; // base64 Curve25519 public key\n algo: string;\n kind: string;\n user_huid: string;\n}\n\ninterface EncryptedKey {\n key_id: string;\n key: string; // base64 nonce+ciphertext\n algo: string;\n}\n\nexport async function sendMessageViaWebSocket(params: {\n client: ApiClient;\n chatId: string;\n body: string;\n timeoutMs?: number;\n}): Promise<{ sync_id: string }> {\n const { client, chatId, body, timeoutMs = 20000 } = params;\n\n await sodium.ready;\n\n const apigwKeys = loadApigwKeys();\n if (!apigwKeys) throw new Error(\"No apigw keys. Run 'express auth login' first.\");\n\n const config = loadConfig();\n const host = new URL(getBaseUrl(config)).hostname;\n const webOrigin = getWebOrigin(config);\n const ctsToken = getAuthToken();\n const ctsKey = apigwKeys.ctsKey ?? apigwKeys.encryptionKey;\n const encKeyId = ctsKey.keyId;\n\n // Step 1: get participant key_ids via WebSocket chat_info.\n // The server rejects message_new with `invalid_keys` unless keys[] matches this\n // set exactly — no extra/superseded key_ids allowed, so encrypt for these only.\n const participantKeyIds = await getChatKeyIds(host, webOrigin, ctsToken, encKeyId, chatId);\n\n // Step 2: fetch public keys from KDC (only cts keys are usable for E2E)\n const kdcKeys = await client.get<KdcKey[]>(\n `/api/v1/kdc/keys/?ids=${participantKeyIds.join(\",\")}`,\n ) ?? [];\n const publicKeys = kdcKeys.filter((k) => k.kind === \"cts\");\n\n // Step 3: generate symmetric key + sync_id (sync_id is part of the body AAD)\n const symmetricKey = randomBytes(32);\n const syncId = randomUUID();\n\n // Step 4: encrypt symmetric key for each participant\n const encryptedKeys: EncryptedKey[] = publicKeys.map((kdcKey) => {\n const recipientPubKey = new Uint8Array(Buffer.from(kdcKey.body, \"base64\"));\n const nonce = randomBytes(nacl.box.nonceLength);\n const ciphertext = nacl.box(\n symmetricKey,\n nonce,\n recipientPubKey,\n ctsKey.privateKey,\n );\n if (!ciphertext) throw new Error(`Failed to encrypt key for ${kdcKey.id}`);\n const combined = Buffer.concat([nonce, Buffer.from(ciphertext)]);\n return {\n key_id: kdcKey.id,\n key: combined.toString(\"base64\"),\n algo: \"xsalsa20:xchacha20_aead_ietf\",\n };\n });\n\n // Step 5: encrypt message body with XChaCha20-Poly1305 IETF.\n // AAD = `${group_chat_id}:${sync_id}` — recipients authenticate against it, so\n // it must match or they get \"Can't decrypt\".\n const selfHuid = (await new UserApi(client).getSelfProfile()).user_huid;\n const plaintext = new Uint8Array(Buffer.from(buildTextPayload(body, selfHuid, chatId)));\n const msgNonce = randomBytes(sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);\n const ciphertext = sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(\n plaintext, payloadAad(chatId, syncId), null,\n new Uint8Array(msgNonce),\n new Uint8Array(symmetricKey),\n );\n const encryptedPayload = Buffer.concat([msgNonce, Buffer.from(ciphertext)]).toString(\"base64\");\n\n // Step 6: send via WebSocket (no signature required for DMs)\n // Sign the base64 payload string with ed25519 (browser requires this to decrypt)\n const signingKey = apigwKeys.signingKey;\n const signBytes = signEd25519(\n signingKey.privateKey,\n new Uint8Array(Buffer.from(encryptedPayload, \"utf8\")),\n );\n const signature = {\n sign: Buffer.from(signBytes).toString(\"base64\"),\n sign_key_id: signingKey.keyId,\n sign_algo: \"ed25519\",\n };\n\n return sendMessageNew({\n host,\n webOrigin,\n ctsToken,\n encKeyId,\n chatId,\n syncId,\n encryptedKeys,\n encryptedPayload,\n signature,\n timeoutMs,\n });\n}\n\nasync function getChatKeyIds(\n host: string,\n webOrigin: string,\n ctsToken: string,\n encKeyId: string,\n chatId: string,\n): Promise<string[]> {\n const wsUrl = `wss://${host}/socket/user/websocket?vsn=1.0.0&auto_join=true&key_id=${encKeyId}&version=6&background=false&voex_unencrypted=true&instance_id=${randomUUID()}`;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const done = (fn: () => void) => { if (!settled) { settled = true; fn(); } };\n const timer = setTimeout(() => {\n try { ws.close(); } catch {}\n done(() => reject(new Error(\"Timeout getting chat key_ids\")));\n }, 10000);\n\n const ws = new WebSocket(wsUrl, {\n headers: { Origin: webOrigin, \"User-Agent\": \"Mozilla/5.0\" },\n } as ConstructorParameters<typeof WebSocket>[1]);\n\n let ref = 0;\n const authRef = ref++;\n let chatInfoRef: number;\n\n const send = (msg: object) => ws.send(JSON.stringify(msg));\n\n ws.addEventListener(\"open\", () => {\n send({ topic: \"phoenix\", event: \"authenticate\", payload: { token: ctsToken }, ref: authRef });\n });\n\n ws.addEventListener(\"message\", (e) => {\n const msg = JSON.parse(e.data as string) as {\n ref: number; event: string; topic: string;\n payload: { status: string; response: Record<string, unknown> };\n };\n\n if (msg.ref === authRef && msg.event === \"phx_reply\" && msg.payload?.status === \"ok\") {\n chatInfoRef = ref++;\n send({ topic: \"system\", event: \"chat_info\", payload: { group_chat_id: chatId, request_version: 6 }, ref: chatInfoRef });\n return;\n }\n\n if (msg.ref === chatInfoRef && msg.event === \"phx_reply\") {\n clearTimeout(timer);\n ws.close();\n const chatInfo = (msg.payload?.response?.chat_info ?? msg.payload?.response) as Record<string, unknown>;\n const keys = (chatInfo?.keys as string[]) ?? [];\n done(() => resolve(keys));\n }\n });\n\n ws.addEventListener(\"error\", (err) => {\n clearTimeout(timer);\n done(() => reject(new Error(`WS error: ${String(err)}`)));\n });\n\n ws.addEventListener(\"close\", () => {\n clearTimeout(timer);\n done(() => reject(new Error(\"WS closed before chat_info\")));\n });\n });\n}\n\nasync function sendMessageNew(params: {\n host: string;\n webOrigin: string;\n ctsToken: string;\n encKeyId: string;\n chatId: string;\n syncId: string;\n encryptedKeys: EncryptedKey[];\n encryptedPayload: string;\n signature: { sign: string; sign_key_id: string; sign_algo: string };\n timeoutMs: number;\n}): Promise<{ sync_id: string }> {\n const { host, webOrigin, ctsToken, encKeyId, chatId, syncId, encryptedKeys, encryptedPayload, signature, timeoutMs } = params;\n const wsUrl = `wss://${host}/socket/user/websocket?vsn=1.0.0&auto_join=true&key_id=${encKeyId}&version=6&background=false&voex_unencrypted=true&instance_id=${randomUUID()}`;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const done = (fn: () => void) => { if (!settled) { settled = true; fn(); } };\n const timer = setTimeout(() => {\n try { ws.close(); } catch {}\n done(() => reject(new Error(\"Timeout sending message\")));\n }, timeoutMs);\n\n const ws = new WebSocket(wsUrl, {\n headers: { Origin: webOrigin, \"User-Agent\": \"Mozilla/5.0\" },\n } as ConstructorParameters<typeof WebSocket>[1]);\n\n let ref = 0;\n const authRef = ref++;\n let msgRef: number;\n\n const send = (msg: object) => ws.send(JSON.stringify(msg));\n\n ws.addEventListener(\"open\", () => {\n send({ topic: \"phoenix\", event: \"authenticate\", payload: { token: ctsToken }, ref: authRef });\n });\n\n ws.addEventListener(\"message\", (e) => {\n const msg = JSON.parse(e.data as string) as {\n ref: number; event: string; topic: string;\n payload: { status: string; response: Record<string, unknown> };\n };\n\n if (msg.ref === authRef && msg.event === \"phx_reply\" && msg.payload?.status === \"ok\") {\n msgRef = ref++;\n send({\n topic: `groupchat:${chatId}`,\n event: \"message_new\",\n payload: {\n keys: encryptedKeys,\n group_chat_id: chatId,\n sync_id: syncId,\n payload: encryptedPayload,\n signature,\n },\n ref: msgRef,\n });\n return;\n }\n\n if (msg.ref === msgRef && msg.event === \"phx_reply\") {\n clearTimeout(timer);\n ws.close();\n if (msg.payload?.status === \"ok\") {\n done(() => resolve({ sync_id: syncId }));\n } else {\n done(() => reject(new Error(`message_new failed: ${JSON.stringify(msg.payload?.response)}`)));\n }\n }\n });\n\n ws.addEventListener(\"error\", (err) => {\n clearTimeout(timer);\n done(() => reject(new Error(`WS error: ${String(err)}`)));\n });\n\n ws.addEventListener(\"close\", () => {\n clearTimeout(timer);\n done(() => reject(new Error(\"WS closed before message_new reply\")));\n });\n });\n}\n","import { ApiClient } from \"./client.js\";\nimport { ChatsApi } from \"./chats.js\";\nimport { UserApi } from \"./user.js\";\nimport type { ExpressChat } from \"../types/index.js\";\n\n/** List chats with DM display names resolved to the other participant's full name. */\nexport async function listChatsWithNames(client: ApiClient): Promise<ExpressChat[]> {\n const chats = await new ChatsApi(client).listChats();\n const dmChats = chats.filter((c) => c.chat_type === \"chat\" && c.member_huids?.length);\n if (dmChats.length === 0) return chats;\n\n const userApi = new UserApi(client);\n const myHuid = (await userApi.getSelfProfile()).user_huid;\n const otherHuids = [...new Set(dmChats.flatMap((c) => (c.member_huids ?? []).filter((h) => h !== myHuid)))];\n if (otherHuids.length === 0) return chats;\n\n const nameMap = new Map((await userApi.getProfilesByHuid(otherHuids)).map((p) => [p.user_huid, p.name]));\n for (const chat of chats) {\n if (chat.chat_type === \"chat\" && chat.member_huids) {\n const other = chat.member_huids.find((h) => h !== myHuid);\n if (other) chat.name = nameMap.get(other) ?? chat.name;\n }\n }\n return chats;\n}\n\n/** Resolve a chat name (partial match) or UUID to a full chat_id. Throws on 0/many matches. */\nexport async function resolveChatId(client: ApiClient, chatIdOrName: string): Promise<string> {\n if (/^[0-9a-f-]{36}$/i.test(chatIdOrName)) return chatIdOrName;\n\n const chats = await listChatsWithNames(client);\n const lower = chatIdOrName.toLowerCase();\n const matches = chats.filter((c) => (c.name ?? \"\").toLowerCase().includes(lower));\n if (matches.length === 0) throw new Error(`No chat found matching \"${chatIdOrName}\"`);\n if (matches.length > 1) {\n const names = matches.map((c) => ` ${c.name} (${c.group_chat_id})`).join(\"\\n\");\n throw new Error(`Multiple chats match \"${chatIdOrName}\":\\n${names}\\nUse the full chat ID.`);\n }\n return matches[0].group_chat_id;\n}\n","import { Command } from \"commander\";\nimport { ApiClient } from \"../api/client.js\";\nimport { UserApi } from \"../api/user.js\";\nimport { UploadsApi } from \"../api/uploads.js\";\nimport { formatProfileTable, formatOutput, type OutputFormat } from \"./output.js\";\nimport { writeFileSync } from \"node:fs\";\n\nexport function createAvatarCommand(): Command {\n const cmd = new Command(\"avatar\");\n\n cmd.description(\"Download user avatars\");\n\n cmd\n .command(\"get <huid>\")\n .description(\"Download avatar for a user by HUID\")\n .option(\"-o, --output <path>\", \"Output file path (default: <huid>.png)\")\n .option(\"--host <host>\", \"eXpress host\")\n .action(async (huid: string, opts: { output?: string; host?: string }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const userApi = new UserApi(client);\n const uploadsApi = new UploadsApi(client);\n\n const profiles = await userApi.getProfilesByHuid([huid]);\n const profile = profiles?.[0];\n const avatarUrl = profile?.custom_avatar ?? profile?.avatar;\n\n if (!avatarUrl) {\n console.log(\"No avatar found for this user.\");\n return;\n }\n\n const { data, contentType } = await uploadsApi.download(avatarUrl);\n const ext = contentType?.includes(\"jpeg\") ? \".jpg\" : contentType?.includes(\"png\") ? \".png\" : \".png\";\n const outputPath = opts.output ?? `${huid}${ext}`;\n\n writeFileSync(outputPath, Buffer.from(data));\n console.log(`Avatar saved to ${outputPath}`);\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n cmd\n .command(\"self\")\n .description(\"Download your own avatar\")\n .option(\"-o, --output <path>\", \"Output file path (default: self_avatar.png)\")\n .option(\"--host <host>\", \"eXpress host\")\n .action(async (opts: { output?: string; host?: string }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const userApi = new UserApi(client);\n const uploadsApi = new UploadsApi(client);\n\n const profile = await userApi.getSelfProfile();\n const avatarUrl = profile.custom_avatar ?? profile.avatar;\n\n if (!avatarUrl) {\n console.log(\"No avatar found for your profile.\");\n return;\n }\n\n const { data, contentType } = await uploadsApi.download(avatarUrl);\n const ext = contentType?.includes(\"jpeg\") ? \".jpg\" : contentType?.includes(\"png\") ? \".png\" : \".png\";\n const outputPath = opts.output ?? `self_avatar${ext}`;\n\n writeFileSync(outputPath, Buffer.from(data));\n console.log(`Avatar saved to ${outputPath}`);\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { ApiClient } from \"./client.js\";\n\nexport class UploadsApi {\n constructor(private client: ApiClient) {}\n\n async downloadAvatar(huid: string): Promise<{ data: ArrayBuffer; contentType: string | null } | null> {\n const profile = await this.client.get<{ custom_avatar?: string; avatar?: string }>(\n `/api/v1/phonebook/cts_profiles/query`,\n );\n return null;\n }\n\n async download(url: string): Promise<{ data: ArrayBuffer; contentType: string | null }> {\n const res = await this.client.downloadFile(url);\n if (!res.ok) {\n throw new Error(`Download failed: ${res.status} ${res.statusText}`);\n }\n const data = await res.arrayBuffer();\n const contentType = res.headers.get(\"content-type\");\n return { data, contentType };\n }\n}\n","import { Command } from \"commander\";\nimport { ApiClient } from \"../api/client.js\";\nimport { UploadsApi } from \"../api/uploads.js\";\nimport { writeFileSync } from \"node:fs\";\n\nexport function createDownloadCommand(): Command {\n const cmd = new Command(\"download\");\n\n cmd\n .description(\"Download a file from eXpress uploads\")\n .argument(\"<url>\", \"Full URL or path (e.g. /uploads/files/...)\")\n .option(\"-o, --output <path>\", \"Output file path (default: auto from URL)\")\n .option(\"--host <host>\", \"eXpress host\")\n .action(async (url: string, opts: { output?: string; host?: string }) => {\n try {\n const client = new ApiClient(opts.host ? { host: opts.host } : undefined);\n const uploadsApi = new UploadsApi(client);\n\n const { data, contentType } = await uploadsApi.download(url);\n const urlPath = new URL(url.startsWith(\"http\") ? url : `https://x${url}`).pathname;\n const baseName = urlPath.split(\"/\").pop() ?? \"download\";\n const outputPath = opts.output ?? baseName;\n\n writeFileSync(outputPath, Buffer.from(data));\n console.log(`Downloaded to ${outputPath} (${contentType ?? \"unknown\"}, ${data.byteLength} bytes)`);\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from \"commander\";\nimport { readMessages } from \"../api/messages-read.js\";\nimport { formatOutput, type OutputFormat } from \"./output.js\";\n\nexport function createMessagesCommand(): Command {\n const cmd = new Command(\"messages\");\n\n cmd.description(\"Read and decrypt chat messages\");\n\n cmd\n .command(\"list <chat-id>\")\n .description(\"List recent messages from a chat\")\n .option(\"-n, --limit <number>\", \"Number of messages\", \"20\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"-o, --output <format>\", \"Output format\", \"table\")\n .action(async (chatId: string, opts: { limit: string; host?: string; output: OutputFormat }) => {\n try {\n const messages = await readMessages({\n chatId,\n limit: parseInt(opts.limit, 10) || 20,\n host: opts.host,\n });\n\n if (opts.output === \"json\") {\n console.log(formatOutput(messages, opts.output));\n return;\n }\n\n for (const msg of messages) {\n const time = msg.inserted_at ? new Date(msg.inserted_at).toLocaleString(\"ru-RU\") : \"?\";\n const sender = msg.sender ? msg.sender.slice(0, 8) + \"...\" : \"unknown\";\n if (msg.decrypted) {\n console.log(`[${time}] ${sender}: ${msg.body}`);\n } else {\n console.log(`[${time}] ${sender}: [DECRYPT FAILED: ${msg.error}]`);\n }\n }\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { randomUUID } from \"node:crypto\";\nimport { loadApigwKeys } from \"../auth/keys.js\";\nimport { getAuthToken } from \"../config/store.js\";\nimport { loadConfig, getBaseUrl, getWebOrigin } from \"../config/index.js\";\nimport { decryptMessages, type HistoryMessage, type DecryptedMessage } from \"./decrypt.js\";\n\nexport async function readMessages(params: {\n chatId: string;\n limit?: number;\n timeoutMs?: number;\n direction?: \"backward\" | \"forward\";\n host?: string;\n}): Promise<DecryptedMessage[]> {\n const { chatId, limit = 20, timeoutMs = 20000, direction = \"backward\", host } = params;\n\n const apigwKeys = loadApigwKeys();\n if (!apigwKeys) throw new Error(\"No apigw keys. Run 'express auth login' first.\");\n\n const config = loadConfig(host ? { host } : {});\n const ctsHost = new URL(getBaseUrl(config)).hostname;\n const webOrigin = getWebOrigin(config);\n const ctsToken = getAuthToken();\n const ctsKey = apigwKeys.ctsKey ?? apigwKeys.encryptionKey;\n\n const history = await fetchEventsHistory(ctsHost, webOrigin, ctsToken, ctsKey.keyId, chatId, limit, timeoutMs, direction);\n return decryptMessages(history, apigwKeys);\n}\n\nasync function fetchEventsHistory(\n host: string,\n webOrigin: string,\n ctsToken: string,\n encKeyId: string,\n chatId: string,\n limit: number,\n timeoutMs: number,\n direction: \"backward\" | \"forward\" = \"backward\",\n): Promise<HistoryMessage[]> {\n const wsUrl = `wss://${host}/socket/user/websocket?vsn=1.0.0&auto_join=true&key_id=${encKeyId}&version=6&background=false&voex_unencrypted=true&instance_id=${randomUUID()}`;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const done = (fn: () => void) => { if (!settled) { settled = true; fn(); } };\n const timer = setTimeout(() => {\n try { ws.close(); } catch {}\n done(() => reject(new Error(\"Timeout fetching messages\")));\n }, timeoutMs);\n\n const ws = new WebSocket(wsUrl, {\n headers: { Origin: webOrigin, \"User-Agent\": \"Mozilla/5.0\" },\n } as ConstructorParameters<typeof WebSocket>[1]);\n\n let ref = 0;\n const authRef = ref++;\n let subRef = 0;\n let histRef = 0;\n\n const send = (msg: object) => ws.send(JSON.stringify(msg));\n\n ws.addEventListener(\"open\", () => {\n send({ topic: \"phoenix\", event: \"authenticate\", payload: { token: ctsToken }, ref: authRef });\n });\n\n ws.addEventListener(\"message\", (e) => {\n const msg = JSON.parse(e.data as string) as {\n ref: number | string; event: string; topic: string;\n payload: Record<string, unknown>;\n };\n\n const msgRef = typeof msg.ref === \"string\" ? parseInt(msg.ref, 10) : msg.ref;\n\n if (msgRef === authRef && msg.event === \"phx_reply\" && msg.payload?.status === \"ok\") {\n subRef = ref++;\n send({ topic: `groupchat:${chatId}`, event: \"subscribe_to_chat_activities\", payload: { group_chat_id: chatId }, ref: subRef });\n return;\n }\n\n if (msgRef === subRef && msg.event === \"phx_reply\") {\n histRef = ref++;\n send({\n topic: `groupchat:${chatId}`,\n event: \"events_history\",\n payload: {\n direction,\n group_chat_id: chatId,\n limit,\n skip_non_affecting_rc: true,\n skip_to_sync_id_event: true,\n last_ignore_messages_at: null,\n },\n ref: histRef,\n });\n return;\n }\n\n if (msgRef === histRef && msg.event === \"phx_reply\") {\n clearTimeout(timer);\n ws.close();\n const response = (msg.payload?.response ?? msg.payload) as Record<string, unknown>;\n const history = (response?.history ?? []) as HistoryMessage[];\n done(() => resolve(Array.isArray(history) ? history : []));\n return;\n }\n });\n\n ws.addEventListener(\"error\", (err) => {\n clearTimeout(timer);\n done(() => reject(new Error(`WS error: ${String(err)}`)));\n });\n\n ws.addEventListener(\"close\", () => {\n clearTimeout(timer);\n done(() => reject(new Error(\"WS closed before messages received\")));\n });\n });\n}\n","import nacl from \"tweetnacl\";\nimport sodium from \"libsodium-wrappers-sumo\";\nimport { loadApigwKeys } from \"../auth/keys.js\";\nimport { ApiClient } from \"./client.js\";\n\nexport interface HistoryMessage {\n sync_id: string;\n payload: string;\n key: { algo: string; key: string; key_id: string };\n sender: string;\n sender_key_id: string;\n group_chat_id: string;\n inserted_at: string;\n event_type: string;\n}\n\nexport interface ImageAttachment {\n fileName: string;\n mimeType?: string;\n /** Inline base64 data-URI (blur_preview_file) — renderable without download/decryption. */\n previewDataUri?: string;\n width?: number;\n height?: number;\n}\n\nexport interface DecryptedMessage {\n sync_id: string;\n body: string;\n sender: string;\n inserted_at: string;\n decrypted: boolean;\n error?: string;\n type?: string;\n image?: ImageAttachment;\n}\n\ntype KdcKeyMap = Map<string, { id: string; body: string; user_huid: string }>;\ntype ApigwKeys = NonNullable<ReturnType<typeof loadApigwKeys>>;\n\n/**\n * Decrypt a single history/message_new event.\n * E2E: nacl.box.open(encrypted symmetric key) → XChaCha20-Poly1305 IETF body,\n * with AAD `${group_chat_id}:${sync_id}` (must match the sender).\n */\nfunction decryptMessage(\n msg: HistoryMessage,\n ctsPrivateKey: Uint8Array,\n myKeyId: string,\n keyMap: KdcKeyMap,\n apigwKeys: ApigwKeys,\n): DecryptedPayload {\n const encKey = msg.key;\n if (encKey.key_id !== myKeyId) {\n throw new Error(`key not for us (key_id=${encKey.key_id}, myKeyId=${myKeyId})`);\n }\n\n const keyRaw = Uint8Array.from(Buffer.from(encKey.key, \"base64\"));\n const nonce = keyRaw.slice(0, nacl.box.nonceLength);\n const ciphertext = keyRaw.slice(nacl.box.nonceLength);\n\n const senderPubKey = getSenderPublicKey(msg, keyMap, apigwKeys);\n if (!senderPubKey) throw new Error(\"cannot determine sender public key\");\n\n const symmetricKey = nacl.box.open(ciphertext, nonce, senderPubKey, ctsPrivateKey);\n if (!symmetricKey) throw new Error(\"nacl.box.open failed — wrong key pair\");\n\n const payloadRaw = Uint8Array.from(Buffer.from(msg.payload, \"base64\"));\n const msgNonce = payloadRaw.slice(0, sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);\n const msgCiphertext = payloadRaw.slice(sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);\n\n const aad = new Uint8Array(Buffer.from(`${msg.group_chat_id}:${msg.sync_id}`));\n const plaintext = sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(null, msgCiphertext, aad, msgNonce, symmetricKey);\n\n return JSON.parse(new TextDecoder().decode(plaintext)) as DecryptedPayload;\n}\n\n/** Shape of the decrypted wire payload (text or image message). */\ninterface DecryptedPayload {\n type?: string;\n body?: string;\n payload?: {\n file_name?: string;\n file_mime_type?: string;\n blur_preview_file?: string;\n file_preview_width?: number;\n file_preview_height?: number;\n };\n}\n\nfunction toDecrypted(msg: HistoryMessage, payload: DecryptedPayload): DecryptedMessage {\n const base = { sync_id: msg.sync_id, sender: msg.sender ?? \"\", inserted_at: msg.inserted_at, decrypted: true, type: payload.type };\n if (payload.type === \"image\" && payload.payload) {\n const p = payload.payload;\n return {\n ...base,\n body: payload.body ?? \"\",\n image: {\n fileName: p.file_name ?? \"image\",\n mimeType: p.file_mime_type,\n previewDataUri: p.blur_preview_file,\n width: p.file_preview_width,\n height: p.file_preview_height,\n },\n };\n }\n return { ...base, body: payload.body ?? \"\" };\n}\n\nexport function getSenderPublicKey(\n msg: HistoryMessage,\n keyMap: KdcKeyMap,\n apigwKeys: ApigwKeys,\n): Uint8Array | null {\n const senderKeyId = msg.sender_key_id;\n if (!senderKeyId) return null;\n\n if (senderKeyId === apigwKeys.ctsKey?.keyId) return apigwKeys.ctsKey.publicKey;\n if (senderKeyId === apigwKeys.encryptionKey?.keyId) return apigwKeys.encryptionKey.publicKey;\n\n const kdcKey = keyMap.get(senderKeyId);\n if (kdcKey) return new Uint8Array(Buffer.from(kdcKey.body, \"base64\"));\n return null;\n}\n\n/**\n * Fetch the sender public keys from KDC and decrypt a batch of message events.\n * Shared by `messages list` and the live session layer.\n */\nexport async function decryptMessages(\n events: HistoryMessage[],\n apigwKeys: ApigwKeys,\n client: ApiClient = new ApiClient(),\n): Promise<DecryptedMessage[]> {\n await sodium.ready;\n const ctsKey = apigwKeys.ctsKey ?? apigwKeys.encryptionKey;\n const messages = events.filter((e) => e.event_type === \"message_new\" && e.payload && e.key);\n if (messages.length === 0) return [];\n\n const keyIds = [...new Set([\n ...messages.map((m) => m.sender_key_id).filter(Boolean),\n ...messages.map((m) => m.key.key_id),\n ])];\n const kdcKeys = await client.get<Array<{ id: string; body: string; user_huid: string }>>(\n `/api/v1/kdc/keys/?ids=${keyIds.join(\",\")}`,\n ) ?? [];\n const keyMap: KdcKeyMap = new Map(kdcKeys.map((k) => [k.id, k]));\n\n return messages.map((msg) => {\n try {\n return toDecrypted(msg, decryptMessage(msg, ctsKey.privateKey, ctsKey.keyId, keyMap, apigwKeys));\n } catch (err) {\n return { sync_id: msg.sync_id, body: \"\", sender: msg.sender ?? \"\", inserted_at: msg.inserted_at, decrypted: false, error: (err as Error).message };\n }\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { ExpressSession, type SessionMessage, type SessionActivity } from \"../session/session.js\";\nimport type { ExpressChat } from \"../types/index.js\";\n\nexport function createListenCommand(): Command {\n const cmd = new Command(\"listen\");\n\n cmd\n .description(\"Open a persistent session and stream incoming messages/notifications\")\n .option(\"--host <host>\", \"eXpress host\")\n .option(\"--activity\", \"Also print raw activity events (before decryption)\", false)\n .action(async (opts: { host?: string; activity?: boolean }) => {\n let session: ExpressSession;\n try {\n session = new ExpressSession();\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n\n const names = new Map<string, string>();\n const label = (chatId: string) => names.get(chatId) ?? chatId.slice(0, 8);\n const ts = (iso: string) => (iso ? new Date(iso).toLocaleTimeString(\"ru-RU\") : new Date().toLocaleTimeString(\"ru-RU\"));\n\n session.on(\"connected\", () => console.log(chalk.green(\"● connected\")));\n\n session.on(\"chats\", (chats: ExpressChat[]) => {\n for (const c of chats) {\n const id = (c as { group_chat_id?: string; id?: string }).group_chat_id ?? (c as { id?: string }).id;\n const name = (c as { name?: string }).name;\n if (id) names.set(id, name || id.slice(0, 8));\n }\n console.log(chalk.dim(` ${chats.length} chats loaded, subscribing to activity…`));\n });\n\n if (opts.activity) {\n session.on(\"activity\", (a: SessionActivity) => {\n console.log(chalk.dim(` · activity in ${label(a.chatId)} (${a.syncId.slice(0, 8)})`));\n });\n }\n\n session.on(\"message\", (m: SessionMessage) => {\n const who = m.sender.slice(0, 8);\n if (m.decrypted) {\n console.log(`${chalk.dim(`[${ts(m.insertedAt)}]`)} ${chalk.cyan(label(m.chatId))} ${chalk.yellow(who)}: ${m.body}`);\n } else {\n console.log(`${chalk.dim(`[${ts(m.insertedAt)}]`)} ${chalk.cyan(label(m.chatId))} ${chalk.yellow(who)}: ${chalk.red(`[decrypt failed: ${m.error}]`)}`);\n }\n });\n\n session.on(\"reconnecting\", ({ attempt, delayMs }: { attempt: number; delayMs: number }) => {\n console.log(chalk.yellow(`○ reconnecting (attempt ${attempt}) in ${Math.round(delayMs / 1000)}s…`));\n });\n session.on(\"disconnected\", ({ code }: { code: number }) => console.log(chalk.yellow(`○ disconnected (code=${code})`)));\n session.on(\"error\", (err: Error) => console.error(chalk.red(`! ${err.message}`)));\n\n const shutdown = () => { console.log(chalk.dim(\"\\nclosing…\")); session.close(); process.exit(0); };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n try {\n await session.connect();\n console.log(chalk.dim(\"Listening. Press Ctrl+C to stop.\"));\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n session.close();\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { EventEmitter } from \"node:events\";\nimport { randomUUID } from \"node:crypto\";\nimport { loadApigwKeys, type ApigwKeys } from \"../auth/keys.js\";\nimport { getAuthToken } from \"../config/store.js\";\nimport { loadConfig, getBaseUrl, getWebOrigin } from \"../config/index.js\";\nimport { refreshToken } from \"../auth/token-refresh.js\";\nimport { decryptMessages, type HistoryMessage, type ImageAttachment } from \"../api/decrypt.js\";\nimport type { ExpressChat } from \"../types/index.js\";\n\nexport interface SessionMessage {\n chatId: string;\n syncId: string;\n sender: string;\n body: string;\n decrypted: boolean;\n error?: string;\n insertedAt: string;\n type?: string;\n image?: ImageAttachment;\n}\n\nexport interface SessionActivity {\n chatId: string;\n syncId: string;\n sender: string;\n senderKeyId: string;\n}\n\n/** A discussion/thread — a chat-like entity keyed by thread_id under a parent chat. */\nexport interface ThreadSummary {\n thread_id: string;\n group_chat_id: string;\n counter?: number;\n last_event_inserted_at?: string | null;\n}\n\ninterface PhxFrame {\n ref: number | string | null;\n topic: string;\n event: string;\n payload: Record<string, unknown> & { status?: string; response?: Record<string, unknown> };\n}\n\ninterface Pending {\n resolve: (response: Record<string, unknown>) => void;\n reject: (err: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\nconst HEARTBEAT_MS = 25_000;\nconst REQUEST_TIMEOUT_MS = 15_000;\nconst MAX_RECONNECT_DELAY_MS = 30_000;\n\n/**\n * Persistent, stateful eXpress connection. One WebSocket stays open: it holds the\n * chat list, subscribes to every chat's activities, decrypts incoming messages\n * (live pushes carry no key, so we pull `events_history` which returns it), and\n * re-connects with backoff + token refresh. Reused by the TUI and MCP layers.\n *\n * Events: `connected`, `chats` (ExpressChat[]), `activity` (SessionActivity),\n * `message` (SessionMessage), `disconnected` ({code}), `reconnecting`\n * ({attempt, delayMs}), `error` (Error).\n */\nexport class ExpressSession extends EventEmitter {\n private ws: WebSocket | null = null;\n private ref = 0;\n private pending = new Map<number, Pending>();\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private chats: ExpressChat[] = [];\n private threads: ThreadSummary[] = [];\n private subscribed = new Set<string>();\n private closing = false;\n private connecting = false;\n private reconnectAttempt = 0;\n private readonly host: string;\n private readonly webOrigin: string;\n private readonly keyId: string;\n private readonly apigwKeys: ApigwKeys;\n\n constructor() {\n super();\n const config = loadConfig();\n this.host = new URL(getBaseUrl(config)).hostname;\n this.webOrigin = getWebOrigin(config);\n const keys = loadApigwKeys();\n if (!keys) throw new Error(\"No apigw keys. Run 'express auth qr' first.\");\n this.apigwKeys = keys;\n this.keyId = (keys.ctsKey ?? keys.encryptionKey).keyId;\n }\n\n getChats(): ExpressChat[] {\n return this.chats;\n }\n\n getThreads(): ThreadSummary[] {\n return this.threads;\n }\n\n /** Initial connect (awaited by the caller). Reconnection afterwards is driven\n * solely by `handleClose` → `scheduleReconnect`. */\n async connect(): Promise<void> {\n this.closing = false;\n await this.openSocket();\n }\n\n private async openSocket(): Promise<void> {\n if (this.closing) return;\n // Never run two sockets at once — overlapping connections with the same\n // key_id make the server kill each other (observed as a 1006 storm).\n if (this.connecting || (this.ws && this.ws.readyState === this.ws.OPEN)) return;\n this.connecting = true;\n\n const token = getAuthToken();\n if (!token) { this.connecting = false; throw new Error(\"Not authenticated. Run 'express auth qr'.\"); }\n\n const url = `wss://${this.host}/socket/user/websocket?vsn=1.0.0&auto_join=true&key_id=${this.keyId}`\n + `&version=6&background=false&voex_unencrypted=true&voex_multistream=true&voex_audio_bridge=true&instance_id=${randomUUID()}`;\n const ws = new WebSocket(url, {\n headers: { Origin: this.webOrigin, \"User-Agent\": \"Mozilla/5.0\" },\n } as ConstructorParameters<typeof WebSocket>[1]);\n this.ws = ws;\n\n // Only the currently-active socket's events matter; ignore stale ones.\n ws.addEventListener(\"message\", (e) => { if (this.ws === ws) this.onMessage(e.data as string); });\n ws.addEventListener(\"close\", () => this.handleClose(ws));\n ws.addEventListener(\"error\", () => { /* a close event always follows; reconnect is handled there */ });\n\n try {\n await new Promise<void>((resolve, reject) => {\n const openTimer = setTimeout(() => { try { ws.close(); } catch { /* ignore */ } reject(new Error(\"WebSocket open timeout\")); }, REQUEST_TIMEOUT_MS);\n ws.addEventListener(\"open\", () => {\n clearTimeout(openTimer);\n this.request(\"phoenix\", \"authenticate\", { token }).then(() => resolve()).catch(reject);\n });\n ws.addEventListener(\"close\", () => { clearTimeout(openTimer); reject(new Error(\"closed during connect\")); });\n });\n } catch (err) {\n if (this.ws === ws) { this.connecting = false; try { ws.close(); } catch { /* ignore */ } }\n throw err; // handleClose (fired by the close event) drives the reconnect\n }\n\n if (this.ws !== ws) return; // a newer socket superseded us — abandon this one\n this.connecting = false;\n this.reconnectAttempt = 0;\n this.startHeartbeat();\n this.emit(\"connected\");\n await this.loadChats(ws);\n }\n\n close(): void {\n this.closing = true;\n this.connecting = false;\n if (this.reconnectTimer) { clearTimeout(this.reconnectTimer); this.reconnectTimer = null; }\n this.stopHeartbeat();\n const ws = this.ws;\n this.ws = null;\n try { ws?.close(); } catch { /* ignore */ }\n }\n\n /** chat_type values that accept `subscribe_to_chat_activities` (others like\n * \"global\"/\"voex_call\" reply \"unmatched topic\"). */\n private static readonly SUBSCRIBABLE = new Set([\"chat\", \"group_chat\", \"channel\", \"notes\"]);\n\n /** Load the chat list and subscribe to each real chat's live activities.\n * Bails if the socket changes/closes mid-way (avoids error spam on teardown). */\n private async loadChats(ws: WebSocket): Promise<void> {\n const response = await this.request(\"system\", \"chat_list\", { since: null, request_version: 6 });\n const chats = (response.chat_list ?? []) as ExpressChat[];\n this.chats = Array.isArray(chats) ? chats : [];\n this.emit(\"chats\", this.chats);\n\n const ids = this.chats\n .filter((c) => !c.chat_type || ExpressSession.SUBSCRIBABLE.has(c.chat_type))\n .map((c) => c.group_chat_id)\n .filter((id): id is string => Boolean(id));\n\n await Promise.allSettled(ids.map((id) => this.subscribe(id, ws)));\n\n // Discussions (threads) — chat-like entities read via events_history by thread_id.\n // Thread messages carry group_chat_id = thread_id, so subscribing routes their\n // live pushes through the same message pipeline (chatId === thread_id).\n try {\n const tl = await this.request(\"system\", \"thread_list\", { group_chat_id: null, limit: 200, request_version: 2 });\n this.threads = (tl.thread_list ?? []) as ThreadSummary[];\n this.emit(\"threads\", this.threads);\n const threadIds = this.threads.map((t) => t.thread_id).filter(Boolean);\n await Promise.allSettled(threadIds.map((id) => this.subscribe(id, ws)));\n } catch { /* threads are optional; ignore on failure */ }\n }\n\n private async subscribe(chatId: string, ws: WebSocket): Promise<void> {\n if (this.subscribed.has(chatId) || this.ws !== ws) return;\n try {\n await this.request(`groupchat:${chatId}`, \"subscribe_to_chat_activities\", { group_chat_id: chatId });\n this.subscribed.add(chatId);\n } catch {\n // Transient (socket closing / server hiccup) — next reconnect re-subscribes. Stay quiet.\n }\n }\n\n private onMessage(data: string): void {\n let frame: PhxFrame;\n try { frame = JSON.parse(data) as PhxFrame; } catch { return; }\n\n const ref = frame.ref == null ? null : (typeof frame.ref === \"string\" ? parseInt(frame.ref, 10) : frame.ref);\n\n // Reply to one of our requests\n if (ref != null && this.pending.has(ref) && frame.event === \"phx_reply\") {\n const p = this.pending.get(ref)!;\n this.pending.delete(ref);\n clearTimeout(p.timer);\n if (frame.payload?.status === \"ok\") p.resolve(frame.payload.response ?? {});\n else p.reject(new Error(`${frame.event} failed: ${JSON.stringify(frame.payload?.response)}`));\n return;\n }\n\n // Live push: a new message in a subscribed chat (carries no decryption key)\n if (ref == null && frame.event === \"message_new\") {\n const p = frame.payload as Record<string, unknown>;\n const chatId = (p.group_chat_id as string) ?? frame.topic.replace(\"groupchat:\", \"\");\n const activity: SessionActivity = {\n chatId,\n syncId: (p.sync_id as string) ?? \"\",\n sender: (p.sender as string) ?? \"\",\n senderKeyId: (p.sender_key_id as string) ?? \"\",\n };\n this.emit(\"activity\", activity);\n void this.resolveMessage(activity);\n }\n }\n\n /** Pushes have `key: null`; pull recent history (which includes our key) and decrypt. */\n private async resolveMessage(activity: SessionActivity): Promise<void> {\n try {\n const response = await this.request(`groupchat:${activity.chatId}`, \"events_history\", {\n direction: \"backward\",\n group_chat_id: activity.chatId,\n limit: 5,\n skip_non_affecting_rc: true,\n skip_to_sync_id_event: true,\n last_ignore_messages_at: null,\n });\n const history = (response.history ?? []) as HistoryMessage[];\n const decrypted = await decryptMessages(history, this.apigwKeys);\n const match = decrypted.find((m) => m.sync_id === activity.syncId) ?? decrypted[0];\n if (!match) return;\n const msg: SessionMessage = {\n chatId: activity.chatId,\n syncId: match.sync_id,\n sender: match.sender,\n body: match.body,\n decrypted: match.decrypted,\n error: match.error,\n insertedAt: match.inserted_at,\n type: match.type,\n image: match.image,\n };\n this.emit(\"message\", msg);\n } catch (err) {\n this.emit(\"error\", new Error(`decrypt push failed: ${(err as Error).message}`));\n }\n }\n\n private request(topic: string, event: string, payload: Record<string, unknown>): Promise<Record<string, unknown>> {\n const ws = this.ws;\n if (!ws || ws.readyState !== ws.OPEN) return Promise.reject(new Error(\"WebSocket not open\"));\n const ref = this.ref++;\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pending.delete(ref);\n reject(new Error(`request timeout: ${event}`));\n }, REQUEST_TIMEOUT_MS);\n this.pending.set(ref, { resolve, reject, timer });\n ws.send(JSON.stringify({ topic, event, payload, ref }));\n });\n }\n\n private startHeartbeat(): void {\n this.stopHeartbeat();\n this.heartbeatTimer = setInterval(() => {\n const ws = this.ws;\n if (ws && ws.readyState === ws.OPEN) {\n ws.send(JSON.stringify({ topic: \"phoenix\", event: \"heartbeat\", payload: {}, ref: this.ref++ }));\n }\n }, HEARTBEAT_MS);\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) { clearInterval(this.heartbeatTimer); this.heartbeatTimer = null; }\n }\n\n /** Sole reconnect trigger. Ignores events from stale sockets. */\n private handleClose(ws: WebSocket): void {\n if (this.ws !== ws) return; // stale socket from a previous connection\n this.ws = null;\n this.connecting = false;\n this.stopHeartbeat();\n for (const [, p] of this.pending) { clearTimeout(p.timer); p.reject(new Error(\"WebSocket closed\")); }\n this.pending.clear();\n this.subscribed.clear();\n this.emit(\"disconnected\", { code: 1006 });\n if (!this.closing) this.scheduleReconnect();\n }\n\n private scheduleReconnect(): void {\n if (this.closing || this.reconnectTimer) return; // single pending timer\n this.reconnectAttempt += 1;\n const delayMs = Math.min(1000 * 2 ** (this.reconnectAttempt - 1), MAX_RECONNECT_DELAY_MS);\n this.emit(\"reconnecting\", { attempt: this.reconnectAttempt, delayMs });\n this.reconnectTimer = setTimeout(async () => {\n this.reconnectTimer = null;\n if (this.closing) return;\n await refreshToken().catch(() => false); // best-effort; keep a valid token across reconnects\n // Failure closes the socket → handleClose reschedules; don't schedule here (avoids storms).\n this.openSocket().catch(() => { /* handled via handleClose */ });\n }, delayMs);\n }\n}\n","import { Command } from \"commander\";\nimport { runTui } from \"../tui/index.js\";\n\nexport function createTuiCommand(): Command {\n const cmd = new Command(\"tui\");\n\n cmd\n .description(\"Interactive terminal UI: chat list + live message thread\")\n .option(\"--host <host>\", \"eXpress host\")\n .action(async () => {\n try {\n await runTui();\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { render } from \"ink\";\nimport { App } from \"./app.js\";\n\nexport async function runTui(): Promise<void> {\n const { waitUntilExit } = render(<App />);\n await waitUntilExit();\n}\n","import { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Box, Text, useApp, useInput, useStdin, useStdout } from \"ink\";\nimport TextInput from \"ink-text-input\";\nimport { ExpressSession, type SessionMessage, type ThreadSummary } from \"../session/session.js\";\nimport { readMessages } from \"../api/messages-read.js\";\nimport { sendMessageViaWebSocket } from \"../api/messaging-ws.js\";\nimport { UserApi } from \"../api/user.js\";\nimport { ApiClient } from \"../api/client.js\";\nimport { renderImage } from \"./image.js\";\nimport type { ImageAttachment } from \"../api/decrypt.js\";\nimport type { ExpressChat } from \"../types/index.js\";\n\ninterface DisplayMsg {\n syncId: string;\n sender: string;\n body: string;\n decrypted: boolean;\n error?: string;\n insertedAt: string;\n type?: string;\n image?: ImageAttachment;\n}\n\ntype Focus = \"chats\" | \"thread\" | \"input\" | \"discussions\";\n\nconst LIST_TYPES = new Set([\"chat\", \"group_chat\", \"channel\", \"notes\"]);\nconst shortHuid = (h: string) => (h ? h.slice(0, 8) : \"unknown\");\nconst clock = (iso: string) => {\n const d = iso ? new Date(iso) : new Date();\n return Number.isNaN(d.getTime()) ? \"--:--\" : d.toLocaleTimeString(\"ru-RU\", { hour: \"2-digit\", minute: \"2-digit\" });\n};\n\nconst MENTION_RE = /@\\{mention:([0-9a-fA-F-]{36})\\}/g;\ntype Seg = { mention?: string; text?: string };\nfunction parseBody(body: string): Seg[] {\n const out: Seg[] = [];\n let last = 0;\n let m: RegExpExecArray | null;\n MENTION_RE.lastIndex = 0;\n while ((m = MENTION_RE.exec(body))) {\n if (m.index > last) out.push({ text: body.slice(last, m.index) });\n out.push({ mention: m[1] });\n last = m.index + m[0].length;\n }\n if (last < body.length) out.push({ text: body.slice(last) });\n return out.length ? out : [{ text: body }];\n}\n\nconst toDisplay = (m: { sync_id: string; sender: string; body: string; decrypted: boolean; error?: string; inserted_at: string; type?: string; image?: ImageAttachment }): DisplayMsg =>\n ({ syncId: m.sync_id, sender: m.sender, body: m.body, decrypted: m.decrypted, error: m.error, insertedAt: m.inserted_at, type: m.type, image: m.image });\n\nexport function App() {\n const { exit } = useApp();\n const { stdout } = useStdout();\n const { isRawModeSupported } = useStdin();\n const rows = stdout?.rows ?? 24;\n const cols = stdout?.columns ?? 80;\n\n const sessionRef = useRef<ExpressSession | null>(null);\n const [chats, setChats] = useState<ExpressChat[]>([]);\n const [threads, setThreads] = useState<ThreadSummary[]>([]);\n const [selected, setSelected] = useState(0);\n const [messages, setMessages] = useState<Record<string, DisplayMsg[]>>({});\n const [status, setStatus] = useState<{ text: string; color: string }>({ text: \"connecting…\", color: \"yellow\" });\n const [focus, setFocus] = useState<Focus>(\"chats\");\n const [draft, setDraft] = useState(\"\");\n const [selfHuid, setSelfHuid] = useState(\"\");\n const [names, setNames] = useState<Record<string, string>>({});\n const [unread, setUnread] = useState<Record<string, number>>({});\n const [msgCursor, setMsgCursor] = useState(0);\n const [discussionsOpen, setDiscussionsOpen] = useState(false);\n const [threadCursor, setThreadCursor] = useState(0);\n const [openThreadId, setOpenThreadId] = useState<string | null>(null);\n const [threadTitles, setThreadTitles] = useState<Record<string, string>>({});\n const [renderedImages, setRenderedImages] = useState<Record<string, string>>({});\n const requested = useRef<Set<string>>(new Set());\n const titleRequested = useRef<Set<string>>(new Set());\n const imgRequested = useRef<Set<string>>(new Set());\n const currentIdRef = useRef<string | undefined>(undefined);\n\n const visibleChats = useMemo(\n () =>\n chats\n .filter((c) => LIST_TYPES.has(c.chat_type) && !c.left)\n .sort((a, b) => (b.last_event_inserted_at ?? \"\").localeCompare(a.last_event_inserted_at ?? \"\")),\n [chats],\n );\n\n const current = visibleChats[selected];\n const currentId = current?.group_chat_id;\n currentIdRef.current = currentId;\n\n const threadsForChat = useMemo(\n () => threads.filter((t) => t.group_chat_id === currentId).sort((a, b) => (b.last_event_inserted_at ?? \"\").localeCompare(a.last_event_inserted_at ?? \"\")),\n [threads, currentId],\n );\n const activeMessages = openThreadId ? messages[openThreadId] : (currentId ? messages[currentId] : undefined);\n\n const resolveHuids = (huids: string[]) => {\n const need = [...new Set(huids)].filter((h) => h && h.length >= 30 && !requested.current.has(h));\n if (need.length === 0) return;\n need.forEach((h) => requested.current.add(h));\n new UserApi(new ApiClient()).getProfilesByHuid(need)\n .then((profiles) => setNames((prev) => {\n const next = { ...prev };\n for (const p of profiles) if (p.name) next[p.user_huid] = p.name;\n return next;\n }))\n .catch(() => need.forEach((h) => requested.current.delete(h)));\n };\n\n const displayChatName = (c: ExpressChat): string => {\n if (c.chat_type === \"chat\" && c.member_huids && selfHuid) {\n const other = c.member_huids.find((h) => h !== selfHuid);\n if (other && names[other]) return names[other];\n }\n return c.name?.trim() || c.group_chat_id.slice(0, 8);\n };\n\n const senderLabel = (huid: string): string =>\n huid === selfHuid || huid === \"me\" ? \"you\" : names[huid] || shortHuid(huid);\n\n // A thread's title = its root (oldest) message\n const fetchThreadTitle = (threadId: string) => {\n if (threadTitles[threadId] || titleRequested.current.has(threadId)) return;\n titleRequested.current.add(threadId);\n readMessages({ chatId: threadId, limit: 1, direction: \"forward\" })\n .then((h) => {\n const root = h.find((m) => m.decrypted && m.body);\n if (root) setThreadTitles((p) => ({ ...p, [threadId]: root.body.replace(/\\s+/g, \" \").trim() }));\n })\n .catch(() => titleRequested.current.delete(threadId));\n };\n const threadTitle = (threadId: string) => threadTitles[threadId];\n\n // Session lifecycle\n useEffect(() => {\n let session: ExpressSession;\n try {\n session = new ExpressSession();\n } catch (err) {\n setStatus({ text: (err as Error).message, color: \"red\" });\n return;\n }\n sessionRef.current = session;\n\n session.on(\"connected\", () => setStatus({ text: \"connected\", color: \"green\" }));\n session.on(\"chats\", (list: ExpressChat[]) => setChats(list));\n session.on(\"threads\", (list: ThreadSummary[]) => setThreads(list));\n session.on(\"message\", (m: SessionMessage) => {\n setMessages((prev) => {\n const list = prev[m.chatId] ?? [];\n if (list.some((x) => x.syncId === m.syncId)) return prev;\n const next: DisplayMsg = { syncId: m.syncId, sender: m.sender, body: m.body, decrypted: m.decrypted, error: m.error, insertedAt: m.insertedAt, type: m.type, image: m.image };\n return { ...prev, [m.chatId]: [...list, next].slice(-200) };\n });\n if (m.chatId !== currentIdRef.current) setUnread((u) => ({ ...u, [m.chatId]: (u[m.chatId] ?? 0) + 1 }));\n });\n session.on(\"reconnecting\", ({ attempt }: { attempt: number }) => setStatus({ text: `reconnecting (#${attempt})…`, color: \"yellow\" }));\n session.on(\"disconnected\", () => setStatus({ text: \"disconnected\", color: \"yellow\" }));\n session.on(\"error\", () => { /* status reflects it on disconnect */ });\n\n session.connect().catch((err) => setStatus({ text: (err as Error).message, color: \"red\" }));\n new UserApi(new ApiClient()).getSelfProfile().then((p) => setSelfHuid(p.user_huid)).catch(() => {});\n return () => session.close();\n }, []);\n\n const send = async (text: string) => {\n const body = text.trim();\n setDraft(\"\");\n const target = openThreadId ?? currentId;\n if (!body || !target) return;\n const localId = `local-${Date.now()}`;\n const optimistic: DisplayMsg = { syncId: localId, sender: selfHuid || \"me\", body, decrypted: true, insertedAt: new Date().toISOString() };\n setMessages((prev) => ({ ...prev, [target]: [...(prev[target] ?? []), optimistic].slice(-200) }));\n try {\n await sendMessageViaWebSocket({ client: new ApiClient(), chatId: target, body });\n } catch (err) {\n setMessages((prev) => ({\n ...prev,\n [target]: (prev[target] ?? []).map((m) => (m.syncId === localId ? { ...m, decrypted: false, error: (err as Error).message } : m)),\n }));\n }\n };\n\n // Load history for a chat / thread when first opened (threads read the same way)\n const loadHistory = (id: string) => {\n if (messages[id]) return;\n readMessages({ chatId: id, limit: 40 })\n .then((h) => setMessages((prev) => (prev[id] ? prev : { ...prev, [id]: h.map(toDisplay) })))\n .catch(() => setMessages((prev) => (prev[id] ? prev : { ...prev, [id]: [] })));\n };\n useEffect(() => { if (currentId) loadHistory(currentId); }, [currentId]);\n useEffect(() => { if (openThreadId) { loadHistory(openThreadId); fetchThreadTitle(openThreadId); setMsgCursor((messages[openThreadId]?.length ?? 1) - 1); } }, [openThreadId]);\n\n // Resolve DM partner names\n useEffect(() => {\n if (!selfHuid) return;\n resolveHuids(visibleChats.filter((c) => c.chat_type === \"chat\").flatMap((c) => (c.member_huids ?? []).filter((h) => h !== selfHuid)));\n }, [chats, selfHuid]);\n\n // Resolve sender + mention names for the active message view\n useEffect(() => {\n if (!activeMessages) return;\n resolveHuids(activeMessages.flatMap((m) => [m.sender, ...parseBody(m.body).filter((s) => s.mention).map((s) => s.mention!)]));\n }, [activeMessages]);\n\n // Reset per-chat view state on chat change\n useEffect(() => {\n setDiscussionsOpen(false);\n setOpenThreadId(null);\n if (currentId) setUnread((u) => (u[currentId] ? { ...u, [currentId]: 0 } : u));\n }, [currentId]);\n\n // Fetch thread titles (root messages) when the discussions panel is open\n useEffect(() => {\n if (!discussionsOpen) return;\n threadsForChat.forEach((t) => fetchThreadTitle(t.thread_id));\n }, [discussionsOpen, threadsForChat]);\n\n // Render the inline preview of the currently-selected image message\n useEffect(() => {\n const m = focus === \"thread\" ? activeMessages?.[msgCursor] : undefined;\n const uri = m?.image?.previewDataUri;\n if (!m || !uri || renderedImages[m.syncId] || imgRequested.current.has(m.syncId)) return;\n imgRequested.current.add(m.syncId);\n const w = Math.min(40, Math.max(10, cols - 36));\n renderImage(uri, w)\n .then((s) => setRenderedImages((p) => ({ ...p, [m.syncId]: s })))\n .catch(() => imgRequested.current.delete(m.syncId));\n }, [focus, msgCursor, activeMessages]);\n\n useInput((input, key) => {\n if (focus === \"input\") { if (key.escape) setFocus(openThreadId ? \"thread\" : \"chats\"); return; }\n if (input === \"q\" || (key.ctrl && input === \"c\")) { sessionRef.current?.close(); exit(); return; }\n\n // Toggle discussions panel for the current chat\n if (input === \"t\" && currentId && !openThreadId) {\n if (discussionsOpen) { setDiscussionsOpen(false); setFocus(\"chats\"); }\n else { setDiscussionsOpen(true); setThreadCursor(0); setFocus(\"discussions\"); }\n return;\n }\n\n if (focus === \"chats\") {\n if (key.upArrow || input === \"k\") setSelected((i) => Math.max(0, i - 1));\n else if (key.downArrow || input === \"j\") setSelected((i) => Math.min(visibleChats.length - 1, i + 1));\n else if ((key.rightArrow || key.tab) && currentId) { setMsgCursor((activeMessages?.length ?? 1) - 1); setFocus(\"thread\"); }\n else if (key.return && currentId) setFocus(\"input\");\n } else if (focus === \"discussions\") {\n if (key.upArrow || input === \"k\") setThreadCursor((c) => Math.max(0, c - 1));\n else if (key.downArrow || input === \"j\") setThreadCursor((c) => Math.min(threadsForChat.length - 1, c + 1));\n else if (key.return && threadsForChat[threadCursor]) { setOpenThreadId(threadsForChat[threadCursor].thread_id); setFocus(\"thread\"); }\n else if (key.leftArrow || key.escape) { setDiscussionsOpen(false); setFocus(\"chats\"); }\n } else if (focus === \"thread\") {\n const len = activeMessages?.length ?? 0;\n if (key.upArrow || input === \"k\") setMsgCursor((c) => Math.max(0, c - 1));\n else if (key.downArrow || input === \"j\") setMsgCursor((c) => Math.min(len - 1, c + 1));\n else if (key.leftArrow || key.escape) {\n if (openThreadId) { setOpenThreadId(null); setFocus(\"discussions\"); }\n else setFocus(\"chats\");\n }\n else if (key.return) setFocus(\"input\");\n }\n }, { isActive: isRawModeSupported });\n\n // --- Layout / viewport ---\n const bodyHeight = Math.max(4, rows - 4);\n const rightWidth = Math.max(20, cols - 34);\n const listWindow = windowAround(selected, visibleChats.length, bodyHeight);\n const showDiscussions = discussionsOpen && !openThreadId;\n\n const estLines = (m: DisplayMsg): number => {\n let n = 9 + senderLabel(m.sender).length + 2;\n for (const seg of parseBody(m.body)) n += seg.mention ? 1 + (names[seg.mention]?.length ?? 8) : (seg.text?.length ?? 0);\n return Math.max(1, Math.ceil(n / rightWidth));\n };\n let threadStart = activeMessages ? activeMessages.length : 0;\n if (activeMessages) {\n let used = 0;\n while (threadStart > 0 && used < bodyHeight) { used += estLines(activeMessages[threadStart - 1]); threadStart--; }\n if (focus === \"thread\" && msgCursor < threadStart) threadStart = msgCursor;\n }\n const threadView = activeMessages ? activeMessages.slice(threadStart) : undefined;\n\n const renderBody = (m: DisplayMsg) =>\n parseBody(m.body).map((seg, i) =>\n seg.mention\n ? <Text key={i} color=\"magenta\">@{names[seg.mention] || shortHuid(seg.mention)}</Text>\n : <Text key={i}>{seg.text}</Text>,\n );\n\n const rightBorder = focus === \"input\" ? \"green\" : (focus === \"thread\" || focus === \"discussions\") ? \"cyan\" : \"gray\";\n const rightTitle = openThreadId\n ? `💬 ${threadTitle(openThreadId) ?? \"Обсуждение\"}`\n : (current ? displayChatName(current) : \"—\") + (threadsForChat.length ? ` 💬 ${threadsForChat.length}` : \"\");\n\n return (\n <Box flexDirection=\"column\" height={rows}>\n <Box>\n <Text> </Text>\n <Text color={status.color}>●</Text>\n <Text> eXpress TUI — </Text>\n <Text color={status.color}>{status.text}</Text>\n <Text dimColor> ({visibleChats.length} chats)</Text>\n </Box>\n\n <Box flexGrow={1}>\n <Box flexDirection=\"column\" width={32} borderStyle=\"single\" borderColor={focus === \"chats\" ? \"cyan\" : \"gray\"} paddingX={1}>\n {visibleChats.length === 0 && <Text dimColor>loading…</Text>}\n {visibleChats.slice(listWindow.start, listWindow.end).map((c, i) => {\n const idx = listWindow.start + i;\n const active = idx === selected;\n const n = unread[c.group_chat_id] ?? 0;\n return (\n <Text key={c.group_chat_id} color={active ? \"black\" : n > 0 ? \"cyan\" : undefined} backgroundColor={active ? \"cyan\" : undefined} bold={n > 0 && !active} wrap=\"truncate\">\n {active ? \"› \" : \" \"}{displayChatName(c)}{n > 0 ? ` (${n})` : \"\"}\n </Text>\n );\n })}\n </Box>\n\n <Box flexDirection=\"column\" flexGrow={1} borderStyle=\"single\" borderColor={rightBorder} paddingX={1}>\n <Text bold wrap=\"truncate\">{rightTitle}</Text>\n <Box flexDirection=\"column\" flexGrow={1}>\n {showDiscussions ? (\n <>\n {threadsForChat.length === 0 && <Text dimColor>no discussions</Text>}\n {threadsForChat.map((t, i) => {\n const on = focus === \"discussions\" && i === threadCursor;\n const title = threadTitle(t.thread_id) ?? t.thread_id.slice(0, 8);\n return (\n <Text key={t.thread_id} color={on ? \"black\" : undefined} backgroundColor={on ? \"cyan\" : undefined} wrap=\"truncate\">\n {on ? \"› \" : \" \"}💬 {title} <Text dimColor={!on}>· {t.counter ?? 0} · {clock(t.last_event_inserted_at ?? \"\")}</Text>\n </Text>\n );\n })}\n </>\n ) : (\n <>\n {!current && <Text dimColor>select a chat</Text>}\n {current && !threadView && <Text dimColor>loading messages…</Text>}\n {threadView && threadView.length === 0 && <Text dimColor>no messages</Text>}\n {threadView?.map((m, i) => {\n const idx = threadStart + i;\n const mine = m.sender === selfHuid || m.sender === \"me\";\n const onCursor = focus === \"thread\" && idx === msgCursor;\n const img = renderedImages[m.syncId];\n return (\n <Box key={m.syncId} flexDirection=\"column\">\n <Text wrap=\"wrap\">\n <Text color={onCursor ? \"cyan\" : undefined}>{onCursor ? \"▍\" : \" \"}</Text>\n <Text dimColor>[{clock(m.insertedAt)}] </Text>\n <Text color={mine ? \"green\" : \"yellow\"}>{senderLabel(m.sender)}</Text>\n <Text>: </Text>\n {!m.decrypted\n ? <Text color=\"red\">[{m.error ? \"send failed\" : \"decrypt failed\"}]</Text>\n : m.image\n ? <Text color=\"cyan\">🖼 {m.image.fileName}{m.body ? ` — ${m.body}` : \"\"}</Text>\n : renderBody(m)}\n </Text>\n {onCursor && m.image?.previewDataUri && (img ? <Text>{img}</Text> : <Text dimColor> rendering preview…</Text>)}\n </Box>\n );\n })}\n </>\n )}\n </Box>\n {current && !showDiscussions && (\n <Box>\n <Text color={focus === \"input\" ? \"green\" : \"gray\"}>{focus === \"input\" ? \"› \" : \" \"}</Text>\n <TextInput value={draft} onChange={setDraft} onSubmit={send} focus={focus === \"input\"} placeholder={focus === \"input\" ? \"type a message…\" : \"Enter to write\"} />\n </Box>\n )}\n </Box>\n </Box>\n\n <Box>\n <Text dimColor> {footerHint(focus, openThreadId != null)}</Text>\n </Box>\n </Box>\n );\n}\n\nfunction footerHint(focus: Focus, inThread: boolean): string {\n if (focus === \"input\") return \"Enter send · Esc cancel\";\n if (focus === \"discussions\") return \"↑/↓ discussions · Enter open · Esc back\";\n if (focus === \"thread\") return `↑/↓ messages · ← ${inThread ? \"discussions\" : \"chats\"} · Enter write · q quit`;\n return \"↑/↓ chats · → open thread · t discussions · Enter write · q quit\";\n}\n\n/** Scrolling window that keeps `selected` visible within `size` rows. */\nfunction windowAround(selected: number, total: number, size: number): { start: number; end: number } {\n if (total <= size) return { start: 0, end: total };\n let start = selected - Math.floor(size / 2);\n start = Math.max(0, Math.min(start, total - size));\n return { start, end: start + size };\n}\n","import terminalImage from \"terminal-image\";\n\n/**\n * Render a base64 image (raw or `data:*;base64,` URI) as Ink-compatible ANSI\n * half-block art. `preferNativeRender: false` forces the block fallback (colored\n * Unicode half-blocks) instead of iTerm2/Kitty escapes, which break Ink layout.\n */\nexport async function renderImage(data: string, cols: number, rows?: number): Promise<string> {\n const b64 = data.includes(\",\") ? data.slice(data.indexOf(\",\") + 1) : data;\n const buf = Buffer.from(b64, \"base64\");\n const out = await terminalImage.buffer(buf, {\n width: Math.max(4, cols),\n ...(rows ? { height: rows } : {}),\n preserveAspectRatio: true,\n preferNativeRender: false,\n });\n return out.replace(/\\n$/, \"\");\n}\n","import { Command } from \"commander\";\nimport { runMcpServer } from \"../mcp/server.js\";\n\nexport function createMcpCommand(): Command {\n const cmd = new Command(\"mcp\");\n\n cmd\n .description(\"Run as an MCP server (stdio): exposes chats/messages/contacts tools to MCP hosts\")\n .action(async () => {\n try {\n await runMcpServer();\n } catch (err) {\n console.error(`Error: ${(err as Error).message}`);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { ApiClient } from \"../api/client.js\";\nimport { PhonebookApi } from \"../api/phonebook.js\";\nimport { UserApi } from \"../api/user.js\";\nimport { readMessages } from \"../api/messages-read.js\";\nimport { sendMessageViaWebSocket } from \"../api/messaging-ws.js\";\nimport { resolveChatId, listChatsWithNames } from \"../api/resolve.js\";\nimport { getAuthToken, getTokenExpiresAt } from \"../config/store.js\";\nimport { ExpressSession, type SessionMessage } from \"../session/session.js\";\nimport type { ExpressChat } from \"../types/index.js\";\n\nconst ok = (data: unknown) => ({\n content: [{ type: \"text\" as const, text: typeof data === \"string\" ? data : JSON.stringify(data, null, 2) }],\n});\n\ninterface Incoming { seq: number; chatId: string; sender: string; body: string; time: string; decrypted: boolean; image?: string }\n\n/** Buffers incoming messages so `wait_for_messages` can hand an agent everything\n * new since its last call, blocking up to a timeout when nothing is pending. */\nclass Inbox {\n private buf: Incoming[] = [];\n private seq = 0;\n private cursor = 0;\n private waiters: Array<() => void> = [];\n\n add(m: SessionMessage): void {\n this.buf.push({ seq: ++this.seq, chatId: m.chatId, sender: m.sender, body: m.body, time: m.insertedAt, decrypted: m.decrypted, image: m.image?.fileName });\n if (this.buf.length > 500) this.buf.splice(0, this.buf.length - 500);\n const woken = this.waiters; this.waiters = []; woken.forEach((fn) => fn());\n }\n\n private pending(): Incoming[] { return this.buf.filter((x) => x.seq > this.cursor); }\n\n /** Return (and consume) messages arrived since the last take, waiting up to timeoutMs. */\n async take(timeoutMs: number): Promise<Incoming[]> {\n if (this.pending().length === 0) {\n await new Promise<void>((resolve) => {\n const fn = () => { clearTimeout(t); resolve(); };\n const t = setTimeout(() => { this.waiters = this.waiters.filter((w) => w !== fn); resolve(); }, timeoutMs);\n this.waiters.push(fn);\n });\n }\n const items = this.pending();\n if (this.buf.length) this.cursor = this.buf[this.buf.length - 1].seq;\n return items;\n }\n}\n\n/**\n * MCP server (stdio) exposing eXpress chat over the existing api layer. Reuses the\n * same E2E send/read code as the CLI, so nothing is duplicated. stdout carries only\n * the MCP protocol (the request/refresh path is free of stdout logging).\n */\nexport async function runMcpServer(): Promise<void> {\n const server = new McpServer({ name: \"express-cli\", version: \"0.1.0\" });\n\n // Persistent session that buffers incoming messages for wait_for_messages.\n const inbox = new Inbox();\n const chatNames = new Map<string, string>();\n const senderNames = new Map<string, string>();\n let sessionReady = false;\n let session: ExpressSession | null = null;\n try {\n session = new ExpressSession();\n session.on(\"connected\", () => { sessionReady = true; });\n session.on(\"chats\", (list: ExpressChat[]) => { for (const c of list) chatNames.set(c.group_chat_id, c.name?.trim() || c.group_chat_id.slice(0, 8)); });\n session.on(\"message\", (m: SessionMessage) => inbox.add(m));\n session.connect().catch((err) => { process.stderr.write(`[mcp] session connect failed: ${(err as Error).message}\\n`); });\n // Resolve DM names in the background for nicer chat labels\n listChatsWithNames(new ApiClient()).then((chats) => { for (const c of chats) chatNames.set(c.group_chat_id, c.name ?? c.group_chat_id.slice(0, 8)); }).catch(() => {});\n } catch (err) {\n process.stderr.write(`[mcp] session unavailable: ${(err as Error).message}\\n`);\n }\n\n const enrich = async (items: Incoming[]) => {\n const unknown = [...new Set(items.map((i) => i.sender))].filter((h) => h && h.length >= 30 && !senderNames.has(h));\n if (unknown.length) {\n try {\n const profiles = await new UserApi(new ApiClient()).getProfilesByHuid(unknown);\n for (const p of profiles) if (p.name) senderNames.set(p.user_huid, p.name);\n } catch { /* names are best-effort */ }\n }\n return items.map((i) => ({\n time: i.time,\n chat: chatNames.get(i.chatId) ?? i.chatId.slice(0, 8),\n chat_id: i.chatId,\n sender: senderNames.get(i.sender) ?? i.sender.slice(0, 8),\n message: i.decrypted ? (i.image ? `🖼 ${i.image}` : i.body) : \"[decrypt failed]\",\n }));\n };\n\n server.registerTool(\"chats_list\", {\n title: \"List chats\",\n description: \"List chats (DMs, groups, channels) with names and full chat IDs. DM names are resolved to the person's full name.\",\n inputSchema: { type: z.enum([\"all\", \"dm\", \"group\", \"channel\"]).optional().describe(\"Filter by chat type (default all)\") },\n }, async ({ type }) => {\n const chats = await listChatsWithNames(new ApiClient());\n const kind: Record<string, string> = { dm: \"chat\", group: \"group_chat\", channel: \"channel\" };\n const filtered = !type || type === \"all\" ? chats : chats.filter((c) => c.chat_type === kind[type]);\n return ok(filtered.map((c) => ({ name: c.name, chat_id: c.group_chat_id, type: c.chat_type, members: c.members_count })));\n });\n\n server.registerTool(\"chats_find\", {\n title: \"Find a chat by name\",\n description: \"Find chats whose name (person or group) contains the query. Returns name + full chat_id to use with other tools.\",\n inputSchema: { query: z.string().describe(\"Part of the chat or person name\") },\n }, async ({ query }) => {\n const chats = await listChatsWithNames(new ApiClient());\n const q = query.toLowerCase();\n return ok(chats.filter((c) => (c.name ?? \"\").toLowerCase().includes(q)).map((c) => ({ name: c.name, chat_id: c.group_chat_id, type: c.chat_type })));\n });\n\n server.registerTool(\"messages_list\", {\n title: \"Read messages\",\n description: \"Read and decrypt recent messages from a chat, identified by name or chat_id.\",\n inputSchema: {\n chat: z.string().describe(\"Chat name (partial ok) or full chat_id\"),\n limit: z.number().int().min(1).max(200).optional().describe(\"How many recent messages (default 20)\"),\n },\n }, async ({ chat, limit }) => {\n const client = new ApiClient();\n const chatId = await resolveChatId(client, chat);\n const msgs = await readMessages({ chatId, limit: limit ?? 20 });\n return ok(msgs.map((m) => ({\n time: m.inserted_at,\n sender: m.sender,\n body: m.decrypted ? (m.image ? `🖼 ${m.image.fileName}${m.body ? ` — ${m.body}` : \"\"}` : m.body) : `[decrypt failed: ${m.error}]`,\n })));\n });\n\n server.registerTool(\"send_message\", {\n title: \"Send a message\",\n description: \"Send a text message to a chat, identified by name (partial ok) or chat_id. Returns the sync_id.\",\n inputSchema: { chat: z.string().describe(\"Chat name or full chat_id\"), text: z.string().describe(\"Message text\") },\n }, async ({ chat, text }) => {\n const client = new ApiClient();\n const chatId = await resolveChatId(client, chat);\n const res = await sendMessageViaWebSocket({ client, chatId, body: text });\n return ok({ sent: true, chat_id: chatId, sync_id: res.sync_id });\n });\n\n server.registerTool(\"contacts_search\", {\n title: \"Search employees\",\n description: \"Global company phonebook search across all employees by name.\",\n inputSchema: { query: z.string().describe(\"Name to search\"), limit: z.number().int().min(1).max(50).optional() },\n }, async ({ query, limit }) => {\n const profiles = await new PhonebookApi(new ApiClient()).searchUsers(query, limit ?? 20);\n return ok(profiles.map((p) => ({ name: p.name, huid: p.user_huid, email: p.email, position: p.company_position, department: p.department })));\n });\n\n server.registerTool(\"contacts_self\", {\n title: \"My profile\",\n description: \"Get the authenticated user's own profile.\",\n inputSchema: {},\n }, async () => ok(await new UserApi(new ApiClient()).getSelfProfile()));\n\n server.registerTool(\"wait_for_messages\", {\n title: \"Wait for incoming messages\",\n description: \"Block until new incoming messages arrive (from any chat/discussion), then return them. Returns messages received since the previous call to this tool; if none are pending, waits up to timeout_seconds. Your own sent messages are not included. Use this to react to new messages instead of polling.\",\n inputSchema: { timeout_seconds: z.number().int().min(1).max(120).optional().describe(\"Max seconds to wait when nothing is pending (default 30)\") },\n }, async ({ timeout_seconds }) => {\n if (!session) return ok({ error: \"Session unavailable — run 'express auth qr' to authenticate.\" });\n const items = await inbox.take((timeout_seconds ?? 30) * 1000);\n return ok({ connected: sessionReady, count: items.length, messages: await enrich(items) });\n });\n\n server.registerTool(\"status\", {\n title: \"Auth status\",\n description: \"Check authentication and access-token status.\",\n inputSchema: {},\n }, async () => {\n const exp = getTokenExpiresAt();\n return ok({\n authenticated: !!getAuthToken(),\n token_expires_in_seconds: exp ? Math.max(0, Math.floor((exp - Date.now()) / 1000)) : null,\n });\n });\n\n await server.connect(new StdioServerTransport());\n}\n","import { createRootCommand } from \"./cli/root.js\";\n\nconst program = createRootCommand();\nprogram.parse();\n"],"mappings":"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","names":["Command","nacl","randomUUID","randomBytes","nacl","extractResult","fetchCurrentAccountCtsKey","refreshToken","Command","text","Command","Command","Command","Command","Command","Command","chalk","randomUUID","entries","Command","chalk","Command","Command","Command","Table","chalk","Command","Command","randomBytes","randomUUID","nacl","randomUUID","randomBytes","nacl","ciphertext","Command","Command","Command","Command","writeFileSync","Command","Command","randomUUID","nacl","sodium","nacl","sodium","randomUUID","Command","Command","chalk","randomUUID","randomUUID","Command","chalk","Command","status","jsx","Command","Command","z","z","Command","program","Command"]}