@mindstudio-ai/local-model-tunnel 0.5.21 → 0.5.22

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.
@@ -217,7 +217,7 @@ async function handleScreenshot(state, emit2) {
217
217
  }
218
218
  try {
219
219
  const startTime = Date.now();
220
- const result = await state.proxy.dispatchBrowserCommand([{ command: "screenshot" }]);
220
+ const result = await state.proxy.dispatchBrowserCommand([{ command: "screenshot" }], 12e4);
221
221
  const stepResult = result.steps?.[0]?.result;
222
222
  if (!stepResult?.image) {
223
223
  fail("Screenshot capture returned no image data");
@@ -535,4 +535,4 @@ async function startHeadless(opts = {}) {
535
535
  export {
536
536
  startHeadless
537
537
  };
538
- //# sourceMappingURL=chunk-YTHFWJU6.js.map
538
+ //# sourceMappingURL=chunk-ENSNEBJJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/dev/session-events.ts","../src/dev/stdin-commands/run-scenario.ts","../src/dev/stdin-commands/run-method.ts","../src/dev/stdin-commands/impersonate.ts","../src/dev/stdin-commands/browser.ts","../src/dev/stdin-commands/screenshot.ts","../src/dev/stdin-commands/dev-server-restarting.ts","../src/dev/stdin-commands/browser-status.ts","../src/dev/stdin-commands/reset-browser.ts","../src/dev/stdin-commands/index.ts","../src/headless.ts"],"sourcesContent":["/**\n * Subscribe to DevRunner events and relay them as JSON to stdout.\n * Returns an array of unsubscribe functions for cleanup on teardown.\n */\n\nimport { devRequestEvents } from './events';\n\ntype EmitFn = (event: string, data?: Record<string, unknown>) => void;\n\nexport function subscribeDevEvents(\n emit: EmitFn,\n shutdown: () => Promise<void>,\n): Array<() => void> {\n const unsubs: Array<() => void> = [];\n\n unsubs.push(\n devRequestEvents.onStart((event) => {\n emit('method-started', { id: event.id, method: event.method });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onComplete((event) => {\n emit('method-completed', {\n id: event.id,\n success: event.success,\n duration: event.duration,\n ...(event.error ? { error: event.error } : {}),\n });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onConnectionWarning((message) => {\n emit('connection-lost', { message });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onConnectionRestored(() => {\n emit('connection-restored');\n }),\n );\n\n unsubs.push(\n devRequestEvents.onSessionExpired(() => {\n emit('session-expired');\n shutdown().then(() => process.exit(1));\n }),\n );\n\n unsubs.push(\n devRequestEvents.onAuthRefreshStart((url) => {\n emit('auth-refresh-start', { url });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onAuthRefreshSuccess(() => {\n emit('auth-refresh-success');\n }),\n );\n\n unsubs.push(\n devRequestEvents.onAuthRefreshFailed(() => {\n emit('auth-refresh-failed');\n }),\n );\n\n unsubs.push(\n devRequestEvents.onImpersonate((event) => {\n emit('impersonation-changed', { roles: event.roles });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onScenarioStart((event) => {\n emit('scenario-started', { id: event.id, name: event.name });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onScenarioComplete((event) => {\n emit('scenario-completed', {\n id: event.id,\n success: event.success,\n duration: event.duration,\n roles: event.roles,\n ...(event.error ? { error: event.error } : {}),\n });\n }),\n );\n\n return unsubs;\n}\n","import { detectAppConfig } from '../app-config';\nimport type { SessionState, EmitFn } from './types';\n\nexport async function handleRunScenario(\n state: SessionState,\n cwd: string,\n cmd: Record<string, unknown>,\n emit: EmitFn,\n): Promise<void> {\n if (!state.runner) {\n emit('command-error', { message: 'No active session' });\n return;\n }\n const freshConfig = detectAppConfig(cwd) ?? state.appConfig;\n const scenario = freshConfig?.scenarios.find((s) => s.id === cmd.scenarioId);\n if (!scenario) {\n emit('command-error', { message: `Unknown scenario: ${cmd.scenarioId}` });\n return;\n }\n await state.runner.runScenario(scenario);\n}\n","import { detectAppConfig } from '../app-config';\nimport type { SessionState, EmitFn } from './types';\n\nexport async function handleRunMethod(\n state: SessionState,\n cwd: string,\n cmd: Record<string, unknown>,\n emit: EmitFn,\n): Promise<void> {\n if (!state.runner) {\n emit('command-error', { message: 'No active session' });\n return;\n }\n const methodName = cmd.method as string;\n if (!methodName) {\n emit('command-error', { message: 'run-method requires \"method\" (export name or ID)' });\n return;\n }\n const freshConfig = detectAppConfig(cwd) ?? state.appConfig;\n const method =\n freshConfig?.methods.find((m) => m.export === methodName) ??\n freshConfig?.methods.find((m) => m.id === methodName);\n if (!method) {\n emit('command-error', { message: `Unknown method: ${methodName}` });\n return;\n }\n emit('method-run-started', { method: method.export });\n const result = await state.runner.runMethod({\n methodExport: method.export,\n methodPath: method.path,\n input: cmd.input ?? {},\n });\n emit('method-run-completed', {\n method: method.export,\n success: result.success,\n output: result.output ?? null,\n error: result.error ?? null,\n stdout: result.stdout ?? [],\n duration: result.duration,\n });\n}\n","import type { SessionState, EmitFn } from './types';\n\nexport async function handleImpersonate(\n state: SessionState,\n cmd: Record<string, unknown>,\n emit: EmitFn,\n): Promise<void> {\n if (!state.runner) {\n emit('command-error', { message: 'No active session' });\n return;\n }\n const roles = cmd.roles as string[];\n if (!Array.isArray(roles)) {\n emit('command-error', { message: 'impersonate requires roles array' });\n return;\n }\n await state.runner.setImpersonation(roles);\n}\n\nexport async function handleClearImpersonation(\n state: SessionState,\n emit: EmitFn,\n): Promise<void> {\n if (!state.runner) {\n emit('command-error', { message: 'No active session' });\n return;\n }\n await state.runner.clearImpersonation();\n}\n","import type { SessionState, EmitFn } from './types';\n\nexport async function handleBrowser(\n state: SessionState,\n cmd: Record<string, unknown>,\n emit: EmitFn,\n): Promise<void> {\n if (!state.proxy) {\n emit('command-error', { message: 'No active proxy — browser commands require a web interface' });\n return;\n }\n const steps = cmd.steps as Array<Record<string, unknown>>;\n if (!Array.isArray(steps) || steps.length === 0) {\n emit('command-error', { message: 'browser action requires a non-empty \"steps\" array' });\n return;\n }\n try {\n const result = await state.proxy.dispatchBrowserCommand(steps);\n emit('browser-completed', {\n steps: result.steps,\n snapshot: result.snapshot,\n logs: result.logs,\n duration: result.duration,\n });\n } catch (err) {\n emit('command-error', {\n message: err instanceof Error ? err.message : 'Browser command failed',\n });\n }\n}\n","import { getUploadUrl } from '../api';\nimport type { SessionState, EmitFn } from './types';\n\nexport async function handleScreenshot(\n state: SessionState,\n emit: EmitFn,\n): Promise<void> {\n const fail = (message: string) => {\n emit('screenshot-completed', {\n url: '',\n width: 0,\n height: 0,\n duration: 0,\n error: message,\n });\n };\n\n if (!state.proxy) {\n fail('No active proxy');\n return;\n }\n if (!state.proxy.isBrowserConnected()) {\n fail('No browser connected, please refresh the MindStudio preview');\n return;\n }\n if (!state.runner?.getSession() || !state.appConfig?.appId) {\n fail('No active session');\n return;\n }\n\n try {\n const startTime = Date.now();\n\n // 1. Dispatch screenshot command to browser\n // Full-page screenshots scroll through the page and capture chunks — can take minutes\n const result = await state.proxy.dispatchBrowserCommand([{ command: 'screenshot' }], 120_000);\n const stepResult = (result.steps as Array<Record<string, unknown>>)?.[0]\n ?.result as { image: string; width: number; height: number };\n\n if (!stepResult?.image) {\n fail('Screenshot capture returned no image data');\n return;\n }\n\n // 2. Get presigned upload URL\n const session = state.runner.getSession()!;\n const { uploadUrl, uploadFields, publicUrl } = await getUploadUrl(\n state.appConfig.appId,\n session.sessionId,\n 'jpg',\n 'image/jpeg',\n );\n\n // 3. Upload to S3\n const imageBuffer = Buffer.from(stepResult.image, 'base64');\n const form = new FormData();\n for (const [key, value] of Object.entries(uploadFields)) {\n form.append(key, value);\n }\n form.append('file', new Blob([imageBuffer], { type: 'image/jpeg' }), 'screenshot.jpg');\n const uploadResult = await fetch(uploadUrl, { method: 'POST', body: form });\n\n if (!uploadResult.ok) {\n fail(`S3 upload failed: ${uploadResult.status}`);\n return;\n }\n\n // 4. Emit result\n emit('screenshot-completed', {\n url: publicUrl,\n width: stepResult.width,\n height: stepResult.height,\n duration: Date.now() - startTime,\n });\n } catch (err) {\n fail(err instanceof Error ? err.message : 'Screenshot failed');\n }\n}\n","import type { SessionState, EmitFn } from './types';\n\n/**\n * Handle explicit signal that the upstream dev server is restarting.\n * Marks the upstream as down so the proxy's health check will detect\n * when it's back and auto-reload the browser.\n */\nexport async function handleDevServerRestarting(\n state: SessionState,\n emit: EmitFn,\n): Promise<void> {\n if (!state.proxy) {\n emit('command-error', { message: 'No active proxy' });\n return;\n }\n state.proxy.markUpstreamDown();\n emit('dev-server-restarting-ack', {});\n}\n","import type { SessionState, EmitFn } from './types';\n\nexport function handleBrowserStatus(\n state: SessionState,\n emit: EmitFn,\n): void {\n emit('browser-status', {\n connected: state.proxy?.isBrowserConnected() ?? false,\n });\n}\n","import type { SessionState, EmitFn } from './types';\n\n/**\n * Reset the browser to a clean state by reloading the page.\n * The agent sends this explicitly when done testing.\n * Fire-and-forget — the reload kills the page so no result comes back.\n */\nexport function handleResetBrowser(\n state: SessionState,\n emit: EmitFn,\n): void {\n if (!state.proxy) {\n emit('command-error', { message: 'No active proxy' });\n return;\n }\n if (!state.proxy.isBrowserConnected()) {\n emit('command-error', { message: 'No browser connected' });\n return;\n }\n state.proxy.dispatchBrowserCommand([{ command: 'reload' }]).catch(() => {});\n emit('reset-browser-completed', {});\n}\n","/**\n * Stdin command router for headless mode.\n *\n * Reads NDJSON commands from stdin and dispatches to individual handlers.\n * Each command lives in its own file for isolation and testability.\n */\n\nimport { handleRunScenario } from './run-scenario';\nimport { handleRunMethod } from './run-method';\nimport { handleImpersonate, handleClearImpersonation } from './impersonate';\nimport { handleBrowser } from './browser';\nimport { handleScreenshot } from './screenshot';\nimport { handleDevServerRestarting } from './dev-server-restarting';\nimport { handleBrowserStatus } from './browser-status';\nimport { handleResetBrowser } from './reset-browser';\nimport type { SessionState, EmitFn } from './types';\n\nexport type { SessionState, EmitFn } from './types';\n\nexport function setupStdinCommands(\n state: SessionState,\n cwd: string,\n emit: EmitFn,\n): void {\n if (!process.stdin.readable) return;\n\n let buffer = '';\n process.stdin.setEncoding('utf-8');\n process.stdin.on('data', (chunk: string) => {\n buffer += chunk;\n let idx: number;\n while ((idx = buffer.indexOf('\\n')) !== -1) {\n const line = buffer.slice(0, idx).trim();\n buffer = buffer.slice(idx + 1);\n if (!line) continue;\n\n try {\n const cmd = JSON.parse(line) as { action: string; [key: string]: unknown };\n handleStdinCommand(cmd, state, cwd, emit);\n } catch {\n emit('command-error', { message: `Invalid JSON on stdin: ${line.slice(0, 100)}` });\n }\n }\n });\n}\n\nasync function handleStdinCommand(\n cmd: { action: string; [key: string]: unknown },\n state: SessionState,\n cwd: string,\n emit: EmitFn,\n): Promise<void> {\n switch (cmd.action) {\n case 'run-scenario':\n return handleRunScenario(state, cwd, cmd, emit);\n case 'run-method':\n return handleRunMethod(state, cwd, cmd, emit);\n case 'impersonate':\n return handleImpersonate(state, cmd, emit);\n case 'clear-impersonation':\n return handleClearImpersonation(state, emit);\n case 'browser':\n return handleBrowser(state, cmd, emit);\n case 'screenshot':\n return handleScreenshot(state, emit);\n case 'dev-server-restarting':\n return handleDevServerRestarting(state, emit);\n case 'browser-status':\n return handleBrowserStatus(state, emit);\n case 'reset-browser':\n return handleResetBrowser(state, emit);\n default:\n emit('command-error', { message: `Unknown action: ${cmd.action}` });\n }\n}\n","/**\n * Headless Dev Mode\n *\n * Runs the MindStudio dev tunnel without a TUI. Designed for programmatic\n * control by a parent process (e.g., a sandbox C&C server or CI pipeline).\n *\n * Outputs structured JSON events to stdout (one per line, newline-delimited).\n * The parent process reads these to track session state, method execution,\n * errors, and connection health.\n *\n * Does NOT start a dev server — the parent process manages that separately.\n * The tunnel just needs to know which port to proxy to.\n *\n * @module\n */\n\nimport { DevRunner } from './dev/runner';\nimport { DevProxy } from './dev/proxy';\nimport { syncSchema } from './dev/api';\nimport {\n detectAppConfig,\n getWebInterfaceConfig,\n readTableSources,\n} from './dev/app-config';\nimport { initRequestLog, closeRequestLog } from './dev/request-log';\nimport { initBrowserLog, closeBrowserLog } from './dev/browser-log';\nimport { subscribeDevEvents } from './dev/session-events';\nimport { setupStdinCommands, type SessionState } from './dev/stdin-commands';\nimport {\n getApiKey,\n getApiBaseUrl,\n getUserId,\n getEnvironment,\n getConfigPath,\n} from './config';\nimport { initLoggerHeadless, log, type LogLevel } from './dev/logger';\nimport { stablePort, detectGitBranch } from './dev/utils';\nimport { watchTableFiles } from './dev/table-watcher';\nimport { watchConfigFile } from './dev/config-watcher';\n\n/**\n * Options for headless dev mode.\n */\nexport interface HeadlessOptions {\n /** Working directory containing mindstudio.json. Defaults to process.cwd(). */\n cwd?: string;\n /** Port the dev server is running on. If omitted, reads from web.json. If neither, proxy is skipped. */\n devPort?: number;\n /** Preferred port for the local proxy. Defaults to a stable port derived from the app ID. */\n proxyPort?: number;\n /** Bind address for the proxy server. Use '0.0.0.0' for hosted sandboxes. Defaults to '127.0.0.1'. */\n bindAddress?: string;\n /** Log level for stderr output. Defaults to 'info'. */\n logLevel?: LogLevel;\n /** URL for the browser agent script. Defaults to unpkg latest. Set to an ngrok URL for development. */\n browserAgentUrl?: string;\n}\n\n/** Write a JSON event to stdout. */\nfunction emit(event: string, data?: Record<string, unknown>): void {\n process.stdout.write(JSON.stringify({ event, ...data }) + '\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Session lifecycle\n// ---------------------------------------------------------------------------\n\nasync function startSession(\n cwd: string,\n opts: HeadlessOptions,\n state: SessionState,\n shutdown: () => Promise<void>,\n): Promise<boolean> {\n const bindAddress = opts.bindAddress ?? '127.0.0.1';\n\n // Read fresh config\n const appConfig = detectAppConfig(cwd);\n if (!appConfig) {\n emit('config-error', { message: 'No valid mindstudio.json found in ' + cwd });\n return false;\n }\n\n if (!appConfig.appId) {\n emit('config-error', { message: 'Missing \"appId\" in mindstudio.json' });\n return false;\n }\n\n state.appConfig = appConfig;\n\n // Resolve dev port\n let devPort = opts.devPort ?? null;\n if (devPort === null) {\n const webConfig = getWebInterfaceConfig(appConfig, cwd);\n devPort = webConfig?.devPort ?? null;\n }\n\n emit('session-starting', { appId: appConfig.appId, name: appConfig.name });\n\n try {\n // Start platform session\n const branch = detectGitBranch();\n const runner = new DevRunner(appConfig.appId, cwd, {\n branch,\n methods: appConfig.methods.map((m) => ({ id: m.id, export: m.export, path: m.path })),\n });\n const session = await runner.start();\n state.runner = runner;\n\n // Initialize logs\n initRequestLog(cwd);\n initBrowserLog(cwd);\n\n // Sync schema\n if (appConfig.tables.length > 0) {\n try {\n const tableSources = readTableSources(appConfig, cwd);\n if (tableSources.length > 0) {\n const syncResult = await syncSchema(appConfig.appId, session.sessionId, tableSources);\n session.databases = syncResult.databases;\n emit('schema-sync-completed', {\n created: syncResult.created,\n altered: syncResult.altered,\n errors: syncResult.errors,\n });\n } else {\n log.warn('No table source files found, skipping schema sync', {\n expected: appConfig.tables.map((t) => t.path),\n });\n }\n } catch (err) {\n emit('schema-sync-completed', {\n created: [],\n altered: [],\n errors: [err instanceof Error ? err.message : 'Schema sync failed'],\n });\n }\n }\n\n // Start proxy\n let proxyPort: number | null = null;\n if (devPort !== null && session.clientContext) {\n const proxy = new DevProxy(devPort, session.clientContext, bindAddress, opts.browserAgentUrl);\n const preferred = opts.proxyPort ?? stablePort(appConfig.appId);\n proxyPort = await proxy.start(preferred);\n runner.setProxyUrl(`http://${bindAddress === '0.0.0.0' ? 'localhost' : bindAddress}:${proxyPort}`);\n runner.setProxy(proxy);\n state.proxy = proxy;\n }\n state.proxyPort = proxyPort;\n\n emit('session-started', {\n sessionId: session.sessionId,\n releaseId: session.releaseId,\n branch: session.branch,\n proxyPort,\n proxyUrl: proxyPort\n ? `http://${bindAddress === '0.0.0.0' ? 'localhost' : bindAddress}:${proxyPort}/`\n : null,\n webInterfaceUrl: session.webInterfaceUrl,\n roles: appConfig.roles.map((r) => ({ id: r.id, name: r.name ?? r.id, description: r.description })),\n scenarios: appConfig.scenarios.map((s) => ({\n id: s.id,\n name: s.name ?? s.export,\n description: s.description,\n path: s.path,\n roles: s.roles,\n })),\n });\n\n // Subscribe to runner events\n state.unsubscribers.push(...subscribeDevEvents(emit, shutdown));\n\n // Watch table source files for changes — auto-sync without session restart\n setupTableWatchers(cwd, state);\n\n return true;\n } catch (err) {\n emit('config-error', {\n message: err instanceof Error ? err.message : 'Failed to start session',\n });\n return false;\n }\n}\n\nfunction setupTableWatchers(cwd: string, state: SessionState): void {\n if (!state.appConfig || state.appConfig.tables.length === 0) return;\n\n const cleanup = watchTableFiles(state.appConfig.tables, cwd, async () => {\n if (!state.runner || !state.appConfig?.appId) return;\n const session = state.runner.getSession();\n if (!session) return;\n\n emit('schema-sync-started');\n log.info('Table source file changed, syncing schema');\n\n try {\n const tableSources = readTableSources(state.appConfig, cwd);\n if (tableSources.length > 0) {\n const result = await syncSchema(state.appConfig.appId, session.sessionId, tableSources);\n session.databases = result.databases;\n emit('schema-sync-completed', {\n created: result.created,\n altered: result.altered,\n errors: result.errors,\n });\n log.info('Schema sync complete', { created: result.created, altered: result.altered });\n } else {\n log.warn('Table source file change detected but file(s) still missing', {\n expected: state.appConfig.tables.map((t) => t.path),\n });\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Schema sync failed';\n emit('command-error', { message });\n log.warn('Schema sync failed', { error: message });\n }\n });\n\n state.unsubscribers.push(cleanup);\n}\n\nasync function teardownSession(state: SessionState): Promise<void> {\n for (const unsub of state.unsubscribers) unsub();\n state.unsubscribers = [];\n\n state.proxy?.stop();\n state.proxy = null;\n state.proxyPort = null;\n\n if (state.runner) {\n await state.runner.stop().catch(() => {});\n state.runner = null;\n }\n\n closeRequestLog();\n closeBrowserLog();\n}\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\n/**\n * Start the dev tunnel in headless mode.\n */\nexport async function startHeadless(opts: HeadlessOptions = {}): Promise<void> {\n initLoggerHeadless(opts.logLevel ?? 'info');\n\n const cwd = opts.cwd ?? process.cwd();\n\n const apiKey = getApiKey();\n const userId = getUserId();\n log.info('Startup config', {\n configPath: getConfigPath(),\n environment: getEnvironment(),\n apiBaseUrl: getApiBaseUrl(),\n hasApiKey: !!apiKey,\n apiKeyPrefix: apiKey ? apiKey.slice(0, 8) + '...' : null,\n hasUserId: !!userId,\n userId: userId ?? null,\n cwd,\n });\n\n const state: SessionState = {\n runner: null,\n proxy: null,\n appConfig: null,\n proxyPort: null,\n unsubscribers: [],\n };\n\n let restarting = false;\n let cleanupConfigWatcher: (() => void) | undefined;\n\n let stopping = false;\n const shutdown = async () => {\n if (stopping) return;\n stopping = true;\n emit('session-stopping');\n cleanupConfigWatcher?.();\n await teardownSession(state);\n emit('session-stopped');\n };\n\n process.on('SIGTERM', () => { shutdown().then(() => process.exit(0)); });\n process.on('SIGINT', () => { shutdown().then(() => process.exit(0)); });\n\n // Initial session start — crash if it fails so the process manager can retry\n const ok = await startSession(cwd, opts, state, shutdown);\n if (!ok) {\n process.exit(1);\n }\n\n // Stdin command loop\n setupStdinCommands(state, cwd, emit);\n\n // Watch mindstudio.json for changes\n cleanupConfigWatcher = watchConfigFile(cwd, async () => {\n if (stopping || restarting) return;\n restarting = true;\n try {\n log.info('mindstudio.json changed, restarting dev session');\n emit('config-changed');\n await teardownSession(state);\n const ok = await startSession(cwd, opts, state, shutdown);\n if (ok && state.proxy) {\n state.proxy.dispatchBrowserCommand([{ command: 'reload' }]).catch(() => {});\n }\n } finally {\n restarting = false;\n }\n });\n\n // Keep the process alive — the poll loop runs in DevRunner\n await new Promise<void>(() => {});\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AASO,SAAS,mBACdA,OACA,UACmB;AACnB,QAAM,SAA4B,CAAC;AAEnC,SAAO;AAAA,IACL,iBAAiB,QAAQ,CAAC,UAAU;AAClC,MAAAA,MAAK,kBAAkB,EAAE,IAAI,MAAM,IAAI,QAAQ,MAAM,OAAO,CAAC;AAAA,IAC/D,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,iBAAiB,WAAW,CAAC,UAAU;AACrC,MAAAA,MAAK,oBAAoB;AAAA,QACvB,IAAI,MAAM;AAAA,QACV,SAAS,MAAM;AAAA,QACf,UAAU,MAAM;AAAA,QAChB,GAAI,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,MAC9C,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,iBAAiB,oBAAoB,CAAC,YAAY;AAChD,MAAAA,MAAK,mBAAmB,EAAE,QAAQ,CAAC;AAAA,IACrC,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,iBAAiB,qBAAqB,MAAM;AAC1C,MAAAA,MAAK,qBAAqB;AAAA,IAC5B,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,iBAAiB,iBAAiB,MAAM;AACtC,MAAAA,MAAK,iBAAiB;AACtB,eAAS,EAAE,KAAK,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,IACvC,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,iBAAiB,mBAAmB,CAAC,QAAQ;AAC3C,MAAAA,MAAK,sBAAsB,EAAE,IAAI,CAAC;AAAA,IACpC,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,iBAAiB,qBAAqB,MAAM;AAC1C,MAAAA,MAAK,sBAAsB;AAAA,IAC7B,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,iBAAiB,oBAAoB,MAAM;AACzC,MAAAA,MAAK,qBAAqB;AAAA,IAC5B,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,iBAAiB,cAAc,CAAC,UAAU;AACxC,MAAAA,MAAK,yBAAyB,EAAE,OAAO,MAAM,MAAM,CAAC;AAAA,IACtD,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,iBAAiB,gBAAgB,CAAC,UAAU;AAC1C,MAAAA,MAAK,oBAAoB,EAAE,IAAI,MAAM,IAAI,MAAM,MAAM,KAAK,CAAC;AAAA,IAC7D,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,iBAAiB,mBAAmB,CAAC,UAAU;AAC7C,MAAAA,MAAK,sBAAsB;AAAA,QACzB,IAAI,MAAM;AAAA,QACV,SAAS,MAAM;AAAA,QACf,UAAU,MAAM;AAAA,QAChB,OAAO,MAAM;AAAA,QACb,GAAI,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,MAC9C,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;AC3FA,eAAsB,kBACpB,OACA,KACA,KACAC,OACe;AACf,MAAI,CAAC,MAAM,QAAQ;AACjB,IAAAA,MAAK,iBAAiB,EAAE,SAAS,oBAAoB,CAAC;AACtD;AAAA,EACF;AACA,QAAM,cAAc,gBAAgB,GAAG,KAAK,MAAM;AAClD,QAAM,WAAW,aAAa,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,IAAI,UAAU;AAC3E,MAAI,CAAC,UAAU;AACb,IAAAA,MAAK,iBAAiB,EAAE,SAAS,qBAAqB,IAAI,UAAU,GAAG,CAAC;AACxE;AAAA,EACF;AACA,QAAM,MAAM,OAAO,YAAY,QAAQ;AACzC;;;ACjBA,eAAsB,gBACpB,OACA,KACA,KACAC,OACe;AACf,MAAI,CAAC,MAAM,QAAQ;AACjB,IAAAA,MAAK,iBAAiB,EAAE,SAAS,oBAAoB,CAAC;AACtD;AAAA,EACF;AACA,QAAM,aAAa,IAAI;AACvB,MAAI,CAAC,YAAY;AACf,IAAAA,MAAK,iBAAiB,EAAE,SAAS,mDAAmD,CAAC;AACrF;AAAA,EACF;AACA,QAAM,cAAc,gBAAgB,GAAG,KAAK,MAAM;AAClD,QAAM,SACJ,aAAa,QAAQ,KAAK,CAAC,MAAM,EAAE,WAAW,UAAU,KACxD,aAAa,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,UAAU;AACtD,MAAI,CAAC,QAAQ;AACX,IAAAA,MAAK,iBAAiB,EAAE,SAAS,mBAAmB,UAAU,GAAG,CAAC;AAClE;AAAA,EACF;AACA,EAAAA,MAAK,sBAAsB,EAAE,QAAQ,OAAO,OAAO,CAAC;AACpD,QAAM,SAAS,MAAM,MAAM,OAAO,UAAU;AAAA,IAC1C,cAAc,OAAO;AAAA,IACrB,YAAY,OAAO;AAAA,IACnB,OAAO,IAAI,SAAS,CAAC;AAAA,EACvB,CAAC;AACD,EAAAA,MAAK,wBAAwB;AAAA,IAC3B,QAAQ,OAAO;AAAA,IACf,SAAS,OAAO;AAAA,IAChB,QAAQ,OAAO,UAAU;AAAA,IACzB,OAAO,OAAO,SAAS;AAAA,IACvB,QAAQ,OAAO,UAAU,CAAC;AAAA,IAC1B,UAAU,OAAO;AAAA,EACnB,CAAC;AACH;;;ACtCA,eAAsB,kBACpB,OACA,KACAC,OACe;AACf,MAAI,CAAC,MAAM,QAAQ;AACjB,IAAAA,MAAK,iBAAiB,EAAE,SAAS,oBAAoB,CAAC;AACtD;AAAA,EACF;AACA,QAAM,QAAQ,IAAI;AAClB,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,IAAAA,MAAK,iBAAiB,EAAE,SAAS,mCAAmC,CAAC;AACrE;AAAA,EACF;AACA,QAAM,MAAM,OAAO,iBAAiB,KAAK;AAC3C;AAEA,eAAsB,yBACpB,OACAA,OACe;AACf,MAAI,CAAC,MAAM,QAAQ;AACjB,IAAAA,MAAK,iBAAiB,EAAE,SAAS,oBAAoB,CAAC;AACtD;AAAA,EACF;AACA,QAAM,MAAM,OAAO,mBAAmB;AACxC;;;AC1BA,eAAsB,cACpB,OACA,KACAC,OACe;AACf,MAAI,CAAC,MAAM,OAAO;AAChB,IAAAA,MAAK,iBAAiB,EAAE,SAAS,kEAA6D,CAAC;AAC/F;AAAA,EACF;AACA,QAAM,QAAQ,IAAI;AAClB,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,GAAG;AAC/C,IAAAA,MAAK,iBAAiB,EAAE,SAAS,oDAAoD,CAAC;AACtF;AAAA,EACF;AACA,MAAI;AACF,UAAM,SAAS,MAAM,MAAM,MAAM,uBAAuB,KAAK;AAC7D,IAAAA,MAAK,qBAAqB;AAAA,MACxB,OAAO,OAAO;AAAA,MACd,UAAU,OAAO;AAAA,MACjB,MAAM,OAAO;AAAA,MACb,UAAU,OAAO;AAAA,IACnB,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,IAAAA,MAAK,iBAAiB;AAAA,MACpB,SAAS,eAAe,QAAQ,IAAI,UAAU;AAAA,IAChD,CAAC;AAAA,EACH;AACF;;;AC1BA,eAAsB,iBACpB,OACAC,OACe;AACf,QAAM,OAAO,CAAC,YAAoB;AAChC,IAAAA,MAAK,wBAAwB;AAAA,MAC3B,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,MAAI,CAAC,MAAM,OAAO;AAChB,SAAK,iBAAiB;AACtB;AAAA,EACF;AACA,MAAI,CAAC,MAAM,MAAM,mBAAmB,GAAG;AACrC,SAAK,6DAA6D;AAClE;AAAA,EACF;AACA,MAAI,CAAC,MAAM,QAAQ,WAAW,KAAK,CAAC,MAAM,WAAW,OAAO;AAC1D,SAAK,mBAAmB;AACxB;AAAA,EACF;AAEA,MAAI;AACF,UAAM,YAAY,KAAK,IAAI;AAI3B,UAAM,SAAS,MAAM,MAAM,MAAM,uBAAuB,CAAC,EAAE,SAAS,aAAa,CAAC,GAAG,IAAO;AAC5F,UAAM,aAAc,OAAO,QAA2C,CAAC,GACnE;AAEJ,QAAI,CAAC,YAAY,OAAO;AACtB,WAAK,2CAA2C;AAChD;AAAA,IACF;AAGA,UAAM,UAAU,MAAM,OAAO,WAAW;AACxC,UAAM,EAAE,WAAW,cAAc,UAAU,IAAI,MAAM;AAAA,MACnD,MAAM,UAAU;AAAA,MAChB,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAGA,UAAM,cAAc,OAAO,KAAK,WAAW,OAAO,QAAQ;AAC1D,UAAM,OAAO,IAAI,SAAS;AAC1B,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,YAAY,GAAG;AACvD,WAAK,OAAO,KAAK,KAAK;AAAA,IACxB;AACA,SAAK,OAAO,QAAQ,IAAI,KAAK,CAAC,WAAW,GAAG,EAAE,MAAM,aAAa,CAAC,GAAG,gBAAgB;AACrF,UAAM,eAAe,MAAM,MAAM,WAAW,EAAE,QAAQ,QAAQ,MAAM,KAAK,CAAC;AAE1E,QAAI,CAAC,aAAa,IAAI;AACpB,WAAK,qBAAqB,aAAa,MAAM,EAAE;AAC/C;AAAA,IACF;AAGA,IAAAA,MAAK,wBAAwB;AAAA,MAC3B,KAAK;AAAA,MACL,OAAO,WAAW;AAAA,MAClB,QAAQ,WAAW;AAAA,MACnB,UAAU,KAAK,IAAI,IAAI;AAAA,IACzB,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,SAAK,eAAe,QAAQ,IAAI,UAAU,mBAAmB;AAAA,EAC/D;AACF;;;ACtEA,eAAsB,0BACpB,OACAC,OACe;AACf,MAAI,CAAC,MAAM,OAAO;AAChB,IAAAA,MAAK,iBAAiB,EAAE,SAAS,kBAAkB,CAAC;AACpD;AAAA,EACF;AACA,QAAM,MAAM,iBAAiB;AAC7B,EAAAA,MAAK,6BAA6B,CAAC,CAAC;AACtC;;;ACfO,SAAS,oBACd,OACAC,OACM;AACN,EAAAA,MAAK,kBAAkB;AAAA,IACrB,WAAW,MAAM,OAAO,mBAAmB,KAAK;AAAA,EAClD,CAAC;AACH;;;ACFO,SAAS,mBACd,OACAC,OACM;AACN,MAAI,CAAC,MAAM,OAAO;AAChB,IAAAA,MAAK,iBAAiB,EAAE,SAAS,kBAAkB,CAAC;AACpD;AAAA,EACF;AACA,MAAI,CAAC,MAAM,MAAM,mBAAmB,GAAG;AACrC,IAAAA,MAAK,iBAAiB,EAAE,SAAS,uBAAuB,CAAC;AACzD;AAAA,EACF;AACA,QAAM,MAAM,uBAAuB,CAAC,EAAE,SAAS,SAAS,CAAC,CAAC,EAAE,MAAM,MAAM;AAAA,EAAC,CAAC;AAC1E,EAAAA,MAAK,2BAA2B,CAAC,CAAC;AACpC;;;ACFO,SAAS,mBACd,OACA,KACAC,OACM;AACN,MAAI,CAAC,QAAQ,MAAM,SAAU;AAE7B,MAAI,SAAS;AACb,UAAQ,MAAM,YAAY,OAAO;AACjC,UAAQ,MAAM,GAAG,QAAQ,CAAC,UAAkB;AAC1C,cAAU;AACV,QAAI;AACJ,YAAQ,MAAM,OAAO,QAAQ,IAAI,OAAO,IAAI;AAC1C,YAAM,OAAO,OAAO,MAAM,GAAG,GAAG,EAAE,KAAK;AACvC,eAAS,OAAO,MAAM,MAAM,CAAC;AAC7B,UAAI,CAAC,KAAM;AAEX,UAAI;AACF,cAAM,MAAM,KAAK,MAAM,IAAI;AAC3B,2BAAmB,KAAK,OAAO,KAAKA,KAAI;AAAA,MAC1C,QAAQ;AACN,QAAAA,MAAK,iBAAiB,EAAE,SAAS,0BAA0B,KAAK,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC;AAAA,MACnF;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,eAAe,mBACb,KACA,OACA,KACAA,OACe;AACf,UAAQ,IAAI,QAAQ;AAAA,IAClB,KAAK;AACH,aAAO,kBAAkB,OAAO,KAAK,KAAKA,KAAI;AAAA,IAChD,KAAK;AACH,aAAO,gBAAgB,OAAO,KAAK,KAAKA,KAAI;AAAA,IAC9C,KAAK;AACH,aAAO,kBAAkB,OAAO,KAAKA,KAAI;AAAA,IAC3C,KAAK;AACH,aAAO,yBAAyB,OAAOA,KAAI;AAAA,IAC7C,KAAK;AACH,aAAO,cAAc,OAAO,KAAKA,KAAI;AAAA,IACvC,KAAK;AACH,aAAO,iBAAiB,OAAOA,KAAI;AAAA,IACrC,KAAK;AACH,aAAO,0BAA0B,OAAOA,KAAI;AAAA,IAC9C,KAAK;AACH,aAAO,oBAAoB,OAAOA,KAAI;AAAA,IACxC,KAAK;AACH,aAAO,mBAAmB,OAAOA,KAAI;AAAA,IACvC;AACE,MAAAA,MAAK,iBAAiB,EAAE,SAAS,mBAAmB,IAAI,MAAM,GAAG,CAAC;AAAA,EACtE;AACF;;;ACfA,SAAS,KAAK,OAAe,MAAsC;AACjE,UAAQ,OAAO,MAAM,KAAK,UAAU,EAAE,OAAO,GAAG,KAAK,CAAC,IAAI,IAAI;AAChE;AAMA,eAAe,aACb,KACA,MACA,OACA,UACkB;AAClB,QAAM,cAAc,KAAK,eAAe;AAGxC,QAAM,YAAY,gBAAgB,GAAG;AACrC,MAAI,CAAC,WAAW;AACd,SAAK,gBAAgB,EAAE,SAAS,uCAAuC,IAAI,CAAC;AAC5E,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,UAAU,OAAO;AACpB,SAAK,gBAAgB,EAAE,SAAS,qCAAqC,CAAC;AACtE,WAAO;AAAA,EACT;AAEA,QAAM,YAAY;AAGlB,MAAI,UAAU,KAAK,WAAW;AAC9B,MAAI,YAAY,MAAM;AACpB,UAAM,YAAY,sBAAsB,WAAW,GAAG;AACtD,cAAU,WAAW,WAAW;AAAA,EAClC;AAEA,OAAK,oBAAoB,EAAE,OAAO,UAAU,OAAO,MAAM,UAAU,KAAK,CAAC;AAEzE,MAAI;AAEF,UAAM,SAAS,gBAAgB;AAC/B,UAAM,SAAS,IAAI,UAAU,UAAU,OAAO,KAAK;AAAA,MACjD;AAAA,MACA,SAAS,UAAU,QAAQ,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,QAAQ,EAAE,QAAQ,MAAM,EAAE,KAAK,EAAE;AAAA,IACtF,CAAC;AACD,UAAM,UAAU,MAAM,OAAO,MAAM;AACnC,UAAM,SAAS;AAGf,mBAAe,GAAG;AAClB,mBAAe,GAAG;AAGlB,QAAI,UAAU,OAAO,SAAS,GAAG;AAC/B,UAAI;AACF,cAAM,eAAe,iBAAiB,WAAW,GAAG;AACpD,YAAI,aAAa,SAAS,GAAG;AAC3B,gBAAM,aAAa,MAAM,WAAW,UAAU,OAAO,QAAQ,WAAW,YAAY;AACpF,kBAAQ,YAAY,WAAW;AAC/B,eAAK,yBAAyB;AAAA,YAC5B,SAAS,WAAW;AAAA,YACpB,SAAS,WAAW;AAAA,YACpB,QAAQ,WAAW;AAAA,UACrB,CAAC;AAAA,QACH,OAAO;AACL,cAAI,KAAK,qDAAqD;AAAA,YAC5D,UAAU,UAAU,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,UAC9C,CAAC;AAAA,QACH;AAAA,MACF,SAAS,KAAK;AACZ,aAAK,yBAAyB;AAAA,UAC5B,SAAS,CAAC;AAAA,UACV,SAAS,CAAC;AAAA,UACV,QAAQ,CAAC,eAAe,QAAQ,IAAI,UAAU,oBAAoB;AAAA,QACpE,CAAC;AAAA,MACH;AAAA,IACF;AAGA,QAAI,YAA2B;AAC/B,QAAI,YAAY,QAAQ,QAAQ,eAAe;AAC7C,YAAM,QAAQ,IAAI,SAAS,SAAS,QAAQ,eAAe,aAAa,KAAK,eAAe;AAC5F,YAAM,YAAY,KAAK,aAAa,WAAW,UAAU,KAAK;AAC9D,kBAAY,MAAM,MAAM,MAAM,SAAS;AACvC,aAAO,YAAY,UAAU,gBAAgB,YAAY,cAAc,WAAW,IAAI,SAAS,EAAE;AACjG,aAAO,SAAS,KAAK;AACrB,YAAM,QAAQ;AAAA,IAChB;AACA,UAAM,YAAY;AAElB,SAAK,mBAAmB;AAAA,MACtB,WAAW,QAAQ;AAAA,MACnB,WAAW,QAAQ;AAAA,MACnB,QAAQ,QAAQ;AAAA,MAChB;AAAA,MACA,UAAU,YACN,UAAU,gBAAgB,YAAY,cAAc,WAAW,IAAI,SAAS,MAC5E;AAAA,MACJ,iBAAiB,QAAQ;AAAA,MACzB,OAAO,UAAU,MAAM,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,QAAQ,EAAE,IAAI,aAAa,EAAE,YAAY,EAAE;AAAA,MAClG,WAAW,UAAU,UAAU,IAAI,CAAC,OAAO;AAAA,QACzC,IAAI,EAAE;AAAA,QACN,MAAM,EAAE,QAAQ,EAAE;AAAA,QAClB,aAAa,EAAE;AAAA,QACf,MAAM,EAAE;AAAA,QACR,OAAO,EAAE;AAAA,MACX,EAAE;AAAA,IACJ,CAAC;AAGD,UAAM,cAAc,KAAK,GAAG,mBAAmB,MAAM,QAAQ,CAAC;AAG9D,uBAAmB,KAAK,KAAK;AAE7B,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,SAAK,gBAAgB;AAAA,MACnB,SAAS,eAAe,QAAQ,IAAI,UAAU;AAAA,IAChD,CAAC;AACD,WAAO;AAAA,EACT;AACF;AAEA,SAAS,mBAAmB,KAAa,OAA2B;AAClE,MAAI,CAAC,MAAM,aAAa,MAAM,UAAU,OAAO,WAAW,EAAG;AAE7D,QAAM,UAAU,gBAAgB,MAAM,UAAU,QAAQ,KAAK,YAAY;AACvE,QAAI,CAAC,MAAM,UAAU,CAAC,MAAM,WAAW,MAAO;AAC9C,UAAM,UAAU,MAAM,OAAO,WAAW;AACxC,QAAI,CAAC,QAAS;AAEd,SAAK,qBAAqB;AAC1B,QAAI,KAAK,2CAA2C;AAEpD,QAAI;AACF,YAAM,eAAe,iBAAiB,MAAM,WAAW,GAAG;AAC1D,UAAI,aAAa,SAAS,GAAG;AAC3B,cAAM,SAAS,MAAM,WAAW,MAAM,UAAU,OAAO,QAAQ,WAAW,YAAY;AACtF,gBAAQ,YAAY,OAAO;AAC3B,aAAK,yBAAyB;AAAA,UAC5B,SAAS,OAAO;AAAA,UAChB,SAAS,OAAO;AAAA,UAChB,QAAQ,OAAO;AAAA,QACjB,CAAC;AACD,YAAI,KAAK,wBAAwB,EAAE,SAAS,OAAO,SAAS,SAAS,OAAO,QAAQ,CAAC;AAAA,MACvF,OAAO;AACL,YAAI,KAAK,+DAA+D;AAAA,UACtE,UAAU,MAAM,UAAU,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,QACpD,CAAC;AAAA,MACH;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,WAAK,iBAAiB,EAAE,QAAQ,CAAC;AACjC,UAAI,KAAK,sBAAsB,EAAE,OAAO,QAAQ,CAAC;AAAA,IACnD;AAAA,EACF,CAAC;AAED,QAAM,cAAc,KAAK,OAAO;AAClC;AAEA,eAAe,gBAAgB,OAAoC;AACjE,aAAW,SAAS,MAAM,cAAe,OAAM;AAC/C,QAAM,gBAAgB,CAAC;AAEvB,QAAM,OAAO,KAAK;AAClB,QAAM,QAAQ;AACd,QAAM,YAAY;AAElB,MAAI,MAAM,QAAQ;AAChB,UAAM,MAAM,OAAO,KAAK,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACxC,UAAM,SAAS;AAAA,EACjB;AAEA,kBAAgB;AAChB,kBAAgB;AAClB;AASA,eAAsB,cAAc,OAAwB,CAAC,GAAkB;AAC7E,qBAAmB,KAAK,YAAY,MAAM;AAE1C,QAAM,MAAM,KAAK,OAAO,QAAQ,IAAI;AAEpC,QAAM,SAAS,UAAU;AACzB,QAAM,SAAS,UAAU;AACzB,MAAI,KAAK,kBAAkB;AAAA,IACzB,YAAY,cAAc;AAAA,IAC1B,aAAa,eAAe;AAAA,IAC5B,YAAY,cAAc;AAAA,IAC1B,WAAW,CAAC,CAAC;AAAA,IACb,cAAc,SAAS,OAAO,MAAM,GAAG,CAAC,IAAI,QAAQ;AAAA,IACpD,WAAW,CAAC,CAAC;AAAA,IACb,QAAQ,UAAU;AAAA,IAClB;AAAA,EACF,CAAC;AAED,QAAM,QAAsB;AAAA,IAC1B,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,IACX,WAAW;AAAA,IACX,eAAe,CAAC;AAAA,EAClB;AAEA,MAAI,aAAa;AACjB,MAAI;AAEJ,MAAI,WAAW;AACf,QAAM,WAAW,YAAY;AAC3B,QAAI,SAAU;AACd,eAAW;AACX,SAAK,kBAAkB;AACvB,2BAAuB;AACvB,UAAM,gBAAgB,KAAK;AAC3B,SAAK,iBAAiB;AAAA,EACxB;AAEA,UAAQ,GAAG,WAAW,MAAM;AAAE,aAAS,EAAE,KAAK,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,EAAG,CAAC;AACvE,UAAQ,GAAG,UAAU,MAAM;AAAE,aAAS,EAAE,KAAK,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,EAAG,CAAC;AAGtE,QAAM,KAAK,MAAM,aAAa,KAAK,MAAM,OAAO,QAAQ;AACxD,MAAI,CAAC,IAAI;AACP,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,qBAAmB,OAAO,KAAK,IAAI;AAGnC,yBAAuB,gBAAgB,KAAK,YAAY;AACtD,QAAI,YAAY,WAAY;AAC5B,iBAAa;AACb,QAAI;AACF,UAAI,KAAK,iDAAiD;AAC1D,WAAK,gBAAgB;AACrB,YAAM,gBAAgB,KAAK;AAC3B,YAAMC,MAAK,MAAM,aAAa,KAAK,MAAM,OAAO,QAAQ;AACxD,UAAIA,OAAM,MAAM,OAAO;AACrB,cAAM,MAAM,uBAAuB,CAAC,EAAE,SAAS,SAAS,CAAC,CAAC,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MAC5E;AAAA,IACF,UAAE;AACA,mBAAa;AAAA,IACf;AAAA,EACF,CAAC;AAGD,QAAM,IAAI,QAAc,MAAM;AAAA,EAAC,CAAC;AAClC;","names":["emit","emit","emit","emit","emit","emit","emit","emit","emit","emit","ok"]}
package/dist/cli.js CHANGED
@@ -17,7 +17,7 @@ async function main() {
17
17
  logLevel: getFlag("--log-level") ?? void 0
18
18
  });
19
19
  } else {
20
- const { startTUI } = await import("./tui-TUREGKKI.js");
20
+ const { startTUI } = await import("./tui-ZUGRCB5V.js");
21
21
  await startTUI();
22
22
  }
23
23
  process.exit(0);
package/dist/headless.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  startHeadless
3
- } from "./chunk-YTHFWJU6.js";
3
+ } from "./chunk-ENSNEBJJ.js";
4
4
  import "./chunk-VJTZSOKC.js";
5
5
  export {
6
6
  startHeadless
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  startHeadless
3
- } from "./chunk-YTHFWJU6.js";
3
+ } from "./chunk-ENSNEBJJ.js";
4
4
  import {
5
5
  TunnelRunner
6
6
  } from "./chunk-TMIU4S53.js";
@@ -151,7 +151,7 @@ function Header({
151
151
  /* @__PURE__ */ jsx(Text, { bold: true, color: "white", children: "MindStudio Local Tunnel" }),
152
152
  compact && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
153
153
  " v",
154
- "0.5.21"
154
+ "0.5.22"
155
155
  ] }),
156
156
  environment !== "prod" && /* @__PURE__ */ jsxs(Fragment, { children: [
157
157
  /* @__PURE__ */ jsx(Text, { children: " " }),
@@ -169,7 +169,7 @@ function Header({
169
169
  ] }),
170
170
  !compact && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
171
171
  "v",
172
- "0.5.21"
172
+ "0.5.22"
173
173
  ] })
174
174
  ] })
175
175
  ]
@@ -3790,7 +3790,7 @@ function getInstallMethod() {
3790
3790
  return "npm";
3791
3791
  }
3792
3792
  function getCurrentVersion() {
3793
- return "0.5.21";
3793
+ return "0.5.22";
3794
3794
  }
3795
3795
  async function fetchLatestVersion() {
3796
3796
  try {
@@ -4032,4 +4032,4 @@ async function startTUI() {
4032
4032
  export {
4033
4033
  startTUI
4034
4034
  };
4035
- //# sourceMappingURL=tui-TUREGKKI.js.map
4035
+ //# sourceMappingURL=tui-ZUGRCB5V.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindstudio-ai/local-model-tunnel",
3
- "version": "0.5.21",
3
+ "version": "0.5.22",
4
4
  "description": "Run local AI models with MindStudio",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/dev/session-events.ts","../src/dev/stdin-commands/run-scenario.ts","../src/dev/stdin-commands/run-method.ts","../src/dev/stdin-commands/impersonate.ts","../src/dev/stdin-commands/browser.ts","../src/dev/stdin-commands/screenshot.ts","../src/dev/stdin-commands/dev-server-restarting.ts","../src/dev/stdin-commands/browser-status.ts","../src/dev/stdin-commands/reset-browser.ts","../src/dev/stdin-commands/index.ts","../src/headless.ts"],"sourcesContent":["/**\n * Subscribe to DevRunner events and relay them as JSON to stdout.\n * Returns an array of unsubscribe functions for cleanup on teardown.\n */\n\nimport { devRequestEvents } from './events';\n\ntype EmitFn = (event: string, data?: Record<string, unknown>) => void;\n\nexport function subscribeDevEvents(\n emit: EmitFn,\n shutdown: () => Promise<void>,\n): Array<() => void> {\n const unsubs: Array<() => void> = [];\n\n unsubs.push(\n devRequestEvents.onStart((event) => {\n emit('method-started', { id: event.id, method: event.method });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onComplete((event) => {\n emit('method-completed', {\n id: event.id,\n success: event.success,\n duration: event.duration,\n ...(event.error ? { error: event.error } : {}),\n });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onConnectionWarning((message) => {\n emit('connection-lost', { message });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onConnectionRestored(() => {\n emit('connection-restored');\n }),\n );\n\n unsubs.push(\n devRequestEvents.onSessionExpired(() => {\n emit('session-expired');\n shutdown().then(() => process.exit(1));\n }),\n );\n\n unsubs.push(\n devRequestEvents.onAuthRefreshStart((url) => {\n emit('auth-refresh-start', { url });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onAuthRefreshSuccess(() => {\n emit('auth-refresh-success');\n }),\n );\n\n unsubs.push(\n devRequestEvents.onAuthRefreshFailed(() => {\n emit('auth-refresh-failed');\n }),\n );\n\n unsubs.push(\n devRequestEvents.onImpersonate((event) => {\n emit('impersonation-changed', { roles: event.roles });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onScenarioStart((event) => {\n emit('scenario-started', { id: event.id, name: event.name });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onScenarioComplete((event) => {\n emit('scenario-completed', {\n id: event.id,\n success: event.success,\n duration: event.duration,\n roles: event.roles,\n ...(event.error ? { error: event.error } : {}),\n });\n }),\n );\n\n return unsubs;\n}\n","import { detectAppConfig } from '../app-config';\nimport type { SessionState, EmitFn } from './types';\n\nexport async function handleRunScenario(\n state: SessionState,\n cwd: string,\n cmd: Record<string, unknown>,\n emit: EmitFn,\n): Promise<void> {\n if (!state.runner) {\n emit('command-error', { message: 'No active session' });\n return;\n }\n const freshConfig = detectAppConfig(cwd) ?? state.appConfig;\n const scenario = freshConfig?.scenarios.find((s) => s.id === cmd.scenarioId);\n if (!scenario) {\n emit('command-error', { message: `Unknown scenario: ${cmd.scenarioId}` });\n return;\n }\n await state.runner.runScenario(scenario);\n}\n","import { detectAppConfig } from '../app-config';\nimport type { SessionState, EmitFn } from './types';\n\nexport async function handleRunMethod(\n state: SessionState,\n cwd: string,\n cmd: Record<string, unknown>,\n emit: EmitFn,\n): Promise<void> {\n if (!state.runner) {\n emit('command-error', { message: 'No active session' });\n return;\n }\n const methodName = cmd.method as string;\n if (!methodName) {\n emit('command-error', { message: 'run-method requires \"method\" (export name or ID)' });\n return;\n }\n const freshConfig = detectAppConfig(cwd) ?? state.appConfig;\n const method =\n freshConfig?.methods.find((m) => m.export === methodName) ??\n freshConfig?.methods.find((m) => m.id === methodName);\n if (!method) {\n emit('command-error', { message: `Unknown method: ${methodName}` });\n return;\n }\n emit('method-run-started', { method: method.export });\n const result = await state.runner.runMethod({\n methodExport: method.export,\n methodPath: method.path,\n input: cmd.input ?? {},\n });\n emit('method-run-completed', {\n method: method.export,\n success: result.success,\n output: result.output ?? null,\n error: result.error ?? null,\n stdout: result.stdout ?? [],\n duration: result.duration,\n });\n}\n","import type { SessionState, EmitFn } from './types';\n\nexport async function handleImpersonate(\n state: SessionState,\n cmd: Record<string, unknown>,\n emit: EmitFn,\n): Promise<void> {\n if (!state.runner) {\n emit('command-error', { message: 'No active session' });\n return;\n }\n const roles = cmd.roles as string[];\n if (!Array.isArray(roles)) {\n emit('command-error', { message: 'impersonate requires roles array' });\n return;\n }\n await state.runner.setImpersonation(roles);\n}\n\nexport async function handleClearImpersonation(\n state: SessionState,\n emit: EmitFn,\n): Promise<void> {\n if (!state.runner) {\n emit('command-error', { message: 'No active session' });\n return;\n }\n await state.runner.clearImpersonation();\n}\n","import type { SessionState, EmitFn } from './types';\n\nexport async function handleBrowser(\n state: SessionState,\n cmd: Record<string, unknown>,\n emit: EmitFn,\n): Promise<void> {\n if (!state.proxy) {\n emit('command-error', { message: 'No active proxy — browser commands require a web interface' });\n return;\n }\n const steps = cmd.steps as Array<Record<string, unknown>>;\n if (!Array.isArray(steps) || steps.length === 0) {\n emit('command-error', { message: 'browser action requires a non-empty \"steps\" array' });\n return;\n }\n try {\n const result = await state.proxy.dispatchBrowserCommand(steps);\n emit('browser-completed', {\n steps: result.steps,\n snapshot: result.snapshot,\n logs: result.logs,\n duration: result.duration,\n });\n } catch (err) {\n emit('command-error', {\n message: err instanceof Error ? err.message : 'Browser command failed',\n });\n }\n}\n","import { getUploadUrl } from '../api';\nimport type { SessionState, EmitFn } from './types';\n\nexport async function handleScreenshot(\n state: SessionState,\n emit: EmitFn,\n): Promise<void> {\n const fail = (message: string) => {\n emit('screenshot-completed', {\n url: '',\n width: 0,\n height: 0,\n duration: 0,\n error: message,\n });\n };\n\n if (!state.proxy) {\n fail('No active proxy');\n return;\n }\n if (!state.proxy.isBrowserConnected()) {\n fail('No browser connected, please refresh the MindStudio preview');\n return;\n }\n if (!state.runner?.getSession() || !state.appConfig?.appId) {\n fail('No active session');\n return;\n }\n\n try {\n const startTime = Date.now();\n\n // 1. Dispatch screenshot command to browser\n const result = await state.proxy.dispatchBrowserCommand([{ command: 'screenshot' }]);\n const stepResult = (result.steps as Array<Record<string, unknown>>)?.[0]\n ?.result as { image: string; width: number; height: number };\n\n if (!stepResult?.image) {\n fail('Screenshot capture returned no image data');\n return;\n }\n\n // 2. Get presigned upload URL\n const session = state.runner.getSession()!;\n const { uploadUrl, uploadFields, publicUrl } = await getUploadUrl(\n state.appConfig.appId,\n session.sessionId,\n 'jpg',\n 'image/jpeg',\n );\n\n // 3. Upload to S3\n const imageBuffer = Buffer.from(stepResult.image, 'base64');\n const form = new FormData();\n for (const [key, value] of Object.entries(uploadFields)) {\n form.append(key, value);\n }\n form.append('file', new Blob([imageBuffer], { type: 'image/jpeg' }), 'screenshot.jpg');\n const uploadResult = await fetch(uploadUrl, { method: 'POST', body: form });\n\n if (!uploadResult.ok) {\n fail(`S3 upload failed: ${uploadResult.status}`);\n return;\n }\n\n // 4. Emit result\n emit('screenshot-completed', {\n url: publicUrl,\n width: stepResult.width,\n height: stepResult.height,\n duration: Date.now() - startTime,\n });\n } catch (err) {\n fail(err instanceof Error ? err.message : 'Screenshot failed');\n }\n}\n","import type { SessionState, EmitFn } from './types';\n\n/**\n * Handle explicit signal that the upstream dev server is restarting.\n * Marks the upstream as down so the proxy's health check will detect\n * when it's back and auto-reload the browser.\n */\nexport async function handleDevServerRestarting(\n state: SessionState,\n emit: EmitFn,\n): Promise<void> {\n if (!state.proxy) {\n emit('command-error', { message: 'No active proxy' });\n return;\n }\n state.proxy.markUpstreamDown();\n emit('dev-server-restarting-ack', {});\n}\n","import type { SessionState, EmitFn } from './types';\n\nexport function handleBrowserStatus(\n state: SessionState,\n emit: EmitFn,\n): void {\n emit('browser-status', {\n connected: state.proxy?.isBrowserConnected() ?? false,\n });\n}\n","import type { SessionState, EmitFn } from './types';\n\n/**\n * Reset the browser to a clean state by reloading the page.\n * The agent sends this explicitly when done testing.\n * Fire-and-forget — the reload kills the page so no result comes back.\n */\nexport function handleResetBrowser(\n state: SessionState,\n emit: EmitFn,\n): void {\n if (!state.proxy) {\n emit('command-error', { message: 'No active proxy' });\n return;\n }\n if (!state.proxy.isBrowserConnected()) {\n emit('command-error', { message: 'No browser connected' });\n return;\n }\n state.proxy.dispatchBrowserCommand([{ command: 'reload' }]).catch(() => {});\n emit('reset-browser-completed', {});\n}\n","/**\n * Stdin command router for headless mode.\n *\n * Reads NDJSON commands from stdin and dispatches to individual handlers.\n * Each command lives in its own file for isolation and testability.\n */\n\nimport { handleRunScenario } from './run-scenario';\nimport { handleRunMethod } from './run-method';\nimport { handleImpersonate, handleClearImpersonation } from './impersonate';\nimport { handleBrowser } from './browser';\nimport { handleScreenshot } from './screenshot';\nimport { handleDevServerRestarting } from './dev-server-restarting';\nimport { handleBrowserStatus } from './browser-status';\nimport { handleResetBrowser } from './reset-browser';\nimport type { SessionState, EmitFn } from './types';\n\nexport type { SessionState, EmitFn } from './types';\n\nexport function setupStdinCommands(\n state: SessionState,\n cwd: string,\n emit: EmitFn,\n): void {\n if (!process.stdin.readable) return;\n\n let buffer = '';\n process.stdin.setEncoding('utf-8');\n process.stdin.on('data', (chunk: string) => {\n buffer += chunk;\n let idx: number;\n while ((idx = buffer.indexOf('\\n')) !== -1) {\n const line = buffer.slice(0, idx).trim();\n buffer = buffer.slice(idx + 1);\n if (!line) continue;\n\n try {\n const cmd = JSON.parse(line) as { action: string; [key: string]: unknown };\n handleStdinCommand(cmd, state, cwd, emit);\n } catch {\n emit('command-error', { message: `Invalid JSON on stdin: ${line.slice(0, 100)}` });\n }\n }\n });\n}\n\nasync function handleStdinCommand(\n cmd: { action: string; [key: string]: unknown },\n state: SessionState,\n cwd: string,\n emit: EmitFn,\n): Promise<void> {\n switch (cmd.action) {\n case 'run-scenario':\n return handleRunScenario(state, cwd, cmd, emit);\n case 'run-method':\n return handleRunMethod(state, cwd, cmd, emit);\n case 'impersonate':\n return handleImpersonate(state, cmd, emit);\n case 'clear-impersonation':\n return handleClearImpersonation(state, emit);\n case 'browser':\n return handleBrowser(state, cmd, emit);\n case 'screenshot':\n return handleScreenshot(state, emit);\n case 'dev-server-restarting':\n return handleDevServerRestarting(state, emit);\n case 'browser-status':\n return handleBrowserStatus(state, emit);\n case 'reset-browser':\n return handleResetBrowser(state, emit);\n default:\n emit('command-error', { message: `Unknown action: ${cmd.action}` });\n }\n}\n","/**\n * Headless Dev Mode\n *\n * Runs the MindStudio dev tunnel without a TUI. Designed for programmatic\n * control by a parent process (e.g., a sandbox C&C server or CI pipeline).\n *\n * Outputs structured JSON events to stdout (one per line, newline-delimited).\n * The parent process reads these to track session state, method execution,\n * errors, and connection health.\n *\n * Does NOT start a dev server — the parent process manages that separately.\n * The tunnel just needs to know which port to proxy to.\n *\n * @module\n */\n\nimport { DevRunner } from './dev/runner';\nimport { DevProxy } from './dev/proxy';\nimport { syncSchema } from './dev/api';\nimport {\n detectAppConfig,\n getWebInterfaceConfig,\n readTableSources,\n} from './dev/app-config';\nimport { initRequestLog, closeRequestLog } from './dev/request-log';\nimport { initBrowserLog, closeBrowserLog } from './dev/browser-log';\nimport { subscribeDevEvents } from './dev/session-events';\nimport { setupStdinCommands, type SessionState } from './dev/stdin-commands';\nimport {\n getApiKey,\n getApiBaseUrl,\n getUserId,\n getEnvironment,\n getConfigPath,\n} from './config';\nimport { initLoggerHeadless, log, type LogLevel } from './dev/logger';\nimport { stablePort, detectGitBranch } from './dev/utils';\nimport { watchTableFiles } from './dev/table-watcher';\nimport { watchConfigFile } from './dev/config-watcher';\n\n/**\n * Options for headless dev mode.\n */\nexport interface HeadlessOptions {\n /** Working directory containing mindstudio.json. Defaults to process.cwd(). */\n cwd?: string;\n /** Port the dev server is running on. If omitted, reads from web.json. If neither, proxy is skipped. */\n devPort?: number;\n /** Preferred port for the local proxy. Defaults to a stable port derived from the app ID. */\n proxyPort?: number;\n /** Bind address for the proxy server. Use '0.0.0.0' for hosted sandboxes. Defaults to '127.0.0.1'. */\n bindAddress?: string;\n /** Log level for stderr output. Defaults to 'info'. */\n logLevel?: LogLevel;\n /** URL for the browser agent script. Defaults to unpkg latest. Set to an ngrok URL for development. */\n browserAgentUrl?: string;\n}\n\n/** Write a JSON event to stdout. */\nfunction emit(event: string, data?: Record<string, unknown>): void {\n process.stdout.write(JSON.stringify({ event, ...data }) + '\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Session lifecycle\n// ---------------------------------------------------------------------------\n\nasync function startSession(\n cwd: string,\n opts: HeadlessOptions,\n state: SessionState,\n shutdown: () => Promise<void>,\n): Promise<boolean> {\n const bindAddress = opts.bindAddress ?? '127.0.0.1';\n\n // Read fresh config\n const appConfig = detectAppConfig(cwd);\n if (!appConfig) {\n emit('config-error', { message: 'No valid mindstudio.json found in ' + cwd });\n return false;\n }\n\n if (!appConfig.appId) {\n emit('config-error', { message: 'Missing \"appId\" in mindstudio.json' });\n return false;\n }\n\n state.appConfig = appConfig;\n\n // Resolve dev port\n let devPort = opts.devPort ?? null;\n if (devPort === null) {\n const webConfig = getWebInterfaceConfig(appConfig, cwd);\n devPort = webConfig?.devPort ?? null;\n }\n\n emit('session-starting', { appId: appConfig.appId, name: appConfig.name });\n\n try {\n // Start platform session\n const branch = detectGitBranch();\n const runner = new DevRunner(appConfig.appId, cwd, {\n branch,\n methods: appConfig.methods.map((m) => ({ id: m.id, export: m.export, path: m.path })),\n });\n const session = await runner.start();\n state.runner = runner;\n\n // Initialize logs\n initRequestLog(cwd);\n initBrowserLog(cwd);\n\n // Sync schema\n if (appConfig.tables.length > 0) {\n try {\n const tableSources = readTableSources(appConfig, cwd);\n if (tableSources.length > 0) {\n const syncResult = await syncSchema(appConfig.appId, session.sessionId, tableSources);\n session.databases = syncResult.databases;\n emit('schema-sync-completed', {\n created: syncResult.created,\n altered: syncResult.altered,\n errors: syncResult.errors,\n });\n } else {\n log.warn('No table source files found, skipping schema sync', {\n expected: appConfig.tables.map((t) => t.path),\n });\n }\n } catch (err) {\n emit('schema-sync-completed', {\n created: [],\n altered: [],\n errors: [err instanceof Error ? err.message : 'Schema sync failed'],\n });\n }\n }\n\n // Start proxy\n let proxyPort: number | null = null;\n if (devPort !== null && session.clientContext) {\n const proxy = new DevProxy(devPort, session.clientContext, bindAddress, opts.browserAgentUrl);\n const preferred = opts.proxyPort ?? stablePort(appConfig.appId);\n proxyPort = await proxy.start(preferred);\n runner.setProxyUrl(`http://${bindAddress === '0.0.0.0' ? 'localhost' : bindAddress}:${proxyPort}`);\n runner.setProxy(proxy);\n state.proxy = proxy;\n }\n state.proxyPort = proxyPort;\n\n emit('session-started', {\n sessionId: session.sessionId,\n releaseId: session.releaseId,\n branch: session.branch,\n proxyPort,\n proxyUrl: proxyPort\n ? `http://${bindAddress === '0.0.0.0' ? 'localhost' : bindAddress}:${proxyPort}/`\n : null,\n webInterfaceUrl: session.webInterfaceUrl,\n roles: appConfig.roles.map((r) => ({ id: r.id, name: r.name ?? r.id, description: r.description })),\n scenarios: appConfig.scenarios.map((s) => ({\n id: s.id,\n name: s.name ?? s.export,\n description: s.description,\n path: s.path,\n roles: s.roles,\n })),\n });\n\n // Subscribe to runner events\n state.unsubscribers.push(...subscribeDevEvents(emit, shutdown));\n\n // Watch table source files for changes — auto-sync without session restart\n setupTableWatchers(cwd, state);\n\n return true;\n } catch (err) {\n emit('config-error', {\n message: err instanceof Error ? err.message : 'Failed to start session',\n });\n return false;\n }\n}\n\nfunction setupTableWatchers(cwd: string, state: SessionState): void {\n if (!state.appConfig || state.appConfig.tables.length === 0) return;\n\n const cleanup = watchTableFiles(state.appConfig.tables, cwd, async () => {\n if (!state.runner || !state.appConfig?.appId) return;\n const session = state.runner.getSession();\n if (!session) return;\n\n emit('schema-sync-started');\n log.info('Table source file changed, syncing schema');\n\n try {\n const tableSources = readTableSources(state.appConfig, cwd);\n if (tableSources.length > 0) {\n const result = await syncSchema(state.appConfig.appId, session.sessionId, tableSources);\n session.databases = result.databases;\n emit('schema-sync-completed', {\n created: result.created,\n altered: result.altered,\n errors: result.errors,\n });\n log.info('Schema sync complete', { created: result.created, altered: result.altered });\n } else {\n log.warn('Table source file change detected but file(s) still missing', {\n expected: state.appConfig.tables.map((t) => t.path),\n });\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Schema sync failed';\n emit('command-error', { message });\n log.warn('Schema sync failed', { error: message });\n }\n });\n\n state.unsubscribers.push(cleanup);\n}\n\nasync function teardownSession(state: SessionState): Promise<void> {\n for (const unsub of state.unsubscribers) unsub();\n state.unsubscribers = [];\n\n state.proxy?.stop();\n state.proxy = null;\n state.proxyPort = null;\n\n if (state.runner) {\n await state.runner.stop().catch(() => {});\n state.runner = null;\n }\n\n closeRequestLog();\n closeBrowserLog();\n}\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\n/**\n * Start the dev tunnel in headless mode.\n */\nexport async function startHeadless(opts: HeadlessOptions = {}): Promise<void> {\n initLoggerHeadless(opts.logLevel ?? 'info');\n\n const cwd = opts.cwd ?? process.cwd();\n\n const apiKey = getApiKey();\n const userId = getUserId();\n log.info('Startup config', {\n configPath: getConfigPath(),\n environment: getEnvironment(),\n apiBaseUrl: getApiBaseUrl(),\n hasApiKey: !!apiKey,\n apiKeyPrefix: apiKey ? apiKey.slice(0, 8) + '...' : null,\n hasUserId: !!userId,\n userId: userId ?? null,\n cwd,\n });\n\n const state: SessionState = {\n runner: null,\n proxy: null,\n appConfig: null,\n proxyPort: null,\n unsubscribers: [],\n };\n\n let restarting = false;\n let cleanupConfigWatcher: (() => void) | undefined;\n\n let stopping = false;\n const shutdown = async () => {\n if (stopping) return;\n stopping = true;\n emit('session-stopping');\n cleanupConfigWatcher?.();\n await teardownSession(state);\n emit('session-stopped');\n };\n\n process.on('SIGTERM', () => { shutdown().then(() => process.exit(0)); });\n process.on('SIGINT', () => { shutdown().then(() => process.exit(0)); });\n\n // Initial session start — crash if it fails so the process manager can retry\n const ok = await startSession(cwd, opts, state, shutdown);\n if (!ok) {\n process.exit(1);\n }\n\n // Stdin command loop\n setupStdinCommands(state, cwd, emit);\n\n // Watch mindstudio.json for changes\n cleanupConfigWatcher = watchConfigFile(cwd, async () => {\n if (stopping || restarting) return;\n restarting = true;\n try {\n log.info('mindstudio.json changed, restarting dev session');\n emit('config-changed');\n await teardownSession(state);\n const ok = await startSession(cwd, opts, state, shutdown);\n if (ok && state.proxy) {\n state.proxy.dispatchBrowserCommand([{ command: 'reload' }]).catch(() => {});\n }\n } finally {\n restarting = false;\n }\n });\n\n // Keep the process alive — the poll loop runs in DevRunner\n await new Promise<void>(() => {});\n}\n"],"mappings":"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","names":["emit","emit","emit","emit","emit","emit","emit","emit","emit","emit","ok"]}