@open-wa/wa-automate 5.4.0 → 5.5.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-runtime-BRj_LUIT.cjs","names":["ApiServer","join","homedir","delimiter","stat","access","constants","toPublicError","readFile","dirname","mkdir","mkdtemp","rm","writeFile","rename","existsSync","readFileSync","dirname","statSync","constants","selectRuntimeDriver","ConfigSchema","resolveConfig","resolve","eventRegistry","resolve","defaultChatSandboxPolicy","selectSharedRuntimeDriver","resolveConfig","makeNodeExecutionSandbox","createClient","observeBrowserProcessMemory","ClientFacade","fileURLToPath"],"sources":["../src/server/hono-server.ts","../src/cli/output-sink.ts","../src/browser-choice.ts","../src/runtime-client.ts","../src/cli-runtime.ts"],"sourcesContent":["import { ApiServer, createApiServer as createSharedApiServer } from '@open-wa/api';\nimport type { Config } from '@open-wa/config';\n\nexport class WAServer extends ApiServer {\n constructor(config: Config) {\n super({ config });\n }\n}\n\nexport function createApiServer(config: Config) {\n return createSharedApiServer(config);\n}\n","import qrcode from 'qrcode-terminal';\n\nexport type CliOutputLevel = 'debug' | 'info' | 'warn' | 'error';\n\nexport interface CliOutputEntry {\n level: CliOutputLevel;\n message: string;\n meta?: Record<string, unknown>;\n}\n\nexport interface CliStatusUpdate {\n phase:\n | 'boot'\n | 'config.resolved'\n | 'server.starting'\n | 'server.started'\n | 'client.starting'\n | 'launch.auth'\n | 'launch.helpers'\n | 'launch.patch'\n | 'launch.license'\n | 'launch.finalize'\n | 'auth.qr'\n | 'client.ready'\n | 'shutdown.starting'\n | 'shutdown.complete'\n | 'error';\n detail?: string;\n sessionId?: string;\n}\n\nexport interface CliQrPayload {\n qr: string;\n sessionId: string;\n}\n\nexport interface CliOutputSink {\n write(entry: CliOutputEntry): void;\n status(update: CliStatusUpdate): void;\n qr(payload: CliQrPayload): void;\n promptChoice?(question: string, choices: readonly string[]): Promise<number>;\n}\n\nexport async function promptChoice(question: string, choices: readonly string[]): Promise<number> {\n if (!process.stdin.isTTY || !process.stderr.isTTY) {\n throw new Error('No browser is installed. Choose --use-chrome, --use-chromium or --use-lightpanda to download one without a prompt.');\n }\n const { createInterface } = await import('node:readline/promises');\n const readline = createInterface({ input: process.stdin, output: process.stderr });\n const abort = new AbortController();\n readline.on('SIGINT', () => abort.abort());\n readline.on('close', () => abort.abort());\n try {\n process.stderr.write(`\\n${question}\\n${choices.map((choice, index) => ` ${index + 1}. ${choice}`).join('\\n')}\\n`);\n while (true) {\n const answer = (await readline.question('Choose a browser [1]: ', { signal: abort.signal })).trim();\n const choice = answer === '' ? 0 : Number(answer) - 1;\n if (Number.isInteger(choice) && choice >= 0 && choice < choices.length) return choice;\n process.stderr.write(`Enter a number from 1 to ${choices.length}.\\n`);\n }\n } catch (cause) {\n throw new Error('Browser selection cancelled.', { cause });\n } finally {\n readline.close();\n }\n}\n\nfunction writeToConsole(level: CliOutputLevel, message: string): void {\n if (level === 'warn') {\n console.warn(message);\n return;\n }\n\n if (level === 'error') {\n console.error(message);\n return;\n }\n\n console.log(message);\n}\n\nexport function createConsoleOutputSink(): CliOutputSink {\n return {\n promptChoice,\n write(entry) {\n writeToConsole(entry.level, entry.message);\n },\n status() {\n // Status updates are semantic signals for richer presenters.\n },\n qr(payload) {\n qrcode.generate(payload.qr, { small: true }, (terminalQrCode) => {\n console.log(`WhatsApp login: ${payload.sessionId}\\n${terminalQrCode}`);\n });\n },\n };\n}\n\nlet activeSink: CliOutputSink = createConsoleOutputSink();\n\nexport function getCliOutputSink(): CliOutputSink {\n return activeSink;\n}\n\nexport function setCliOutputSink(sink: CliOutputSink): void {\n activeSink = sink;\n}\n\nexport function resetCliOutputSink(): void {\n activeSink = createConsoleOutputSink();\n}\n","import { constants } from 'node:fs';\nimport { access, mkdir, mkdtemp, readFile, rename, rm, stat, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { delimiter, dirname, join } from 'node:path';\nimport { toPublicError } from '@open-wa/driver-interface';\nimport { getCliOutputSink, promptChoice } from './cli/output-sink';\n\nexport type BrowserChoice = 'chrome' | 'chromium' | 'lightpanda';\nconst choiceFile = join(homedir(), '.cache', 'open-wa', 'browser-choice.json');\n\nexport async function findSystemBrowser(kind: 'chrome' | 'chromium'): Promise<string | undefined> {\n const app = kind === 'chrome' ? 'Google Chrome' : 'Chromium';\n const names = process.platform === 'win32' ? ['chrome.exe']\n : kind === 'chrome' ? ['google-chrome-stable', 'google-chrome', 'chrome']\n : ['chromium', 'chromium-browser'];\n const candidates = process.platform === 'darwin'\n ? ['/Applications', join(homedir(), 'Applications')].map(root => join(root, `${app}.app`, 'Contents', 'MacOS', app))\n : process.platform === 'win32'\n ? [process.env.LOCALAPPDATA, process.env.PROGRAMFILES, process.env['PROGRAMFILES(X86)']]\n .filter((root): root is string => !!root)\n .map(root => kind === 'chrome' ? join(root, 'Google', 'Chrome', 'Application', 'chrome.exe') : join(root, 'Chromium', 'Application', 'chrome.exe'))\n : kind === 'chrome' ? ['/opt/google/chrome/chrome'] : [];\n candidates.push(...(process.env.PATH ?? '').split(delimiter).filter(Boolean).flatMap(root => names.map(name => join(root, name))));\n for (const candidate of candidates) {\n try {\n if (!(await stat(candidate)).isFile()) continue;\n await access(candidate, constants.X_OK);\n return candidate;\n } catch { }\n }\n return undefined;\n}\n\nexport async function readBrowserChoice(): Promise<{ kind: BrowserChoice; executablePath: string } | undefined> {\n const { Effect, Schema } = await import('effect');\n const recordSchema = Schema.fromJsonString(Schema.Struct({\n kind: Schema.Literals(['chrome', 'chromium', 'lightpanda']),\n executablePath: Schema.String,\n }));\n const io = <A>(operation: () => PromiseLike<A>) => Effect.tryPromise({ try: operation, catch: toPublicError });\n return Effect.runPromise(Effect.gen(function* () {\n const record = yield* Schema.decodeUnknownEffect(recordSchema)(yield* io(() => readFile(choiceFile, 'utf8')));\n const executable = yield* io(() => stat(record.executablePath));\n if (!executable.isFile()) return undefined;\n yield* io(() => access(record.executablePath, constants.X_OK));\n return record;\n }).pipe(Effect.catch(() => Effect.succeed(undefined))));\n}\n\nexport async function writeBrowserChoice(kind: BrowserChoice, executablePath: string): Promise<void> {\n const { Effect } = await import('effect');\n const io = <A>(operation: () => PromiseLike<A>) => Effect.tryPromise({ try: operation, catch: toPublicError });\n const program = Effect.gen(function* () {\n const directory = dirname(choiceFile);\n yield* io(() => mkdir(directory, { recursive: true }));\n const staging = yield* Effect.acquireRelease(\n io(() => mkdtemp(join(directory, '.browser-choice-'))),\n path => io(() => rm(path, { recursive: true, force: true })).pipe(Effect.orDie),\n );\n const temporary = join(staging, 'browser-choice.json');\n yield* io(() => writeFile(temporary, JSON.stringify({ kind, executablePath }), { encoding: 'utf8', flag: 'wx' }));\n yield* io(() => rename(temporary, choiceFile));\n });\n await Effect.runPromise(Effect.scoped(Effect.uninterruptible(program))).catch(cause => { throw toPublicError(cause); });\n}\n\nexport async function chooseBrowser(): Promise<BrowserChoice> {\n const sink = getCliOutputSink();\n const choice = await (sink.promptChoice ?? promptChoice)(\n 'Google Chrome was not found. Which browser would you like to download?',\n [\n 'Chrome for Testing — recommended; highest compatibility, including video and media.',\n 'Chromium — middle ground; proprietary video/audio codecs may be unavailable.',\n 'Lightpanda — lightweight basic automation; low compatibility, experimental WhatsApp support, no video or rendering.',\n ],\n );\n return (['chrome', 'chromium', 'lightpanda'] as const)[choice];\n}\n","import type { CreateClientOptions, OpenWAEventMap } from '@open-wa/core';\nimport type { Client } from '@open-wa/client';\nimport { ConfigSchema, resolveConfig, type PartialConfig, type Config, type TrackedConfig } from '@open-wa/config';\nimport { accessSync, constants, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { getCliOutputSink } from './cli/output-sink';\nimport { chooseBrowser, findSystemBrowser, readBrowserChoice, writeBrowserChoice, type BrowserChoice } from './browser-choice';\n\nexport interface ExecutablePathResolution {\n executablePath?: string;\n source:\n | 'config'\n | 'cache'\n | 'chrome_installation'\n | 'driver_default'\n | 'lightpanda_config'\n | 'lightpanda_managed'\n | 'managed_browser';\n warning?: string;\n}\n\nexport interface DriverSelection {\n driver: CreateClientOptions['driver'];\n engineLabel: 'Puppeteer' | 'Lightpanda';\n executableResolution: ExecutablePathResolution;\n preferLocalChrome: boolean;\n}\n\nfunction readChromePathCache(cacheFilePath: string): { executablePath?: string } | undefined {\n try {\n if (!existsSync(cacheFilePath)) {\n return undefined;\n }\n\n const raw = JSON.parse(readFileSync(cacheFilePath, 'utf8')) as { executablePath?: string };\n if (!raw || typeof raw !== 'object') {\n return undefined;\n }\n\n return {\n executablePath: typeof raw.executablePath === 'string' ? raw.executablePath : undefined,\n };\n } catch {\n return undefined;\n }\n}\n\nfunction writeChromePathCache(executablePath: string, cacheFilePath: string): void {\n mkdirSync(dirname(cacheFilePath), { recursive: true });\n writeFileSync(cacheFilePath, JSON.stringify({ executablePath, updatedAt: new Date().toISOString() }, null, 2), 'utf8');\n}\n\nfunction clearChromePathCache(cacheFilePath: string): void {\n if (existsSync(cacheFilePath)) {\n rmSync(cacheFilePath, { force: true });\n }\n}\n\nfunction isUsableExecutablePath(executablePath?: string): executablePath is string {\n if (!executablePath) return false;\n try {\n if (!statSync(executablePath).isFile()) return false;\n accessSync(executablePath, constants.X_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction getExplicitUseChromePreference(rawConfigs?: TrackedConfig['rawConfigs']): boolean | undefined {\n const explicitConfigSources = [\n rawConfigs?.file,\n rawConfigs?.env,\n rawConfigs?.cli,\n rawConfigs?.programmatic,\n ];\n\n for (let index = explicitConfigSources.length - 1; index >= 0; index -= 1) {\n const source = explicitConfigSources[index];\n if (source?.useChrome !== undefined) {\n return source.useChrome;\n }\n }\n\n return undefined;\n}\n\nexport function shouldPreferLocalChrome(\n config: Config,\n rawConfigs?: TrackedConfig['rawConfigs'],\n defaultPreference = true,\n): boolean {\n if (config.useLightpanda || config.useChromium || config.browser?.kind === 'chromium') {\n return false;\n }\n\n if (config.executablePath || process.env.PUPPETEER_EXECUTABLE_PATH !== undefined) {\n return false;\n }\n\n const explicitUseChrome = getExplicitUseChromePreference(rawConfigs);\n if (explicitUseChrome !== undefined) {\n return explicitUseChrome;\n }\n\n return defaultPreference;\n}\n\nexport async function resolveExecutablePath(\n config: Config,\n options: {\n preferLocalChrome?: boolean;\n cacheFilePath: string;\n kind?: 'chrome' | 'chromium';\n }\n): Promise<ExecutablePathResolution> {\n const configuredPath = config.executablePath ?? process.env.PUPPETEER_EXECUTABLE_PATH;\n if (configuredPath !== undefined) {\n return {\n executablePath: configuredPath,\n source: 'config',\n };\n }\n\n const preferLocalChrome = options.preferLocalChrome ?? config.useChrome;\n if (!preferLocalChrome) {\n return {\n source: 'driver_default',\n };\n }\n\n const matchesKind = (path: string) => options.kind === 'chromium'\n ? /chromium/i.test(path)\n : !/chromium/i.test(path);\n const cachedPath = readChromePathCache(options.cacheFilePath)?.executablePath;\n if (isUsableExecutablePath(cachedPath) && matchesKind(cachedPath)) {\n return {\n executablePath: cachedPath,\n source: 'cache',\n };\n }\n\n if (cachedPath) {\n clearChromePathCache(options.cacheFilePath);\n }\n\n // Check known installation paths and PATH without a synchronous OS-wide\n // application scan, so a missing Chrome reaches the picker promptly.\n const detectedPath = await findSystemBrowser(options.kind ?? 'chrome');\n\n if (detectedPath) {\n writeChromePathCache(detectedPath, options.cacheFilePath);\n return {\n executablePath: detectedPath,\n source: 'chrome_installation',\n };\n }\n\n clearChromePathCache(options.cacheFilePath);\n\n return {\n source: 'driver_default',\n };\n}\n\nexport function resolveLightpandaExecutablePath(config: Config): ExecutablePathResolution {\n const executablePath = config.lightpanda?.executablePath ?? config.executablePath ?? process.env.LIGHTPANDA_EXECUTABLE_PATH;\n if (executablePath) {\n return {\n executablePath,\n source: 'lightpanda_config',\n };\n }\n\n return {\n source: 'lightpanda_managed',\n };\n}\n\nexport async function selectRuntimeDriver(\n config: Config,\n options: {\n rawConfigs?: TrackedConfig['rawConfigs'];\n cacheFilePath: string;\n defaultPreferLocalChrome?: boolean;\n promptForMissingBrowser?: boolean;\n nonInteractive?: boolean;\n }\n): Promise<DriverSelection> {\n const flags = [config.useChrome, config.useChromium, config.useLightpanda].filter(Boolean);\n if (flags.length > 1) throw new Error('Choose only one browser: useChrome, useChromium or useLightpanda.');\n let kind: BrowserChoice | undefined = config.useLightpanda ? 'lightpanda'\n : config.useChromium ? 'chromium'\n : config.useChrome ? 'chrome'\n : config.browser?.kind;\n const explicitChoice = kind !== undefined || getExplicitUseChromePreference(options.rawConfigs) !== undefined\n || config.browser?.download === 'auto';\n const preferLocalChrome = shouldPreferLocalChrome(config, options.rawConfigs, options.defaultPreferLocalChrome ?? true);\n let executableResolution: ExecutablePathResolution = { source: 'driver_default' };\n if (kind !== 'lightpanda') {\n executableResolution = await resolveExecutablePath(config, {\n preferLocalChrome: kind === 'chromium' || preferLocalChrome,\n cacheFilePath: kind === 'chromium' ? `${options.cacheFilePath}.chromium` : options.cacheFilePath,\n kind: kind === 'chromium' ? 'chromium' : 'chrome',\n });\n } else {\n executableResolution = resolveLightpandaExecutablePath(config);\n executableResolution.executablePath ??= config.executablePath;\n }\n if (!executableResolution.executablePath && (kind !== undefined || options.promptForMissingBrowser)\n && !(kind === 'lightpanda' && config.lightpanda?.experimentalWhatsApp !== false)) {\n const remembered = await readBrowserChoice();\n if (remembered && (kind === undefined || remembered.kind === kind)) {\n kind = remembered.kind;\n executableResolution = { source: 'cache', executablePath: remembered.executablePath };\n }\n }\n if (!kind && executableResolution.executablePath === undefined && options.promptForMissingBrowser) {\n // A pre-provisioned Chrome cache is usable even without a remembered choice.\n const { ensureBrowser } = await import('@open-wa/driver-puppeteer');\n try {\n const executablePath = await ensureBrowser({ browser: { ...config.browser, kind: 'chrome', download: 'never' } });\n executableResolution = { source: 'managed_browser', executablePath };\n } catch (error) {\n if (!(error instanceof Error) || !/missing from .* and browser downloads are disabled/.test(error.message)) throw error;\n }\n }\n if (!kind && !executableResolution.executablePath && !explicitChoice && options.promptForMissingBrowser) {\n if (config.browser?.download === 'never') {\n throw new Error('No browser is available and browser downloads are disabled. Configure executablePath or pre-provision a browser cache.');\n }\n if (options.nonInteractive || process.env.CI || process.env.NONINTERACTIVE) {\n throw new Error('No browser is installed. Choose --use-chrome, --use-chromium or --use-lightpanda to download one without a prompt.');\n }\n kind = await chooseBrowser();\n }\n kind ??= 'chrome';\n const sink = getCliOutputSink();\n const ctx = { logger: {\n debug: (message: string) => sink.write({ level: 'debug', message }),\n info: (message: string) => sink.write({ level: 'info', message }),\n warn: (message: string) => sink.write({ level: 'warn', message }),\n error: (message: string) => sink.write({ level: 'error', message }),\n } };\n const browser = {\n ...config.browser,\n ...(explicitChoice || options.promptForMissingBrowser ? { download: config.browser?.download ?? ('auto' as const) } : {}),\n ...(kind !== 'lightpanda' ? { kind } : {}),\n };\n if (kind === 'lightpanda') {\n const { LightpandaDriver, ensureLightpanda } = await import('@open-wa/driver-lightpanda');\n config.lightpanda = ConfigSchema.shape.lightpanda.parse({ ...config.lightpanda, experimentalWhatsApp: config.lightpanda?.experimentalWhatsApp ?? true });\n config.browser = browser;\n const executablePath = await ensureLightpanda({\n executablePath: executableResolution.executablePath,\n browser,\n preferPinnedRelease: config.lightpanda?.experimentalWhatsApp ?? true,\n }, ctx);\n config.useLightpanda = true;\n config.useChrome = false;\n config.useChromium = false;\n sink.write({ level: 'warn', message: 'Lightpanda has low compatibility and experimental WhatsApp support; video, screenshots and rendering are unavailable.' });\n if (options.promptForMissingBrowser) {\n await writeBrowserChoice(kind, executablePath).catch(error => sink.write({ level: 'warn', message: `Could not remember the browser choice: ${error instanceof Error ? error.message : String(error)}` }));\n }\n return {\n driver: new LightpandaDriver(),\n engineLabel: 'Lightpanda',\n executableResolution: { source: 'lightpanda_managed', executablePath },\n preferLocalChrome: false,\n };\n }\n config.browser = browser;\n const { PuppeteerDriver, ensureBrowser } = await import('@open-wa/driver-puppeteer');\n const executablePath = await ensureBrowser({ executablePath: executableResolution.executablePath, browser }, ctx);\n if (!executableResolution.executablePath) executableResolution = { source: 'managed_browser', executablePath };\n if (options.promptForMissingBrowser) {\n await writeBrowserChoice(kind, executablePath).catch(error => sink.write({ level: 'warn', message: `Could not remember the browser choice: ${error instanceof Error ? error.message : String(error)}` }));\n }\n return {\n driver: new PuppeteerDriver(),\n engineLabel: 'Puppeteer',\n executableResolution,\n preferLocalChrome,\n };\n}\n\n/** Load the Node media runtime only when a call needs a source or sink. */\nexport function makeDefaultCallMediaHost(): NonNullable<CreateClientOptions['callMediaHost']> {\n return {\n async prepare(...args) {\n const { makeNodeCallMediaHost } = await import('@open-wa/runtime-node');\n return makeNodeCallMediaHost({ log: message => getCliOutputSink().write({ level: 'info', message }) }).prepare(...args);\n },\n };\n}\n\nexport function toCreateClientOptions(\n config: Config,\n driverSelection: DriverSelection,\n options: {\n debug?: boolean;\n } = {},\n): CreateClientOptions {\n return {\n sessionId: config.sessionId,\n eventMode: config.eventMode,\n driver: driverSelection.driver,\n deleteSessionDataOnLogout: config.deleteSessionDataOnLogout,\n killClientOnLogout: config.killClientOnLogout,\n sessionDataPath: config.sessionDataPath,\n sessionData: config.sessionData,\n skipSessionSave: config.skipSessionSave,\n sessionDataBucketAuth: config.sessionDataBucketAuth,\n sessionDataEncryptionKey: config.sessionDataEncryptionKey,\n sessionDataEncryptionKeyFile: config.sessionDataEncryptionKeyFile,\n s3Sync: config.s3Sync,\n debug: options.debug ?? (config.logLevel === 'debug' || config.logConsole),\n headless: config.headless,\n qrTimeoutMs: typeof config.qrTimeout === 'number' ? config.qrTimeout * 1000 : undefined,\n authTimeoutMs: typeof config.authTimeout === 'number' ? config.authTimeout * 1000 : undefined,\n executablePath: driverSelection.executableResolution.executablePath,\n browserArgs: config.chromiumArgs,\n browser: config.browser,\n allowDangerousBrowserArgs: config.allowDangerousBrowserArgs,\n userDataDir: config.userDataDir,\n ephemeral: config.ephemeral,\n linkCode: config.linkCode,\n qrMax: config.qrMax,\n oorTimeoutMs: config.oorTimeout * 1000,\n logConsole: config.logConsole,\n logConsoleErrors: config.logConsoleErrors,\n blockCrashLogs: config.blockCrashLogs,\n blockAssets: config.blockAssets,\n safeMode: config.safeMode,\n lightpanda: config.useLightpanda ? { experimentalWhatsApp: true, ...config.lightpanda } : undefined,\n licenseKey: config.licenseKey as any,\n calling: config.calling,\n callMediaHost: makeDefaultCallMediaHost(),\n licenseConfig: config.licenseConfig,\n patchConfig: { ghPatch: config.ghPatch, cachedPatch: config.cachedPatch },\n };\n}\n\n/** Options for the ready-to-use messaging client. */\nexport type CreateOptions = Omit<PartialConfig, 's3Sync' | 'calling'> & {\n calling?: import('@open-wa/schema').CallingOptions;\n s3Sync?: Omit<NonNullable<PartialConfig['s3Sync']>, 'region' | 'syncInterval'> & {\n region?: string;\n syncInterval?: number;\n };\n /** Override the default Puppeteer driver. */\n driver?: CreateClientOptions['driver'];\n};\n\n/** Start WhatsApp, display QR login when needed, and return a ready messaging client. */\nexport async function create(options: CreateOptions = {}): Promise<Client> {\n const { createClient: createCoreClient } = await import('@open-wa/core');\n const { Client } = await import('@open-wa/client');\n const { driver, sessionData, sessionDataBucketAuth, s3Sync, calling,\n sessionDataEncryptionKey, sessionDataEncryptionKeyFile, ...configOverrides } = options;\n const { config, rawConfigs } = await resolveConfig({\n programmaticOverrides: {\n qrTimeout: 0, ...configOverrides,\n // Session seeds, encryption keys and bucket credentials bypass tracked/debug config.\n },\n skipConfigFile: true,\n skipEnv: true,\n includeRawConfigs: true,\n });\n\n const driverSelection: DriverSelection = driver ? {\n driver,\n engineLabel: driver.name === 'lightpanda' ? 'Lightpanda' : 'Puppeteer',\n executableResolution: { source: 'config', executablePath: config.executablePath },\n preferLocalChrome: false,\n } : await selectRuntimeDriver(config, {\n rawConfigs,\n cacheFilePath: resolve(process.cwd(), '.open-wa', 'chrome-executable-path.json'),\n defaultPreferLocalChrome: false,\n });\n\n const coreOptions = toCreateClientOptions(config, driverSelection);\n if (calling) coreOptions.calling = calling;\n if (driver) coreOptions.driver = driver;\n coreOptions.sessionData = sessionData;\n coreOptions.sessionDataBucketAuth = sessionDataBucketAuth;\n coreOptions.sessionDataEncryptionKey = sessionDataEncryptionKey;\n coreOptions.sessionDataEncryptionKeyFile = sessionDataEncryptionKeyFile;\n coreOptions.s3Sync = s3Sync;\n\n const core = await createCoreClient(coreOptions);\n const sink = getCliOutputSink();\n const onQr = (event: OpenWAEventMap['launch.auth.qr.generated']) => {\n if (config.qrLogSkip || !event.details?.qr) return;\n sink.write({ level: 'info', message: 'Open WhatsApp on your sending phone: Linked Devices → Link a Device, then scan this QR code.' });\n sink.qr({ qr: event.details.qr, sessionId: config.sessionId });\n };\n const onLinkCode = (event: OpenWAEventMap['launch.auth.linkCode.generated']) => {\n if (event.details?.linkCode && !config.qrLogSkip) {\n sink.write({ level: 'info', message: `Enter this link code on your sending phone: ${event.details.linkCode}` });\n }\n };\n core.events.on('launch.auth.qr.generated', onQr);\n core.events.on('launch.auth.linkCode.generated', onLinkCode);\n let client: Client | undefined;\n try {\n client = new Client({ client: core, transport: core.getTransport() });\n await client.start();\n if (core.getState() !== 'READY' || !core.getReadiness().exposureSafe) {\n throw new Error('WhatsApp startup finished without a messaging-ready session.');\n }\n return client;\n } catch (error) {\n try {\n if (client) await client.stop('startup-failure');\n else await core.stop('startup-failure');\n } catch {\n // Keep the startup failure as the actionable error.\n }\n throw error;\n } finally {\n core.events.off('launch.auth.qr.generated', onQr);\n core.events.off('launch.auth.linkCode.generated', onLinkCode);\n }\n}\n","import { createClient } from '@open-wa/core';\nimport { Client as ClientFacade } from '@open-wa/client';\nimport { selectRuntimeDriver as selectSharedRuntimeDriver, resolveExecutablePath as resolveSharedExecutablePath, makeDefaultCallMediaHost, type DriverSelection } from './runtime-client';\nimport { eventRegistry } from '@open-wa/schema';\nimport { WAServer } from './server/hono-server';\nimport { resolveConfig, type PartialConfig, type Config, type TrackedConfig } from '@open-wa/config';\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { getCliOutputSink, type CliOutputSink } from './cli/output-sink';\nimport {\n defaultChatSandboxPolicy,\n type ChatSandboxPolicy,\n type SandboxIsolation,\n} from '@open-wa/runtime-core';\nimport { makeNodeExecutionSandbox, observeBrowserProcessMemory } from '@open-wa/runtime-node';\n\nexport interface CliRuntimeResult {\n server: WAServer;\n client: ClientFacade;\n config: Config;\n events: ClientFacade['events'];\n dispose(): void;\n}\n\ninterface RuntimeEventPublisher {\n publish(eventName: string, payload: any): void;\n}\n\nfunction bridgeRuntimeEvents(\n openwaClient: Awaited<ReturnType<typeof createClient>>,\n publishRuntimeEvent: (eventName: string, payload: any) => void,\n): () => void {\n if (typeof openwaClient.events.onAny === 'function' && typeof openwaClient.events.offAny === 'function') {\n openwaClient.events.onAny(publishRuntimeEvent);\n return () => openwaClient.events.offAny(publishRuntimeEvent);\n }\n\n const unsubscribers: Array<() => void> = [];\n const bridgedEvents = new Set(eventRegistry.getAll().map((def) => def.meta.eventName));\n bridgedEvents.add('session.refresh.progress');\n\n bridgedEvents.forEach((eventName) => {\n const handler = (payload: any) => publishRuntimeEvent(eventName, payload);\n openwaClient.events.on(eventName as never, handler);\n unsubscribers.push(() => openwaClient.events.off(eventName as never, handler));\n });\n\n return () => {\n unsubscribers.forEach((unsubscribe) => unsubscribe());\n };\n}\n\nfunction attachLaunchNarration(\n openwaClient: Awaited<ReturnType<typeof createClient>>,\n sink: CliOutputSink,\n sessionId: string,\n): () => void {\n const unsubscribers: Array<() => void> = [];\n const on = (event: string, handler: (...args: any[]) => void) => {\n openwaClient.events.on(event as never, handler);\n unsubscribers.push(() => openwaClient.events.off(event as never, handler));\n };\n\n on('launch.auth.check.before', (event: any) => {\n sink.status({ phase: 'launch.auth', sessionId, detail: `Authenticating (timeout=${event?.details?.timeoutMs ?? '∞'}ms)` });\n });\n\n on('launch.auth.check.after', (event: any) => {\n sink.write({ level: 'info', message: `Auth detected via ${event?.details?.method ?? 'unknown'} (${event?.details?.isAuthenticated ? 'authenticated' : 'not-authenticated'})` });\n });\n\n on('launch.helper.pre_api.before', (event: any) => {\n sink.status({ phase: 'launch.helpers', sessionId, detail: event?.details?.mode === 'scripts' ? 'Injecting pre-API helper assets...' : 'Pre-API helpers already present' });\n });\n\n on('launch.helper.pre_api.after', (event: any) => {\n sink.write({ level: 'info', message: `Pre-API helper phase complete (${event?.details?.mode ?? 'unknown'})` });\n });\n\n on('internal_launch_progress', (event: any) => {\n const prefix = (event?.value || event?.value === 0) ? `${event.value}% ` : '';\n if (event?.text) sink.write({ level: 'info', message: `${prefix}${event.text}`.trim() });\n });\n\n on('critical_internal_message', (event: any) => {\n sink.write({ level: 'warn', message: `Internal launch message: ${event?.text ?? event?.value ?? 'unknown'}` });\n });\n\n on('launch.patch.init.before', (event: any) => {\n if (event?.details?.phase === 'preload') {\n sink.status({ phase: 'launch.patch', sessionId, detail: 'Downloading patches from CDN...' });\n }\n });\n\n on('launch.patch.init.after', (event: any) => {\n if (event?.details?.phase === 'preload') {\n const source = event?.details?.source ?? 'unknown';\n const tag = event?.details?.tag ? ` tag=${event.details.tag}` : '';\n const available = Array.isArray(event?.details?.available) ? event.details.available.length : 0;\n const durationMs = event?.durationMs;\n const durationStr = durationMs ? ` in ${(durationMs / 1000).toFixed(2)}s` : '';\n sink.write({ level: 'info', message: `Downloaded patches${durationStr} (source=${source}, available=${available}${tag})` });\n }\n });\n\n on('patch.init.before', (event: any) => {\n if (event?.details?.phase === 'apply') {\n const count = Array.isArray(event?.details?.patchIds) ? event.details.patchIds.length : 0;\n sink.status({ phase: 'launch.patch', sessionId, detail: `Installing patches (${count} queued)` });\n }\n });\n\n on('patch.apply.before', (event: any) => {\n sink.status({ phase: 'launch.patch', sessionId, detail: `Applying patch: ${event?.details?.patchId ?? 'unknown'}` });\n });\n\n on('patch.apply.after', (event: any) => {\n sink.write({\n level: event?.details?.outcome === 'failed' ? 'warn' : 'info',\n message: `Patch ${event?.details?.patchId ?? 'unknown'}: ${event?.details?.outcome ?? (event?.details?.applied ? 'applied' : 'unknown')}${event?.details?.detail ? ` — ${event.details.detail}` : ''}`,\n });\n });\n\n on('patch.init.after', (event: any) => {\n if (event?.details?.phase === 'apply') {\n const applied = Array.isArray(event?.details?.applied) ? event.details.applied : [];\n const outcome = event?.details?.outcome ?? 'unknown';\n const tag = applied.length > 0 ? applied.join(', ') : outcome;\n const durationMs = event?.durationMs;\n const durationStr = durationMs ? ` in ${(durationMs / 1000).toFixed(2)}s` : '';\n sink.write({\n level: event?.details?.blockingFailure ? 'warn' : 'info',\n message: `Patches Installed${durationStr}: ${tag}`,\n });\n }\n });\n\n on('launch.patch.integrity.before', () => {\n sink.status({ phase: 'launch.patch', sessionId, detail: 'Validating patched runtime...' });\n });\n\n on('launch.patch.integrity.after', (event: any) => {\n sink.write({ level: event?.details?.usable ? 'info' : 'warn', message: `Patched runtime validation: ${event?.details?.usable ? 'usable' : 'failed'}${event?.details?.failureReason ? ` (${event.details.failureReason})` : ''}` });\n });\n\n on('launch.license.check.before', (event: any) => {\n sink.status({ phase: 'launch.license', sessionId, detail: `Checking license (${event?.details?.source ?? 'local'})` });\n });\n\n on('launch.license.check.after', (event: any) => {\n sink.write({ level: event?.details?.blockingFailure ? 'warn' : 'info', message: `License check: ${event?.details?.status ?? 'unknown'}${event?.details?.detail ? ` — ${event.details.detail}` : ''}` });\n });\n\n on('license.inject.before', () => {\n sink.status({ phase: 'launch.license', sessionId, detail: 'Injecting license payload...' });\n });\n\n on('license.inject.after', (event: any) => {\n sink.write({ level: event?.details?.success ? 'info' : 'warn', message: `License inject: ${event?.details?.success ? 'success' : 'failed'}${event?.details?.status ? ` (${event.details.status})` : ''}${event?.details?.detail ? ` — ${event.details.detail}` : ''}` });\n });\n\n on('launch.auth.qr.generated', (event: any) => {\n const qrIndex = event?.details?.qrIndex ?? '?';\n sink.status({ phase: 'launch.auth', sessionId, detail: `QR code generated (#${qrIndex})` });\n });\n\n on('launch.client.finalize.before', (event: any) => {\n sink.status({ phase: 'launch.finalize', sessionId, detail: `Finalizing session (${event?.details?.validationStage ?? 'unknown'})` });\n });\n\n on('launch.client.finalize.after', (event: any) => {\n sink.write({ level: event?.details?.success ? 'info' : 'warn', message: `Finalize: ${event?.details?.outcome ?? 'unknown'}${event?.details?.detail ? ` — ${event.details.detail}` : ''}` });\n });\n\n on('error', (event: any) => {\n const scope = event?.scope ?? 'unknown';\n const msg = event?.error?.message ?? String(event?.error ?? 'unknown error');\n const fatal = event?.fatal ? ' [FATAL]' : '';\n sink.write({ level: 'error', message: `${fatal} ${scope}: ${msg}`.trim() });\n });\n\n return () => {\n unsubscribers.forEach((unsubscribe) => unsubscribe());\n };\n}\n\nconst CHROME_CACHE_FILE = resolve(process.cwd(), '.open-wa', 'chrome-executable-path.json');\n\ninterface ChromePathCacheRecord {\n executablePath?: string;\n updatedAt?: string;\n}\n\ninterface ExecutablePathResolution {\n executablePath?: string;\n source:\n | 'config'\n | 'cache'\n | 'chrome_installation'\n | 'driver_default'\n | 'lightpanda_config'\n | 'lightpanda_managed'\n | 'managed_browser';\n warning?: string;\n}\n\nexport interface ParsedCliArgs {\n procName: string;\n pm2: boolean;\n forwardedArgs: string[];\n configPath?: string;\n cliOverrides: PartialConfig;\n verbose: boolean;\n unsupportedWarnings: string[];\n}\n\nexport function getChromeCacheFilePath(): string {\n return CHROME_CACHE_FILE;\n}\n\nexport function readChromePathCache(cacheFilePath: string = getChromeCacheFilePath()): ChromePathCacheRecord | undefined {\n if (!existsSync(cacheFilePath)) {\n return undefined;\n }\n\n try {\n const raw = JSON.parse(readFileSync(cacheFilePath, 'utf8')) as ChromePathCacheRecord;\n if (!raw || typeof raw !== 'object') {\n return undefined;\n }\n\n return {\n executablePath: typeof raw.executablePath === 'string' ? raw.executablePath : undefined,\n updatedAt: typeof raw.updatedAt === 'string' ? raw.updatedAt : undefined,\n };\n } catch {\n return undefined;\n }\n}\n\nexport function writeChromePathCache(executablePath: string, cacheFilePath: string = getChromeCacheFilePath()): void {\n mkdirSync(dirname(cacheFilePath), { recursive: true });\n writeFileSync(cacheFilePath, JSON.stringify({ executablePath, updatedAt: new Date().toISOString() }, null, 2), 'utf8');\n}\n\nexport function clearChromePathCache(cacheFilePath: string = getChromeCacheFilePath()): void {\n if (existsSync(cacheFilePath)) {\n rmSync(cacheFilePath, { force: true });\n }\n}\n\nexport function isUsableExecutablePath(executablePath?: string): executablePath is string {\n return !!executablePath && existsSync(executablePath);\n}\n\nfunction getExplicitUseChromePreference(rawConfigs?: TrackedConfig['rawConfigs']): boolean | undefined {\n const explicitConfigSources = [\n rawConfigs?.file,\n rawConfigs?.env,\n rawConfigs?.cli,\n rawConfigs?.programmatic,\n ];\n\n for (let index = explicitConfigSources.length - 1; index >= 0; index -= 1) {\n const source = explicitConfigSources[index];\n if (source?.useChrome !== undefined) {\n return source.useChrome;\n }\n }\n\n return undefined;\n}\n\nexport function shouldPreferLocalChrome(config: Config, rawConfigs?: TrackedConfig['rawConfigs']): boolean {\n if (config.useLightpanda || config.useChromium || config.browser?.kind === 'chromium') {\n return false;\n }\n\n if (config.executablePath) {\n return false;\n }\n\n const explicitUseChrome = getExplicitUseChromePreference(rawConfigs);\n if (explicitUseChrome !== undefined) {\n return explicitUseChrome;\n }\n\n return true;\n}\n\nfunction getVal(argv: string[], flag: string): string | undefined {\n const index = argv.findIndex(arg => arg === flag);\n return index !== -1 ? argv[index + 1] : undefined;\n}\n\nfunction parseSandboxIsolation(value: string): SandboxIsolation {\n switch (value) {\n case 'worker':\n case 'process':\n case 'container':\n return value;\n default:\n throw new Error(`Invalid --sandbox-isolation value: ${value}`);\n }\n}\n\nexport function resolveChatSandboxPolicy(config: Config['sandboxChats']): ChatSandboxPolicy | undefined {\n if (!config) return undefined;\n\n const overrides = typeof config === 'object'\n ? config as Partial<Omit<ChatSandboxPolicy, 'chats'>>\n : {};\n return {\n ...defaultChatSandboxPolicy,\n ...overrides,\n chats: true,\n networkAllowlist: [...(overrides.networkAllowlist ?? defaultChatSandboxPolicy.networkAllowlist)],\n env: overrides.env === 'none' || overrides.env === undefined\n ? overrides.env ?? defaultChatSandboxPolicy.env\n : [...overrides.env],\n capabilities: [...(overrides.capabilities ?? defaultChatSandboxPolicy.capabilities)],\n };\n}\n\nexport function parseCliArgs(argv: string[] = process.argv.slice(2)): ParsedCliArgs {\n const cliOverrides: PartialConfig = {};\n const unsupportedWarnings: string[] = [];\n let verbose = false;\n let configPath: string | undefined;\n\n const sessionId = getVal(argv, '--session-id');\n if (sessionId) cliOverrides.sessionId = sessionId;\n\n const portValue = getVal(argv, '--port') || getVal(argv, '-p');\n if (portValue) cliOverrides.port = parseInt(portValue, 10);\n\n const host = getVal(argv, '--host') || getVal(argv, '-h');\n if (host) cliOverrides.host = host;\n\n const apiKey = getVal(argv, '--api-key') || getVal(argv, '--key') || getVal(argv, '-k');\n if (apiKey) cliOverrides.apiKey = apiKey;\n\n const logLevel = getVal(argv, '--log-level');\n if (logLevel) cliOverrides.logLevel = logLevel;\n\n if (argv.includes('--no-ezqr')) cliOverrides.ezqr = false;\n if (argv.includes('--headful')) cliOverrides.headless = false;\n if (argv.includes('--headless')) cliOverrides.headless = true;\n const browserFlags = ['--use-chrome', '--use-chromium', '--use-lightpanda'].filter(flag => argv.includes(flag) || flag === '--use-lightpanda' && argv.includes('--lightpanda'));\n if (browserFlags.length > 1) throw new Error('Choose only one of --use-chrome, --use-chromium or --use-lightpanda.');\n if (browserFlags.length) {\n cliOverrides.useChrome = browserFlags[0] === '--use-chrome';\n cliOverrides.useChromium = browserFlags[0] === '--use-chromium';\n cliOverrides.useLightpanda = browserFlags[0] === '--use-lightpanda';\n }\n if (argv.includes('--log-console')) cliOverrides.logConsole = true;\n if (argv.includes('--aggressive-garbage-collection')) cliOverrides.aggressiveGarbageCollection = true;\n if (argv.includes('--no-dashboard')) cliOverrides.dashboard = false;\n if (argv.includes('--ephemeral')) cliOverrides.ephemeral = true;\n if (argv.includes('--sandbox-chats')) cliOverrides.sandboxChats = true;\n\n const sandboxIsolation = getVal(argv, '--sandbox-isolation');\n if (sandboxIsolation) {\n const { chats: _chats, ...sandboxDefaults } = defaultChatSandboxPolicy;\n cliOverrides.sandboxChats = {\n ...sandboxDefaults,\n isolation: parseSandboxIsolation(sandboxIsolation),\n networkAllowlist: [...defaultChatSandboxPolicy.networkAllowlist],\n env: defaultChatSandboxPolicy.env === 'none'\n ? 'none'\n : [...defaultChatSandboxPolicy.env],\n capabilities: [...defaultChatSandboxPolicy.capabilities],\n };\n }\n\n const qrTimeout = getVal(argv, '--qr-timeout');\n if (qrTimeout) cliOverrides.qrTimeout = parseInt(qrTimeout, 10);\n\n const dashboardPort = getVal(argv, '--dashboard-port');\n if (dashboardPort) cliOverrides.dashboardPort = parseInt(dashboardPort, 10);\n\n const licenseKey = getVal(argv, '--license-key') || getVal(argv, '-l');\n if (licenseKey) cliOverrides.licenseKey = licenseKey;\n\n const webhook = getVal(argv, '--webhook') || getVal(argv, '-w');\n if (webhook) cliOverrides.webhook = webhook;\n\n const proxyHost = getVal(argv, '--proxy-host');\n if (proxyHost) cliOverrides.proxyHost = proxyHost;\n\n const proxyToken = getVal(argv, '--proxy-token');\n if (proxyToken) cliOverrides.proxyToken = proxyToken;\n\n const readyWebhook = getVal(argv, '--ready-webhook');\n if (readyWebhook) unsupportedWarnings.push(`--ready-webhook was provided (${readyWebhook}) but ready-webhook delivery is not yet wired in v5 CLI.`);\n\n if (argv.includes('-v') || argv.includes('--verbose')) {\n verbose = true;\n cliOverrides.disableSpins = true;\n cliOverrides.logConsole = true;\n cliOverrides.logLevel = cliOverrides.logLevel || 'debug';\n }\n\n if (argv.includes('--stats')) {\n unsupportedWarnings.push('--stats was provided but swagger-stats parity is not restored; v5 only exposes the compatibility redirect/deprecation route.');\n }\n\n if (argv.includes('--generate-api-docs')) {\n unsupportedWarnings.push('--generate-api-docs was provided; runtime docs are always served from the shared API layer and no separate collection generation step currently runs at CLI boot.');\n }\n\n if (argv.includes('--tunnel')) {\n unsupportedWarnings.push('--tunnel was provided but tunnel setup parity is not yet restored in the v5 CLI.');\n }\n\n if (argv.includes('--chatwoot-url') || argv.includes('--twilio-webhook') || argv.includes('--bot-press-url')) {\n unsupportedWarnings.push('Legacy integration flags (Chatwoot/Twilio/BotPress) were provided but are not yet wired into the v5 CLI boot path.');\n }\n\n if (argv.includes('--use-session-id-in-path') && sessionId) {\n cliOverrides.sessionId = sessionId;\n }\n\n configPath = getVal(argv, '--config') || getVal(argv, '-c');\n\n const procName = getVal(argv, '--name') || sessionId || '@OPEN-WA EASY API';\n const pm2 = argv.includes('--pm2');\n\n return {\n procName,\n pm2,\n forwardedArgs: argv,\n configPath,\n cliOverrides,\n verbose,\n unsupportedWarnings,\n };\n}\n\nexport async function resolveExecutablePath(\n config: Config,\n options: { preferLocalChrome?: boolean; cacheFilePath?: string } = {},\n): Promise<ExecutablePathResolution> {\n return resolveSharedExecutablePath(config, {\n ...options,\n cacheFilePath: options.cacheFilePath ?? getChromeCacheFilePath(),\n kind: config.useChromium || config.browser?.kind === 'chromium' ? 'chromium' : 'chrome',\n });\n}\n\nasync function selectRuntimeDriver(config: Config, rawConfigs?: TrackedConfig['rawConfigs'], nonInteractive = false): Promise<DriverSelection> {\n return selectSharedRuntimeDriver(config, {\n rawConfigs,\n cacheFilePath: getChromeCacheFilePath(),\n promptForMissingBrowser: true,\n nonInteractive,\n });\n}\n\nfunction printStartupSummary(\n config: Config,\n resolution: ExecutablePathResolution,\n preferLocalChrome: boolean,\n engineLabel: DriverSelection['engineLabel'],\n) {\n const host = config.host.includes('http') ? config.host : `http://${config.host}`;\n const sink = getCliOutputSink();\n sink.write({ level: 'info', message: `Easy API session: ${config.sessionId}` });\n sink.write({ level: 'info', message: `Health: ${host}:${config.port}/health` });\n sink.write({ level: 'info', message: `API Explorer: ${host}:${config.port}/api-docs/` });\n sink.write({ level: 'info', message: `Swagger JSON: ${host}:${config.port}/meta/swagger.json` });\n sink.write({ level: 'info', message: `Postman JSON: ${host}:${config.port}/meta/postman.json` });\n sink.write({ level: 'info', message: `Browser mode: ${config.headless ? 'headless' : 'headful'}` });\n sink.write({ level: 'info', message: `Browser engine: ${engineLabel}` });\n if (config.dashboard) {\n sink.write({ level: 'info', message: `Dashboard: ${host}:${config.port}/dashboard/` });\n } else {\n sink.write({ level: 'info', message: 'Dashboard: disabled (--no-dashboard)' });\n }\n if (resolution.source === 'lightpanda_config' && resolution.executablePath) {\n sink.write({ level: 'info', message: `Browser executable: explicit Lightpanda override (${resolution.executablePath})` });\n } else if (resolution.source === 'lightpanda_managed') {\n sink.write({ level: 'info', message: `Browser executable: Lightpanda with experimental WhatsApp setup (${resolution.executablePath})` });\n } else if (resolution.source === 'config' && config.executablePath) {\n sink.write({ level: 'info', message: `Browser executable: explicit override (${config.executablePath})` });\n } else if (resolution.source === 'cache') {\n sink.write({ level: 'info', message: `Browser executable: cached browser (${resolution.executablePath})` });\n } else if (resolution.source === 'chrome_installation') {\n sink.write({ level: 'info', message: `Browser executable: installed ${config.browser?.kind === 'chromium' ? 'Chromium' : 'Chrome'} (${resolution.executablePath})` });\n } else if (resolution.source === 'managed_browser') {\n sink.write({ level: 'info', message: `Browser executable: managed ${config.browser?.kind === 'chromium' ? 'Chromium' : 'Chrome'} (${resolution.executablePath})` });\n }\n if (config.webhook) {\n sink.write({\n level: 'warn',\n message: `Webhook configured (${config.webhook}) but v5 CLI webhook registration parity is not yet restored.`,\n });\n }\n}\n\nexport async function start(parsedArgs: ParsedCliArgs = parseCliArgs()): Promise<CliRuntimeResult> {\n const { configPath, cliOverrides, verbose, unsupportedWarnings } = parsedArgs;\n const sink = getCliOutputSink();\n\n sink.status({ phase: 'boot' });\n\n const { config, sources, configFilePath, rawConfigs } = await resolveConfig({\n configPath,\n cliOverrides: {\n disableSpins: true,\n apiLifecycle: 'hybrid',\n // Let schema defaults, config files, and WA_HOST/WA_PORT resolve\n // before applying host/port flags actually supplied by the user.\n ...cliOverrides,\n },\n includeRawConfigs: true,\n verbose,\n });\n\n if (verbose) {\n sink.write({ level: 'info', message: `Config sources: ${sources.join(', ')}` });\n if (configFilePath) {\n sink.write({ level: 'info', message: `Config file: ${configFilePath}` });\n }\n }\n\n sink.status({ phase: 'config.resolved', sessionId: config.sessionId });\n\n unsupportedWarnings.forEach((warning) => sink.write({ level: 'warn', message: `Compatibility warning: ${warning}` }));\n\n const driverSelection = await selectRuntimeDriver(config, rawConfigs, parsedArgs.forwardedArgs.includes('--non-interactive'));\n const { driver, engineLabel, executableResolution, preferLocalChrome } = driverSelection;\n if (executableResolution.warning) {\n sink.write({ level: 'warn', message: executableResolution.warning });\n }\n\n const server = new WAServer(config);\n sink.status({ phase: 'server.starting', sessionId: config.sessionId });\n\n await server.start();\n sink.status({ phase: 'server.started', sessionId: config.sessionId });\n\n printStartupSummary(config, executableResolution, preferLocalChrome, engineLabel);\n\n sink.status({ phase: 'client.starting', sessionId: config.sessionId });\n sink.write({ level: 'info', message: 'Starting WhatsApp Client...' });\n\n const sandboxPolicy = resolveChatSandboxPolicy(config.sandboxChats);\n const executionSandbox = sandboxPolicy\n ? makeNodeExecutionSandbox({ workspacePath: process.cwd() })\n : undefined;\n\n const openwaClient = await createClient({\n sessionId: config.sessionId,\n eventMode: config.eventMode,\n driver,\n deleteSessionDataOnLogout: config.deleteSessionDataOnLogout,\n killClientOnLogout: config.killClientOnLogout,\n sessionDataPath: config.sessionDataPath,\n sessionData: config.sessionData,\n skipSessionSave: config.skipSessionSave,\n sessionDataBucketAuth: config.sessionDataBucketAuth,\n sessionDataEncryptionKey: config.sessionDataEncryptionKey,\n sessionDataEncryptionKeyFile: config.sessionDataEncryptionKeyFile,\n s3Sync: config.s3Sync,\n debug: config.logLevel === 'debug' || verbose || config.logConsole,\n headless: config.headless,\n qrTimeoutMs: typeof config.qrTimeout === 'number' ? config.qrTimeout * 1000 : undefined,\n authTimeoutMs: typeof config.authTimeout === 'number' ? config.authTimeout * 1000 : undefined,\n executablePath: executableResolution.executablePath,\n browserArgs: config.chromiumArgs,\n browser: config.browser,\n allowDangerousBrowserArgs: config.allowDangerousBrowserArgs,\n userDataDir: config.userDataDir,\n ephemeral: config.ephemeral,\n linkCode: config.linkCode,\n logConsole: config.logConsole,\n logConsoleErrors: config.logConsoleErrors,\n blockCrashLogs: config.blockCrashLogs,\n blockAssets: config.blockAssets,\n safeMode: config.safeMode,\n lightpanda: config.useLightpanda ? { experimentalWhatsApp: true, ...config.lightpanda } : undefined,\n licenseKey: config.licenseKey as any,\n licenseConfig: config.licenseConfig,\n calling: config.calling,\n callMediaHost: makeDefaultCallMediaHost(),\n sandboxPolicy,\n executionSandbox,\n memoryObservation: (observability, getBrowserProcessId) => observeBrowserProcessMemory(\n observability,\n getBrowserProcessId,\n { attributes: { session: config.sessionId } },\n ),\n });\n\n server.setReadinessProvider(() => ({ ...openwaClient.getReadiness(), state: openwaClient.getState() }));\n const detachLaunchNarration = attachLaunchNarration(openwaClient, sink, config.sessionId);\n\n openwaClient.events.on('launch.auth.qr.expired', () => server.setQR(null));\n openwaClient.events.on('launch.auth.qr.scanned', () => server.setQR(null));\n openwaClient.events.on('launch.auth.qr.generated', (event) => {\n const qr = event.details?.qr;\n if (!qr) {\n return;\n }\n\n if (config.qrLogSkip) {\n sink.write({ level: 'info', message: 'New QR Code generated. Not printing in console because qrLogSkip is set to true' });\n } else {\n sink.status({ phase: 'auth.qr', sessionId: config.sessionId, detail: 'QR code generated' });\n sink.qr({ qr, sessionId: config.sessionId });\n }\n\n server.setQR(qr);\n });\n\n openwaClient.events.on('launch.auth.linkCode.generated', (event) => {\n const linkCode = event.details?.linkCode;\n if (!linkCode) {\n return;\n }\n\n sink.status({\n phase: 'launch.auth',\n sessionId: config.sessionId,\n detail: 'Link code generated; enter it on the paired phone',\n });\n sink.write({\n level: 'info',\n message: `Link code (local console only): ${linkCode}`,\n });\n });\n\n const client = new ClientFacade({\n client: openwaClient,\n transport: openwaClient.getTransport(),\n });\n\n server.setClient(client as any);\n\n const runtimeBridgeListeners = new Set<(event: string, value: any) => void>();\n const runtimeEventPublishers: RuntimeEventPublisher[] = [\n {\n publish: (eventName, payload) => {\n runtimeBridgeListeners.forEach((listener) => {\n listener(eventName, payload);\n });\n },\n },\n ];\n\n const publishRuntimeEvent = (eventName: string, payload: any) => {\n runtimeEventPublishers.forEach((publisher) => {\n publisher.publish(eventName, payload);\n });\n };\n\n const detachRuntimeBridge = bridgeRuntimeEvents(openwaClient, publishRuntimeEvent);\n\n // Bridge core events to the socket manager so dashboard clients\n // receive live events when they send register_ev.\n if (typeof server.setEventBridge === 'function') {\n server.setEventBridge({\n onAny: (listener: (event: string, value: any) => void) => {\n runtimeBridgeListeners.add(listener);\n },\n offAny: (listener: (event: string, value: any) => void) => {\n runtimeBridgeListeners.delete(listener);\n },\n });\n }\n\n const handleBrowserInit = async () => {\n const page = openwaClient.getTransport().getPage();\n if (page) {\n await server.setPage(page as any).catch(() => {});\n }\n };\n openwaClient.events.on('launch.browser.init.after', handleBrowserInit);\n\n let disposed = false;\n const dispose = () => {\n if (disposed) return;\n disposed = true;\n detachRuntimeBridge();\n openwaClient.events.off('launch.browser.init.after', handleBrowserInit);\n runtimeBridgeListeners.clear();\n };\n\n try {\n await client.start();\n } catch (startError) {\n const msg = startError instanceof Error ? startError.message : String(startError);\n sink.write({ level: 'error', message: `Bootstrap failed: ${msg}` });\n sink.write({ level: 'warn', message: 'The API server is still running for inspection; the client failed to start.' });\n sink.write({ level: 'warn', message: 'The server is running — use /health and /api-docs to inspect state.' });\n detachLaunchNarration();\n return { server, client, config, events: openwaClient.events, dispose };\n }\n\n const readiness = openwaClient.getReadiness();\n sink.status({\n phase: 'client.ready',\n sessionId: config.sessionId,\n detail: `status=${readiness.status}, exposureSafe=${readiness.exposureSafe}`,\n });\n sink.write({\n level: 'info',\n message: `WhatsApp Client ready with state: ${client.getState()} (status=${readiness.status}, exposureSafe=${readiness.exposureSafe})`,\n });\n\n detachLaunchNarration();\n return { server, client, config, events: openwaClient.events, dispose };\n}\n\nexport async function main(argv: string[] = process.argv.slice(2)): Promise<CliRuntimeResult | void> {\n if (argv[0] === 'init') {\n const { initProject } = await import('./cli/init');\n await initProject(argv.slice(1));\n return;\n }\n const parsedArgs = parseCliArgs(argv);\n\n if (parsedArgs.pm2) {\n const { spawn } = require('child_process');\n const sink = getCliOutputSink();\n const pm2Command = getPm2Command();\n const pm2SpawnOptions = getPm2SpawnOptions();\n try {\n const pm2 = spawn(pm2Command, ['--version'], pm2SpawnOptions);\n\n await new Promise<void>((resolve, reject) => {\n pm2.on('error', reject);\n pm2.on('exit', (code: number | null) => {\n if (code === 0) {\n resolve();\n return;\n }\n\n reject(new Error(`pm2 probe exited with code ${code ?? 'unknown'}`));\n });\n pm2.stdout.on('data', () => resolve());\n });\n\n const pm2Flags = parsedArgs.forwardedArgs.filter((flag: string) => flag !== '--pm2');\n const cliPath = fileURLToPath(new URL('../dist/cli.cjs', import.meta.url));\n\n spawn(pm2Command, [\n 'start',\n cliPath,\n '--name', parsedArgs.procName,\n '--stop-exit-codes', '88',\n '--',\n ...pm2Flags,\n ], {\n ...pm2SpawnOptions,\n stdio: 'inherit',\n detached: true\n });\n return;\n } catch (error: unknown) {\n if (isCommandNotFoundError(error)) {\n sink.write({ level: 'error', message: 'pm2 not found. Please install with: npm install -g pm2' });\n return;\n }\n throw error;\n }\n }\n\n return await start(parsedArgs);\n}\n\nfunction getPm2Command(): string {\n return process.platform === 'win32' ? 'pm2.cmd' : 'pm2';\n}\n\nfunction getPm2SpawnOptions(): { shell: boolean } {\n return { shell: process.platform === 'win32' };\n}\n\nfunction isCommandNotFoundError(error: unknown): boolean {\n if (typeof error !== 'object' || error === null) {\n return false;\n }\n\n const systemError = error as { code?: unknown; errno?: unknown };\n return systemError.code === 'ENOENT' || systemError.errno === -2;\n}\n"],"mappings":"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"}
package/dist/cli.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const require_cli_runtime = require("./cli-runtime-BKwXzp9V.cjs");
3
+ const require_cli_runtime = require("./cli-runtime-BRj_LUIT.cjs");
4
4
  //#region src/cli.ts
5
5
  if (require.main === module) require_cli_runtime.main().catch((err) => {
6
6
  require_cli_runtime.getCliOutputSink().write({
package/dist/index.cjs CHANGED
@@ -1,15 +1,12 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_cli_runtime = require("./cli-runtime-BKwXzp9V.cjs");
2
+ const require_cli_runtime = require("./cli-runtime-BRj_LUIT.cjs");
3
3
  let _open_wa_api = require("@open-wa/api");
4
4
  let node_path = require("node:path");
5
5
  let _open_wa_logger = require("@open-wa/logger");
6
6
  let _open_wa_session_sync = require("@open-wa/session-sync");
7
7
  let _open_wa_core = require("@open-wa/core");
8
- let _open_wa_client = require("@open-wa/client");
9
- let _open_wa_driver_lightpanda = require("@open-wa/driver-lightpanda");
10
- let _open_wa_driver_puppeteer = require("@open-wa/driver-puppeteer");
11
8
  let _open_wa_config = require("@open-wa/config");
12
- let node_fs = require("node:fs");
9
+ let _open_wa_schema = require("@open-wa/schema");
13
10
  //#region src/server/lifecycle-manager.ts
14
11
  var APILifecycleManager = class {
15
12
  config;
@@ -146,223 +143,34 @@ var SessionArchiveManager = class {
146
143
  }
147
144
  };
148
145
  //#endregion
149
- //#region src/runtime-client.ts
150
- function readChromePathCache(cacheFilePath) {
151
- try {
152
- if (!(0, node_fs.existsSync)(cacheFilePath)) return;
153
- const raw = JSON.parse((0, node_fs.readFileSync)(cacheFilePath, "utf8"));
154
- if (!raw || typeof raw !== "object") return;
155
- return { executablePath: typeof raw.executablePath === "string" ? raw.executablePath : void 0 };
156
- } catch {
157
- return;
158
- }
159
- }
160
- function writeChromePathCache(executablePath, cacheFilePath) {
161
- (0, node_fs.mkdirSync)((0, node_path.dirname)(cacheFilePath), { recursive: true });
162
- (0, node_fs.writeFileSync)(cacheFilePath, JSON.stringify({
163
- executablePath,
164
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
165
- }, null, 2), "utf8");
166
- }
167
- function clearChromePathCache(cacheFilePath) {
168
- if ((0, node_fs.existsSync)(cacheFilePath)) (0, node_fs.rmSync)(cacheFilePath, { force: true });
169
- }
170
- function isUsableExecutablePath(executablePath) {
171
- return !!executablePath && (0, node_fs.existsSync)(executablePath);
172
- }
173
- function getExplicitUseChromePreference(rawConfigs) {
174
- const explicitConfigSources = [
175
- rawConfigs?.file,
176
- rawConfigs?.env,
177
- rawConfigs?.cli,
178
- rawConfigs?.programmatic
179
- ];
180
- for (let index = explicitConfigSources.length - 1; index >= 0; index -= 1) {
181
- const source = explicitConfigSources[index];
182
- if (source?.useChrome !== void 0) return source.useChrome;
183
- }
184
- }
185
- function shouldPreferLocalChrome(config, rawConfigs, defaultPreference = true) {
186
- if (config.useLightpanda) return false;
187
- if (config.executablePath) return false;
188
- const explicitUseChrome = getExplicitUseChromePreference(rawConfigs);
189
- if (explicitUseChrome !== void 0) return explicitUseChrome;
190
- return defaultPreference;
191
- }
192
- async function resolveExecutablePath(config, options) {
193
- if (config.executablePath) return {
194
- executablePath: config.executablePath,
195
- source: "config"
196
- };
197
- if (!(options.preferLocalChrome ?? config.useChrome)) return { source: "driver_default" };
198
- const cachedPath = readChromePathCache(options.cacheFilePath)?.executablePath;
199
- if (isUsableExecutablePath(cachedPath)) return {
200
- executablePath: cachedPath,
201
- source: "cache"
202
- };
203
- if (cachedPath) clearChromePathCache(options.cacheFilePath);
204
- const { Launcher } = await import("chrome-launcher");
205
- const detectedPath = Launcher.getInstallations().find((installationPath) => isUsableExecutablePath(installationPath));
206
- if (detectedPath) {
207
- writeChromePathCache(detectedPath, options.cacheFilePath);
208
- return {
209
- executablePath: detectedPath,
210
- source: "chrome_installation"
211
- };
212
- }
213
- clearChromePathCache(options.cacheFilePath);
214
- return {
215
- source: "driver_default",
216
- warning: "Chrome resolution warning: no valid local Chrome installation was found. Falling back to Puppeteer/default driver browser resolution."
217
- };
218
- }
219
- function resolveLightpandaExecutablePath(config) {
220
- const executablePath = config.lightpanda?.executablePath;
221
- if (executablePath) return {
222
- executablePath,
223
- source: "lightpanda_config"
224
- };
225
- return { source: "lightpanda_sdk_default" };
226
- }
227
- async function selectRuntimeDriver(config, options) {
228
- if (config.useLightpanda) return {
229
- driver: new _open_wa_driver_lightpanda.LightpandaDriver(),
230
- engineLabel: "Lightpanda",
231
- executableResolution: resolveLightpandaExecutablePath(config),
232
- preferLocalChrome: false
233
- };
234
- const preferLocalChrome = shouldPreferLocalChrome(config, options.rawConfigs, options.defaultPreferLocalChrome ?? true);
235
- const executableResolution = await resolveExecutablePath(config, {
236
- preferLocalChrome,
237
- cacheFilePath: options.cacheFilePath
238
- });
239
- return {
240
- driver: new _open_wa_driver_puppeteer.PuppeteerDriver(),
241
- engineLabel: "Puppeteer",
242
- executableResolution,
243
- preferLocalChrome
244
- };
245
- }
246
- function toCreateClientOptions(config, driverSelection, options = {}) {
247
- return {
248
- sessionId: config.sessionId,
249
- driver: driverSelection.driver,
250
- deleteSessionDataOnLogout: config.deleteSessionDataOnLogout,
251
- killClientOnLogout: config.killClientOnLogout,
252
- sessionDataPath: config.sessionDataPath,
253
- sessionData: config.sessionData,
254
- skipSessionSave: config.skipSessionSave,
255
- sessionDataBucketAuth: config.sessionDataBucketAuth,
256
- sessionDataEncryptionKey: config.sessionDataEncryptionKey,
257
- sessionDataEncryptionKeyFile: config.sessionDataEncryptionKeyFile,
258
- s3Sync: config.s3Sync,
259
- debug: options.debug ?? (config.logLevel === "debug" || config.logConsole),
260
- headless: config.headless,
261
- qrTimeoutMs: typeof config.qrTimeout === "number" ? config.qrTimeout * 1e3 : void 0,
262
- authTimeoutMs: typeof config.authTimeout === "number" ? config.authTimeout * 1e3 : void 0,
263
- executablePath: driverSelection.executableResolution.executablePath,
264
- browserArgs: config.chromiumArgs,
265
- browser: config.browser,
266
- allowDangerousBrowserArgs: config.allowDangerousBrowserArgs,
267
- userDataDir: config.userDataDir,
268
- ephemeral: config.ephemeral,
269
- linkCode: config.linkCode,
270
- qrMax: config.qrMax,
271
- oorTimeoutMs: config.oorTimeout * 1e3,
272
- logConsole: config.logConsole,
273
- logConsoleErrors: config.logConsoleErrors,
274
- blockCrashLogs: config.blockCrashLogs,
275
- blockAssets: config.blockAssets,
276
- safeMode: config.safeMode,
277
- lightpanda: config.useLightpanda ? config.lightpanda : void 0,
278
- licenseKey: config.licenseKey,
279
- patchConfig: {
280
- ghPatch: config.ghPatch,
281
- cachedPatch: config.cachedPatch
282
- }
283
- };
284
- }
285
- /** Start WhatsApp, display QR login when needed, and return a ready messaging client. */
286
- async function create(options = {}) {
287
- const { driver, sessionData, sessionDataBucketAuth, s3Sync, sessionDataEncryptionKey, sessionDataEncryptionKeyFile, ...configOverrides } = options;
288
- const { config, rawConfigs } = await (0, _open_wa_config.resolveConfig)({
289
- programmaticOverrides: {
290
- qrTimeout: 0,
291
- ...configOverrides
292
- },
293
- skipConfigFile: true,
294
- skipEnv: true,
295
- includeRawConfigs: true
296
- });
297
- const coreOptions = toCreateClientOptions(config, await selectRuntimeDriver(config, {
298
- rawConfigs,
299
- cacheFilePath: (0, node_path.resolve)(process.cwd(), ".open-wa", "chrome-executable-path.json"),
300
- defaultPreferLocalChrome: false
301
- }));
302
- if (driver) coreOptions.driver = driver;
303
- coreOptions.sessionData = sessionData;
304
- coreOptions.sessionDataBucketAuth = sessionDataBucketAuth;
305
- coreOptions.sessionDataEncryptionKey = sessionDataEncryptionKey;
306
- coreOptions.sessionDataEncryptionKeyFile = sessionDataEncryptionKeyFile;
307
- coreOptions.s3Sync = s3Sync;
308
- const core = await (0, _open_wa_core.createClient)(coreOptions);
309
- const sink = require_cli_runtime.getCliOutputSink();
310
- const onQr = (event) => {
311
- if (config.qrLogSkip || !event.details?.qr) return;
312
- sink.write({
313
- level: "info",
314
- message: "Open WhatsApp on your sending phone: Linked Devices → Link a Device, then scan this QR code."
315
- });
316
- sink.qr({
317
- qr: event.details.qr,
318
- sessionId: config.sessionId
319
- });
320
- };
321
- const onLinkCode = (event) => {
322
- if (event.details?.linkCode && !config.qrLogSkip) sink.write({
323
- level: "info",
324
- message: `Enter this link code on your sending phone: ${event.details.linkCode}`
325
- });
326
- };
327
- core.events.on("launch.auth.qr.generated", onQr);
328
- core.events.on("launch.auth.linkCode.generated", onLinkCode);
329
- let client;
330
- try {
331
- client = new _open_wa_client.Client({
332
- client: core,
333
- transport: core.getTransport()
334
- });
335
- await client.start();
336
- if (core.getState() !== "READY" || !core.getReadiness().exposureSafe) throw new Error("WhatsApp startup finished without a messaging-ready session.");
337
- return client;
338
- } catch (error) {
339
- try {
340
- if (client) await client.stop("startup-failure");
341
- else await core.stop("startup-failure");
342
- } catch {}
343
- throw error;
344
- } finally {
345
- core.events.off("launch.auth.qr.generated", onQr);
346
- core.events.off("launch.auth.linkCode.generated", onLinkCode);
347
- }
146
+ //#region src/index.ts
147
+ async function ensureBrowser(...args) {
148
+ const { ensureBrowser: provisionBrowser } = await import("@open-wa/driver-puppeteer");
149
+ return provisionBrowser(...args);
348
150
  }
349
151
  //#endregion
350
152
  exports.APILifecycleManager = APILifecycleManager;
351
- Object.defineProperty(exports, "Config", {
153
+ Object.defineProperty(exports, "ConfigSchema", {
352
154
  enumerable: true,
353
155
  get: function() {
354
- return _open_wa_config.Config;
156
+ return _open_wa_config.ConfigSchema;
355
157
  }
356
158
  });
357
- Object.defineProperty(exports, "ConfigSchema", {
159
+ Object.defineProperty(exports, "MessageAck", {
358
160
  enumerable: true,
359
161
  get: function() {
360
- return _open_wa_config.ConfigSchema;
162
+ return _open_wa_schema.MessageAck;
361
163
  }
362
164
  });
363
165
  exports.SessionArchiveManager = SessionArchiveManager;
166
+ Object.defineProperty(exports, "SimpleListener", {
167
+ enumerable: true,
168
+ get: function() {
169
+ return _open_wa_schema.SimpleListener;
170
+ }
171
+ });
364
172
  exports.WAServer = require_cli_runtime.WAServer;
365
- exports.create = create;
173
+ exports.create = require_cli_runtime.create;
366
174
  Object.defineProperty(exports, "createApiMiddleware", {
367
175
  enumerable: true,
368
176
  get: function() {
@@ -382,18 +190,26 @@ Object.defineProperty(exports, "createClient", {
382
190
  }
383
191
  });
384
192
  exports.createConsoleOutputSink = require_cli_runtime.createConsoleOutputSink;
385
- Object.defineProperty(exports, "ensureBrowser", {
193
+ exports.ensureBrowser = ensureBrowser;
194
+ Object.defineProperty(exports, "ev", {
386
195
  enumerable: true,
387
196
  get: function() {
388
- return _open_wa_driver_puppeteer.ensureBrowser;
197
+ return _open_wa_core.ev;
389
198
  }
390
199
  });
391
200
  exports.getCliOutputSink = require_cli_runtime.getCliOutputSink;
201
+ Object.defineProperty(exports, "onGlobalEvent", {
202
+ enumerable: true,
203
+ get: function() {
204
+ return _open_wa_core.onGlobalEvent;
205
+ }
206
+ });
392
207
  exports.parseCliArgs = require_cli_runtime.parseCliArgs;
393
208
  exports.resetCliOutputSink = require_cli_runtime.resetCliOutputSink;
394
209
  exports.runCli = require_cli_runtime.main;
395
210
  exports.setCliOutputSink = require_cli_runtime.setCliOutputSink;
396
211
  exports.startCli = require_cli_runtime.start;
212
+ var _open_wa_client = require("@open-wa/client");
397
213
  Object.keys(_open_wa_client).forEach(function(k) {
398
214
  if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
399
215
  enumerable: true,
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["getCliOutputSink","WAServer","createLogger","LocalSessionCompression","S3SyncManager","join","dirname","existsSync","readFileSync","dirname","LightpandaDriver","PuppeteerDriver","resolveConfig","resolve","createCoreClient","getCliOutputSink","Client"],"sources":["../src/server/lifecycle-manager.ts","../src/session/SessionArchiveManager.ts","../src/runtime-client.ts"],"sourcesContent":["import { WAServer } from './hono-server';\nimport type { Config } from '@open-wa/config';\nimport { getCliOutputSink } from '../cli/output-sink';\n\nexport class APILifecycleManager {\n private config: Config;\n private server?: WAServer;\n // @ts-ignore\n private _sessionConnected: boolean = false;\n\n constructor(config: Config) {\n this.config = config;\n }\n\n public async initialize(): Promise<void> {\n const sink = getCliOutputSink();\n switch (this.config.apiLifecycle) {\n case 'immediate':\n sink.status({ phase: 'server.starting', sessionId: this.config.sessionId, detail: 'Starting full API immediately' });\n await this.startFullAPI();\n break;\n case 'post-connection':\n this.waitForConnection();\n break;\n case 'hybrid':\n sink.status({ phase: 'server.starting', sessionId: this.config.sessionId, detail: 'Starting minimal API (QR only)' });\n await this.startMinimalAPI();\n break;\n }\n }\n\n private async waitForConnection(): Promise<void> {\n getCliOutputSink().write({ level: 'info', message: 'Waiting for session connection before starting API...' });\n // This will be called by the orchestrator or main entry point when session connects\n }\n\n private async startFullAPI(): Promise<void> {\n getCliOutputSink().write({ level: 'info', message: 'Starting full API immediately...' });\n this.server = new WAServer(this.config);\n await this.server.start();\n }\n\n private async startMinimalAPI(): Promise<void> {\n getCliOutputSink().write({ level: 'info', message: 'Starting minimal API (QR only)...' });\n \n // Create server with full config but we might restrict routes in the future\n // For now, hybrid mode just starts the server, but logic inside routes (like sendText)\n // should check if session is connected before execution.\n // In a more advanced implementation, we would only register public routes here.\n \n this.server = new WAServer(this.config);\n await this.server.start();\n }\n \n public async stop(): Promise<void> {\n if (this.server) {\n await this.server.stop();\n }\n }\n}\n","import { dirname, join } from 'node:path';\nimport { createLogger } from '@open-wa/logger';\nimport { LocalSessionCompression, S3SyncManager, type S3Config } from '@open-wa/session-sync';\n\nexport interface SessionArchiveManagerConfig {\n sessionId: string;\n dataDir: string;\n s3Config: S3Config;\n syncInterval?: number;\n watchLocalChanges?: boolean;\n}\n\nexport class SessionArchiveManager {\n private readonly logger = createLogger({ component: 'SessionArchiveManager' });\n private localCompression?: LocalSessionCompression;\n private s3Sync?: S3SyncManager;\n private syncTimer?: NodeJS.Timeout;\n private started = false;\n\n constructor(private readonly config: SessionArchiveManagerConfig) {\n this.logger.info('session_archive_manager_initialized', { sessionId: config.sessionId });\n }\n\n async start(): Promise<void> {\n if (this.started) return;\n this.started = true;\n\n this.localCompression = new LocalSessionCompression({\n sessionPath: this.config.dataDir,\n sessionId: this.config.sessionId,\n outputPath: this.archivePath,\n intervalMs: this.config.syncInterval,\n });\n if (this.config.watchLocalChanges !== false) {\n this.localCompression.start();\n this.logger.info('local_session_compression_started');\n }\n\n this.s3Sync = new S3SyncManager(this.config.s3Config);\n this.startPeriodicSync();\n this.logger.info('s3_session_sync_started');\n }\n\n async stop(): Promise<void> {\n if (this.syncTimer) {\n clearInterval(this.syncTimer);\n this.syncTimer = undefined;\n }\n\n this.localCompression?.stop();\n this.localCompression = undefined;\n this.s3Sync = undefined;\n this.started = false;\n this.logger.info('session_archive_manager_stopped');\n }\n\n async backupSession(): Promise<string | null> {\n if (!this.s3Sync || !this.localCompression) {\n this.logger.warn('session_archive_manager_not_started');\n return null;\n }\n\n try {\n await this.localCompression.compress();\n const filename = await this.s3Sync.backupSession(this.archivePath);\n this.logger.info('session_backed_up', { filename });\n return filename;\n } catch (error) {\n this.logger.error('session_backup_failed', { error });\n throw error;\n }\n }\n\n async restoreSession(filename: string): Promise<void> {\n if (!this.s3Sync) {\n throw new Error('Session archive manager is not started');\n }\n\n const restored = await this.s3Sync.restoreSession(filename, this.config.dataDir);\n if (!restored) {\n throw new Error(`Failed to restore session backup: ${filename}`);\n }\n this.logger.info('session_restored', { filename });\n }\n\n async getSessionBackupUrl(filename: string, expiresIn = 3600): Promise<string | null> {\n if (!this.s3Sync) {\n return null;\n }\n\n return this.s3Sync.getDownloadUrl(filename, expiresIn);\n }\n\n private get archivePath(): string {\n return join(dirname(this.config.dataDir), `${this.config.sessionId}.data.zst`);\n }\n\n private startPeriodicSync(): void {\n if (!this.s3Sync || this.syncTimer) return;\n\n this.syncTimer = setInterval(() => {\n void this.backupSession().catch((error) => {\n this.logger.error('periodic_session_sync_failed', { error });\n });\n }, this.config.syncInterval ?? 600_000);\n this.syncTimer.unref();\n }\n}\n","import { createClient as createCoreClient, type CreateClientOptions, type OpenWAEventMap } from '@open-wa/core';\nimport { Client } from '@open-wa/client';\nimport { resolveConfig, type PartialConfig, type Config, type TrackedConfig } from '@open-wa/config';\nimport { LightpandaDriver } from '@open-wa/driver-lightpanda';\nimport { PuppeteerDriver } from '@open-wa/driver-puppeteer';\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { getCliOutputSink } from './cli/output-sink';\n\nexport interface ExecutablePathResolution {\n executablePath?: string;\n source:\n | 'config'\n | 'cache'\n | 'chrome_installation'\n | 'driver_default'\n | 'lightpanda_config'\n | 'lightpanda_sdk_default';\n warning?: string;\n}\n\nexport interface DriverSelection {\n driver: PuppeteerDriver | LightpandaDriver;\n engineLabel: 'Puppeteer' | 'Lightpanda';\n executableResolution: ExecutablePathResolution;\n preferLocalChrome: boolean;\n}\n\nfunction readChromePathCache(cacheFilePath: string): { executablePath?: string } | undefined {\n try {\n if (!existsSync(cacheFilePath)) {\n return undefined;\n }\n\n const raw = JSON.parse(readFileSync(cacheFilePath, 'utf8')) as { executablePath?: string };\n if (!raw || typeof raw !== 'object') {\n return undefined;\n }\n\n return {\n executablePath: typeof raw.executablePath === 'string' ? raw.executablePath : undefined,\n };\n } catch {\n return undefined;\n }\n}\n\nfunction writeChromePathCache(executablePath: string, cacheFilePath: string): void {\n mkdirSync(dirname(cacheFilePath), { recursive: true });\n writeFileSync(cacheFilePath, JSON.stringify({ executablePath, updatedAt: new Date().toISOString() }, null, 2), 'utf8');\n}\n\nfunction clearChromePathCache(cacheFilePath: string): void {\n if (existsSync(cacheFilePath)) {\n rmSync(cacheFilePath, { force: true });\n }\n}\n\nfunction isUsableExecutablePath(executablePath?: string): executablePath is string {\n return !!executablePath && existsSync(executablePath);\n}\n\nfunction getExplicitUseChromePreference(rawConfigs?: TrackedConfig['rawConfigs']): boolean | undefined {\n const explicitConfigSources = [\n rawConfigs?.file,\n rawConfigs?.env,\n rawConfigs?.cli,\n rawConfigs?.programmatic,\n ];\n\n for (let index = explicitConfigSources.length - 1; index >= 0; index -= 1) {\n const source = explicitConfigSources[index];\n if (source?.useChrome !== undefined) {\n return source.useChrome;\n }\n }\n\n return undefined;\n}\n\nexport function shouldPreferLocalChrome(\n config: Config,\n rawConfigs?: TrackedConfig['rawConfigs'],\n defaultPreference = true,\n): boolean {\n if (config.useLightpanda) {\n return false;\n }\n\n if (config.executablePath) {\n return false;\n }\n\n const explicitUseChrome = getExplicitUseChromePreference(rawConfigs);\n if (explicitUseChrome !== undefined) {\n return explicitUseChrome;\n }\n\n return defaultPreference;\n}\n\nexport async function resolveExecutablePath(\n config: Config,\n options: {\n preferLocalChrome?: boolean;\n cacheFilePath: string;\n }\n): Promise<ExecutablePathResolution> {\n if (config.executablePath) {\n return {\n executablePath: config.executablePath,\n source: 'config',\n };\n }\n\n const preferLocalChrome = options.preferLocalChrome ?? config.useChrome;\n if (!preferLocalChrome) {\n return {\n source: 'driver_default',\n };\n }\n\n const cachedPath = readChromePathCache(options.cacheFilePath)?.executablePath;\n if (isUsableExecutablePath(cachedPath)) {\n return {\n executablePath: cachedPath,\n source: 'cache',\n };\n }\n\n if (cachedPath) {\n clearChromePathCache(options.cacheFilePath);\n }\n\n const { Launcher } = await import('chrome-launcher');\n const detectedPath = Launcher.getInstallations().find((installationPath) => isUsableExecutablePath(installationPath));\n\n if (detectedPath) {\n writeChromePathCache(detectedPath, options.cacheFilePath);\n return {\n executablePath: detectedPath,\n source: 'chrome_installation',\n };\n }\n\n clearChromePathCache(options.cacheFilePath);\n\n return {\n source: 'driver_default',\n warning: 'Chrome resolution warning: no valid local Chrome installation was found. Falling back to Puppeteer/default driver browser resolution.',\n };\n}\n\nexport function resolveLightpandaExecutablePath(config: Config): ExecutablePathResolution {\n const executablePath = config.lightpanda?.executablePath;\n if (executablePath) {\n return {\n executablePath,\n source: 'lightpanda_config',\n };\n }\n\n return {\n source: 'lightpanda_sdk_default',\n };\n}\n\nexport async function selectRuntimeDriver(\n config: Config,\n options: {\n rawConfigs?: TrackedConfig['rawConfigs'];\n cacheFilePath: string;\n defaultPreferLocalChrome?: boolean;\n }\n): Promise<DriverSelection> {\n if (config.useLightpanda) {\n return {\n driver: new LightpandaDriver(),\n engineLabel: 'Lightpanda',\n executableResolution: resolveLightpandaExecutablePath(config),\n preferLocalChrome: false,\n };\n }\n\n const preferLocalChrome = shouldPreferLocalChrome(config, options.rawConfigs, options.defaultPreferLocalChrome ?? true);\n const executableResolution = await resolveExecutablePath(config, {\n preferLocalChrome,\n cacheFilePath: options.cacheFilePath,\n });\n\n return {\n driver: new PuppeteerDriver(),\n engineLabel: 'Puppeteer',\n executableResolution,\n preferLocalChrome,\n };\n}\n\nexport function toCreateClientOptions(\n config: Config,\n driverSelection: DriverSelection,\n options: {\n debug?: boolean;\n } = {},\n): CreateClientOptions {\n return {\n sessionId: config.sessionId,\n driver: driverSelection.driver,\n deleteSessionDataOnLogout: config.deleteSessionDataOnLogout,\n killClientOnLogout: config.killClientOnLogout,\n sessionDataPath: config.sessionDataPath,\n sessionData: config.sessionData,\n skipSessionSave: config.skipSessionSave,\n sessionDataBucketAuth: config.sessionDataBucketAuth,\n sessionDataEncryptionKey: config.sessionDataEncryptionKey,\n sessionDataEncryptionKeyFile: config.sessionDataEncryptionKeyFile,\n s3Sync: config.s3Sync,\n debug: options.debug ?? (config.logLevel === 'debug' || config.logConsole),\n headless: config.headless,\n qrTimeoutMs: typeof config.qrTimeout === 'number' ? config.qrTimeout * 1000 : undefined,\n authTimeoutMs: typeof config.authTimeout === 'number' ? config.authTimeout * 1000 : undefined,\n executablePath: driverSelection.executableResolution.executablePath,\n browserArgs: config.chromiumArgs,\n browser: config.browser,\n allowDangerousBrowserArgs: config.allowDangerousBrowserArgs,\n userDataDir: config.userDataDir,\n ephemeral: config.ephemeral,\n linkCode: config.linkCode,\n qrMax: config.qrMax,\n oorTimeoutMs: config.oorTimeout * 1000,\n logConsole: config.logConsole,\n logConsoleErrors: config.logConsoleErrors,\n blockCrashLogs: config.blockCrashLogs,\n blockAssets: config.blockAssets,\n safeMode: config.safeMode,\n lightpanda: config.useLightpanda ? config.lightpanda : undefined,\n licenseKey: config.licenseKey as any,\n patchConfig: { ghPatch: config.ghPatch, cachedPatch: config.cachedPatch },\n };\n}\n\n/** Options for the ready-to-use messaging client. */\nexport type CreateOptions = Omit<PartialConfig, 's3Sync'> & {\n s3Sync?: Omit<NonNullable<PartialConfig['s3Sync']>, 'region' | 'syncInterval'> & {\n region?: string;\n syncInterval?: number;\n };\n /** Override the default Puppeteer driver. */\n driver?: CreateClientOptions['driver'];\n};\n\n/** Start WhatsApp, display QR login when needed, and return a ready messaging client. */\nexport async function create(options: CreateOptions = {}): Promise<Client> {\n const { driver, sessionData, sessionDataBucketAuth, s3Sync,\n sessionDataEncryptionKey, sessionDataEncryptionKeyFile, ...configOverrides } = options;\n const { config, rawConfigs } = await resolveConfig({\n programmaticOverrides: {\n qrTimeout: 0, ...configOverrides,\n // Session seeds, encryption keys and bucket credentials bypass tracked/debug config.\n },\n skipConfigFile: true,\n skipEnv: true,\n includeRawConfigs: true,\n });\n\n const driverSelection = await selectRuntimeDriver(config, {\n rawConfigs,\n cacheFilePath: resolve(process.cwd(), '.open-wa', 'chrome-executable-path.json'),\n defaultPreferLocalChrome: false,\n });\n\n const coreOptions = toCreateClientOptions(config, driverSelection);\n if (driver) coreOptions.driver = driver;\n coreOptions.sessionData = sessionData;\n coreOptions.sessionDataBucketAuth = sessionDataBucketAuth;\n coreOptions.sessionDataEncryptionKey = sessionDataEncryptionKey;\n coreOptions.sessionDataEncryptionKeyFile = sessionDataEncryptionKeyFile;\n coreOptions.s3Sync = s3Sync;\n\n const core = await createCoreClient(coreOptions);\n const sink = getCliOutputSink();\n const onQr = (event: OpenWAEventMap['launch.auth.qr.generated']) => {\n if (config.qrLogSkip || !event.details?.qr) return;\n sink.write({ level: 'info', message: 'Open WhatsApp on your sending phone: Linked Devices → Link a Device, then scan this QR code.' });\n sink.qr({ qr: event.details.qr, sessionId: config.sessionId });\n };\n const onLinkCode = (event: OpenWAEventMap['launch.auth.linkCode.generated']) => {\n if (event.details?.linkCode && !config.qrLogSkip) {\n sink.write({ level: 'info', message: `Enter this link code on your sending phone: ${event.details.linkCode}` });\n }\n };\n core.events.on('launch.auth.qr.generated', onQr);\n core.events.on('launch.auth.linkCode.generated', onLinkCode);\n let client: Client | undefined;\n try {\n client = new Client({ client: core, transport: core.getTransport() });\n await client.start();\n if (core.getState() !== 'READY' || !core.getReadiness().exposureSafe) {\n throw new Error('WhatsApp startup finished without a messaging-ready session.');\n }\n return client;\n } catch (error) {\n try {\n if (client) await client.stop('startup-failure');\n else await core.stop('startup-failure');\n } catch {\n // Keep the startup failure as the actionable error.\n }\n throw error;\n } finally {\n core.events.off('launch.auth.qr.generated', onQr);\n core.events.off('launch.auth.linkCode.generated', onLinkCode);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["getCliOutputSink","WAServer","createLogger","LocalSessionCompression","S3SyncManager","join","dirname"],"sources":["../src/server/lifecycle-manager.ts","../src/session/SessionArchiveManager.ts","../src/index.ts"],"sourcesContent":["import { WAServer } from './hono-server';\nimport type { Config } from '@open-wa/config';\nimport { getCliOutputSink } from '../cli/output-sink';\n\nexport class APILifecycleManager {\n private config: Config;\n private server?: WAServer;\n // @ts-ignore\n private _sessionConnected: boolean = false;\n\n constructor(config: Config) {\n this.config = config;\n }\n\n public async initialize(): Promise<void> {\n const sink = getCliOutputSink();\n switch (this.config.apiLifecycle) {\n case 'immediate':\n sink.status({ phase: 'server.starting', sessionId: this.config.sessionId, detail: 'Starting full API immediately' });\n await this.startFullAPI();\n break;\n case 'post-connection':\n this.waitForConnection();\n break;\n case 'hybrid':\n sink.status({ phase: 'server.starting', sessionId: this.config.sessionId, detail: 'Starting minimal API (QR only)' });\n await this.startMinimalAPI();\n break;\n }\n }\n\n private async waitForConnection(): Promise<void> {\n getCliOutputSink().write({ level: 'info', message: 'Waiting for session connection before starting API...' });\n // This will be called by the orchestrator or main entry point when session connects\n }\n\n private async startFullAPI(): Promise<void> {\n getCliOutputSink().write({ level: 'info', message: 'Starting full API immediately...' });\n this.server = new WAServer(this.config);\n await this.server.start();\n }\n\n private async startMinimalAPI(): Promise<void> {\n getCliOutputSink().write({ level: 'info', message: 'Starting minimal API (QR only)...' });\n \n // Create server with full config but we might restrict routes in the future\n // For now, hybrid mode just starts the server, but logic inside routes (like sendText)\n // should check if session is connected before execution.\n // In a more advanced implementation, we would only register public routes here.\n \n this.server = new WAServer(this.config);\n await this.server.start();\n }\n \n public async stop(): Promise<void> {\n if (this.server) {\n await this.server.stop();\n }\n }\n}\n","import { dirname, join } from 'node:path';\nimport { createLogger } from '@open-wa/logger';\nimport { LocalSessionCompression, S3SyncManager, type S3Config } from '@open-wa/session-sync';\n\nexport interface SessionArchiveManagerConfig {\n sessionId: string;\n dataDir: string;\n s3Config: S3Config;\n syncInterval?: number;\n watchLocalChanges?: boolean;\n}\n\nexport class SessionArchiveManager {\n private readonly logger = createLogger({ component: 'SessionArchiveManager' });\n private localCompression?: LocalSessionCompression;\n private s3Sync?: S3SyncManager;\n private syncTimer?: NodeJS.Timeout;\n private started = false;\n\n constructor(private readonly config: SessionArchiveManagerConfig) {\n this.logger.info('session_archive_manager_initialized', { sessionId: config.sessionId });\n }\n\n async start(): Promise<void> {\n if (this.started) return;\n this.started = true;\n\n this.localCompression = new LocalSessionCompression({\n sessionPath: this.config.dataDir,\n sessionId: this.config.sessionId,\n outputPath: this.archivePath,\n intervalMs: this.config.syncInterval,\n });\n if (this.config.watchLocalChanges !== false) {\n this.localCompression.start();\n this.logger.info('local_session_compression_started');\n }\n\n this.s3Sync = new S3SyncManager(this.config.s3Config);\n this.startPeriodicSync();\n this.logger.info('s3_session_sync_started');\n }\n\n async stop(): Promise<void> {\n if (this.syncTimer) {\n clearInterval(this.syncTimer);\n this.syncTimer = undefined;\n }\n\n this.localCompression?.stop();\n this.localCompression = undefined;\n this.s3Sync = undefined;\n this.started = false;\n this.logger.info('session_archive_manager_stopped');\n }\n\n async backupSession(): Promise<string | null> {\n if (!this.s3Sync || !this.localCompression) {\n this.logger.warn('session_archive_manager_not_started');\n return null;\n }\n\n try {\n await this.localCompression.compress();\n const filename = await this.s3Sync.backupSession(this.archivePath);\n this.logger.info('session_backed_up', { filename });\n return filename;\n } catch (error) {\n this.logger.error('session_backup_failed', { error });\n throw error;\n }\n }\n\n async restoreSession(filename: string): Promise<void> {\n if (!this.s3Sync) {\n throw new Error('Session archive manager is not started');\n }\n\n const restored = await this.s3Sync.restoreSession(filename, this.config.dataDir);\n if (!restored) {\n throw new Error(`Failed to restore session backup: ${filename}`);\n }\n this.logger.info('session_restored', { filename });\n }\n\n async getSessionBackupUrl(filename: string, expiresIn = 3600): Promise<string | null> {\n if (!this.s3Sync) {\n return null;\n }\n\n return this.s3Sync.getDownloadUrl(filename, expiresIn);\n }\n\n private get archivePath(): string {\n return join(dirname(this.config.dataDir), `${this.config.sessionId}.data.zst`);\n }\n\n private startPeriodicSync(): void {\n if (!this.s3Sync || this.syncTimer) return;\n\n this.syncTimer = setInterval(() => {\n void this.backupSession().catch((error) => {\n this.logger.error('periodic_session_sync_failed', { error });\n });\n }, this.config.syncInterval ?? 600_000);\n this.syncTimer.unref();\n }\n}\n","export { WAServer } from './server/hono-server';\nexport { APILifecycleManager } from './server/lifecycle-manager';\nexport { SessionArchiveManager } from './session/SessionArchiveManager';\nexport { main as runCli, start as startCli, parseCliArgs } from './cli-runtime';\nexport type { CliRuntimeResult } from './cli-runtime';\nexport { createConsoleOutputSink, getCliOutputSink, resetCliOutputSink, setCliOutputSink } from './cli/output-sink';\nexport type { CliOutputEntry, CliOutputLevel, CliOutputSink, CliQrPayload, CliStatusUpdate } from './cli/output-sink';\nexport { ConfigSchema } from '@open-wa/config';\nexport type { Config } from '@open-wa/config';\nexport { SimpleListener, MessageAck } from '@open-wa/schema';\nexport { createApiServer, createApiMiddleware } from '@open-wa/api';\nexport * from '@open-wa/client';\nexport { createClient } from '@open-wa/core';\nexport { ev, onGlobalEvent } from '@open-wa/core';\nexport type { CreateClientOptions, OpenWAClient, PortableSessionStatus } from '@open-wa/core';\nexport { create } from './runtime-client';\nexport type { CreateOptions } from './runtime-client';\nexport async function ensureBrowser(...args: Parameters<typeof import('@open-wa/driver-puppeteer').ensureBrowser>): Promise<string> {\n const { ensureBrowser: provisionBrowser } = await import('@open-wa/driver-puppeteer');\n return provisionBrowser(...args);\n}\n"],"mappings":"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"}