@xopcai/xopc 0.0.77 → 0.0.78

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.
Files changed (126) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{agents-DN3vr8pb.js → agents-Bh_9-1KB.js} +2 -2
  4. package/dist/gateway/static/root/assets/{agents-DN3vr8pb.js.map → agents-Bh_9-1KB.js.map} +1 -1
  5. package/dist/gateway/static/root/assets/{apps-page-BUn41aPi.js → apps-page-CB5anZpc.js} +2 -2
  6. package/dist/gateway/static/root/assets/{apps-page-BUn41aPi.js.map → apps-page-CB5anZpc.js.map} +1 -1
  7. package/dist/gateway/static/root/assets/{channels-settings-CYMmWDtP.js → channels-settings-Bt1sprhC.js} +2 -2
  8. package/dist/gateway/static/root/assets/{channels-settings-CYMmWDtP.js.map → channels-settings-Bt1sprhC.js.map} +1 -1
  9. package/dist/gateway/static/root/assets/{channels-status-swr-sJj4ueTp.js → channels-status-swr-Crgak3fg.js} +2 -2
  10. package/dist/gateway/static/root/assets/{channels-status-swr-sJj4ueTp.js.map → channels-status-swr-Crgak3fg.js.map} +1 -1
  11. package/dist/gateway/static/root/assets/{cron-api-CLxnaHdq.js → cron-api-CzJGvQQ7.js} +2 -2
  12. package/dist/gateway/static/root/assets/{cron-api-CLxnaHdq.js.map → cron-api-CzJGvQQ7.js.map} +1 -1
  13. package/dist/gateway/static/root/assets/{cron-page-BAQ8xSnJ.js → cron-page-BoNRJNVV.js} +2 -2
  14. package/dist/gateway/static/root/assets/{cron-page-BAQ8xSnJ.js.map → cron-page-BoNRJNVV.js.map} +1 -1
  15. package/dist/gateway/static/root/assets/{dist-BfJYxiK5.js → dist-a-eaOUvs.js} +2 -2
  16. package/dist/gateway/static/root/assets/{dist-BfJYxiK5.js.map → dist-a-eaOUvs.js.map} +1 -1
  17. package/dist/gateway/static/root/assets/{extension-debug-page-bgvVs-Sy.js → extension-debug-page-D-O1XjAa.js} +2 -2
  18. package/dist/gateway/static/root/assets/{extension-debug-page-bgvVs-Sy.js.map → extension-debug-page-D-O1XjAa.js.map} +1 -1
  19. package/dist/gateway/static/root/assets/{extension-page-SG4TVv-u.js → extension-page-B2VpqBTH.js} +2 -2
  20. package/dist/gateway/static/root/assets/{extension-page-SG4TVv-u.js.map → extension-page-B2VpqBTH.js.map} +1 -1
  21. package/dist/gateway/static/root/assets/{extension-settings-page-CJZRTsjF.js → extension-settings-page-CmBcQfeO.js} +2 -2
  22. package/dist/gateway/static/root/assets/{extension-settings-page-CJZRTsjF.js.map → extension-settings-page-CmBcQfeO.js.map} +1 -1
  23. package/dist/gateway/static/root/assets/{fetch-K_0JRCXU.js → fetch-EGO9T3MN.js} +3 -3
  24. package/dist/gateway/static/root/assets/{fetch-K_0JRCXU.js.map → fetch-EGO9T3MN.js.map} +1 -1
  25. package/dist/gateway/static/root/assets/{field-primitives-Z76hyBYS.js → field-primitives-Bh7G1y4D.js} +2 -2
  26. package/dist/gateway/static/root/assets/{field-primitives-Z76hyBYS.js.map → field-primitives-Bh7G1y4D.js.map} +1 -1
  27. package/dist/gateway/static/root/assets/{heartbeat-config-api-BqfDabSI.js → heartbeat-config-api-DxpIEZNs.js} +2 -2
  28. package/dist/gateway/static/root/assets/{heartbeat-config-api-BqfDabSI.js.map → heartbeat-config-api-DxpIEZNs.js.map} +1 -1
  29. package/dist/gateway/static/root/assets/{index-ChiUhJAs.js → index-Dxy9ZCtC.js} +5 -5
  30. package/dist/gateway/static/root/assets/{index-ChiUhJAs.js.map → index-Dxy9ZCtC.js.map} +1 -1
  31. package/dist/gateway/static/root/assets/{logs-page-DrIMhDE2.js → logs-page-Dw58E2GE.js} +2 -2
  32. package/dist/gateway/static/root/assets/{logs-page-DrIMhDE2.js.map → logs-page-Dw58E2GE.js.map} +1 -1
  33. package/dist/gateway/static/root/assets/{sessions-page-B-RGO3N0.js → sessions-page-CPkhCy57.js} +2 -2
  34. package/dist/gateway/static/root/assets/{sessions-page-B-RGO3N0.js.map → sessions-page-CPkhCy57.js.map} +1 -1
  35. package/dist/gateway/static/root/assets/{settings-form-section-Csvl1iL6.js → settings-form-section-DLZDVMEf.js} +2 -2
  36. package/dist/gateway/static/root/assets/{settings-form-section-Csvl1iL6.js.map → settings-form-section-DLZDVMEf.js.map} +1 -1
  37. package/dist/gateway/static/root/assets/settings-page-CVPCa0PE.js +4 -0
  38. package/dist/gateway/static/root/assets/settings-page-CVPCa0PE.js.map +1 -0
  39. package/dist/gateway/static/root/assets/{skills-page-dHwx2vh0.js → skills-page-DueZ9Qfg.js} +2 -2
  40. package/dist/gateway/static/root/assets/{skills-page-dHwx2vh0.js.map → skills-page-DueZ9Qfg.js.map} +1 -1
  41. package/dist/gateway/static/root/assets/{theme-store-Bl5A2Fd_.js → theme-store-CWPq9gW1.js} +2 -2
  42. package/dist/gateway/static/root/assets/{theme-store-Bl5A2Fd_.js.map → theme-store-CWPq9gW1.js.map} +1 -1
  43. package/dist/gateway/static/root/assets/{utils-COYrNFF7.js → utils-Cnix55r9.js} +2 -2
  44. package/dist/gateway/static/root/assets/{utils-COYrNFF7.js.map → utils-Cnix55r9.js.map} +1 -1
  45. package/dist/gateway/static/root/assets/{voice-api-key-field-5WZZaxH3.js → voice-api-key-field-BR3Ut06g.js} +2 -2
  46. package/dist/gateway/static/root/assets/{voice-api-key-field-5WZZaxH3.js.map → voice-api-key-field-BR3Ut06g.js.map} +1 -1
  47. package/dist/gateway/static/root/index.html +3 -3
  48. package/dist/package.js +1 -1
  49. package/dist/src/browser/providers/browser-ext-install.js +23 -4
  50. package/dist/src/browser/providers/browser-ext-install.js.map +1 -1
  51. package/dist/src/cli/commands/tunnel.js +4 -5
  52. package/dist/src/cli/commands/tunnel.js.map +1 -1
  53. package/dist/src/config/index.js +2 -2
  54. package/dist/src/config/rules.js +0 -5
  55. package/dist/src/config/rules.js.map +1 -1
  56. package/dist/src/config/schema.d.ts +0 -27
  57. package/dist/src/config/schema.js +4 -18
  58. package/dist/src/config/schema.js.map +1 -1
  59. package/dist/src/gateway/auth-rate-limit.d.ts +2 -0
  60. package/dist/src/gateway/auth-rate-limit.js +9 -3
  61. package/dist/src/gateway/auth-rate-limit.js.map +1 -1
  62. package/dist/src/gateway/hono/app.js +19 -13
  63. package/dist/src/gateway/hono/app.js.map +1 -1
  64. package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -1
  65. package/dist/src/gateway/hono/lib/config-payload.js +1 -2
  66. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  67. package/dist/src/gateway/hono/routes/tunnel.js +32 -30
  68. package/dist/src/gateway/hono/routes/tunnel.js.map +1 -1
  69. package/dist/src/gateway/host.d.ts +24 -0
  70. package/dist/src/gateway/host.js +33 -1
  71. package/dist/src/gateway/host.js.map +1 -1
  72. package/dist/src/gateway/index.d.ts +1 -1
  73. package/dist/src/gateway/index.js +2 -2
  74. package/dist/src/gateway/runtime-config.js +1 -8
  75. package/dist/src/gateway/runtime-config.js.map +1 -1
  76. package/dist/src/gateway/security/audit.js +4 -4
  77. package/dist/src/gateway/security/audit.js.map +1 -1
  78. package/dist/src/gateway/server.js +2 -3
  79. package/dist/src/gateway/server.js.map +1 -1
  80. package/dist/src/gateway/service/types.d.ts +2 -0
  81. package/dist/src/gateway/service.d.ts +2 -0
  82. package/dist/src/gateway/service.js +7 -2
  83. package/dist/src/gateway/service.js.map +1 -1
  84. package/dist/src/tunnel/frp-subdomain-host.d.ts +2 -0
  85. package/dist/src/tunnel/frp-subdomain-host.js +15 -0
  86. package/dist/src/tunnel/frp-subdomain-host.js.map +1 -0
  87. package/dist/src/tunnel/gateway-lifecycle.d.ts +0 -4
  88. package/dist/src/tunnel/gateway-lifecycle.js +9 -11
  89. package/dist/src/tunnel/gateway-lifecycle.js.map +1 -1
  90. package/dist/src/tunnel/index.d.ts +2 -4
  91. package/dist/src/tunnel/index.js +2 -4
  92. package/dist/src/tunnel/pair-url.js +7 -1
  93. package/dist/src/tunnel/pair-url.js.map +1 -1
  94. package/dist/src/tunnel/pairing.d.ts +13 -0
  95. package/dist/src/tunnel/pairing.js +48 -1
  96. package/dist/src/tunnel/pairing.js.map +1 -1
  97. package/dist/src/tunnel/tunnel-config.js +2 -16
  98. package/dist/src/tunnel/tunnel-config.js.map +1 -1
  99. package/dist/src/tunnel/tunnel-service.d.ts +1 -10
  100. package/dist/src/tunnel/tunnel-service.js +7 -60
  101. package/dist/src/tunnel/tunnel-service.js.map +1 -1
  102. package/dist/src/tunnel/tunnel-types.d.ts +3 -18
  103. package/dist/src/tunnel/well-known.d.ts +5 -0
  104. package/dist/src/tunnel/well-known.js +2 -1
  105. package/dist/src/tunnel/well-known.js.map +1 -1
  106. package/package.json +2 -2
  107. package/dist/gateway/static/root/assets/settings-page-nxAc0ta1.js +0 -4
  108. package/dist/gateway/static/root/assets/settings-page-nxAc0ta1.js.map +0 -1
  109. package/dist/src/tunnel/acme-cert-store.d.ts +0 -34
  110. package/dist/src/tunnel/acme-cert-store.js +0 -184
  111. package/dist/src/tunnel/acme-cert-store.js.map +0 -1
  112. package/dist/src/tunnel/acme-client.d.ts +0 -50
  113. package/dist/src/tunnel/acme-client.js +0 -473
  114. package/dist/src/tunnel/acme-client.js.map +0 -1
  115. package/dist/src/tunnel/acme-crypto.d.ts +0 -25
  116. package/dist/src/tunnel/acme-crypto.js +0 -58
  117. package/dist/src/tunnel/acme-crypto.js.map +0 -1
  118. package/dist/src/tunnel/acme-csr.d.ts +0 -5
  119. package/dist/src/tunnel/acme-csr.js +0 -48
  120. package/dist/src/tunnel/acme-csr.js.map +0 -1
  121. package/dist/src/tunnel/tls-server.d.ts +0 -14
  122. package/dist/src/tunnel/tls-server.js +0 -126
  123. package/dist/src/tunnel/tls-server.js.map +0 -1
  124. package/dist/src/tunnel/tunnel-e2e-config.d.ts +0 -11
  125. package/dist/src/tunnel/tunnel-e2e-config.js +0 -29
  126. package/dist/src/tunnel/tunnel-e2e-config.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"browser-ext-install.js","names":[],"sources":["../../../../src/browser/providers/browser-ext-install.ts"],"sourcesContent":["/**\n * Install bundled Chrome extension artifacts into {resolveBinDir()}/browser-ext/.\n */\n\nimport { cpSync, existsSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, symlinkSync } from 'node:fs';\nimport { readFile, readdir, rm } from 'node:fs/promises';\nimport { spawn } from 'node:child_process';\nimport { dirname, join, relative, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { PACKAGE_VERSION } from '../../package-version.js';\nimport { resolveBinDir } from '../../config/paths.js';\nimport { resolvePackageRoot } from '../../infra/update-check.js';\nimport { writeTextAtomic } from '../../infra/write-file-atomic.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { assertCacheDir } from '../cache-dir-policy.js';\n\nconst log = createLogger('BrowserExtInstall');\n\nconst META_FILENAME = '.meta.json';\nconst CURRENT_LINK = 'current';\nconst STAGING_MAX_AGE_MS = 60 * 60 * 1000;\n\nexport const BROWSER_EXT_REQUIRED_FILES = [\n 'manifest.json',\n 'popup.html',\n 'dist/background.js',\n 'dist/content.js',\n 'dist/popup.js',\n] as const;\n\nexport type BrowserExtBundledFrom = 'npm-dist' | 'git-dev' | 'electron-asar' | 'env-override';\n\nexport interface BrowserExtInstallMeta {\n xopcVersion: string;\n manifestVersion: string;\n source: 'bundled';\n bundledFrom: BrowserExtBundledFrom;\n installedAt: string;\n installPath: string;\n previousVersion?: string;\n}\n\nexport interface BrowserExtDoctor {\n bundledAvailable: boolean;\n installed: boolean;\n xopcVersion: string;\n installedVersion?: string;\n manifestVersion?: string;\n extensionDir?: string;\n cacheDir: string;\n needsRefresh: boolean;\n needsChromeReload?: boolean;\n bundledFrom?: BrowserExtBundledFrom;\n runtimeExtensionVersion?: string;\n}\n\nexport interface EnsureBrowserExtResult {\n extensionDir: string;\n xopcVersion: string;\n copied: boolean;\n previousVersion?: string;\n}\n\nfunction moduleDir(): string {\n return dirname(fileURLToPath(import.meta.url));\n}\n\n/** Validate a directory contains a loadable extension tree. */\nexport function validateBrowserExtLayout(dir: string): boolean {\n return BROWSER_EXT_REQUIRED_FILES.every((rel) => existsSync(join(dir, rel)));\n}\n\nfunction readManifestVersion(dir: string): string | undefined {\n try {\n const raw = readFileSync(join(dir, 'manifest.json'), 'utf8');\n const parsed = JSON.parse(raw) as { version?: unknown };\n return typeof parsed.version === 'string' ? parsed.version : undefined;\n } catch {\n return undefined;\n }\n}\n\nasync function readMeta(metaPath: string): Promise<BrowserExtInstallMeta | null> {\n try {\n const raw = await readFile(metaPath, 'utf8');\n const parsed = JSON.parse(raw) as BrowserExtInstallMeta;\n if (parsed && typeof parsed === 'object' && typeof parsed.xopcVersion === 'string') {\n return parsed;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction browserExtRoot(cacheDir: string): string {\n return join(cacheDir, 'browser-ext');\n}\n\nfunction resolveCurrentPath(cacheDir: string): string {\n return join(browserExtRoot(cacheDir), CURRENT_LINK);\n}\n\nfunction resolveMetaPath(cacheDir: string): string {\n return join(browserExtRoot(cacheDir), META_FILENAME);\n}\n\nfunction resolveCurrentRealPath(cacheDir: string): string | null {\n const current = resolveCurrentPath(cacheDir);\n if (!existsSync(current)) return null;\n try {\n const real = realpathSync(current);\n return validateBrowserExtLayout(real) ? real : null;\n } catch {\n return null;\n }\n}\n\nfunction walkAncestorsForGitDevBundled(start: string): string | null {\n let dir = start;\n for (let i = 0; i < 12; i++) {\n const candidate = join(dir, 'packages/browser-ext');\n if (validateBrowserExtLayout(candidate)) {\n return candidate;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\n/**\n * Resolve the bundled extension source directory (read-only).\n */\nexport async function resolveBundledBrowserExtDir(): Promise<{\n dir: string;\n bundledFrom: BrowserExtBundledFrom;\n} | null> {\n const envOverride = process.env.XOPC_BROWSER_EXT_BUNDLED_ROOT?.trim();\n if (envOverride && validateBrowserExtLayout(envOverride)) {\n return { dir: envOverride, bundledFrom: 'env-override' };\n }\n\n const fromModule = join(moduleDir(), '../../../browser-ext');\n if (validateBrowserExtLayout(fromModule)) {\n const root = await resolvePackageRoot();\n const bundledFrom: BrowserExtBundledFrom =\n process.versions.electron && root && root.includes('app.asar') ? 'electron-asar' : 'npm-dist';\n return { dir: fromModule, bundledFrom };\n }\n\n const gitDev = walkAncestorsForGitDevBundled(moduleDir());\n if (gitDev) {\n return { dir: gitDev, bundledFrom: 'git-dev' };\n }\n\n const root = await resolvePackageRoot();\n if (root) {\n const distBundled = join(root, 'dist/browser-ext');\n if (validateBrowserExtLayout(distBundled)) {\n const bundledFrom: BrowserExtBundledFrom =\n process.versions.electron && root.includes('app.asar') ? 'electron-asar' : 'npm-dist';\n return { dir: distBundled, bundledFrom };\n }\n }\n\n return null;\n}\n\nexport function computeNeedsRefresh(params: {\n force?: boolean;\n bundledManifestVersion: string;\n currentRealPath: string | null;\n meta: BrowserExtInstallMeta | null;\n}): boolean {\n if (params.force) return true;\n if (!params.currentRealPath || !validateBrowserExtLayout(params.currentRealPath)) return true;\n\n const currentManifest = readManifestVersion(params.currentRealPath);\n if (!currentManifest || currentManifest !== params.bundledManifestVersion) return true;\n\n if (!params.meta || params.meta.xopcVersion !== PACKAGE_VERSION) return true;\n\n return false;\n}\n\nasync function cleanupStaleStaging(root: string): Promise<void> {\n if (!existsSync(root)) return;\n let entries: string[];\n try {\n entries = await readdir(root);\n } catch {\n return;\n }\n const now = Date.now();\n for (const name of entries) {\n if (!name.startsWith('.staging-')) continue;\n const full = join(root, name);\n try {\n const st = statSync(full);\n if (now - st.mtimeMs > STAGING_MAX_AGE_MS) {\n await rm(full, { recursive: true, force: true });\n }\n } catch {\n /* */\n }\n }\n}\n\nfunction switchCurrentLink(root: string, versionDir: string): void {\n const currentPath = join(root, CURRENT_LINK);\n const versionName = relative(root, versionDir);\n const tmpLink = join(root, `.current-${process.pid}`);\n\n if (existsSync(tmpLink)) {\n rmSync(tmpLink, { recursive: true, force: true });\n }\n if (existsSync(currentPath)) {\n rmSync(currentPath, { recursive: true, force: true });\n }\n\n if (process.platform === 'win32') {\n const target = resolve(versionDir);\n cpSync(target, currentPath, { recursive: true });\n return;\n }\n\n try {\n symlinkSync(versionName, tmpLink, 'dir');\n renameSync(tmpLink, currentPath);\n } catch {\n cpSync(versionDir, currentPath, { recursive: true });\n }\n}\n\nasync function gcOldVersions(root: string, keepVersions: Set<string>): Promise<void> {\n if (!existsSync(root)) return;\n let entries: string[];\n try {\n entries = await readdir(root);\n } catch {\n return;\n }\n for (const name of entries) {\n if (name === CURRENT_LINK || name === META_FILENAME || name.startsWith('.')) continue;\n if (!keepVersions.has(name)) {\n try {\n await rm(join(root, name), { recursive: true, force: true });\n log.info({ version: name }, 'Removed old browser extension version directory');\n } catch (err) {\n log.warn({ err, version: name }, 'Failed to remove old browser extension version');\n }\n }\n }\n}\n\nfunction copyBundledTree(src: string, dest: string): void {\n mkdirSync(dest, { recursive: true });\n for (const name of ['manifest.json', 'popup.html']) {\n cpSync(join(src, name), join(dest, name));\n }\n cpSync(join(src, 'dist'), join(dest, 'dist'), { recursive: true });\n cpSync(join(src, 'icons'), join(dest, 'icons'), { recursive: true });\n if (!validateBrowserExtLayout(dest)) {\n throw new Error('Bundled browser extension copy failed validation');\n }\n}\n\nexport async function browserExtDoctor(opts?: {\n cacheDir?: string;\n runtimeExtensionVersion?: string;\n}): Promise<BrowserExtDoctor> {\n const resolvedCache = opts?.cacheDir?.trim()\n ? assertCacheDir(opts.cacheDir)\n : resolveBinDir();\n const cacheDir = resolvedCache || resolveBinDir();\n\n const bundled = await resolveBundledBrowserExtDir();\n const bundledManifestVersion = bundled ? readManifestVersion(bundled.dir) : undefined;\n const currentRealPath = resolveCurrentRealPath(cacheDir);\n const meta = await readMeta(resolveMetaPath(cacheDir));\n\n const needsRefresh = bundled\n ? computeNeedsRefresh({\n force: false,\n bundledManifestVersion: bundledManifestVersion ?? PACKAGE_VERSION,\n currentRealPath,\n meta,\n })\n : false;\n\n const installed = Boolean(currentRealPath) && !needsRefresh;\n const manifestVersion = currentRealPath ? readManifestVersion(currentRealPath) : undefined;\n\n let needsChromeReload: boolean | undefined;\n const runtimeVer = opts?.runtimeExtensionVersion?.trim();\n if (runtimeVer && manifestVersion && runtimeVer !== manifestVersion) {\n needsChromeReload = true;\n }\n\n return {\n bundledAvailable: Boolean(bundled),\n installed,\n xopcVersion: PACKAGE_VERSION,\n installedVersion: meta?.xopcVersion,\n manifestVersion,\n extensionDir: currentRealPath ?? undefined,\n cacheDir,\n needsRefresh,\n needsChromeReload,\n bundledFrom: bundled?.bundledFrom,\n runtimeExtensionVersion: runtimeVer,\n };\n}\n\nexport async function ensureBrowserExtensionArtifacts(opts?: {\n force?: boolean;\n cacheDir?: string;\n}): Promise<EnsureBrowserExtResult> {\n const resolvedCache = opts?.cacheDir?.trim()\n ? assertCacheDir(opts.cacheDir)\n : resolveBinDir();\n const cacheDir = resolvedCache || resolveBinDir();\n\n const bundled = await resolveBundledBrowserExtDir();\n if (!bundled) {\n throw new Error(\n 'Bundled browser extension not found. Reinstall xopc or run from a built checkout (pnpm run build).',\n );\n }\n\n const bundledManifestVersion = readManifestVersion(bundled.dir) ?? PACKAGE_VERSION;\n const root = browserExtRoot(cacheDir);\n mkdirSync(root, { recursive: true });\n await cleanupStaleStaging(root);\n\n const meta = await readMeta(resolveMetaPath(cacheDir));\n const currentRealPath = resolveCurrentRealPath(cacheDir);\n const needsRefresh = computeNeedsRefresh({\n force: opts?.force,\n bundledManifestVersion,\n currentRealPath,\n meta,\n });\n\n if (!needsRefresh && currentRealPath) {\n return {\n extensionDir: currentRealPath,\n xopcVersion: PACKAGE_VERSION,\n copied: false,\n previousVersion: meta?.previousVersion,\n };\n }\n\n const versionKey = PACKAGE_VERSION;\n const versionDir = join(root, versionKey);\n const stagingDir = join(root, `.staging-${versionKey}-${process.pid}`);\n\n if (existsSync(stagingDir)) {\n rmSync(stagingDir, { recursive: true, force: true });\n }\n copyBundledTree(bundled.dir, stagingDir);\n\n if (existsSync(versionDir)) {\n rmSync(versionDir, { recursive: true, force: true });\n }\n renameSync(stagingDir, versionDir);\n\n switchCurrentLink(root, versionDir);\n const extensionDir = resolveCurrentRealPath(cacheDir) ?? versionDir;\n\n const previousVersion =\n meta?.xopcVersion && meta.xopcVersion !== PACKAGE_VERSION ? meta.xopcVersion : meta?.previousVersion;\n\n const nextMeta: BrowserExtInstallMeta = {\n xopcVersion: PACKAGE_VERSION,\n manifestVersion: bundledManifestVersion,\n source: 'bundled',\n bundledFrom: bundled.bundledFrom,\n installedAt: new Date().toISOString(),\n installPath: versionDir,\n ...(previousVersion ? { previousVersion } : {}),\n };\n await writeTextAtomic(resolveMetaPath(cacheDir), JSON.stringify(nextMeta, null, 2));\n\n const keep = new Set<string>([versionKey]);\n if (previousVersion) keep.add(previousVersion);\n await gcOldVersions(root, keep);\n\n log.info(\n { extensionDir, xopcVersion: PACKAGE_VERSION, bundledFrom: bundled.bundledFrom },\n 'Browser extension artifacts installed',\n );\n\n return {\n extensionDir,\n xopcVersion: PACKAGE_VERSION,\n copied: true,\n previousVersion,\n };\n}\n\n/**\n * Gateway startup hook: ensure artifacts when extension backend is enabled or prior install exists.\n */\nexport async function ensureBrowserExtensionOnStartup(config: {\n agents?: { defaults?: { browser?: { backend?: string } } };\n}): Promise<void> {\n const backend = config.agents?.defaults?.browser?.backend;\n const cacheDir = resolveBinDir();\n const metaExists = existsSync(resolveMetaPath(cacheDir));\n if (backend !== 'extension' && !metaExists) {\n return;\n }\n await ensureBrowserExtensionArtifacts();\n}\n\nexport async function readInstalledExtensionDir(cacheDir?: string): Promise<string | null> {\n const dir = cacheDir?.trim() ? assertCacheDir(cacheDir) : resolveBinDir();\n return resolveCurrentRealPath(dir || resolveBinDir());\n}\n\nexport type BrowserExtensionOpenAction = 'chrome' | 'folder' | 'both';\n\nfunction spawnDetached(command: string, args: readonly string[]): void {\n spawn(command, [...args], { stdio: 'ignore', detached: true }).unref();\n}\n\nfunction openChromeExtensionsPage(): void {\n const chromeUrl = 'chrome://extensions';\n if (process.platform === 'darwin') {\n spawnDetached('open', ['-a', 'Google Chrome', chromeUrl]);\n return;\n }\n if (process.platform === 'win32') {\n spawnDetached('cmd', ['/c', 'start', 'chrome', chromeUrl]);\n return;\n }\n spawnDetached('xdg-open', [chromeUrl]);\n}\n\nfunction revealFolderInFileManager(dir: string): void {\n if (process.platform === 'darwin') {\n spawnDetached('open', [dir]);\n return;\n }\n if (process.platform === 'win32') {\n spawnDetached('explorer', [dir]);\n return;\n }\n spawnDetached('xdg-open', [dir]);\n}\n\n/**\n * Open chrome://extensions and/or reveal the installed extension folder on the gateway host.\n */\nexport async function openBrowserExtensionInstallUi(opts: {\n action: BrowserExtensionOpenAction;\n cacheDir?: string;\n}): Promise<{ extensionDir: string }> {\n const doctor = await browserExtDoctor({ cacheDir: opts.cacheDir });\n const dir = doctor.extensionDir;\n if (!dir) {\n throw new Error('Extension not installed. Run xopc browser extension install first.');\n }\n\n if (opts.action === 'chrome' || opts.action === 'both') {\n openChromeExtensionsPage();\n }\n if (opts.action === 'folder' || opts.action === 'both') {\n revealFolderInFileManager(dir);\n }\n\n return { extensionDir: dir };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"browser-ext-install.js","names":[],"sources":["../../../../src/browser/providers/browser-ext-install.ts"],"sourcesContent":["/**\n * Install bundled Chrome extension artifacts into {resolveBinDir()}/browser-ext/.\n */\n\nimport {\n cpSync,\n existsSync,\n mkdirSync,\n readFileSync,\n realpathSync,\n renameSync,\n rmSync,\n statSync,\n symlinkSync,\n writeFileSync,\n} from 'node:fs';\nimport { readFile, readdir, rm } from 'node:fs/promises';\nimport { spawn } from 'node:child_process';\nimport { dirname, join, relative, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { PACKAGE_VERSION } from '../../package-version.js';\nimport { resolveBinDir } from '../../config/paths.js';\nimport { resolvePackageRoot } from '../../infra/update-check.js';\nimport { writeTextAtomic } from '../../infra/write-file-atomic.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { assertCacheDir } from '../cache-dir-policy.js';\n\nconst log = createLogger('BrowserExtInstall');\n\nconst META_FILENAME = '.meta.json';\nconst CURRENT_LINK = 'current';\nconst STAGING_MAX_AGE_MS = 60 * 60 * 1000;\n\nexport const BROWSER_EXT_REQUIRED_FILES = [\n 'manifest.json',\n 'popup.html',\n 'dist/background.js',\n 'dist/content.js',\n 'dist/popup.js',\n] as const;\n\nexport type BrowserExtBundledFrom = 'npm-dist' | 'git-dev' | 'electron-asar' | 'env-override';\n\nexport interface BrowserExtInstallMeta {\n xopcVersion: string;\n manifestVersion: string;\n source: 'bundled';\n bundledFrom: BrowserExtBundledFrom;\n installedAt: string;\n installPath: string;\n previousVersion?: string;\n}\n\nexport interface BrowserExtDoctor {\n bundledAvailable: boolean;\n installed: boolean;\n xopcVersion: string;\n installedVersion?: string;\n manifestVersion?: string;\n extensionDir?: string;\n cacheDir: string;\n needsRefresh: boolean;\n needsChromeReload?: boolean;\n bundledFrom?: BrowserExtBundledFrom;\n runtimeExtensionVersion?: string;\n}\n\nexport interface EnsureBrowserExtResult {\n extensionDir: string;\n xopcVersion: string;\n copied: boolean;\n previousVersion?: string;\n}\n\nfunction moduleDir(): string {\n return dirname(fileURLToPath(import.meta.url));\n}\n\n/** Validate a directory contains a loadable extension tree. */\nexport function validateBrowserExtLayout(dir: string): boolean {\n return BROWSER_EXT_REQUIRED_FILES.every((rel) => existsSync(join(dir, rel)));\n}\n\nfunction readManifestVersion(dir: string): string | undefined {\n try {\n const raw = readFileSync(join(dir, 'manifest.json'), 'utf8');\n const parsed = JSON.parse(raw) as { version?: unknown };\n return typeof parsed.version === 'string' ? parsed.version : undefined;\n } catch {\n return undefined;\n }\n}\n\nasync function readMeta(metaPath: string): Promise<BrowserExtInstallMeta | null> {\n try {\n const raw = await readFile(metaPath, 'utf8');\n const parsed = JSON.parse(raw) as BrowserExtInstallMeta;\n if (parsed && typeof parsed === 'object' && typeof parsed.xopcVersion === 'string') {\n return parsed;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction browserExtRoot(cacheDir: string): string {\n return join(cacheDir, 'browser-ext');\n}\n\nfunction resolveCurrentPath(cacheDir: string): string {\n return join(browserExtRoot(cacheDir), CURRENT_LINK);\n}\n\nfunction resolveMetaPath(cacheDir: string): string {\n return join(browserExtRoot(cacheDir), META_FILENAME);\n}\n\nfunction resolveCurrentRealPath(cacheDir: string): string | null {\n const current = resolveCurrentPath(cacheDir);\n if (!existsSync(current)) return null;\n try {\n const real = realpathSync(current);\n return validateBrowserExtLayout(real) ? real : null;\n } catch {\n return null;\n }\n}\n\nfunction walkAncestorsForGitDevBundled(start: string): string | null {\n let dir = start;\n for (let i = 0; i < 12; i++) {\n const candidate = join(dir, 'packages/browser-ext');\n if (validateBrowserExtLayout(candidate)) {\n return candidate;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\n/**\n * Resolve the bundled extension source directory (read-only).\n */\nexport async function resolveBundledBrowserExtDir(): Promise<{\n dir: string;\n bundledFrom: BrowserExtBundledFrom;\n} | null> {\n const envOverride = process.env.XOPC_BROWSER_EXT_BUNDLED_ROOT?.trim();\n if (envOverride && validateBrowserExtLayout(envOverride)) {\n return { dir: envOverride, bundledFrom: 'env-override' };\n }\n\n const fromModule = join(moduleDir(), '../../../browser-ext');\n if (validateBrowserExtLayout(fromModule)) {\n const root = await resolvePackageRoot();\n const bundledFrom: BrowserExtBundledFrom =\n process.versions.electron && root && root.includes('app.asar') ? 'electron-asar' : 'npm-dist';\n return { dir: fromModule, bundledFrom };\n }\n\n const gitDev = walkAncestorsForGitDevBundled(moduleDir());\n if (gitDev) {\n return { dir: gitDev, bundledFrom: 'git-dev' };\n }\n\n const root = await resolvePackageRoot();\n if (root) {\n const distBundled = join(root, 'dist/browser-ext');\n if (validateBrowserExtLayout(distBundled)) {\n const bundledFrom: BrowserExtBundledFrom =\n process.versions.electron && root.includes('app.asar') ? 'electron-asar' : 'npm-dist';\n return { dir: distBundled, bundledFrom };\n }\n }\n\n return null;\n}\n\nexport function computeNeedsRefresh(params: {\n force?: boolean;\n bundledManifestVersion: string;\n currentRealPath: string | null;\n meta: BrowserExtInstallMeta | null;\n}): boolean {\n if (params.force) return true;\n if (!params.currentRealPath || !validateBrowserExtLayout(params.currentRealPath)) return true;\n\n const currentManifest = readManifestVersion(params.currentRealPath);\n if (!currentManifest || currentManifest !== params.bundledManifestVersion) return true;\n\n if (!params.meta || params.meta.xopcVersion !== PACKAGE_VERSION) return true;\n\n return false;\n}\n\nasync function cleanupStaleStaging(root: string): Promise<void> {\n if (!existsSync(root)) return;\n let entries: string[];\n try {\n entries = await readdir(root);\n } catch {\n return;\n }\n const now = Date.now();\n for (const name of entries) {\n if (!name.startsWith('.staging-')) continue;\n const full = join(root, name);\n try {\n const st = statSync(full);\n if (now - st.mtimeMs > STAGING_MAX_AGE_MS) {\n await rm(full, { recursive: true, force: true });\n }\n } catch {\n /* */\n }\n }\n}\n\nfunction switchCurrentLink(root: string, versionDir: string): void {\n const currentPath = join(root, CURRENT_LINK);\n const versionName = relative(root, versionDir);\n const tmpLink = join(root, `.current-${process.pid}`);\n\n if (existsSync(tmpLink)) {\n rmSync(tmpLink, { recursive: true, force: true });\n }\n if (existsSync(currentPath)) {\n rmSync(currentPath, { recursive: true, force: true });\n }\n\n if (process.platform === 'win32') {\n const target = resolve(versionDir);\n cpSync(target, currentPath, { recursive: true });\n return;\n }\n\n try {\n symlinkSync(versionName, tmpLink, 'dir');\n renameSync(tmpLink, currentPath);\n } catch {\n cpSync(versionDir, currentPath, { recursive: true });\n }\n}\n\nasync function gcOldVersions(root: string, keepVersions: Set<string>): Promise<void> {\n if (!existsSync(root)) return;\n let entries: string[];\n try {\n entries = await readdir(root);\n } catch {\n return;\n }\n for (const name of entries) {\n if (name === CURRENT_LINK || name === META_FILENAME || name.startsWith('.')) continue;\n if (!keepVersions.has(name)) {\n try {\n await rm(join(root, name), { recursive: true, force: true });\n log.info({ version: name }, 'Removed old browser extension version directory');\n } catch (err) {\n log.warn({ err, version: name }, 'Failed to remove old browser extension version');\n }\n }\n }\n}\n\n/** Copy one bundled file (read/write works when src is inside Electron app.asar). */\nfunction copyBundledFile(src: string, dest: string): void {\n mkdirSync(dirname(dest), { recursive: true });\n writeFileSync(dest, readFileSync(src));\n}\n\nconst BROWSER_EXT_DIST_FILES = ['background.js', 'content.js', 'popup.js'] as const;\nconst BROWSER_EXT_ICON_FILES = ['icon-16.png', 'icon-32.png', 'icon-48.png', 'icon-128.png'] as const;\n\nfunction copyBundledTree(src: string, dest: string): void {\n mkdirSync(dest, { recursive: true });\n for (const name of ['manifest.json', 'popup.html']) {\n copyBundledFile(join(src, name), join(dest, name));\n }\n for (const file of BROWSER_EXT_DIST_FILES) {\n copyBundledFile(join(src, 'dist', file), join(dest, 'dist', file));\n }\n for (const icon of BROWSER_EXT_ICON_FILES) {\n const iconSrc = join(src, 'icons', icon);\n if (existsSync(iconSrc)) {\n copyBundledFile(iconSrc, join(dest, 'icons', icon));\n }\n }\n if (!validateBrowserExtLayout(dest)) {\n throw new Error('Bundled browser extension copy failed validation');\n }\n}\n\nexport async function browserExtDoctor(opts?: {\n cacheDir?: string;\n runtimeExtensionVersion?: string;\n}): Promise<BrowserExtDoctor> {\n const resolvedCache = opts?.cacheDir?.trim()\n ? assertCacheDir(opts.cacheDir)\n : resolveBinDir();\n const cacheDir = resolvedCache || resolveBinDir();\n\n const bundled = await resolveBundledBrowserExtDir();\n const bundledManifestVersion = bundled ? readManifestVersion(bundled.dir) : undefined;\n const currentRealPath = resolveCurrentRealPath(cacheDir);\n const meta = await readMeta(resolveMetaPath(cacheDir));\n\n const needsRefresh = bundled\n ? computeNeedsRefresh({\n force: false,\n bundledManifestVersion: bundledManifestVersion ?? PACKAGE_VERSION,\n currentRealPath,\n meta,\n })\n : false;\n\n const installed = Boolean(currentRealPath) && !needsRefresh;\n const manifestVersion = currentRealPath ? readManifestVersion(currentRealPath) : undefined;\n\n let needsChromeReload: boolean | undefined;\n const runtimeVer = opts?.runtimeExtensionVersion?.trim();\n if (runtimeVer && manifestVersion && runtimeVer !== manifestVersion) {\n needsChromeReload = true;\n }\n\n return {\n bundledAvailable: Boolean(bundled),\n installed,\n xopcVersion: PACKAGE_VERSION,\n installedVersion: meta?.xopcVersion,\n manifestVersion,\n extensionDir: currentRealPath ?? undefined,\n cacheDir,\n needsRefresh,\n needsChromeReload,\n bundledFrom: bundled?.bundledFrom,\n runtimeExtensionVersion: runtimeVer,\n };\n}\n\nexport async function ensureBrowserExtensionArtifacts(opts?: {\n force?: boolean;\n cacheDir?: string;\n}): Promise<EnsureBrowserExtResult> {\n const resolvedCache = opts?.cacheDir?.trim()\n ? assertCacheDir(opts.cacheDir)\n : resolveBinDir();\n const cacheDir = resolvedCache || resolveBinDir();\n\n const bundled = await resolveBundledBrowserExtDir();\n if (!bundled) {\n throw new Error(\n 'Bundled browser extension not found. Reinstall xopc or run from a built checkout (pnpm run build).',\n );\n }\n\n const bundledManifestVersion = readManifestVersion(bundled.dir) ?? PACKAGE_VERSION;\n const root = browserExtRoot(cacheDir);\n mkdirSync(root, { recursive: true });\n await cleanupStaleStaging(root);\n\n const meta = await readMeta(resolveMetaPath(cacheDir));\n const currentRealPath = resolveCurrentRealPath(cacheDir);\n const needsRefresh = computeNeedsRefresh({\n force: opts?.force,\n bundledManifestVersion,\n currentRealPath,\n meta,\n });\n\n if (!needsRefresh && currentRealPath) {\n return {\n extensionDir: currentRealPath,\n xopcVersion: PACKAGE_VERSION,\n copied: false,\n previousVersion: meta?.previousVersion,\n };\n }\n\n const versionKey = PACKAGE_VERSION;\n const versionDir = join(root, versionKey);\n const stagingDir = join(root, `.staging-${versionKey}-${process.pid}`);\n\n if (existsSync(stagingDir)) {\n rmSync(stagingDir, { recursive: true, force: true });\n }\n copyBundledTree(bundled.dir, stagingDir);\n\n if (existsSync(versionDir)) {\n rmSync(versionDir, { recursive: true, force: true });\n }\n renameSync(stagingDir, versionDir);\n\n switchCurrentLink(root, versionDir);\n const extensionDir = resolveCurrentRealPath(cacheDir) ?? versionDir;\n\n const previousVersion =\n meta?.xopcVersion && meta.xopcVersion !== PACKAGE_VERSION ? meta.xopcVersion : meta?.previousVersion;\n\n const nextMeta: BrowserExtInstallMeta = {\n xopcVersion: PACKAGE_VERSION,\n manifestVersion: bundledManifestVersion,\n source: 'bundled',\n bundledFrom: bundled.bundledFrom,\n installedAt: new Date().toISOString(),\n installPath: versionDir,\n ...(previousVersion ? { previousVersion } : {}),\n };\n await writeTextAtomic(resolveMetaPath(cacheDir), JSON.stringify(nextMeta, null, 2));\n\n const keep = new Set<string>([versionKey]);\n if (previousVersion) keep.add(previousVersion);\n await gcOldVersions(root, keep);\n\n log.info(\n { extensionDir, xopcVersion: PACKAGE_VERSION, bundledFrom: bundled.bundledFrom },\n 'Browser extension artifacts installed',\n );\n\n return {\n extensionDir,\n xopcVersion: PACKAGE_VERSION,\n copied: true,\n previousVersion,\n };\n}\n\n/**\n * Gateway startup hook: ensure artifacts when extension backend is enabled or prior install exists.\n */\nexport async function ensureBrowserExtensionOnStartup(config: {\n agents?: { defaults?: { browser?: { backend?: string } } };\n}): Promise<void> {\n const backend = config.agents?.defaults?.browser?.backend;\n const cacheDir = resolveBinDir();\n const metaExists = existsSync(resolveMetaPath(cacheDir));\n if (backend !== 'extension' && !metaExists) {\n return;\n }\n await ensureBrowserExtensionArtifacts();\n}\n\nexport async function readInstalledExtensionDir(cacheDir?: string): Promise<string | null> {\n const dir = cacheDir?.trim() ? assertCacheDir(cacheDir) : resolveBinDir();\n return resolveCurrentRealPath(dir || resolveBinDir());\n}\n\nexport type BrowserExtensionOpenAction = 'chrome' | 'folder' | 'both';\n\nfunction spawnDetached(command: string, args: readonly string[]): void {\n spawn(command, [...args], { stdio: 'ignore', detached: true }).unref();\n}\n\nfunction openChromeExtensionsPage(): void {\n const chromeUrl = 'chrome://extensions';\n if (process.platform === 'darwin') {\n spawnDetached('open', ['-a', 'Google Chrome', chromeUrl]);\n return;\n }\n if (process.platform === 'win32') {\n spawnDetached('cmd', ['/c', 'start', 'chrome', chromeUrl]);\n return;\n }\n spawnDetached('xdg-open', [chromeUrl]);\n}\n\nfunction revealFolderInFileManager(dir: string): void {\n if (process.platform === 'darwin') {\n spawnDetached('open', [dir]);\n return;\n }\n if (process.platform === 'win32') {\n spawnDetached('explorer', [dir]);\n return;\n }\n spawnDetached('xdg-open', [dir]);\n}\n\n/**\n * Open chrome://extensions and/or reveal the installed extension folder on the gateway host.\n */\nexport async function openBrowserExtensionInstallUi(opts: {\n action: BrowserExtensionOpenAction;\n cacheDir?: string;\n}): Promise<{ extensionDir: string }> {\n const doctor = await browserExtDoctor({ cacheDir: opts.cacheDir });\n const dir = doctor.extensionDir;\n if (!dir) {\n throw new Error('Extension not installed. Run xopc browser extension install first.');\n }\n\n if (opts.action === 'chrome' || opts.action === 'both') {\n openChromeExtensionsPage();\n }\n if (opts.action === 'folder' || opts.action === 'both') {\n revealFolderInFileManager(dir);\n }\n\n return { extensionDir: dir };\n}\n"],"mappings":";;;;;;;;;;;;;;;;sBAqB2D;YACL;wBAEa;aACd;uBACG;AAExD,MAAM,MAAM,aAAa,oBAAoB;AAE7C,MAAM,gBAAgB;AACtB,MAAM,eAAe;AACrB,MAAM,qBAAqB,OAAU;AAErC,MAAa,6BAA6B;CACxC;CACA;CACA;CACA;CACA;CACD;AAmCD,SAAS,YAAoB;AAC3B,QAAO,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;;;AAIhD,SAAgB,yBAAyB,KAAsB;AAC7D,QAAO,2BAA2B,OAAO,QAAQ,WAAW,KAAK,KAAK,IAAI,CAAC,CAAC;;AAG9E,SAAS,oBAAoB,KAAiC;AAC5D,KAAI;EACF,MAAM,MAAM,aAAa,KAAK,KAAK,gBAAgB,EAAE,OAAO;EAC5D,MAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,SAAO,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU,KAAA;SACvD;AACN;;;AAIJ,eAAe,SAAS,UAAyD;AAC/E,KAAI;EACF,MAAM,MAAM,MAAM,SAAS,UAAU,OAAO;EAC5C,MAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,MAAI,UAAU,OAAO,WAAW,YAAY,OAAO,OAAO,gBAAgB,SACxE,QAAO;AAET,SAAO;SACD;AACN,SAAO;;;AAIX,SAAS,eAAe,UAA0B;AAChD,QAAO,KAAK,UAAU,cAAc;;AAGtC,SAAS,mBAAmB,UAA0B;AACpD,QAAO,KAAK,eAAe,SAAS,EAAE,aAAa;;AAGrD,SAAS,gBAAgB,UAA0B;AACjD,QAAO,KAAK,eAAe,SAAS,EAAE,cAAc;;AAGtD,SAAS,uBAAuB,UAAiC;CAC/D,MAAM,UAAU,mBAAmB,SAAS;AAC5C,KAAI,CAAC,WAAW,QAAQ,CAAE,QAAO;AACjC,KAAI;EACF,MAAM,OAAO,aAAa,QAAQ;AAClC,SAAO,yBAAyB,KAAK,GAAG,OAAO;SACzC;AACN,SAAO;;;AAIX,SAAS,8BAA8B,OAA8B;CACnE,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;EAC3B,MAAM,YAAY,KAAK,KAAK,uBAAuB;AACnD,MAAI,yBAAyB,UAAU,CACrC,QAAO;EAET,MAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,WAAW,IAAK;AACpB,QAAM;;AAER,QAAO;;;;;AAMT,eAAsB,8BAGZ;CACR,MAAM,cAAc,QAAQ,IAAI,+BAA+B,MAAM;AACrE,KAAI,eAAe,yBAAyB,YAAY,CACtD,QAAO;EAAE,KAAK;EAAa,aAAa;EAAgB;CAG1D,MAAM,aAAa,KAAK,WAAW,EAAE,uBAAuB;AAC5D,KAAI,yBAAyB,WAAW,EAAE;EACxC,MAAM,OAAO,MAAM,oBAAoB;AAGvC,SAAO;GAAE,KAAK;GAAY,aADxB,QAAQ,SAAS,YAAY,QAAQ,KAAK,SAAS,WAAW,GAAG,kBAAkB;GAC9C;;CAGzC,MAAM,SAAS,8BAA8B,WAAW,CAAC;AACzD,KAAI,OACF,QAAO;EAAE,KAAK;EAAQ,aAAa;EAAW;CAGhD,MAAM,OAAO,MAAM,oBAAoB;AACvC,KAAI,MAAM;EACR,MAAM,cAAc,KAAK,MAAM,mBAAmB;AAClD,MAAI,yBAAyB,YAAY,CAGvC,QAAO;GAAE,KAAK;GAAa,aADzB,QAAQ,SAAS,YAAY,KAAK,SAAS,WAAW,GAAG,kBAAkB;GACrC;;AAI5C,QAAO;;AAGT,SAAgB,oBAAoB,QAKxB;AACV,KAAI,OAAO,MAAO,QAAO;AACzB,KAAI,CAAC,OAAO,mBAAmB,CAAC,yBAAyB,OAAO,gBAAgB,CAAE,QAAO;CAEzF,MAAM,kBAAkB,oBAAoB,OAAO,gBAAgB;AACnE,KAAI,CAAC,mBAAmB,oBAAoB,OAAO,uBAAwB,QAAO;AAElF,KAAI,CAAC,OAAO,QAAQ,OAAO,KAAK,gBAAgB,gBAAiB,QAAO;AAExE,QAAO;;AAGT,eAAe,oBAAoB,MAA6B;AAC9D,KAAI,CAAC,WAAW,KAAK,CAAE;CACvB,IAAI;AACJ,KAAI;AACF,YAAU,MAAM,QAAQ,KAAK;SACvB;AACN;;CAEF,MAAM,MAAM,KAAK,KAAK;AACtB,MAAK,MAAM,QAAQ,SAAS;AAC1B,MAAI,CAAC,KAAK,WAAW,YAAY,CAAE;EACnC,MAAM,OAAO,KAAK,MAAM,KAAK;AAC7B,MAAI;AAEF,OAAI,MADO,SAAS,KACR,CAAC,UAAU,mBACrB,OAAM,GAAG,MAAM;IAAE,WAAW;IAAM,OAAO;IAAM,CAAC;UAE5C;;;AAMZ,SAAS,kBAAkB,MAAc,YAA0B;CACjE,MAAM,cAAc,KAAK,MAAM,aAAa;CAC5C,MAAM,cAAc,SAAS,MAAM,WAAW;CAC9C,MAAM,UAAU,KAAK,MAAM,YAAY,QAAQ,MAAM;AAErD,KAAI,WAAW,QAAQ,CACrB,QAAO,SAAS;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;AAEnD,KAAI,WAAW,YAAY,CACzB,QAAO,aAAa;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;AAGvD,KAAI,QAAQ,aAAa,SAAS;AAEhC,SADe,QAAQ,WACV,EAAE,aAAa,EAAE,WAAW,MAAM,CAAC;AAChD;;AAGF,KAAI;AACF,cAAY,aAAa,SAAS,MAAM;AACxC,aAAW,SAAS,YAAY;SAC1B;AACN,SAAO,YAAY,aAAa,EAAE,WAAW,MAAM,CAAC;;;AAIxD,eAAe,cAAc,MAAc,cAA0C;AACnF,KAAI,CAAC,WAAW,KAAK,CAAE;CACvB,IAAI;AACJ,KAAI;AACF,YAAU,MAAM,QAAQ,KAAK;SACvB;AACN;;AAEF,MAAK,MAAM,QAAQ,SAAS;AAC1B,MAAI,SAAS,gBAAgB,SAAS,iBAAiB,KAAK,WAAW,IAAI,CAAE;AAC7E,MAAI,CAAC,aAAa,IAAI,KAAK,CACzB,KAAI;AACF,SAAM,GAAG,KAAK,MAAM,KAAK,EAAE;IAAE,WAAW;IAAM,OAAO;IAAM,CAAC;AAC5D,OAAI,KAAK,EAAE,SAAS,MAAM,EAAE,kDAAkD;WACvE,KAAK;AACZ,OAAI,KAAK;IAAE;IAAK,SAAS;IAAM,EAAE,iDAAiD;;;;;AAO1F,SAAS,gBAAgB,KAAa,MAAoB;AACxD,WAAU,QAAQ,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AAC7C,eAAc,MAAM,aAAa,IAAI,CAAC;;AAGxC,MAAM,yBAAyB;CAAC;CAAiB;CAAc;CAAW;AAC1E,MAAM,yBAAyB;CAAC;CAAe;CAAe;CAAe;CAAe;AAE5F,SAAS,gBAAgB,KAAa,MAAoB;AACxD,WAAU,MAAM,EAAE,WAAW,MAAM,CAAC;AACpC,MAAK,MAAM,QAAQ,CAAC,iBAAiB,aAAa,CAChD,iBAAgB,KAAK,KAAK,KAAK,EAAE,KAAK,MAAM,KAAK,CAAC;AAEpD,MAAK,MAAM,QAAQ,uBACjB,iBAAgB,KAAK,KAAK,QAAQ,KAAK,EAAE,KAAK,MAAM,QAAQ,KAAK,CAAC;AAEpE,MAAK,MAAM,QAAQ,wBAAwB;EACzC,MAAM,UAAU,KAAK,KAAK,SAAS,KAAK;AACxC,MAAI,WAAW,QAAQ,CACrB,iBAAgB,SAAS,KAAK,MAAM,SAAS,KAAK,CAAC;;AAGvD,KAAI,CAAC,yBAAyB,KAAK,CACjC,OAAM,IAAI,MAAM,mDAAmD;;AAIvE,eAAsB,iBAAiB,MAGT;CAI5B,MAAM,YAHgB,MAAM,UAAU,MAAM,GACxC,eAAe,KAAK,SAAS,GAC7B,eAAe,KACe,eAAe;CAEjD,MAAM,UAAU,MAAM,6BAA6B;CACnD,MAAM,yBAAyB,UAAU,oBAAoB,QAAQ,IAAI,GAAG,KAAA;CAC5E,MAAM,kBAAkB,uBAAuB,SAAS;CACxD,MAAM,OAAO,MAAM,SAAS,gBAAgB,SAAS,CAAC;CAEtD,MAAM,eAAe,UACjB,oBAAoB;EAClB,OAAO;EACP,wBAAwB,0BAA0B;EAClD;EACA;EACD,CAAC,GACF;CAEJ,MAAM,YAAY,QAAQ,gBAAgB,IAAI,CAAC;CAC/C,MAAM,kBAAkB,kBAAkB,oBAAoB,gBAAgB,GAAG,KAAA;CAEjF,IAAI;CACJ,MAAM,aAAa,MAAM,yBAAyB,MAAM;AACxD,KAAI,cAAc,mBAAmB,eAAe,gBAClD,qBAAoB;AAGtB,QAAO;EACL,kBAAkB,QAAQ,QAAQ;EAClC;EACA,aAAa;EACb,kBAAkB,MAAM;EACxB;EACA,cAAc,mBAAmB,KAAA;EACjC;EACA;EACA;EACA,aAAa,SAAS;EACtB,yBAAyB;EAC1B;;AAGH,eAAsB,gCAAgC,MAGlB;CAIlC,MAAM,YAHgB,MAAM,UAAU,MAAM,GACxC,eAAe,KAAK,SAAS,GAC7B,eAAe,KACe,eAAe;CAEjD,MAAM,UAAU,MAAM,6BAA6B;AACnD,KAAI,CAAC,QACH,OAAM,IAAI,MACR,qGACD;CAGH,MAAM,yBAAyB,oBAAoB,QAAQ,IAAI,IAAI;CACnE,MAAM,OAAO,eAAe,SAAS;AACrC,WAAU,MAAM,EAAE,WAAW,MAAM,CAAC;AACpC,OAAM,oBAAoB,KAAK;CAE/B,MAAM,OAAO,MAAM,SAAS,gBAAgB,SAAS,CAAC;CACtD,MAAM,kBAAkB,uBAAuB,SAAS;AAQxD,KAAI,CAPiB,oBAAoB;EACvC,OAAO,MAAM;EACb;EACA;EACA;EACD,CAEgB,IAAI,gBACnB,QAAO;EACL,cAAc;EACd,aAAa;EACb,QAAQ;EACR,iBAAiB,MAAM;EACxB;CAGH,MAAM,aAAa;CACnB,MAAM,aAAa,KAAK,MAAM,WAAW;CACzC,MAAM,aAAa,KAAK,MAAM,YAAY,WAAW,GAAG,QAAQ,MAAM;AAEtE,KAAI,WAAW,WAAW,CACxB,QAAO,YAAY;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;AAEtD,iBAAgB,QAAQ,KAAK,WAAW;AAExC,KAAI,WAAW,WAAW,CACxB,QAAO,YAAY;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;AAEtD,YAAW,YAAY,WAAW;AAElC,mBAAkB,MAAM,WAAW;CACnC,MAAM,eAAe,uBAAuB,SAAS,IAAI;CAEzD,MAAM,kBACJ,MAAM,eAAe,KAAK,gBAAgB,kBAAkB,KAAK,cAAc,MAAM;CAEvF,MAAM,WAAkC;EACtC,aAAa;EACb,iBAAiB;EACjB,QAAQ;EACR,aAAa,QAAQ;EACrB,8BAAa,IAAI,MAAM,EAAC,aAAa;EACrC,aAAa;EACb,GAAI,kBAAkB,EAAE,iBAAiB,GAAG,EAAE;EAC/C;AACD,OAAM,gBAAgB,gBAAgB,SAAS,EAAE,KAAK,UAAU,UAAU,MAAM,EAAE,CAAC;CAEnF,MAAM,OAAO,IAAI,IAAY,CAAC,WAAW,CAAC;AAC1C,KAAI,gBAAiB,MAAK,IAAI,gBAAgB;AAC9C,OAAM,cAAc,MAAM,KAAK;AAE/B,KAAI,KACF;EAAE;EAAc,aAAa;EAAiB,aAAa,QAAQ;EAAa,EAChF,wCACD;AAED,QAAO;EACL;EACA,aAAa;EACb,QAAQ;EACR;EACD;;;;;AAMH,eAAsB,gCAAgC,QAEpC;CAChB,MAAM,UAAU,OAAO,QAAQ,UAAU,SAAS;CAElD,MAAM,aAAa,WAAW,gBADb,eACqC,CAAC,CAAC;AACxD,KAAI,YAAY,eAAe,CAAC,WAC9B;AAEF,OAAM,iCAAiC;;AAGzC,eAAsB,0BAA0B,UAA2C;AAEzF,QAAO,wBADK,UAAU,MAAM,GAAG,eAAe,SAAS,GAAG,eAAe,KACpC,eAAe,CAAC;;AAKvD,SAAS,cAAc,SAAiB,MAA+B;AACrE,OAAM,SAAS,CAAC,GAAG,KAAK,EAAE;EAAE,OAAO;EAAU,UAAU;EAAM,CAAC,CAAC,OAAO;;AAGxE,SAAS,2BAAiC;CACxC,MAAM,YAAY;AAClB,KAAI,QAAQ,aAAa,UAAU;AACjC,gBAAc,QAAQ;GAAC;GAAM;GAAiB;GAAU,CAAC;AACzD;;AAEF,KAAI,QAAQ,aAAa,SAAS;AAChC,gBAAc,OAAO;GAAC;GAAM;GAAS;GAAU;GAAU,CAAC;AAC1D;;AAEF,eAAc,YAAY,CAAC,UAAU,CAAC;;AAGxC,SAAS,0BAA0B,KAAmB;AACpD,KAAI,QAAQ,aAAa,UAAU;AACjC,gBAAc,QAAQ,CAAC,IAAI,CAAC;AAC5B;;AAEF,KAAI,QAAQ,aAAa,SAAS;AAChC,gBAAc,YAAY,CAAC,IAAI,CAAC;AAChC;;AAEF,eAAc,YAAY,CAAC,IAAI,CAAC;;;;;AAMlC,eAAsB,8BAA8B,MAGd;CAEpC,MAAM,OAAM,MADS,iBAAiB,EAAE,UAAU,KAAK,UAAU,CAAC,EAC/C;AACnB,KAAI,CAAC,IACH,OAAM,IAAI,MAAM,qEAAqE;AAGvF,KAAI,KAAK,WAAW,YAAY,KAAK,WAAW,OAC9C,2BAA0B;AAE5B,KAAI,KAAK,WAAW,YAAY,KAAK,WAAW,OAC9C,2BAA0B,IAAI;AAGhC,QAAO,EAAE,cAAc,KAAK"}
@@ -9,7 +9,7 @@ import { resolveTunnelBrokerUrl, resolveTunnelRegistrationSecret } from "../../t
9
9
  import { ensureFrpcBinary } from "../../tunnel/frpc-binary.js";
10
10
  import { loadTunnelState } from "../../tunnel/tunnel-state.js";
11
11
  import { getTunnelService } from "../../tunnel/tunnel-service.js";
12
- import { resolveFrpSubdomainHost, resolveTunnelE2eConfig } from "../../tunnel/tunnel-e2e-config.js";
12
+ import { resolveFrpSubdomainHost } from "../../tunnel/frp-subdomain-host.js";
13
13
  import { applyTunnelConsentToConfig, mergeTunnelConfigPatch, setTunnelEnabledInConfig } from "../../tunnel/tunnel-config.js";
14
14
  import "../../tunnel/index.js";
15
15
  import { Command } from "commander";
@@ -34,14 +34,13 @@ function resolveGatewayToken(config) {
34
34
  }
35
35
  function configureTunnel(ctx) {
36
36
  const config = loadConfig(ctx.configPath);
37
- const { port, host } = resolveGatewayPortHost(config);
37
+ const { host } = resolveGatewayPortHost(config);
38
38
  const brokerUrl = resolveTunnelBrokerUrl(config.tunnel?.brokerUrl);
39
39
  getTunnelService().configure({
40
40
  brokerUrl,
41
41
  registrationSecret: resolveTunnelRegistrationSecret(process.env, brokerUrl, config.tunnel?.registrationSecret),
42
42
  autoStart: config.tunnel?.autoStart ?? false,
43
43
  gatewayHost: host,
44
- e2e: resolveTunnelE2eConfig(config.tunnel, port),
45
44
  frpSubdomainHost: resolveFrpSubdomainHost(resolveTunnelBrokerUrl(config.tunnel?.brokerUrl))
46
45
  });
47
46
  }
@@ -213,10 +212,10 @@ function createTunnelCommand(ctx) {
213
212
  consentValid: hasValidTunnelConsent(config)
214
213
  }, null, 2));
215
214
  });
216
- cmd.command("qr").description("Print mobile connect QR payload (tunnel must be active)").action(() => {
215
+ cmd.command("qr").description("Print mobile connect QR payload (tunnel must be active)").action(async () => {
217
216
  configureTunnel(ctx);
218
217
  const { port, host } = resolveGatewayPortHost(loadConfig(ctx.configPath));
219
- const qr = getTunnelService().buildQr(port, host);
218
+ const qr = await getTunnelService().buildQr(port, host);
220
219
  if (!qr.qrPayload) {
221
220
  console.error("No active tunnel. Run: xopc tunnel start");
222
221
  process.exit(1);
@@ -1 +1 @@
1
- {"version":3,"file":"tunnel.js","names":[],"sources":["../../../../src/cli/commands/tunnel.ts"],"sourcesContent":["import { Command } from 'commander';\n\nimport { loadConfig, saveConfig } from '../../config/index.js';\nimport { createLogger } from '../../utils/logger.js';\nimport {\n assertTunnelMayStart,\n hasValidTunnelConsent,\n TUNNEL_RISK_SUMMARY_LINES,\n TunnelConsentError,\n} from '../../tunnel/consent.js';\nimport { resolveTunnelBrokerUrl, resolveTunnelRegistrationSecret } from '../../tunnel/env.js';\nimport { ensureFrpcBinary, getTunnelService } from '../../tunnel/index.js';\nimport { resolveFrpSubdomainHost, resolveTunnelE2eConfig } from '../../tunnel/tunnel-e2e-config.js';\nimport { applyTunnelConsentToConfig, mergeTunnelConfigPatch, setTunnelEnabledInConfig } from '../../tunnel/tunnel-config.js';\nimport { loadTunnelState } from '../../tunnel/tunnel-state.js';\nimport { formatExamples, register, type CLIContext } from '../registry.js';\n\nconst log = createLogger('TunnelCommand');\n\nfunction isInteractive(): boolean {\n return Boolean(process.stdin.isTTY && process.stdout.isTTY);\n}\n\nimport { resolveGatewayEffectiveHost } from '../../config/gateway-bind.js';\n\nfunction resolveGatewayPortHost(config: ReturnType<typeof loadConfig>): { port: number; host: string } {\n return {\n port: config.gateway.port ?? 18790,\n host: resolveGatewayEffectiveHost(config),\n };\n}\n\nfunction resolveGatewayToken(config: ReturnType<typeof loadConfig>): string {\n const fromEnv = process.env.XOPC_GATEWAY_TOKEN?.trim();\n if (fromEnv) return fromEnv;\n const token = config.gateway.auth?.token?.trim();\n if (token) return token;\n throw new Error('Gateway token not configured. Set gateway.auth.token or XOPC_GATEWAY_TOKEN.');\n}\n\nfunction configureTunnel(ctx: CLIContext): void {\n const config = loadConfig(ctx.configPath);\n const { port, host } = resolveGatewayPortHost(config);\n const brokerUrl = resolveTunnelBrokerUrl(config.tunnel?.brokerUrl);\n getTunnelService().configure({\n brokerUrl,\n registrationSecret: resolveTunnelRegistrationSecret(\n process.env,\n brokerUrl,\n config.tunnel?.registrationSecret,\n ),\n autoStart: config.tunnel?.autoStart ?? false,\n gatewayHost: host,\n e2e: resolveTunnelE2eConfig(config.tunnel, port),\n frpSubdomainHost: resolveFrpSubdomainHost(resolveTunnelBrokerUrl(config.tunnel?.brokerUrl)),\n });\n}\n\nasync function ensureCliTunnelConsent(\n ctx: CLIContext,\n opts: { acceptRisk?: boolean; yes?: boolean },\n): Promise<void> {\n const config = loadConfig(ctx.configPath);\n if (hasValidTunnelConsent(config)) return;\n\n if (opts.acceptRisk) {\n applyTunnelConsentToConfig(config);\n await saveConfig(config, ctx.configPath);\n return;\n }\n\n if (opts.yes) {\n throw new TunnelConsentError(\n 'Security consent not recorded. Run without --yes and confirm, or pass --accept-risk after reading the risks.',\n );\n }\n\n if (!isInteractive()) {\n throw new TunnelConsentError(\n 'Security consent required. Run interactively, use --accept-risk, or accept in gateway settings.',\n );\n }\n\n const { confirm } = await import('@inquirer/prompts');\n console.log('');\n console.log('⚠️ Remote access security notice');\n for (const line of TUNNEL_RISK_SUMMARY_LINES) {\n console.log(` • ${line}`);\n }\n console.log('');\n const accepted = await confirm({\n message: 'I understand these risks and want to enable remote access',\n default: false,\n });\n if (!accepted) {\n throw new TunnelConsentError('Remote access not started (consent declined).');\n }\n applyTunnelConsentToConfig(config);\n await saveConfig(config, ctx.configPath);\n}\n\nasync function readTunnelRegistrationSecretFromCli(opts: {\n secretArg?: string;\n stdin?: boolean;\n}): Promise<string> {\n const fromArg = opts.secretArg?.trim();\n if (fromArg) return fromArg;\n\n if (opts.stdin) {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n const value = Buffer.concat(chunks).toString('utf8').trim();\n if (!value) {\n throw new Error('Empty registration secret from stdin.');\n }\n return value;\n }\n\n if (isInteractive()) {\n const { password } = await import('@inquirer/prompts');\n const value = await password({\n message: 'Tunnel broker registration secret',\n mask: '*',\n });\n if (!value?.trim()) {\n throw new Error('Registration secret is required.');\n }\n return value.trim();\n }\n\n throw new Error(\n 'Provide the secret as an argument, pass --stdin, or run in an interactive terminal.',\n );\n}\n\nasync function saveTunnelRegistrationSecret(ctx: CLIContext, secret: string): Promise<void> {\n const config = loadConfig(ctx.configPath);\n const result = mergeTunnelConfigPatch(config, { registrationSecret: secret });\n if (result.ok === false) {\n throw new Error(result.message);\n }\n await saveConfig(config, ctx.configPath);\n}\n\nfunction createTunnelCommand(ctx: CLIContext): Command {\n const cmd = new Command('tunnel')\n .description('Manage FRP remote access tunnel')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc tunnel start',\n 'xopc tunnel start --accept-risk',\n 'xopc tunnel stop',\n 'xopc tunnel status',\n 'xopc tunnel qr',\n 'xopc tunnel consent',\n 'xopc tunnel prefetch',\n 'xopc tunnel secret set',\n 'xopc tunnel secret set --stdin',\n ]),\n );\n\n cmd\n .command('prefetch')\n .description('Download frpc to the state bin directory without starting the tunnel')\n .action(async () => {\n try {\n const path = await ensureFrpcBinary({\n onProgress: (progress) => {\n if (!process.stderr.isTTY) return;\n if (progress.phase === 'extracting') {\n process.stderr.write('\\rExtracting frpc… \\n');\n return;\n }\n if (progress.percent != null) {\n process.stderr.write(`\\rDownloading frpc… ${progress.percent}%`);\n } else if (progress.bytesReceived != null) {\n process.stderr.write(`\\rDownloading frpc… ${progress.bytesReceived} bytes`);\n }\n },\n });\n if (process.stderr.isTTY) process.stderr.write('\\n');\n console.log(`frpc ready at ${path}`);\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ err }, `frpc prefetch failed: ${em}`);\n process.exit(1);\n }\n });\n\n cmd\n .command('consent')\n .description('Record acceptance of the remote access security notice')\n .option('--accept-risk', 'Non-interactive: record consent without prompts')\n .action(async (opts: { acceptRisk?: boolean }) => {\n await ensureCliTunnelConsent(ctx, { acceptRisk: opts.acceptRisk, yes: false });\n console.log('Tunnel security consent recorded.');\n });\n\n const secretCmd = cmd.command('secret').description('Manage tunnel broker registration secret in config');\n\n secretCmd\n .command('set')\n .description('Save tunnel.registrationSecret to xopc.json (env XOPC_TUNNEL_REGISTRATION_SECRET overrides at runtime)')\n .argument('[secret]', 'Registration secret (prompts securely when omitted in a TTY)')\n .option('--stdin', 'Read secret from stdin (single line, trimmed)')\n .action(async (secretArg: string | undefined, opts: { stdin?: boolean }) => {\n try {\n const secret = await readTunnelRegistrationSecretFromCli({\n secretArg,\n stdin: opts.stdin,\n });\n await saveTunnelRegistrationSecret(ctx, secret);\n if (process.env.XOPC_TUNNEL_REGISTRATION_SECRET?.trim()) {\n console.log(\n 'Note: XOPC_TUNNEL_REGISTRATION_SECRET is set in the environment and overrides the saved config at runtime.',\n );\n }\n console.log(`Saved tunnel registration secret to ${ctx.configPath}.`);\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ err, phase: 'tunnel_secret_set' }, `Tunnel secret set failed: ${em}`);\n console.error(em);\n process.exit(1);\n }\n });\n\n cmd\n .command('start')\n .description('Register tunnel, start frpc, print connection info')\n .option('--yes', 'Skip interactive consent prompt when consent is already recorded')\n .option(\n '--accept-risk',\n 'Record security consent and start (non-interactive; read risks in docs/tunnel-security.md first)',\n )\n .action(async (opts: { yes?: boolean; acceptRisk?: boolean }) => {\n configureTunnel(ctx);\n await ensureCliTunnelConsent(ctx, { acceptRisk: opts.acceptRisk, yes: opts.yes });\n\n const config = loadConfig(ctx.configPath);\n assertTunnelMayStart(config);\n\n const { port, host } = resolveGatewayPortHost(config);\n const token = resolveGatewayToken(config);\n const tunnel = getTunnelService();\n\n console.log('🚀 Starting tunnel...');\n try {\n const qr = await tunnel.start(port, token);\n setTunnelEnabledInConfig(config, true);\n await saveConfig(config, ctx.configPath);\n\n const status = tunnel.getStatus();\n console.log('');\n console.log('✅ Tunnel is active');\n if (status.publicUrl) console.log(` URL: ${status.publicUrl}`);\n if (qr.lanUrl) console.log(` LAN: ${qr.lanUrl}`);\n console.log('');\n console.log('📱 Mobile connect QR payload:');\n console.log(qr.qrPayload);\n console.log('');\n console.log(\n `💡 Gateway must be running at ${host}:${port}. Keep frpc alive or use gateway / Web console.`,\n );\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ err }, `Tunnel start failed: ${em}`);\n process.exit(1);\n }\n });\n\n cmd\n .command('stop')\n .description('Stop frpc (keeps broker registration for stable subdomain)')\n .option(\n '--release',\n 'Deregister from broker and clear saved subdomain (next start gets a new public URL)',\n )\n .option('--yes', 'Skip confirmation when using --release')\n .action(async (opts: { release?: boolean; yes?: boolean }) => {\n configureTunnel(ctx);\n if (opts.release) {\n if (!opts.yes && isInteractive()) {\n const { confirm } = await import('@inquirer/prompts');\n const ok = await confirm({\n message:\n 'Release will revoke the public URL and subdomain on the broker. Continue?',\n default: false,\n });\n if (!ok) {\n console.log('Cancelled.');\n return;\n }\n }\n }\n const { released } = await getTunnelService().stop({ release: opts.release });\n const config = loadConfig(ctx.configPath);\n setTunnelEnabledInConfig(config, false);\n await saveConfig(config, ctx.configPath);\n console.log(released ? 'Tunnel stopped and broker registration released.' : 'Tunnel stopped.');\n });\n\n cmd\n .command('status')\n .description('Show tunnel status')\n .action(() => {\n configureTunnel(ctx);\n const config = loadConfig(ctx.configPath);\n const status = getTunnelService().getStatus();\n const persisted = loadTunnelState();\n console.log(\n JSON.stringify(\n {\n ...status,\n persistedSubdomain: persisted?.subdomain ?? null,\n consentValid: hasValidTunnelConsent(config),\n },\n null,\n 2,\n ),\n );\n });\n\n cmd\n .command('qr')\n .description('Print mobile connect QR payload (tunnel must be active)')\n .action(() => {\n configureTunnel(ctx);\n const config = loadConfig(ctx.configPath);\n const { port, host } = resolveGatewayPortHost(config);\n const qr = getTunnelService().buildQr(port, host);\n if (!qr.qrPayload) {\n console.error('No active tunnel. Run: xopc tunnel start');\n process.exit(1);\n }\n console.log(qr.qrPayload);\n });\n\n cmd\n .command('broker')\n .description('Self-hosted FRP broker helpers')\n .addCommand(\n new Command('init')\n .description('Print a starter frps + broker configuration template')\n .option('--domain <domain>', 'Public domain for frps', 'tunnel.example.com')\n .action((opts) => {\n const domain = String(opts.domain ?? 'tunnel.example.com');\n console.log(`# Self-hosted FRP broker sketch for ${domain}`);\n console.log('# 1. Run frps with vhost HTTP/HTTPS and a registration token');\n console.log(`# 2. Point tunnel.brokerUrl to https://${domain}/api`);\n console.log(`# 3. Set XOPC_TUNNEL_REGISTRATION_SECRET in the gateway environment`);\n console.log('');\n console.log(JSON.stringify({\n frps: {\n bindPort: 7000,\n vhostHTTPPort: 8080,\n subdomainHost: domain,\n },\n broker: {\n apiUrl: `https://${domain}/api`,\n registrationSecretEnv: 'XOPC_TUNNEL_REGISTRATION_SECRET',\n },\n }, null, 2));\n }),\n );\n\n return cmd;\n}\n\nregister({\n id: 'tunnel',\n name: 'tunnel',\n description: 'FRP remote access tunnel',\n factory: createTunnelCommand,\n metadata: {\n category: 'runtime',\n examples: ['xopc tunnel start', 'xopc tunnel status', 'xopc tunnel secret set'],\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"tunnel.js","names":[],"sources":["../../../../src/cli/commands/tunnel.ts"],"sourcesContent":["import { Command } from 'commander';\n\nimport { loadConfig, saveConfig } from '../../config/index.js';\nimport { createLogger } from '../../utils/logger.js';\nimport {\n assertTunnelMayStart,\n hasValidTunnelConsent,\n TUNNEL_RISK_SUMMARY_LINES,\n TunnelConsentError,\n} from '../../tunnel/consent.js';\nimport { resolveTunnelBrokerUrl, resolveTunnelRegistrationSecret } from '../../tunnel/env.js';\nimport { ensureFrpcBinary, getTunnelService } from '../../tunnel/index.js';\nimport { resolveFrpSubdomainHost } from '../../tunnel/frp-subdomain-host.js';\nimport { applyTunnelConsentToConfig, mergeTunnelConfigPatch, setTunnelEnabledInConfig } from '../../tunnel/tunnel-config.js';\nimport { loadTunnelState } from '../../tunnel/tunnel-state.js';\nimport { formatExamples, register, type CLIContext } from '../registry.js';\n\nconst log = createLogger('TunnelCommand');\n\nfunction isInteractive(): boolean {\n return Boolean(process.stdin.isTTY && process.stdout.isTTY);\n}\n\nimport { resolveGatewayEffectiveHost } from '../../config/gateway-bind.js';\n\nfunction resolveGatewayPortHost(config: ReturnType<typeof loadConfig>): { port: number; host: string } {\n return {\n port: config.gateway.port ?? 18790,\n host: resolveGatewayEffectiveHost(config),\n };\n}\n\nfunction resolveGatewayToken(config: ReturnType<typeof loadConfig>): string {\n const fromEnv = process.env.XOPC_GATEWAY_TOKEN?.trim();\n if (fromEnv) return fromEnv;\n const token = config.gateway.auth?.token?.trim();\n if (token) return token;\n throw new Error('Gateway token not configured. Set gateway.auth.token or XOPC_GATEWAY_TOKEN.');\n}\n\nfunction configureTunnel(ctx: CLIContext): void {\n const config = loadConfig(ctx.configPath);\n const { host } = resolveGatewayPortHost(config);\n const brokerUrl = resolveTunnelBrokerUrl(config.tunnel?.brokerUrl);\n getTunnelService().configure({\n brokerUrl,\n registrationSecret: resolveTunnelRegistrationSecret(\n process.env,\n brokerUrl,\n config.tunnel?.registrationSecret,\n ),\n autoStart: config.tunnel?.autoStart ?? false,\n gatewayHost: host,\n frpSubdomainHost: resolveFrpSubdomainHost(resolveTunnelBrokerUrl(config.tunnel?.brokerUrl)),\n });\n}\n\nasync function ensureCliTunnelConsent(\n ctx: CLIContext,\n opts: { acceptRisk?: boolean; yes?: boolean },\n): Promise<void> {\n const config = loadConfig(ctx.configPath);\n if (hasValidTunnelConsent(config)) return;\n\n if (opts.acceptRisk) {\n applyTunnelConsentToConfig(config);\n await saveConfig(config, ctx.configPath);\n return;\n }\n\n if (opts.yes) {\n throw new TunnelConsentError(\n 'Security consent not recorded. Run without --yes and confirm, or pass --accept-risk after reading the risks.',\n );\n }\n\n if (!isInteractive()) {\n throw new TunnelConsentError(\n 'Security consent required. Run interactively, use --accept-risk, or accept in gateway settings.',\n );\n }\n\n const { confirm } = await import('@inquirer/prompts');\n console.log('');\n console.log('⚠️ Remote access security notice');\n for (const line of TUNNEL_RISK_SUMMARY_LINES) {\n console.log(` • ${line}`);\n }\n console.log('');\n const accepted = await confirm({\n message: 'I understand these risks and want to enable remote access',\n default: false,\n });\n if (!accepted) {\n throw new TunnelConsentError('Remote access not started (consent declined).');\n }\n applyTunnelConsentToConfig(config);\n await saveConfig(config, ctx.configPath);\n}\n\nasync function readTunnelRegistrationSecretFromCli(opts: {\n secretArg?: string;\n stdin?: boolean;\n}): Promise<string> {\n const fromArg = opts.secretArg?.trim();\n if (fromArg) return fromArg;\n\n if (opts.stdin) {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n const value = Buffer.concat(chunks).toString('utf8').trim();\n if (!value) {\n throw new Error('Empty registration secret from stdin.');\n }\n return value;\n }\n\n if (isInteractive()) {\n const { password } = await import('@inquirer/prompts');\n const value = await password({\n message: 'Tunnel broker registration secret',\n mask: '*',\n });\n if (!value?.trim()) {\n throw new Error('Registration secret is required.');\n }\n return value.trim();\n }\n\n throw new Error(\n 'Provide the secret as an argument, pass --stdin, or run in an interactive terminal.',\n );\n}\n\nasync function saveTunnelRegistrationSecret(ctx: CLIContext, secret: string): Promise<void> {\n const config = loadConfig(ctx.configPath);\n const result = mergeTunnelConfigPatch(config, { registrationSecret: secret });\n if (result.ok === false) {\n throw new Error(result.message);\n }\n await saveConfig(config, ctx.configPath);\n}\n\nfunction createTunnelCommand(ctx: CLIContext): Command {\n const cmd = new Command('tunnel')\n .description('Manage FRP remote access tunnel')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc tunnel start',\n 'xopc tunnel start --accept-risk',\n 'xopc tunnel stop',\n 'xopc tunnel status',\n 'xopc tunnel qr',\n 'xopc tunnel consent',\n 'xopc tunnel prefetch',\n 'xopc tunnel secret set',\n 'xopc tunnel secret set --stdin',\n ]),\n );\n\n cmd\n .command('prefetch')\n .description('Download frpc to the state bin directory without starting the tunnel')\n .action(async () => {\n try {\n const path = await ensureFrpcBinary({\n onProgress: (progress) => {\n if (!process.stderr.isTTY) return;\n if (progress.phase === 'extracting') {\n process.stderr.write('\\rExtracting frpc… \\n');\n return;\n }\n if (progress.percent != null) {\n process.stderr.write(`\\rDownloading frpc… ${progress.percent}%`);\n } else if (progress.bytesReceived != null) {\n process.stderr.write(`\\rDownloading frpc… ${progress.bytesReceived} bytes`);\n }\n },\n });\n if (process.stderr.isTTY) process.stderr.write('\\n');\n console.log(`frpc ready at ${path}`);\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ err }, `frpc prefetch failed: ${em}`);\n process.exit(1);\n }\n });\n\n cmd\n .command('consent')\n .description('Record acceptance of the remote access security notice')\n .option('--accept-risk', 'Non-interactive: record consent without prompts')\n .action(async (opts: { acceptRisk?: boolean }) => {\n await ensureCliTunnelConsent(ctx, { acceptRisk: opts.acceptRisk, yes: false });\n console.log('Tunnel security consent recorded.');\n });\n\n const secretCmd = cmd.command('secret').description('Manage tunnel broker registration secret in config');\n\n secretCmd\n .command('set')\n .description('Save tunnel.registrationSecret to xopc.json (env XOPC_TUNNEL_REGISTRATION_SECRET overrides at runtime)')\n .argument('[secret]', 'Registration secret (prompts securely when omitted in a TTY)')\n .option('--stdin', 'Read secret from stdin (single line, trimmed)')\n .action(async (secretArg: string | undefined, opts: { stdin?: boolean }) => {\n try {\n const secret = await readTunnelRegistrationSecretFromCli({\n secretArg,\n stdin: opts.stdin,\n });\n await saveTunnelRegistrationSecret(ctx, secret);\n if (process.env.XOPC_TUNNEL_REGISTRATION_SECRET?.trim()) {\n console.log(\n 'Note: XOPC_TUNNEL_REGISTRATION_SECRET is set in the environment and overrides the saved config at runtime.',\n );\n }\n console.log(`Saved tunnel registration secret to ${ctx.configPath}.`);\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ err, phase: 'tunnel_secret_set' }, `Tunnel secret set failed: ${em}`);\n console.error(em);\n process.exit(1);\n }\n });\n\n cmd\n .command('start')\n .description('Register tunnel, start frpc, print connection info')\n .option('--yes', 'Skip interactive consent prompt when consent is already recorded')\n .option(\n '--accept-risk',\n 'Record security consent and start (non-interactive; read risks in docs/tunnel-security.md first)',\n )\n .action(async (opts: { yes?: boolean; acceptRisk?: boolean }) => {\n configureTunnel(ctx);\n await ensureCliTunnelConsent(ctx, { acceptRisk: opts.acceptRisk, yes: opts.yes });\n\n const config = loadConfig(ctx.configPath);\n assertTunnelMayStart(config);\n\n const { port, host } = resolveGatewayPortHost(config);\n const token = resolveGatewayToken(config);\n const tunnel = getTunnelService();\n\n console.log('🚀 Starting tunnel...');\n try {\n const qr = await tunnel.start(port, token);\n setTunnelEnabledInConfig(config, true);\n await saveConfig(config, ctx.configPath);\n\n const status = tunnel.getStatus();\n console.log('');\n console.log('✅ Tunnel is active');\n if (status.publicUrl) console.log(` URL: ${status.publicUrl}`);\n if (qr.lanUrl) console.log(` LAN: ${qr.lanUrl}`);\n console.log('');\n console.log('📱 Mobile connect QR payload:');\n console.log(qr.qrPayload);\n console.log('');\n console.log(\n `💡 Gateway must be running at ${host}:${port}. Keep frpc alive or use gateway / Web console.`,\n );\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ err }, `Tunnel start failed: ${em}`);\n process.exit(1);\n }\n });\n\n cmd\n .command('stop')\n .description('Stop frpc (keeps broker registration for stable subdomain)')\n .option(\n '--release',\n 'Deregister from broker and clear saved subdomain (next start gets a new public URL)',\n )\n .option('--yes', 'Skip confirmation when using --release')\n .action(async (opts: { release?: boolean; yes?: boolean }) => {\n configureTunnel(ctx);\n if (opts.release) {\n if (!opts.yes && isInteractive()) {\n const { confirm } = await import('@inquirer/prompts');\n const ok = await confirm({\n message:\n 'Release will revoke the public URL and subdomain on the broker. Continue?',\n default: false,\n });\n if (!ok) {\n console.log('Cancelled.');\n return;\n }\n }\n }\n const { released } = await getTunnelService().stop({ release: opts.release });\n const config = loadConfig(ctx.configPath);\n setTunnelEnabledInConfig(config, false);\n await saveConfig(config, ctx.configPath);\n console.log(released ? 'Tunnel stopped and broker registration released.' : 'Tunnel stopped.');\n });\n\n cmd\n .command('status')\n .description('Show tunnel status')\n .action(() => {\n configureTunnel(ctx);\n const config = loadConfig(ctx.configPath);\n const status = getTunnelService().getStatus();\n const persisted = loadTunnelState();\n console.log(\n JSON.stringify(\n {\n ...status,\n persistedSubdomain: persisted?.subdomain ?? null,\n consentValid: hasValidTunnelConsent(config),\n },\n null,\n 2,\n ),\n );\n });\n\n cmd\n .command('qr')\n .description('Print mobile connect QR payload (tunnel must be active)')\n .action(async () => {\n configureTunnel(ctx);\n const config = loadConfig(ctx.configPath);\n const { port, host } = resolveGatewayPortHost(config);\n const qr = await getTunnelService().buildQr(port, host);\n if (!qr.qrPayload) {\n console.error('No active tunnel. Run: xopc tunnel start');\n process.exit(1);\n }\n console.log(qr.qrPayload);\n });\n\n cmd\n .command('broker')\n .description('Self-hosted FRP broker helpers')\n .addCommand(\n new Command('init')\n .description('Print a starter frps + broker configuration template')\n .option('--domain <domain>', 'Public domain for frps', 'tunnel.example.com')\n .action((opts) => {\n const domain = String(opts.domain ?? 'tunnel.example.com');\n console.log(`# Self-hosted FRP broker sketch for ${domain}`);\n console.log('# 1. Run frps with vhost HTTP/HTTPS and a registration token');\n console.log(`# 2. Point tunnel.brokerUrl to https://${domain}/api`);\n console.log(`# 3. Set XOPC_TUNNEL_REGISTRATION_SECRET in the gateway environment`);\n console.log('');\n console.log(JSON.stringify({\n frps: {\n bindPort: 7000,\n vhostHTTPPort: 8080,\n subdomainHost: domain,\n },\n broker: {\n apiUrl: `https://${domain}/api`,\n registrationSecretEnv: 'XOPC_TUNNEL_REGISTRATION_SECRET',\n },\n }, null, 2));\n }),\n );\n\n return cmd;\n}\n\nregister({\n id: 'tunnel',\n name: 'tunnel',\n description: 'FRP remote access tunnel',\n factory: createTunnelCommand,\n metadata: {\n category: 'runtime',\n examples: ['xopc tunnel start', 'xopc tunnel status', 'xopc tunnel secret set'],\n },\n});\n"],"mappings":"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"}
@@ -4,7 +4,7 @@ import { resolveDefaultAgentWorkspaceDir } from "./workspace-defaults.js";
4
4
  import { resolveAgentDir as resolveAgentDir$1, resolveAgentHomeDir as resolveAgentHomeDir$1, resolveAgentWorkspaceDir, resolveSessionsDir as resolveSessionsDir$1 } from "../agent/agent-scope.js";
5
5
  import { TelegramAccountConfigSchema, TelegramConfigSchema, TelegramGroupConfigSchema, TelegramTopicConfigSchema } from "../../extensions/telegram/src/config-schema.js";
6
6
  import { WeixinAccountConfigSchema, WeixinConfigSchema } from "../../extensions/weixin/src/config-schema.js";
7
- import { AgentConfigSchema, AgentDefaultsSchema, AgentImageGenerationModelSchema, AgentModelRefSchema, AgentsConfigSchema, BindingMatchSchema, BindingRuleSchema, BindingsConfigSchema, ChannelsConfigSchema, ConfigSchema, CronConfigSchema, ExtensionSecurityConfigSchema, ExtensionSlotsConfigSchema, ExtensionsConfigSchema, GatewayAuthRateLimitSchema, GatewayAuthSchema, GatewayBindModeSchema, GatewayChannelConnectDeferModeSchema, GatewayConfigSchema, GatewayModeSchema, GatewayRemoteSchema, GatewaySecuritySchema, GatewayTailscaleConsentSchema, GatewayTailscaleSchema, GatewayTlsSchema, GatewayTrustedProxySchema, GoalsConfigSchema, HeartbeatConfigSchema, McpConfigSchema, McpServerSchema, MediaUnderstandingCapabilitiesSchema, MediaUnderstandingModelSchema, MessagesConfigSchema, ModelsDevConfigSchema, ProviderAuthConfigSchema, ProviderAzureConfigSchema, ProviderRequestOverridesSchema, ProvidersConfigSchema, STTConfigSchema, STTFallbackConfigSchema, STTProviderConfigSchema, SearchProviderEntrySchema, SessionConfigSchema, SessionDmScopeSchema, SessionStorageConfigSchema, TTSConfigSchema, TTSEdgeConfigSchema, TTSFallbackConfigSchema, TTSModelOverridesConfigSchema, TTSProviderConfigSchema, TTSSummarizationConfigSchema, ToolsConfigSchema, ToolsMediaAudioConfigSchema, ToolsMediaConfigSchema, TunnelConfigSchema, TunnelConsentSchema, TunnelE2eSchema, TunnelExposureModeSchema, UpdateAutoConfigSchema, UpdateConfigSchema, WebSearchConfigSchema, WebToolsConfigSchema, WebsiteBlocklistSchema, WorkspaceConfigSchema, WorkspaceImportConfigSchema, getAgentDefaultModelRef, getWorkspacePath, init_schema, parseModelRef } from "./schema.js";
7
+ import { AgentConfigSchema, AgentDefaultsSchema, AgentImageGenerationModelSchema, AgentModelRefSchema, AgentsConfigSchema, BindingMatchSchema, BindingRuleSchema, BindingsConfigSchema, ChannelsConfigSchema, ConfigSchema, CronConfigSchema, ExtensionSecurityConfigSchema, ExtensionSlotsConfigSchema, ExtensionsConfigSchema, GatewayAuthRateLimitSchema, GatewayAuthSchema, GatewayBindModeSchema, GatewayChannelConnectDeferModeSchema, GatewayConfigSchema, GatewayModeSchema, GatewayRemoteSchema, GatewaySecuritySchema, GatewayTailscaleConsentSchema, GatewayTailscaleSchema, GatewayTlsSchema, GatewayTrustedProxySchema, GoalsConfigSchema, HeartbeatConfigSchema, McpConfigSchema, McpServerSchema, MediaUnderstandingCapabilitiesSchema, MediaUnderstandingModelSchema, MessagesConfigSchema, ModelsDevConfigSchema, ProviderAuthConfigSchema, ProviderAzureConfigSchema, ProviderRequestOverridesSchema, ProvidersConfigSchema, STTConfigSchema, STTFallbackConfigSchema, STTProviderConfigSchema, SearchProviderEntrySchema, SessionConfigSchema, SessionDmScopeSchema, SessionStorageConfigSchema, TTSConfigSchema, TTSEdgeConfigSchema, TTSFallbackConfigSchema, TTSModelOverridesConfigSchema, TTSProviderConfigSchema, TTSSummarizationConfigSchema, ToolsConfigSchema, ToolsMediaAudioConfigSchema, ToolsMediaConfigSchema, TunnelConfigSchema, TunnelConsentSchema, UpdateAutoConfigSchema, UpdateConfigSchema, WebSearchConfigSchema, WebToolsConfigSchema, WebsiteBlocklistSchema, WorkspaceConfigSchema, WorkspaceImportConfigSchema, getAgentDefaultModelRef, getWorkspacePath, init_schema, parseModelRef } from "./schema.js";
8
8
  import { applyConfigOverrides, getConfigOverrides, resetConfigOverrides, setConfigOverride, unsetConfigOverride } from "./runtime-overrides.js";
9
9
  import { extractProfileAgentId, resolveEffectiveAgentProfile, resolveEffectiveAgentProfileForSession } from "./agent-profile.js";
10
10
  import { resolveSessionFilePath, resolveSessionTranscriptPathInDir } from "../session/parity/transcript-paths.js";
@@ -28,6 +28,6 @@ init_workspace_path();
28
28
  init_models_json();
29
29
  init_resolve_config_value();
30
30
  //#endregion
31
- export { AgentConfigSchema, AgentDefaultsSchema, AgentImageGenerationModelSchema, AgentModelRefSchema, AgentsConfigSchema, BASE_RELOAD_RULES, BindingMatchSchema, BindingRuleSchema, BindingsConfigSchema, ChannelsConfigSchema, ConfigHotReloader, ConfigSchema, CronConfigSchema, CustomModelSchema, ENV_VARS, ExtensionSecurityConfigSchema, ExtensionSlotsConfigSchema, ExtensionsConfigSchema, FILENAMES, GatewayAuthRateLimitSchema, GatewayAuthSchema, GatewayBindModeSchema, GatewayChannelConnectDeferModeSchema, GatewayConfigSchema, GatewayModeSchema, GatewayRemoteSchema, GatewaySecuritySchema, GatewayTailscaleConsentSchema, GatewayTailscaleSchema, GatewayTlsSchema, GatewayTrustedProxySchema, GoalsConfigSchema, HeartbeatConfigSchema, McpConfigSchema, McpServerSchema, MediaUnderstandingCapabilitiesSchema, MediaUnderstandingModelSchema, MessagesConfigSchema, ModelOverrideSchema, ModelsDevConfigSchema, ModelsJsonSchema, OpenAICompatSchema, OpenAICompletionsCompatSchema, OpenAIResponsesCompatSchema, OpenRouterRoutingSchema, ProfileManager, ProviderAuthConfigSchema, ProviderAzureConfigSchema, ProviderConfigSchema, ProviderRequestOverridesSchema, ProvidersConfigSchema, STTConfigSchema, STTFallbackConfigSchema, STTProviderConfigSchema, SearchProviderEntrySchema, SessionConfigSchema, SessionDmScopeSchema, SessionStorageConfigSchema, TTSConfigSchema, TTSEdgeConfigSchema, TTSFallbackConfigSchema, TTSModelOverridesConfigSchema, TTSProviderConfigSchema, TTSSummarizationConfigSchema, TelegramAccountConfigSchema, TelegramConfigSchema, TelegramGroupConfigSchema, TelegramTopicConfigSchema, ToolsConfigSchema, ToolsMediaAudioConfigSchema, ToolsMediaConfigSchema, TunnelConfigSchema, TunnelConsentSchema, TunnelE2eSchema, TunnelExposureModeSchema, UpdateAutoConfigSchema, UpdateConfigSchema, VercelGatewayRoutingSchema, WORKSPACE_FILES, WebSearchConfigSchema, WebToolsConfigSchema, WebsiteBlocklistSchema, WeixinAccountConfigSchema, WeixinConfigSchema, WorkspaceConfigSchema, WorkspaceImportConfigSchema, applyConfigOverrides, buildReloadPlan, canonicalizeConfiguredMcpServer, clearConfigValueCache, createProfile, deleteProfile, diffConfigPaths, existsSync, expandWorkspacePathString, extractProfileAgentId, formatThinkingLevels, getAgentDefaultModelRef, getAllowedCommands, getCacheStats, getConfigOverrides, getCurrentProfile, getDefaultModelValues, resolveModelsJsonPath as getModelsJsonPath, getProfileManager, getProfileNameFromDir, getSwitchCommand, getWorkspacePath, isKnownCliMcpTypeAlias, listAgentProfileMarkdownDirs, listAgentWorkspaceDirs, listConfiguredMcpServers, listProfiles, listThinkingLevels, loadConfig, loadModelsJson, matchReloadRule, modelsJsonExists, normalizeConfiguredMcpServers, normalizeElevatedMode, normalizeReasoningLevel, normalizeThinkLevel, normalizeVerboseLevel, normalizeWorkspaceDir, parseModelRef, registerChannelConfigValidator, resetConfigOverrides, resolveAgentAuthProfilesPath, resolveAgentDir, resolveAgentDir$1 as resolveAgentDirFromConfig, resolveAgentHomeDir, resolveAgentHomeDir$1 as resolveAgentHomeDirFromConfig, resolveAgentMetadataPath, resolveAgentProfileDir, resolveAgentProfileMarkdownPath, resolveAgentWorkspaceDir, resolveAuthProfilesPath, resolveBinDir, resolveBundledExtensionsDir, resolveBundledSkillsDir, resolveConfigPath, resolveConfigValue, resolveCredentialsDir, resolveCronDir, resolveCronJobsPath, resolveCronLogPath, resolveCronLogsDir, resolveCronRunsDir, resolveDefaultAgentWorkspaceDir, resolveEffectiveAgentProfile, resolveEffectiveAgentProfileForSession, resolveExtensionSdkPath, resolveExtensionsDir, resolveExtensionsLockPath, resolveHeaders, resolveHomeDir, resolveInboxDir, resolveInboxMessagePath, resolveInboxPendingDir, resolveInboxProcessedDir, resolveLogPath, resolveLogsDir, resolveMemoryDir, resolveMemoryPath, resolveModelsJsonPath, resolveNodeBinDir, resolveNodeBinPath, resolveNodeToolsDir, resolveNpmBinPath, resolveOAuthPath, resolvePidPath, resolveProfileStateDir, resolveSessionFilePath, resolveSessionTranscriptPath, resolveSessionTranscriptPathInDir, resolveSessionsArchiveDir, resolveSessionsDir, resolveSessionsDir$1 as resolveSessionsDirFromConfig, resolveSessionsMapPath, resolveSkillPath, resolveSkillsCachePath, resolveSkillsDir, resolveSkillsLockPath, resolveSocketPath, resolveStateDir, resolveStatusPath, resolveToolsDir, resolveWorkspaceExtensionsDir, resolveWorkspaceFile, resolveWorkspaceRoot, resolveWorkspaceStateDir, resolveWorkspaceStatePath, resolveXopcBinPath, resolveXopcMcpTransportAlias, saveConfig, saveModelsJson, setConfigOverride, setConfiguredMcpServer, testApiKeyResolution, thinkLevelToNumber, unsetConfigOverride, unsetConfiguredMcpServer, validateModelsConfig };
31
+ export { AgentConfigSchema, AgentDefaultsSchema, AgentImageGenerationModelSchema, AgentModelRefSchema, AgentsConfigSchema, BASE_RELOAD_RULES, BindingMatchSchema, BindingRuleSchema, BindingsConfigSchema, ChannelsConfigSchema, ConfigHotReloader, ConfigSchema, CronConfigSchema, CustomModelSchema, ENV_VARS, ExtensionSecurityConfigSchema, ExtensionSlotsConfigSchema, ExtensionsConfigSchema, FILENAMES, GatewayAuthRateLimitSchema, GatewayAuthSchema, GatewayBindModeSchema, GatewayChannelConnectDeferModeSchema, GatewayConfigSchema, GatewayModeSchema, GatewayRemoteSchema, GatewaySecuritySchema, GatewayTailscaleConsentSchema, GatewayTailscaleSchema, GatewayTlsSchema, GatewayTrustedProxySchema, GoalsConfigSchema, HeartbeatConfigSchema, McpConfigSchema, McpServerSchema, MediaUnderstandingCapabilitiesSchema, MediaUnderstandingModelSchema, MessagesConfigSchema, ModelOverrideSchema, ModelsDevConfigSchema, ModelsJsonSchema, OpenAICompatSchema, OpenAICompletionsCompatSchema, OpenAIResponsesCompatSchema, OpenRouterRoutingSchema, ProfileManager, ProviderAuthConfigSchema, ProviderAzureConfigSchema, ProviderConfigSchema, ProviderRequestOverridesSchema, ProvidersConfigSchema, STTConfigSchema, STTFallbackConfigSchema, STTProviderConfigSchema, SearchProviderEntrySchema, SessionConfigSchema, SessionDmScopeSchema, SessionStorageConfigSchema, TTSConfigSchema, TTSEdgeConfigSchema, TTSFallbackConfigSchema, TTSModelOverridesConfigSchema, TTSProviderConfigSchema, TTSSummarizationConfigSchema, TelegramAccountConfigSchema, TelegramConfigSchema, TelegramGroupConfigSchema, TelegramTopicConfigSchema, ToolsConfigSchema, ToolsMediaAudioConfigSchema, ToolsMediaConfigSchema, TunnelConfigSchema, TunnelConsentSchema, UpdateAutoConfigSchema, UpdateConfigSchema, VercelGatewayRoutingSchema, WORKSPACE_FILES, WebSearchConfigSchema, WebToolsConfigSchema, WebsiteBlocklistSchema, WeixinAccountConfigSchema, WeixinConfigSchema, WorkspaceConfigSchema, WorkspaceImportConfigSchema, applyConfigOverrides, buildReloadPlan, canonicalizeConfiguredMcpServer, clearConfigValueCache, createProfile, deleteProfile, diffConfigPaths, existsSync, expandWorkspacePathString, extractProfileAgentId, formatThinkingLevels, getAgentDefaultModelRef, getAllowedCommands, getCacheStats, getConfigOverrides, getCurrentProfile, getDefaultModelValues, resolveModelsJsonPath as getModelsJsonPath, getProfileManager, getProfileNameFromDir, getSwitchCommand, getWorkspacePath, isKnownCliMcpTypeAlias, listAgentProfileMarkdownDirs, listAgentWorkspaceDirs, listConfiguredMcpServers, listProfiles, listThinkingLevels, loadConfig, loadModelsJson, matchReloadRule, modelsJsonExists, normalizeConfiguredMcpServers, normalizeElevatedMode, normalizeReasoningLevel, normalizeThinkLevel, normalizeVerboseLevel, normalizeWorkspaceDir, parseModelRef, registerChannelConfigValidator, resetConfigOverrides, resolveAgentAuthProfilesPath, resolveAgentDir, resolveAgentDir$1 as resolveAgentDirFromConfig, resolveAgentHomeDir, resolveAgentHomeDir$1 as resolveAgentHomeDirFromConfig, resolveAgentMetadataPath, resolveAgentProfileDir, resolveAgentProfileMarkdownPath, resolveAgentWorkspaceDir, resolveAuthProfilesPath, resolveBinDir, resolveBundledExtensionsDir, resolveBundledSkillsDir, resolveConfigPath, resolveConfigValue, resolveCredentialsDir, resolveCronDir, resolveCronJobsPath, resolveCronLogPath, resolveCronLogsDir, resolveCronRunsDir, resolveDefaultAgentWorkspaceDir, resolveEffectiveAgentProfile, resolveEffectiveAgentProfileForSession, resolveExtensionSdkPath, resolveExtensionsDir, resolveExtensionsLockPath, resolveHeaders, resolveHomeDir, resolveInboxDir, resolveInboxMessagePath, resolveInboxPendingDir, resolveInboxProcessedDir, resolveLogPath, resolveLogsDir, resolveMemoryDir, resolveMemoryPath, resolveModelsJsonPath, resolveNodeBinDir, resolveNodeBinPath, resolveNodeToolsDir, resolveNpmBinPath, resolveOAuthPath, resolvePidPath, resolveProfileStateDir, resolveSessionFilePath, resolveSessionTranscriptPath, resolveSessionTranscriptPathInDir, resolveSessionsArchiveDir, resolveSessionsDir, resolveSessionsDir$1 as resolveSessionsDirFromConfig, resolveSessionsMapPath, resolveSkillPath, resolveSkillsCachePath, resolveSkillsDir, resolveSkillsLockPath, resolveSocketPath, resolveStateDir, resolveStatusPath, resolveToolsDir, resolveWorkspaceExtensionsDir, resolveWorkspaceFile, resolveWorkspaceRoot, resolveWorkspaceStateDir, resolveWorkspaceStatePath, resolveXopcBinPath, resolveXopcMcpTransportAlias, saveConfig, saveModelsJson, setConfigOverride, setConfiguredMcpServer, testApiKeyResolution, thinkLevelToNumber, unsetConfigOverride, unsetConfiguredMcpServer, validateModelsConfig };
32
32
 
33
33
  //# sourceMappingURL=index.js.map
@@ -230,11 +230,6 @@ const BASE_RELOAD_RULES = [
230
230
  kind: "hot",
231
231
  description: "MCP server definitions and idle TTL"
232
232
  },
233
- {
234
- prefix: "tunnel.e2e",
235
- kind: "restart",
236
- description: "Tunnel E2E TLS settings"
237
- },
238
233
  {
239
234
  prefix: "tunnel",
240
235
  kind: "hot",
@@ -1 +1 @@
1
- {"version":3,"file":"rules.js","names":[],"sources":["../../../src/config/rules.ts"],"sourcesContent":["/**\n * Configuration reload rules\n * \n * Defines how different config paths are handled:\n * - hot: Apply changes immediately without restart\n * - restart: Require gateway restart\n * - none: Ignore changes (no action needed)\n */\n\nimport type { ChannelPlugin } from '../channels/plugin-types.js';\nimport { bundledChannelPlugins } from '../generated/bundled-channel-plugins.js';\nimport { listChannelPlugins } from '../channels/plugins/registry.js';\n\nexport type ReloadKind = 'hot' | 'restart' | 'none';\n\nexport interface ReloadRule {\n prefix: string;\n kind: ReloadKind;\n description?: string;\n}\n\nexport interface ReloadPlan {\n changedPaths: string[];\n hotPaths: string[];\n restartPaths: string[];\n noopPaths: string[];\n requiresRestart: boolean;\n requiresHotReload: boolean;\n}\n\n/**\n * Base reload rules for config paths\n */\nexport const BASE_RELOAD_RULES: ReloadRule[] = [\n // Models config - hot reload\n { prefix: 'models.providers', kind: 'hot', description: 'Model provider API keys, base URLs' },\n { prefix: 'models.mode', kind: 'hot', description: 'Model merge mode' },\n \n // Agent defaults - hot reload\n { prefix: 'agents.defaults.model', kind: 'hot', description: 'Model configuration' },\n { prefix: 'agents.defaults.maxTaskDurationMs', kind: 'hot', description: 'Per-turn wall-clock timeout (ms)' },\n { prefix: 'agents.defaults.maxTokens', kind: 'hot', description: 'Max tokens' },\n { prefix: 'agents.defaults.temperature', kind: 'hot', description: 'Temperature' },\n { prefix: 'agents.defaults.maxToolIterations', kind: 'hot', description: 'Max tool iterations' },\n { prefix: 'agents.defaults.compaction', kind: 'hot', description: 'Compaction settings' },\n { prefix: 'agents.defaults.pruning', kind: 'hot', description: 'Pruning settings' },\n { prefix: 'agents.defaults.webExtract', kind: 'hot', description: 'Web extract model and limits' },\n { prefix: 'agents.defaults.browser', kind: 'hot', description: 'Browser automation (Playwright) tools' },\n { prefix: 'agents.defaults.delegate', kind: 'hot', description: 'delegate_task sub-agent tool' },\n { prefix: 'agents.defaults.executeCode', kind: 'hot', description: 'execute_code sandbox tool' },\n {\n prefix: 'agents.defaults.backgroundReview',\n kind: 'hot',\n description: 'Post-turn memory/skill nudge + background review',\n },\n { prefix: 'agents.defaults.workspace', kind: 'none', description: 'Workspace path - no runtime effect' },\n \n // Gateway - restart required\n { prefix: 'gateway.bind', kind: 'restart', description: 'Gateway bind mode' },\n { prefix: 'gateway.customBindHost', kind: 'restart', description: 'Gateway custom bind host' },\n { prefix: 'gateway.port', kind: 'restart', description: 'Port number' },\n { prefix: 'gateway.mode', kind: 'restart', description: 'Gateway local/remote CLI mode' },\n { prefix: 'gateway.remote', kind: 'restart', description: 'Remote gateway CLI target' },\n { prefix: 'gateway.tailscale', kind: 'restart', description: 'Tailscale Serve/Funnel exposure' },\n { prefix: 'gateway.tls', kind: 'restart', description: 'Gateway native TLS' },\n { prefix: 'gateway.auth', kind: 'restart', description: 'Authentication settings' },\n { prefix: 'gateway.security', kind: 'restart', description: 'Gateway security policy' },\n { prefix: 'gateway.corsOrigins', kind: 'restart', description: 'CORS settings' },\n { prefix: 'gateway.trustedProxies', kind: 'restart', description: 'Trusted reverse proxy CIDRs' },\n {\n prefix: 'gateway.allowRealIpFallback',\n kind: 'restart',\n description: 'Trusted-proxy X-Real-IP fallback',\n },\n {\n prefix: 'gateway.dangerouslyAllowHostHeaderOriginFallback',\n kind: 'restart',\n description: 'Host-header origin fallback',\n },\n { prefix: 'gateway.maxSseConnections', kind: 'restart', description: 'SSE connection limit' },\n { prefix: 'gateway.channelConnectDeferMode', kind: 'restart', description: 'Channel connect defer mode' },\n { prefix: 'gateway.channelConnectDeferIds', kind: 'restart', description: 'Explicit channel connect defer list' },\n { prefix: 'gateway.channelConnectDeferSkipIds', kind: 'restart', description: 'Channel connect defer skip list' },\n { prefix: 'gateway.share', kind: 'restart', description: 'File share policy' },\n {\n prefix: 'gateway.skillsStoreBaseUrl',\n kind: 'restart',\n description: 'Skills marketplace API base URL',\n },\n { prefix: 'gateway.enableHotReload', kind: 'hot', description: 'Hot reload toggle' },\n \n // Channels - hot reload (channel-specific prefixes are registered by channel plugins)\n { prefix: 'channels', kind: 'hot', description: 'Any channel subtree (e.g. future extensions)' },\n \n // Cron - hot reload\n { prefix: 'cron', kind: 'hot', description: 'Scheduled tasks' },\n \n // Heartbeat lives under gateway.heartbeat in config JSON (not top-level `heartbeat`)\n { prefix: 'gateway.heartbeat', kind: 'hot', description: 'Heartbeat settings' },\n \n // Web search - hot reload\n { prefix: 'webSearch', kind: 'hot', description: 'Web search settings' },\n { prefix: 'webTools', kind: 'hot', description: 'Web tools settings' },\n \n // Extension list toggles — still require process restart to load/unload modules\n {\n prefix: 'extensions.enabled',\n kind: 'restart',\n description: 'Extension enable list (requires restart)',\n },\n {\n prefix: 'extensions.disabled',\n kind: 'restart',\n description: 'Extension disable list (requires restart)',\n },\n // Extension instance config — hot-reloaded via extension registerReload handlers\n {\n prefix: 'extensions',\n kind: 'hot',\n description: 'Extension configuration (hot-reloaded via extension handlers)',\n },\n \n // Tools - hot reload (for tool-specific settings)\n { prefix: 'tools', kind: 'hot', description: 'Tools configuration' },\n\n // MCP servers - hot reload (dispose and reconnect runtimes)\n { prefix: 'mcp', kind: 'hot', description: 'MCP server definitions and idle TTL' },\n\n // Tunnel E2E TLS — restart (local HTTPS terminator port)\n { prefix: 'tunnel.e2e', kind: 'restart', description: 'Tunnel E2E TLS settings' },\n { prefix: 'tunnel', kind: 'hot', description: 'Tunnel broker and auto-start settings' },\n];\n\nfunction pluginsForReloadRules(): ChannelPlugin[] {\n const listed = listChannelPlugins();\n return listed.length > 0 ? [...listed] : [...bundledChannelPlugins];\n}\n\nfunction getChannelReloadRules(): ReloadRule[] {\n return pluginsForReloadRules()\n .filter((plugin) => plugin.reload?.configPrefixes?.length)\n .flatMap((plugin) =>\n plugin.reload!.configPrefixes.map((prefix) => ({\n prefix,\n kind: 'hot' as const,\n description: `${plugin.meta.label} settings`,\n })),\n );\n}\n\nfunction mergedReloadRules(): ReloadRule[] {\n return [...BASE_RELOAD_RULES, ...getChannelReloadRules()];\n}\n\n/**\n * Find matching rule for a config path\n */\nexport function matchReloadRule(path: string): ReloadRule | null {\n const merged = mergedReloadRules();\n const exact = merged.find((r) => r.prefix === path);\n if (exact) return exact;\n const sorted = [...merged].sort((a, b) => b.prefix.length - a.prefix.length);\n for (const rule of sorted) {\n if (path === rule.prefix || path.startsWith(`${rule.prefix}.`)) {\n return rule;\n }\n }\n return null;\n}\n\n/**\n * Build reload plan from changed paths\n */\nexport function buildReloadPlan(changedPaths: string[]): ReloadPlan {\n const plan: ReloadPlan = {\n changedPaths,\n hotPaths: [],\n restartPaths: [],\n noopPaths: [],\n requiresRestart: false,\n requiresHotReload: false,\n };\n\n for (const path of changedPaths) {\n const rule = matchReloadRule(path);\n \n if (!rule) {\n // No rule matched - default to restart for safety\n plan.restartPaths.push(path);\n plan.requiresRestart = true;\n continue;\n }\n\n switch (rule.kind) {\n case 'hot':\n plan.hotPaths.push(path);\n plan.requiresHotReload = true;\n break;\n case 'restart':\n plan.restartPaths.push(path);\n plan.requiresRestart = true;\n break;\n case 'none':\n plan.noopPaths.push(path);\n break;\n }\n }\n\n return plan;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"rules.js","names":[],"sources":["../../../src/config/rules.ts"],"sourcesContent":["/**\n * Configuration reload rules\n * \n * Defines how different config paths are handled:\n * - hot: Apply changes immediately without restart\n * - restart: Require gateway restart\n * - none: Ignore changes (no action needed)\n */\n\nimport type { ChannelPlugin } from '../channels/plugin-types.js';\nimport { bundledChannelPlugins } from '../generated/bundled-channel-plugins.js';\nimport { listChannelPlugins } from '../channels/plugins/registry.js';\n\nexport type ReloadKind = 'hot' | 'restart' | 'none';\n\nexport interface ReloadRule {\n prefix: string;\n kind: ReloadKind;\n description?: string;\n}\n\nexport interface ReloadPlan {\n changedPaths: string[];\n hotPaths: string[];\n restartPaths: string[];\n noopPaths: string[];\n requiresRestart: boolean;\n requiresHotReload: boolean;\n}\n\n/**\n * Base reload rules for config paths\n */\nexport const BASE_RELOAD_RULES: ReloadRule[] = [\n // Models config - hot reload\n { prefix: 'models.providers', kind: 'hot', description: 'Model provider API keys, base URLs' },\n { prefix: 'models.mode', kind: 'hot', description: 'Model merge mode' },\n \n // Agent defaults - hot reload\n { prefix: 'agents.defaults.model', kind: 'hot', description: 'Model configuration' },\n { prefix: 'agents.defaults.maxTaskDurationMs', kind: 'hot', description: 'Per-turn wall-clock timeout (ms)' },\n { prefix: 'agents.defaults.maxTokens', kind: 'hot', description: 'Max tokens' },\n { prefix: 'agents.defaults.temperature', kind: 'hot', description: 'Temperature' },\n { prefix: 'agents.defaults.maxToolIterations', kind: 'hot', description: 'Max tool iterations' },\n { prefix: 'agents.defaults.compaction', kind: 'hot', description: 'Compaction settings' },\n { prefix: 'agents.defaults.pruning', kind: 'hot', description: 'Pruning settings' },\n { prefix: 'agents.defaults.webExtract', kind: 'hot', description: 'Web extract model and limits' },\n { prefix: 'agents.defaults.browser', kind: 'hot', description: 'Browser automation (Playwright) tools' },\n { prefix: 'agents.defaults.delegate', kind: 'hot', description: 'delegate_task sub-agent tool' },\n { prefix: 'agents.defaults.executeCode', kind: 'hot', description: 'execute_code sandbox tool' },\n {\n prefix: 'agents.defaults.backgroundReview',\n kind: 'hot',\n description: 'Post-turn memory/skill nudge + background review',\n },\n { prefix: 'agents.defaults.workspace', kind: 'none', description: 'Workspace path - no runtime effect' },\n \n // Gateway - restart required\n { prefix: 'gateway.bind', kind: 'restart', description: 'Gateway bind mode' },\n { prefix: 'gateway.customBindHost', kind: 'restart', description: 'Gateway custom bind host' },\n { prefix: 'gateway.port', kind: 'restart', description: 'Port number' },\n { prefix: 'gateway.mode', kind: 'restart', description: 'Gateway local/remote CLI mode' },\n { prefix: 'gateway.remote', kind: 'restart', description: 'Remote gateway CLI target' },\n { prefix: 'gateway.tailscale', kind: 'restart', description: 'Tailscale Serve/Funnel exposure' },\n { prefix: 'gateway.tls', kind: 'restart', description: 'Gateway native TLS' },\n { prefix: 'gateway.auth', kind: 'restart', description: 'Authentication settings' },\n { prefix: 'gateway.security', kind: 'restart', description: 'Gateway security policy' },\n { prefix: 'gateway.corsOrigins', kind: 'restart', description: 'CORS settings' },\n { prefix: 'gateway.trustedProxies', kind: 'restart', description: 'Trusted reverse proxy CIDRs' },\n {\n prefix: 'gateway.allowRealIpFallback',\n kind: 'restart',\n description: 'Trusted-proxy X-Real-IP fallback',\n },\n {\n prefix: 'gateway.dangerouslyAllowHostHeaderOriginFallback',\n kind: 'restart',\n description: 'Host-header origin fallback',\n },\n { prefix: 'gateway.maxSseConnections', kind: 'restart', description: 'SSE connection limit' },\n { prefix: 'gateway.channelConnectDeferMode', kind: 'restart', description: 'Channel connect defer mode' },\n { prefix: 'gateway.channelConnectDeferIds', kind: 'restart', description: 'Explicit channel connect defer list' },\n { prefix: 'gateway.channelConnectDeferSkipIds', kind: 'restart', description: 'Channel connect defer skip list' },\n { prefix: 'gateway.share', kind: 'restart', description: 'File share policy' },\n {\n prefix: 'gateway.skillsStoreBaseUrl',\n kind: 'restart',\n description: 'Skills marketplace API base URL',\n },\n { prefix: 'gateway.enableHotReload', kind: 'hot', description: 'Hot reload toggle' },\n \n // Channels - hot reload (channel-specific prefixes are registered by channel plugins)\n { prefix: 'channels', kind: 'hot', description: 'Any channel subtree (e.g. future extensions)' },\n \n // Cron - hot reload\n { prefix: 'cron', kind: 'hot', description: 'Scheduled tasks' },\n \n // Heartbeat lives under gateway.heartbeat in config JSON (not top-level `heartbeat`)\n { prefix: 'gateway.heartbeat', kind: 'hot', description: 'Heartbeat settings' },\n \n // Web search - hot reload\n { prefix: 'webSearch', kind: 'hot', description: 'Web search settings' },\n { prefix: 'webTools', kind: 'hot', description: 'Web tools settings' },\n \n // Extension list toggles — still require process restart to load/unload modules\n {\n prefix: 'extensions.enabled',\n kind: 'restart',\n description: 'Extension enable list (requires restart)',\n },\n {\n prefix: 'extensions.disabled',\n kind: 'restart',\n description: 'Extension disable list (requires restart)',\n },\n // Extension instance config — hot-reloaded via extension registerReload handlers\n {\n prefix: 'extensions',\n kind: 'hot',\n description: 'Extension configuration (hot-reloaded via extension handlers)',\n },\n \n // Tools - hot reload (for tool-specific settings)\n { prefix: 'tools', kind: 'hot', description: 'Tools configuration' },\n\n // MCP servers - hot reload (dispose and reconnect runtimes)\n { prefix: 'mcp', kind: 'hot', description: 'MCP server definitions and idle TTL' },\n\n // Tunnel E2E TLS — restart (local HTTPS terminator port)\n { prefix: 'tunnel', kind: 'hot', description: 'Tunnel broker and auto-start settings' },\n];\n\nfunction pluginsForReloadRules(): ChannelPlugin[] {\n const listed = listChannelPlugins();\n return listed.length > 0 ? [...listed] : [...bundledChannelPlugins];\n}\n\nfunction getChannelReloadRules(): ReloadRule[] {\n return pluginsForReloadRules()\n .filter((plugin) => plugin.reload?.configPrefixes?.length)\n .flatMap((plugin) =>\n plugin.reload!.configPrefixes.map((prefix) => ({\n prefix,\n kind: 'hot' as const,\n description: `${plugin.meta.label} settings`,\n })),\n );\n}\n\nfunction mergedReloadRules(): ReloadRule[] {\n return [...BASE_RELOAD_RULES, ...getChannelReloadRules()];\n}\n\n/**\n * Find matching rule for a config path\n */\nexport function matchReloadRule(path: string): ReloadRule | null {\n const merged = mergedReloadRules();\n const exact = merged.find((r) => r.prefix === path);\n if (exact) return exact;\n const sorted = [...merged].sort((a, b) => b.prefix.length - a.prefix.length);\n for (const rule of sorted) {\n if (path === rule.prefix || path.startsWith(`${rule.prefix}.`)) {\n return rule;\n }\n }\n return null;\n}\n\n/**\n * Build reload plan from changed paths\n */\nexport function buildReloadPlan(changedPaths: string[]): ReloadPlan {\n const plan: ReloadPlan = {\n changedPaths,\n hotPaths: [],\n restartPaths: [],\n noopPaths: [],\n requiresRestart: false,\n requiresHotReload: false,\n };\n\n for (const path of changedPaths) {\n const rule = matchReloadRule(path);\n \n if (!rule) {\n // No rule matched - default to restart for safety\n plan.restartPaths.push(path);\n plan.requiresRestart = true;\n continue;\n }\n\n switch (rule.kind) {\n case 'hot':\n plan.hotPaths.push(path);\n plan.requiresHotReload = true;\n break;\n case 'restart':\n plan.restartPaths.push(path);\n plan.requiresRestart = true;\n break;\n case 'none':\n plan.noopPaths.push(path);\n break;\n }\n }\n\n return plan;\n}\n"],"mappings":"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"}
@@ -838,34 +838,16 @@ export declare const TunnelConsentSchema: z.ZodObject<{
838
838
  version: z.ZodString;
839
839
  acceptedAt: z.ZodString;
840
840
  }, z.core.$strip>;
841
- export declare const TunnelE2eSchema: z.ZodDefault<z.ZodObject<{
842
- enabled: z.ZodDefault<z.ZodBoolean>;
843
- tlsPort: z.ZodDefault<z.ZodNumber>;
844
- staging: z.ZodDefault<z.ZodBoolean>;
845
- }, z.core.$strip>>;
846
- export declare const TunnelExposureModeSchema: z.ZodEnum<{
847
- public: "public";
848
- "pairing-only": "pairing-only";
849
- }>;
850
841
  export declare const TunnelConfigSchema: z.ZodDefault<z.ZodObject<{
851
842
  enabled: z.ZodDefault<z.ZodBoolean>;
852
843
  brokerUrl: z.ZodDefault<z.ZodString>;
853
844
  registrationSecret: z.ZodOptional<z.ZodString>;
854
845
  autoStart: z.ZodDefault<z.ZodBoolean>;
855
846
  subdomain: z.ZodOptional<z.ZodString>;
856
- exposure: z.ZodDefault<z.ZodEnum<{
857
- public: "public";
858
- "pairing-only": "pairing-only";
859
- }>>;
860
847
  consent: z.ZodOptional<z.ZodObject<{
861
848
  version: z.ZodString;
862
849
  acceptedAt: z.ZodString;
863
850
  }, z.core.$strip>>;
864
- e2e: z.ZodOptional<z.ZodDefault<z.ZodObject<{
865
- enabled: z.ZodDefault<z.ZodBoolean>;
866
- tlsPort: z.ZodDefault<z.ZodNumber>;
867
- staging: z.ZodDefault<z.ZodBoolean>;
868
- }, z.core.$strip>>>;
869
851
  }, z.core.$strip>>;
870
852
  export type TunnelConfig = z.infer<typeof TunnelConfigSchema>;
871
853
  /**
@@ -1911,19 +1893,10 @@ export declare const ConfigSchema: z.ZodDefault<z.ZodObject<{
1911
1893
  registrationSecret: z.ZodOptional<z.ZodString>;
1912
1894
  autoStart: z.ZodDefault<z.ZodBoolean>;
1913
1895
  subdomain: z.ZodOptional<z.ZodString>;
1914
- exposure: z.ZodDefault<z.ZodEnum<{
1915
- public: "public";
1916
- "pairing-only": "pairing-only";
1917
- }>>;
1918
1896
  consent: z.ZodOptional<z.ZodObject<{
1919
1897
  version: z.ZodString;
1920
1898
  acceptedAt: z.ZodString;
1921
1899
  }, z.core.$strip>>;
1922
- e2e: z.ZodOptional<z.ZodDefault<z.ZodObject<{
1923
- enabled: z.ZodDefault<z.ZodBoolean>;
1924
- tlsPort: z.ZodDefault<z.ZodNumber>;
1925
- staging: z.ZodDefault<z.ZodBoolean>;
1926
- }, z.core.$strip>>>;
1927
1900
  }, z.core.$strip>>>;
1928
1901
  workspace: z.ZodOptional<z.ZodObject<{
1929
1902
  import: z.ZodOptional<z.ZodObject<{
@@ -33,7 +33,7 @@ function parseModelRef(ref) {
33
33
  model: trimmed.slice(idx + 1).trim()
34
34
  };
35
35
  }
36
- var AgentModelRefSchema, AgentImageGenerationModelSchema, AgentDefaultsSchema, AgentConfigSchema, AgentsConfigSchema, BindingMatchSchema, BindingRuleSchema, BindingsConfigSchema, SessionDmScopeSchema, SessionStorageConfigSchema, SessionConfigSchema, ChannelsConfigSchema, SearchProviderEntrySchema, WebSearchConfigSchema, WebsiteBlocklistSchema, WebToolsConfigSchema, ToolsConfigSchema, GatewayAuthRateLimitSchema, GatewaySecuritySchema, GatewayTrustedProxySchema, GatewayAuthSchema, GatewayTailscaleConsentSchema, GatewayTailscaleSchema, GatewayRemoteSchema, GatewayTlsSchema, GatewayModeSchema, HeartbeatConfigSchema, GatewayChannelConnectDeferModeSchema, TunnelConsentSchema, TunnelE2eSchema, TunnelExposureModeSchema, TunnelConfigSchema, WorkspaceImportConfigSchema, WorkspaceConfigSchema, GatewayBindModeSchema, GatewayConfigSchema, CronConfigSchema, ModelsDevConfigSchema, SttProviderConfigCatchallSchema, STTProviderConfigSchema, STTFallbackConfigSchema, MediaUnderstandingCapabilitiesSchema, MediaUnderstandingModelSchema, STTConfigSchema, TtsProviderConfigCatchallSchema, TTSProviderConfigSchema, TTSFallbackConfigSchema, TTSModelOverridesConfigSchema, TTSEdgeConfigSchema, TTSSummarizationConfigSchema, TTSConfigSchema, MessagesConfigSchema, ToolsMediaAudioConfigSchema, ToolsMediaConfigSchema, ProviderAzureConfigSchema, ProviderRequestOverridesSchema, ProviderAuthConfigSchema, ProvidersConfigSchema, ExtensionSecurityConfigSchema, ExtensionSlotsConfigSchema, ExtensionsConfigSchema, UpdateAutoConfigSchema, GoalsConfigSchema, UpdateConfigSchema, McpHttpUrlSchema, McpServerSchema, McpConfigSchema, ConfigSchema;
36
+ var AgentModelRefSchema, AgentImageGenerationModelSchema, AgentDefaultsSchema, AgentConfigSchema, AgentsConfigSchema, BindingMatchSchema, BindingRuleSchema, BindingsConfigSchema, SessionDmScopeSchema, SessionStorageConfigSchema, SessionConfigSchema, ChannelsConfigSchema, SearchProviderEntrySchema, WebSearchConfigSchema, WebsiteBlocklistSchema, WebToolsConfigSchema, ToolsConfigSchema, GatewayAuthRateLimitSchema, GatewaySecuritySchema, GatewayTrustedProxySchema, GatewayAuthSchema, GatewayTailscaleConsentSchema, GatewayTailscaleSchema, GatewayRemoteSchema, GatewayTlsSchema, GatewayModeSchema, HeartbeatConfigSchema, GatewayChannelConnectDeferModeSchema, TunnelConsentSchema, TunnelConfigSchema, WorkspaceImportConfigSchema, WorkspaceConfigSchema, GatewayBindModeSchema, GatewayConfigSchema, CronConfigSchema, ModelsDevConfigSchema, SttProviderConfigCatchallSchema, STTProviderConfigSchema, STTFallbackConfigSchema, MediaUnderstandingCapabilitiesSchema, MediaUnderstandingModelSchema, STTConfigSchema, TtsProviderConfigCatchallSchema, TTSProviderConfigSchema, TTSFallbackConfigSchema, TTSModelOverridesConfigSchema, TTSEdgeConfigSchema, TTSSummarizationConfigSchema, TTSConfigSchema, MessagesConfigSchema, ToolsMediaAudioConfigSchema, ToolsMediaConfigSchema, ProviderAzureConfigSchema, ProviderRequestOverridesSchema, ProviderAuthConfigSchema, ProvidersConfigSchema, ExtensionSecurityConfigSchema, ExtensionSlotsConfigSchema, ExtensionsConfigSchema, UpdateAutoConfigSchema, GoalsConfigSchema, UpdateConfigSchema, McpHttpUrlSchema, McpServerSchema, McpConfigSchema, ConfigSchema;
37
37
  var init_schema = __esmMin((() => {
38
38
  init_agent_scope();
39
39
  init_cache_dir_policy();
@@ -585,16 +585,6 @@ strict: z.boolean().optional() }).optional();
585
585
  version: z.string().min(1),
586
586
  acceptedAt: z.string().min(1)
587
587
  });
588
- TunnelE2eSchema = z.object({
589
- enabled: z.boolean().default(true),
590
- tlsPort: z.number().int().min(1024).max(65535).default(18791),
591
- staging: z.boolean().default(false)
592
- }).default({
593
- enabled: true,
594
- tlsPort: 18791,
595
- staging: false
596
- });
597
- TunnelExposureModeSchema = z.enum(["public", "pairing-only"]);
598
588
  TunnelConfigSchema = z.object({
599
589
  enabled: z.boolean().default(false),
600
590
  brokerUrl: z.string().url().default("https://frp.xopc.ai/api"),
@@ -602,15 +592,11 @@ strict: z.boolean().optional() }).optional();
602
592
  registrationSecret: z.string().min(1).optional(),
603
593
  autoStart: z.boolean().default(false),
604
594
  subdomain: z.string().optional(),
605
- /** public: full gateway; pairing-only: broker routes only mobile pair endpoints. */
606
- exposure: TunnelExposureModeSchema.default("public"),
607
- consent: TunnelConsentSchema.optional(),
608
- e2e: TunnelE2eSchema.optional()
595
+ consent: TunnelConsentSchema.optional()
609
596
  }).default({
610
597
  enabled: false,
611
598
  brokerUrl: "https://frp.xopc.ai/api",
612
- autoStart: false,
613
- exposure: "public"
599
+ autoStart: false
614
600
  });
615
601
  WorkspaceImportConfigSchema = z.object({
616
602
  /** Workspace-relative subdir for imported files. Default `imports`. */
@@ -1094,6 +1080,6 @@ tts: TTSConfigSchema.optional() }).optional();
1094
1080
  }));
1095
1081
  //#endregion
1096
1082
  init_schema();
1097
- export { AgentConfigSchema, AgentDefaultsSchema, AgentImageGenerationModelSchema, AgentModelRefSchema, AgentsConfigSchema, BindingMatchSchema, BindingRuleSchema, BindingsConfigSchema, ChannelsConfigSchema, ConfigSchema, CronConfigSchema, ExtensionSecurityConfigSchema, ExtensionSlotsConfigSchema, ExtensionsConfigSchema, GatewayAuthRateLimitSchema, GatewayAuthSchema, GatewayBindModeSchema, GatewayChannelConnectDeferModeSchema, GatewayConfigSchema, GatewayModeSchema, GatewayRemoteSchema, GatewaySecuritySchema, GatewayTailscaleConsentSchema, GatewayTailscaleSchema, GatewayTlsSchema, GatewayTrustedProxySchema, GoalsConfigSchema, HeartbeatConfigSchema, McpConfigSchema, McpServerSchema, MediaUnderstandingCapabilitiesSchema, MediaUnderstandingModelSchema, MessagesConfigSchema, ModelsDevConfigSchema, ProviderAuthConfigSchema, ProviderAzureConfigSchema, ProviderRequestOverridesSchema, ProvidersConfigSchema, STTConfigSchema, STTFallbackConfigSchema, STTProviderConfigSchema, SearchProviderEntrySchema, SessionConfigSchema, SessionDmScopeSchema, SessionStorageConfigSchema, TTSConfigSchema, TTSEdgeConfigSchema, TTSFallbackConfigSchema, TTSModelOverridesConfigSchema, TTSProviderConfigSchema, TTSSummarizationConfigSchema, TelegramAccountConfigSchema, TelegramConfigSchema, TelegramGroupConfigSchema, TelegramTopicConfigSchema, ToolsConfigSchema, ToolsMediaAudioConfigSchema, ToolsMediaConfigSchema, TunnelConfigSchema, TunnelConsentSchema, TunnelE2eSchema, TunnelExposureModeSchema, UpdateAutoConfigSchema, UpdateConfigSchema, WebSearchConfigSchema, WebToolsConfigSchema, WebsiteBlocklistSchema, WeixinAccountConfigSchema, WeixinConfigSchema, WorkspaceConfigSchema, WorkspaceImportConfigSchema, getAgentDefaultModelRef, getWorkspacePath, init_schema, parseModelRef };
1083
+ export { AgentConfigSchema, AgentDefaultsSchema, AgentImageGenerationModelSchema, AgentModelRefSchema, AgentsConfigSchema, BindingMatchSchema, BindingRuleSchema, BindingsConfigSchema, ChannelsConfigSchema, ConfigSchema, CronConfigSchema, ExtensionSecurityConfigSchema, ExtensionSlotsConfigSchema, ExtensionsConfigSchema, GatewayAuthRateLimitSchema, GatewayAuthSchema, GatewayBindModeSchema, GatewayChannelConnectDeferModeSchema, GatewayConfigSchema, GatewayModeSchema, GatewayRemoteSchema, GatewaySecuritySchema, GatewayTailscaleConsentSchema, GatewayTailscaleSchema, GatewayTlsSchema, GatewayTrustedProxySchema, GoalsConfigSchema, HeartbeatConfigSchema, McpConfigSchema, McpServerSchema, MediaUnderstandingCapabilitiesSchema, MediaUnderstandingModelSchema, MessagesConfigSchema, ModelsDevConfigSchema, ProviderAuthConfigSchema, ProviderAzureConfigSchema, ProviderRequestOverridesSchema, ProvidersConfigSchema, STTConfigSchema, STTFallbackConfigSchema, STTProviderConfigSchema, SearchProviderEntrySchema, SessionConfigSchema, SessionDmScopeSchema, SessionStorageConfigSchema, TTSConfigSchema, TTSEdgeConfigSchema, TTSFallbackConfigSchema, TTSModelOverridesConfigSchema, TTSProviderConfigSchema, TTSSummarizationConfigSchema, TelegramAccountConfigSchema, TelegramConfigSchema, TelegramGroupConfigSchema, TelegramTopicConfigSchema, ToolsConfigSchema, ToolsMediaAudioConfigSchema, ToolsMediaConfigSchema, TunnelConfigSchema, TunnelConsentSchema, UpdateAutoConfigSchema, UpdateConfigSchema, WebSearchConfigSchema, WebToolsConfigSchema, WebsiteBlocklistSchema, WeixinAccountConfigSchema, WeixinConfigSchema, WorkspaceConfigSchema, WorkspaceImportConfigSchema, getAgentDefaultModelRef, getWorkspacePath, init_schema, parseModelRef };
1098
1084
 
1099
1085
  //# sourceMappingURL=schema.js.map