opentray 0.33.0 → 0.33.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +53 -12
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +111 -25
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["isRecord","PROTOCOL_VERSION","isConnectionDeadSource","isNodeError","createBrokerEndpointIdentity","normalizeAppIdentityField","formatWindowsPipeName","formatUnixSocketPath","PROTOCOL_VERSION","noop"],"sources":["../src/app-icon.ts","../src/native-extension-artifact.ts","../src/client.ts","../src/daemon/caller-label.ts","../src/daemon/native-target.ts","../src/daemon/broker-command.ts","../src/daemon/lifecycle.ts","../src/daemon/package-version.ts","../src/daemon/paths.ts","../src/local-broker.ts","../src/transport-supervision.ts","../src/menu-input.ts","../src/app-launch.ts","../src/sdk.ts"],"sourcesContent":["// Orthogonal intents (maintained 2026-07-20; original user request: appIcon\n// must be a strict platform-standard asset array distinct from trayIcon):\n// 1. Validate platform coverage and uniqueness before broker startup.\n// 2. Prove declared native formats against source bytes.\n// 3. Reject every tray-oriented, remote, text, template, and raw RGBA shape.\n\nimport { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport type {\n AppIcon,\n AppIconSource,\n AppIconVariant,\n} from \"@opentray/spec\";\n\nexport type AppIconPlatform = \"darwin\" | \"windows\" | \"linux\";\nexport const DEFAULT_APP_ICON_VARIANT = \"default\" as const;\nconst APP_ICON_VARIANT_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;\n\nexport class InvalidAppIconError extends Error {\n readonly code = \"OPENTRAY_INVALID_APP_ICON\";\n readonly reason: string;\n\n constructor(reason: string, platform: NodeJS.Platform = process.platform) {\n super(`invalid appIcon for ${platform}: ${reason}`);\n this.name = \"InvalidAppIconError\";\n this.reason = reason;\n }\n}\n\nexport class AppIconVariantNotFoundError extends Error {\n readonly code = \"OPENTRAY_APP_ICON_VARIANT_NOT_FOUND\";\n readonly variant: string;\n\n constructor(variant: string, platform: NodeJS.Platform = process.platform) {\n super(`appIcon variant ${variant} is unavailable for ${platform}`);\n this.name = \"AppIconVariantNotFoundError\";\n this.variant = variant;\n }\n}\n\n/** Validate an explicit AppIcon, including native file signatures, before broker startup. */\nexport const validateAppIcon = async (\n icon: unknown,\n platform: NodeJS.Platform = process.platform\n): Promise<void> => {\n if (!Array.isArray(icon) || icon.length === 0) {\n throw new InvalidAppIconError(\n \"the asset array must not be empty\",\n platform\n );\n }\n\n const variantPlatforms = new Map<string, Set<AppIconPlatform>>();\n const seenDarwin = new Set<string>();\n const seenWindows = new Set<string>();\n const seenLinuxPngSizes = new Set<string>();\n const seenLinuxSvg = new Set<string>();\n for (const asset of icon) {\n if (!isRecord(asset)) {\n throw new InvalidAppIconError(\"asset must be an object\", platform);\n }\n const assetPlatform = asset.platform;\n const format = asset.format;\n const variants = validateVariantNames(asset.variant, platform);\n if (assetPlatform === \"darwin\" && format === \"icns\") {\n assertExactKeys(\n asset,\n [\"platform\", \"format\", \"source\"],\n platform,\n [\"variant\"]\n );\n rejectDuplicateVariants(seenDarwin, variants, \"darwin\", platform);\n await validateSource(asset.source, \"icns\", platform);\n recordVariantPlatforms(variantPlatforms, variants, \"darwin\");\n continue;\n }\n if (assetPlatform === \"windows\" && format === \"ico\") {\n assertExactKeys(\n asset,\n [\"platform\", \"format\", \"source\"],\n platform,\n [\"variant\"]\n );\n rejectDuplicateVariants(seenWindows, variants, \"windows\", platform);\n await validateSource(asset.source, \"ico\", platform);\n recordVariantPlatforms(variantPlatforms, variants, \"windows\");\n continue;\n }\n if (assetPlatform === \"linux\" && format === \"png\") {\n assertExactKeys(\n asset,\n [\"platform\", \"format\", \"size\", \"source\"],\n platform,\n [\"variant\"]\n );\n if (\n !Number.isInteger(asset.size) ||\n typeof asset.size !== \"number\" ||\n asset.size <= 0\n ) {\n throw new InvalidAppIconError(\n \"Linux PNG assets require a positive integer size\",\n platform\n );\n }\n for (const variant of variants) {\n const key = `${variant}\\0${asset.size}`;\n if (seenLinuxPngSizes.has(key)) {\n throw new InvalidAppIconError(\n `duplicate Linux PNG size ${asset.size} for variant ${variant}`,\n platform\n );\n }\n seenLinuxPngSizes.add(key);\n }\n await validateSource(asset.source, \"png\", platform);\n recordVariantPlatforms(variantPlatforms, variants, \"linux\");\n continue;\n }\n if (assetPlatform === \"linux\" && format === \"svg\") {\n assertExactKeys(\n asset,\n [\"platform\", \"format\", \"source\"],\n platform,\n [\"variant\"]\n );\n rejectDuplicateVariants(seenLinuxSvg, variants, \"Linux SVG\", platform);\n await validateSource(asset.source, \"svg\", platform);\n recordVariantPlatforms(variantPlatforms, variants, \"linux\");\n continue;\n }\n throw new InvalidAppIconError(\n `unsupported platform/format pair ${String(assetPlatform)}/${String(\n format\n )}`,\n platform\n );\n }\n\n const currentPlatform = normalizePlatform(platform);\n if (currentPlatform !== undefined) {\n if (!variantPlatforms.get(DEFAULT_APP_ICON_VARIANT)?.has(currentPlatform)) {\n throw new InvalidAppIconError(\n `no ${currentPlatform} ${DEFAULT_APP_ICON_VARIANT} asset was provided`,\n platform\n );\n }\n for (const [variant, platforms] of variantPlatforms) {\n if (!platforms.has(currentPlatform)) {\n throw new InvalidAppIconError(\n `variant ${variant} has no ${currentPlatform} asset`,\n platform\n );\n }\n }\n }\n};\n\n/** Normalize encoded sources into JSON array bytes for the Rust wire protocol. */\nexport const normalizeAppIcon = (icon: AppIcon): AppIcon =>\n icon.map((asset) => {\n const source = normalizeSource(asset.source);\n const variant = normalizeVariant(asset.variant);\n if (asset.platform === \"darwin\") return { ...asset, variant, source };\n if (asset.platform === \"windows\") return { ...asset, variant, source };\n if (asset.format === \"png\") return { ...asset, variant, source };\n return { ...asset, variant, source };\n });\n\n/** Select one semantic variant while retaining every platform's matching native asset. */\nexport const selectAppIconVariant = (\n icon: AppIcon,\n variant: string,\n platform: NodeJS.Platform = process.platform\n): AppIcon => {\n validateVariantName(variant, platform);\n const selected = icon.filter((asset) =>\n normalizedVariantNames(asset.variant).includes(variant)\n );\n const currentPlatform = normalizePlatform(platform);\n if (\n selected.length === 0 ||\n (currentPlatform !== undefined &&\n !selected.some((asset) => asset.platform === currentPlatform))\n ) {\n throw new AppIconVariantNotFoundError(variant, platform);\n }\n return selected;\n};\n\nconst normalizeSource = (source: AppIconSource): AppIconSource =>\n source.type === \"encoded\"\n ? { type: \"encoded\", data: Array.from(source.data) }\n : { type: \"file\", path: resolve(source.path) };\n\nconst normalizeVariant = (\n variant: AppIconVariant | undefined\n): AppIconVariant =>\n variant === undefined\n ? DEFAULT_APP_ICON_VARIANT\n : typeof variant === \"string\"\n ? variant\n : [...variant];\n\nconst normalizedVariantNames = (\n variant: AppIconVariant | undefined\n): readonly string[] =>\n variant === undefined\n ? [DEFAULT_APP_ICON_VARIANT]\n : typeof variant === \"string\"\n ? [variant]\n : variant;\n\nconst validateVariantNames = (\n variant: unknown,\n platform: NodeJS.Platform\n): readonly string[] => {\n const names =\n variant === undefined\n ? [DEFAULT_APP_ICON_VARIANT]\n : typeof variant === \"string\"\n ? [variant]\n : Array.isArray(variant)\n ? variant\n : [];\n if (names.length === 0) {\n throw new InvalidAppIconError(\n \"variant must be a name or non-empty name array\",\n platform\n );\n }\n const seen = new Set<string>();\n for (const name of names) {\n validateVariantName(name, platform);\n if (seen.has(name)) {\n throw new InvalidAppIconError(\n `duplicate variant name ${name} on one asset`,\n platform\n );\n }\n seen.add(name);\n }\n return names;\n};\n\nfunction validateVariantName(\n variant: unknown,\n platform: NodeJS.Platform\n): asserts variant is string {\n if (typeof variant !== \"string\" || !APP_ICON_VARIANT_PATTERN.test(variant)) {\n throw new InvalidAppIconError(\n `variant must match ${APP_ICON_VARIANT_PATTERN}`,\n platform\n );\n }\n}\n\nconst rejectDuplicateVariants = (\n seen: Set<string>,\n variants: readonly string[],\n label: string,\n hostPlatform: NodeJS.Platform\n): void => {\n for (const variant of variants) {\n if (seen.has(variant)) {\n throw new InvalidAppIconError(\n `duplicate ${label} asset for variant ${variant}`,\n hostPlatform\n );\n }\n seen.add(variant);\n }\n};\n\nconst recordVariantPlatforms = (\n variants: Map<string, Set<AppIconPlatform>>,\n names: readonly string[],\n platform: AppIconPlatform\n): void => {\n for (const name of names) {\n const platforms = variants.get(name) ?? new Set<AppIconPlatform>();\n platforms.add(platform);\n variants.set(name, platforms);\n }\n};\n\nconst validateSource = async (\n source: unknown,\n format: \"icns\" | \"ico\" | \"png\" | \"svg\",\n platform: NodeJS.Platform\n): Promise<void> => {\n if (!isRecord(source)) {\n throw new InvalidAppIconError(\n \"asset source must be a file or encoded payload\",\n platform\n );\n }\n let bytes: Uint8Array;\n if (source.type === \"file\") {\n assertExactKeys(source, [\"type\", \"path\"], platform);\n if (typeof source.path !== \"string\" || source.path.trim().length === 0) {\n throw new InvalidAppIconError(\n \"file source path must not be empty\",\n platform\n );\n }\n try {\n bytes = await readFile(source.path);\n } catch (error) {\n throw new InvalidAppIconError(\n `unable to read ${source.path}: ${errorMessage(error)}`,\n platform\n );\n }\n } else if (source.type === \"encoded\") {\n assertExactKeys(source, [\"type\", \"data\"], platform);\n bytes = encodedBytes(source.data, platform);\n } else {\n throw new InvalidAppIconError(\"unsupported app icon source type\", platform);\n }\n if (!matchesFormat(bytes, format)) {\n throw new InvalidAppIconError(\n `source bytes do not contain a valid ${format.toUpperCase()} asset`,\n platform\n );\n }\n};\n\nconst encodedBytes = (data: unknown, platform: NodeJS.Platform): Uint8Array => {\n if (data instanceof Uint8Array && data.byteLength > 0) return data;\n if (\n Array.isArray(data) &&\n data.length > 0 &&\n data.every((value) => Number.isInteger(value) && value >= 0 && value <= 255)\n ) {\n return Uint8Array.from(data);\n }\n throw new InvalidAppIconError(\n \"encoded source must contain one or more bytes in the range 0..255\",\n platform\n );\n};\n\nconst matchesFormat = (\n bytes: Uint8Array,\n format: \"icns\" | \"ico\" | \"png\" | \"svg\"\n): boolean => {\n if (format === \"icns\") return hasPrefix(bytes, [0x69, 0x63, 0x6e, 0x73]);\n if (format === \"ico\") {\n return (\n bytes.length >= 6 && hasPrefix(bytes, [0, 0, 1, 0]) && bytes[4] !== 0\n );\n }\n if (format === \"png\") {\n return hasPrefix(bytes, [137, 80, 78, 71, 13, 10, 26, 10]);\n }\n const source = new TextDecoder()\n .decode(bytes.subarray(0, 4096))\n .replace(/^\\uFEFF/, \"\");\n return /<(?:\\?xml[^>]*>\\s*)?(?:!--[\\s\\S]*?-->\\s*)*svg(?:\\s|>)/i.test(\n source.trimStart()\n );\n};\n\nconst hasPrefix = (bytes: Uint8Array, prefix: readonly number[]): boolean =>\n bytes.length >= prefix.length &&\n prefix.every((byte, index) => bytes[index] === byte);\n\nconst assertExactKeys = (\n record: Record<string, unknown>,\n expected: readonly string[],\n platform: NodeJS.Platform,\n optional: readonly string[] = []\n): void => {\n const actual = Object.keys(record);\n const allowed = new Set([...expected, ...optional]);\n const unexpected = actual.find((key) => !allowed.has(key));\n if (unexpected !== undefined) {\n throw new InvalidAppIconError(\n `unexpected asset field ${unexpected}`,\n platform\n );\n }\n const missing = expected.find((key) => !(key in record));\n if (missing !== undefined) {\n throw new InvalidAppIconError(`missing asset field ${missing}`, platform);\n }\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst errorMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\nconst normalizePlatform = (\n platform: NodeJS.Platform\n): AppIconPlatform | undefined => {\n if (platform === \"darwin\") return \"darwin\";\n if (platform === \"win32\") return \"windows\";\n if (platform === \"linux\") return \"linux\";\n return undefined;\n};\n","// Orthogonal intents (2026-07-19; original user request: pnpm install must be sufficient):\n// 1. Describe package-owned and exact-file native extension artifacts without importing binaries.\n// 2. Resolve platform packages from the declaring facade's dependency closure.\n// 3. Reject missing targets, invalid package metadata, and inaccessible native libraries precisely.\n// 4. Resolve embedded per-target libraries through the staging manifest identity chain with\n// root containment and adversarial rejection (add-ext-dialog section 6.1/section 6.4).\n\nimport { createHash } from \"node:crypto\";\nimport { readFile, realpath } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport type { ExpectedExtensionIdentity } from \"@opentray/spec\";\n\nexport type NativeExtensionArch = \"arm64\" | \"x64\";\nexport type NativeExtensionTarget = `${NodeJS.Platform}-${NativeExtensionArch}`;\n\nexport interface NativeExtensionPackageTarget {\n packageName: string;\n libraryPath: string;\n}\n\nexport interface NativeExtensionIdentitySource {\n packageJsonUrl: string;\n contractManifestUrl: string;\n}\n\nexport interface NativeExtensionPackageArtifact\n extends NativeExtensionIdentitySource {\n kind: \"package\";\n targets: Partial<Record<NativeExtensionTarget, NativeExtensionPackageTarget>>;\n}\n\n/** One embedded per-target library, relative to the facade package root (add-ext-dialog section 6.1). */\nexport interface NativeExtensionEmbeddedTarget {\n libraryPath: string;\n}\n\n/**\n * Frozen embedded staging matrix (add-ext-dialog section 6.4): a facade that\n * embeds platform binaries stages exactly these four targets. The runtime\n * resolver requires the staging manifest to be complete over this matrix\n * (release staging enforces the same set before anything is packed); one\n * missing cell is a manifest-invalid artifact, never a silently thinner\n * catalog.\n */\nexport const NATIVE_EXTENSION_EMBEDDED_TARGET_MATRIX = [\n \"darwin-arm64\",\n \"darwin-x64\",\n \"win32-arm64\",\n \"win32-x64\",\n] as const;\n\n/** One cell of the frozen embedded staging matrix. */\nexport type NativeExtensionEmbeddedMatrixTarget =\n (typeof NATIVE_EXTENSION_EMBEDDED_TARGET_MATRIX)[number];\n\n/**\n * Facade package that ships its platform libraries inside its own tarball via\n * `platforms/<target>/` plus the root-contained staging manifest\n * `platforms/manifest.json` (add-ext-dialog section 6.4 identity chain). No\n * optionalDependencies platform packages are involved. The declared catalog\n * is complete over the frozen matrix: an incomplete embedded catalog is not\n * representable, and the runtime manifest check carries the same\n * completeness rule for untyped consumers.\n */\nexport interface NativeExtensionEmbeddedArtifact\n extends NativeExtensionIdentitySource {\n kind: \"embedded\";\n targets: Record<\n NativeExtensionEmbeddedMatrixTarget,\n NativeExtensionEmbeddedTarget\n >;\n}\n\ninterface NativeExtensionFileArtifactBase {\n kind: \"file\";\n path: string;\n}\n\nexport type NativeExtensionFileArtifact = NativeExtensionFileArtifactBase &\n (\n | {\n expectedIdentity: NativeExtensionExpectedIdentity;\n identitySource?: never;\n }\n | {\n expectedIdentity?: never;\n identitySource: NativeExtensionIdentitySource;\n }\n );\n\nexport type NativeExtensionArtifact =\n | NativeExtensionPackageArtifact\n | NativeExtensionFileArtifact\n | NativeExtensionEmbeddedArtifact;\n\nexport type NativeExtensionExpectedIdentity = ExpectedExtensionIdentity;\n\nexport interface ResolvedNativeExtensionArtifact {\n path: string;\n packageName?: string;\n packageVersion?: string;\n expectedIdentity: NativeExtensionExpectedIdentity;\n target: NativeExtensionTarget;\n}\n\nexport class NativeExtensionArtifactResolutionError extends Error {\n readonly code = \"OPENTRAY_NATIVE_EXTENSION_ARTIFACT_RESOLUTION_FAILED\";\n readonly packageName?: string;\n readonly facadePackageJsonUrl?: string;\n\n constructor(\n message: string,\n readonly target: NativeExtensionTarget,\n options: ErrorOptions & {\n packageName?: string;\n facadePackageJsonUrl?: string;\n } = {}\n ) {\n super(message, options);\n this.name = \"NativeExtensionArtifactResolutionError\";\n if (options.packageName !== undefined) {\n this.packageName = options.packageName;\n }\n if (options.facadePackageJsonUrl !== undefined) {\n this.facadePackageJsonUrl = options.facadePackageJsonUrl;\n }\n }\n}\n\n/**\n * Structured embedded-artifact rejection reasons (add-ext-dialog section 6.1): the\n * four-class replacement of a single resolution-failed error. Consumers match\n * on `reason`/`code`; the human message is not a contract.\n */\nexport type NativeExtensionEmbeddedErrorReason =\n | \"target-unsupported\"\n | \"path-outside-facade\"\n | \"manifest-invalid\"\n | \"library-unreadable\";\n\n/** Stable machine code per embedded rejection reason (same family style as the resolution error). */\nexport const NATIVE_EXTENSION_EMBEDDED_ERROR_CODES: Record<\n NativeExtensionEmbeddedErrorReason,\n string\n> = {\n \"target-unsupported\": \"OPENTRAY_NATIVE_EXTENSION_TARGET_UNSUPPORTED\",\n \"path-outside-facade\": \"OPENTRAY_NATIVE_EXTENSION_PATH_OUTSIDE_FACADE\",\n \"manifest-invalid\": \"OPENTRAY_NATIVE_EXTENSION_MANIFEST_INVALID\",\n \"library-unreadable\": \"OPENTRAY_NATIVE_EXTENSION_LIBRARY_UNREADABLE\",\n};\n\nexport class NativeExtensionEmbeddedArtifactError extends Error {\n readonly reason: NativeExtensionEmbeddedErrorReason;\n readonly code: string;\n readonly target: NativeExtensionTarget;\n readonly facadePackageJsonUrl?: string;\n\n constructor(\n reason: NativeExtensionEmbeddedErrorReason,\n message: string,\n options: ErrorOptions & {\n target: NativeExtensionTarget;\n facadePackageJsonUrl?: string;\n }\n ) {\n super(message, options);\n this.name = \"NativeExtensionEmbeddedArtifactError\";\n this.reason = reason;\n this.code = NATIVE_EXTENSION_EMBEDDED_ERROR_CODES[reason];\n this.target = options.target;\n if (options.facadePackageJsonUrl !== undefined) {\n this.facadePackageJsonUrl = options.facadePackageJsonUrl;\n }\n }\n}\n\n/** Resolve one exact native library from the dependency closure that owns the facade. */\nexport const resolveNativeExtensionArtifact = async (\n artifact: NativeExtensionArtifact,\n platform: NodeJS.Platform = process.platform,\n arch: string = process.arch\n): Promise<ResolvedNativeExtensionArtifact> => {\n const target = nativeExtensionTarget(platform, arch);\n if (artifact.kind === \"file\") {\n return {\n path: await resolveAccessibleLibrary(artifact.path, target),\n expectedIdentity:\n artifact.expectedIdentity ??\n (await resolveExpectedIdentity(artifact.identitySource, target)),\n target,\n };\n }\n\n if (artifact.kind === \"embedded\") {\n return resolveEmbeddedExtensionArtifact(artifact, target);\n }\n\n const packageTarget = artifact.targets[target];\n if (packageTarget === undefined) {\n throw new NativeExtensionArtifactResolutionError(\n `native extension does not support target ${target}`,\n target\n );\n }\n\n const expectedIdentity = await resolveExpectedIdentity(artifact, target);\n\n const resolveFromFacade = createRequire(artifact.packageJsonUrl);\n let platformPackageJsonPath: string;\n try {\n platformPackageJsonPath = resolveFromFacade.resolve(\n `${packageTarget.packageName}/package.json`\n );\n } catch (cause) {\n throw new NativeExtensionArtifactResolutionError(\n `unable to resolve native extension package \"${packageTarget.packageName}\" for ${target} from ${artifact.packageJsonUrl}`,\n target,\n {\n cause,\n packageName: packageTarget.packageName,\n facadePackageJsonUrl: artifact.packageJsonUrl,\n }\n );\n }\n\n const manifest = await readPlatformPackageManifest(\n platformPackageJsonPath,\n target,\n packageTarget.packageName\n );\n const libraryPath = join(dirname(platformPackageJsonPath), packageTarget.libraryPath);\n return {\n path: await resolveAccessibleLibrary(libraryPath, target, packageTarget.packageName),\n packageName: packageTarget.packageName,\n packageVersion: manifest.version,\n expectedIdentity,\n target,\n };\n};\n\nconst resolveExpectedIdentity = async (\n source: NativeExtensionIdentitySource,\n target: NativeExtensionTarget\n): Promise<NativeExtensionExpectedIdentity> => {\n const [facadeManifest, contractManifest] = await Promise.all([\n readFacadePackageManifest(source.packageJsonUrl, target),\n readExtensionContractManifest(source.contractManifestUrl, target),\n ]);\n const [os, arch] = splitTarget(target);\n return {\n extensionName: contractManifest.extensionName,\n artifactSetVersion: facadeManifest.version,\n contractFingerprint: contractManifest.contractFingerprint,\n target: { os, arch },\n };\n};\n\n// ---------------------------------------------------------------------------\n// Embedded artifacts (add-ext-dialog section 6.1/section 6.4): the facade ships its own\n// platform libraries plus a root-contained staging manifest carrying the\n// identity chain (per-target path, SHA-256, buildIdentity, facade version,\n// contract fingerprint). Resolution validates containment on every path,\n// cross-checks the manifest against the facade/contract manifests, hashes the\n// selected library's real bytes, and feeds sha256/buildIdentity into the\n// LoadExt expected identity (the broker re-hashes before dlopen).\n// ---------------------------------------------------------------------------\n\n/** Fixed location of the embedded staging manifest inside the facade package. */\nexport const EMBEDDED_STAGING_MANIFEST_PATH = \"platforms/manifest.json\";\n\ninterface EmbeddedStagingManifestTargetEntry {\n path: string;\n sha256: string;\n buildIdentity: string;\n}\n\ninterface EmbeddedStagingManifest {\n facadeVersion: string;\n contractFingerprint: string;\n targets: Record<string, EmbeddedStagingManifestTargetEntry>;\n}\n\nconst sha256HexPattern = /^[a-f0-9]{64}$/u;\n\nconst isEmbeddedMatrixTarget = (\n target: NativeExtensionTarget\n): target is NativeExtensionEmbeddedMatrixTarget =>\n (NATIVE_EXTENSION_EMBEDDED_TARGET_MATRIX as readonly string[]).includes(target);\n\nconst lexicalContained = (root: string, candidate: string): boolean => {\n const rel = relative(root, candidate);\n if (rel.length === 0) {\n return false;\n }\n return !(rel === \"..\" || rel.startsWith(`..${sep}`) || isAbsolute(rel));\n};\n\nconst resolveEmbeddedExtensionArtifact = async (\n artifact: NativeExtensionEmbeddedArtifact,\n target: NativeExtensionTarget\n): Promise<ResolvedNativeExtensionArtifact> => {\n const facadePackageJsonUrl = artifact.packageJsonUrl;\n const embeddedError = (\n reason: NativeExtensionEmbeddedErrorReason,\n message: string,\n options: { cause?: unknown } = {}\n ): NativeExtensionEmbeddedArtifactError =>\n new NativeExtensionEmbeddedArtifactError(reason, message, {\n target,\n facadePackageJsonUrl,\n ...(options.cause === undefined ? {} : { cause: options.cause }),\n });\n\n // Targets outside the frozen matrix are unsupported platforms for the\n // embedded artifact kind (linux resolves here, for example).\n if (!isEmbeddedMatrixTarget(target)) {\n throw embeddedError(\n \"target-unsupported\",\n `embedded native extension supports only the frozen staging matrix (${NATIVE_EXTENSION_EMBEDDED_TARGET_MATRIX.join(\", \")}); ${target} is outside it`\n );\n }\n const embeddedTarget = artifact.targets[target];\n if (embeddedTarget === undefined) {\n // Unreachable for typed callers (the descriptor is complete over the\n // matrix); untyped consumers still get the structured rejection.\n throw embeddedError(\n \"target-unsupported\",\n `embedded native extension does not declare target ${target}`\n );\n }\n\n const facadeRoot = dirname(fileURLToPath(new URL(facadePackageJsonUrl)));\n\n // Lexical containment first: absolute and traversal (`../../outside`)\n // libraryPath values are rejected before touching the filesystem.\n if (isAbsolute(embeddedTarget.libraryPath)) {\n throw embeddedError(\n \"path-outside-facade\",\n `embedded library path must be relative to the facade package root: ${embeddedTarget.libraryPath}`\n );\n }\n const candidatePath = resolve(facadeRoot, embeddedTarget.libraryPath);\n if (!lexicalContained(facadeRoot, candidatePath)) {\n throw embeddedError(\n \"path-outside-facade\",\n `embedded library path escapes the facade package root: ${embeddedTarget.libraryPath}`\n );\n }\n\n // Identity-chain inputs: facade package.json and contract.json. Any read or\n // shape failure here means the staging identity chain cannot be established.\n const [facadeManifest, contractManifest] = await Promise.all([\n readEmbeddedJson(facadePackageJsonUrl, embeddedError).then((parsed) => {\n if (!isFacadePackageManifest(parsed)) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded facade package manifest is invalid at ${facadePackageJsonUrl}`\n );\n }\n return parsed;\n }),\n readEmbeddedJson(artifact.contractManifestUrl, embeddedError).then((parsed) => {\n if (!isExtensionContractManifest(parsed)) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded extension contract manifest is invalid at ${artifact.contractManifestUrl}`\n );\n }\n return parsed;\n }),\n ]);\n\n const manifestPath = join(facadeRoot, EMBEDDED_STAGING_MANIFEST_PATH);\n const manifest = await readEmbeddedJson(\n pathToFileURL(manifestPath).href,\n embeddedError\n ).then((parsed) => {\n if (!isEmbeddedStagingManifest(parsed)) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest is invalid at ${manifestPath}`\n );\n }\n return parsed;\n });\n\n if (manifest.facadeVersion !== facadeManifest.version) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest facade version ${manifest.facadeVersion} does not match facade package version ${facadeManifest.version}`\n );\n }\n if (manifest.contractFingerprint !== contractManifest.contractFingerprint) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest contract fingerprint does not match the contract manifest at ${artifact.contractManifestUrl}`\n );\n }\n // Manifest completeness over the frozen matrix (section 6.4): every cell\n // must be present, and no key outside the matrix may appear. An incomplete\n // or widened manifest is a staging-chain break, not a thinner catalog.\n for (const matrixTarget of NATIVE_EXTENSION_EMBEDDED_TARGET_MATRIX) {\n if (manifest.targets[matrixTarget] === undefined) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest is missing required matrix target ${matrixTarget}`\n );\n }\n }\n for (const manifestTarget of Object.keys(manifest.targets)) {\n if (!isEmbeddedMatrixTarget(manifestTarget as NativeExtensionTarget)) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest declares target ${manifestTarget} outside the frozen staging matrix`\n );\n }\n if (\n artifact.targets[manifestTarget as NativeExtensionEmbeddedMatrixTarget] ===\n undefined\n ) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest declares undeclared target ${manifestTarget}`\n );\n }\n }\n const manifestEntry = manifest.targets[target];\n if (manifestEntry === undefined) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest has no entry for target ${target}`\n );\n }\n\n if (isAbsolute(manifestEntry.path)) {\n throw embeddedError(\n \"path-outside-facade\",\n `embedded staging manifest library path must be relative to the facade package root: ${manifestEntry.path}`\n );\n }\n const manifestLibraryPath = resolve(facadeRoot, manifestEntry.path);\n if (!lexicalContained(facadeRoot, manifestLibraryPath)) {\n throw embeddedError(\n \"path-outside-facade\",\n `embedded staging manifest library path escapes the facade package root: ${manifestEntry.path}`\n );\n }\n if (manifestLibraryPath !== candidatePath) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest path ${manifestEntry.path} does not match the declared library path ${embeddedTarget.libraryPath} for target ${target}`\n );\n }\n\n // Realpath containment catches symlink escapes: a link inside the facade\n // that resolves outside is rejected even though it is lexically contained.\n const realRoot = await realpath(facadeRoot).catch(() => facadeRoot);\n let realCandidate: string;\n try {\n realCandidate = await realpath(candidatePath);\n } catch (cause) {\n throw embeddedError(\n \"library-unreadable\",\n `embedded native extension library is not accessible at ${candidatePath}`,\n { cause }\n );\n }\n if (!lexicalContained(realRoot, realCandidate)) {\n throw embeddedError(\n \"path-outside-facade\",\n `embedded library resolves outside the facade package root: ${embeddedTarget.libraryPath}`\n );\n }\n\n // Hash the real bytes: a replaced library must never pass a manifest claim\n // (the broker re-checks the same value before dlopen).\n let libraryBytes: Buffer;\n try {\n libraryBytes = await readFile(realCandidate);\n } catch (cause) {\n throw embeddedError(\n \"library-unreadable\",\n `embedded native extension library is not readable at ${realCandidate}`,\n { cause }\n );\n }\n const sha256 = createHash(\"sha256\").update(libraryBytes).digest(\"hex\");\n if (sha256 !== manifestEntry.sha256) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded library bytes do not match the staging manifest SHA-256 for target ${target}`\n );\n }\n\n const [os, arch] = splitTarget(target);\n const expectedIdentity: NativeExtensionExpectedIdentity = {\n extensionName: contractManifest.extensionName,\n artifactSetVersion: facadeManifest.version,\n contractFingerprint: contractManifest.contractFingerprint,\n target: { os, arch },\n sha256,\n buildIdentity: manifestEntry.buildIdentity,\n };\n return { path: realCandidate, expectedIdentity, target };\n};\n\nconst readEmbeddedJson = async (\n url: string,\n embeddedError: (\n reason: NativeExtensionEmbeddedErrorReason,\n message: string,\n options?: { cause?: unknown }\n ) => NativeExtensionEmbeddedArtifactError\n): Promise<unknown> => {\n try {\n return JSON.parse(await readFile(new URL(url), \"utf8\"));\n } catch (cause) {\n throw embeddedError(\n \"manifest-invalid\",\n `unable to read embedded identity-chain manifest at ${url}`,\n { cause }\n );\n }\n};\n\nconst isEmbeddedStagingManifest = (\n value: unknown\n): value is EmbeddedStagingManifest => {\n if (!isRecordLike(value) || !isRecordLike(value.targets)) {\n return false;\n }\n if (\n typeof value.facadeVersion !== \"string\" ||\n typeof value.contractFingerprint !== \"string\"\n ) {\n return false;\n }\n for (const entry of Object.values(value.targets)) {\n if (\n !isRecordLike(entry) ||\n typeof entry.path !== \"string\" ||\n typeof entry.sha256 !== \"string\" ||\n !sha256HexPattern.test(entry.sha256) ||\n typeof entry.buildIdentity !== \"string\" ||\n entry.buildIdentity.length === 0\n ) {\n return false;\n }\n }\n return true;\n};\n\nconst isRecordLike = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst nativeExtensionTarget = (\n platform: NodeJS.Platform,\n arch: string\n): NativeExtensionTarget => {\n if (arch !== \"arm64\" && arch !== \"x64\") {\n throw new Error(`unsupported native extension architecture: ${arch}`);\n }\n return `${platform}-${arch}`;\n};\n\ninterface PlatformPackageManifest {\n name: string;\n version: string;\n os?: string[];\n cpu?: string[];\n}\n\ninterface FacadePackageManifest {\n name: string;\n version: string;\n}\n\ninterface ExtensionContractManifest {\n extensionName: string;\n contractFingerprint: string;\n}\n\nconst readFacadePackageManifest = async (\n packageJsonUrl: string,\n target: NativeExtensionTarget\n): Promise<FacadePackageManifest> => {\n const parsed = await readJsonUrl(packageJsonUrl, target, \"facade package manifest\");\n if (!isFacadePackageManifest(parsed)) {\n throw new NativeExtensionArtifactResolutionError(\n `native extension facade manifest is invalid at ${packageJsonUrl}`,\n target,\n { facadePackageJsonUrl: packageJsonUrl }\n );\n }\n return parsed;\n};\n\nconst readExtensionContractManifest = async (\n contractManifestUrl: string,\n target: NativeExtensionTarget\n): Promise<ExtensionContractManifest> => {\n const parsed = await readJsonUrl(\n contractManifestUrl,\n target,\n \"extension contract manifest\"\n );\n if (!isExtensionContractManifest(parsed)) {\n throw new NativeExtensionArtifactResolutionError(\n `native extension contract manifest is invalid at ${contractManifestUrl}`,\n target\n );\n }\n return parsed;\n};\n\nconst readJsonUrl = async (\n url: string,\n target: NativeExtensionTarget,\n label: string\n): Promise<unknown> => {\n try {\n return JSON.parse(await readFile(new URL(url), \"utf8\"));\n } catch (cause) {\n throw new NativeExtensionArtifactResolutionError(\n `unable to read ${label} at ${url}`,\n target,\n { cause }\n );\n }\n};\n\nconst readPlatformPackageManifest = async (\n packageJsonPath: string,\n target: NativeExtensionTarget,\n packageName: string\n): Promise<PlatformPackageManifest> => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(await readFile(packageJsonPath, \"utf8\"));\n } catch (cause) {\n throw new NativeExtensionArtifactResolutionError(\n `unable to read native extension package manifest at ${packageJsonPath}`,\n target,\n { cause, packageName }\n );\n }\n if (!isPlatformPackageManifest(parsed) || parsed.name !== packageName) {\n throw new NativeExtensionArtifactResolutionError(\n `native extension package manifest at ${packageJsonPath} does not identify ${packageName}`,\n target,\n { packageName }\n );\n }\n const [platform, arch] = splitTarget(target);\n if (parsed.os !== undefined && !parsed.os.includes(platform)) {\n throw new NativeExtensionArtifactResolutionError(\n `native extension package ${packageName} does not support os ${platform}`,\n target,\n { packageName }\n );\n }\n if (parsed.cpu !== undefined && !parsed.cpu.includes(arch)) {\n throw new NativeExtensionArtifactResolutionError(\n `native extension package ${packageName} does not support cpu ${arch}`,\n target,\n { packageName }\n );\n }\n return parsed;\n};\n\nconst isPlatformPackageManifest = (\n value: unknown\n): value is PlatformPackageManifest =>\n typeof value === \"object\" &&\n value !== null &&\n \"name\" in value &&\n typeof value.name === \"string\" &&\n \"version\" in value &&\n typeof value.version === \"string\" &&\n (!(\"os\" in value) ||\n (Array.isArray(value.os) && value.os.every((item) => typeof item === \"string\"))) &&\n (!(\"cpu\" in value) ||\n (Array.isArray(value.cpu) && value.cpu.every((item) => typeof item === \"string\")));\n\nconst isFacadePackageManifest = (value: unknown): value is FacadePackageManifest =>\n typeof value === \"object\" &&\n value !== null &&\n \"name\" in value &&\n typeof value.name === \"string\" &&\n \"version\" in value &&\n typeof value.version === \"string\";\n\nconst isExtensionContractManifest = (\n value: unknown\n): value is ExtensionContractManifest =>\n typeof value === \"object\" &&\n value !== null &&\n \"extensionName\" in value &&\n typeof value.extensionName === \"string\" &&\n \"contractFingerprint\" in value &&\n typeof value.contractFingerprint === \"string\";\n\nconst splitTarget = (\n target: NativeExtensionTarget\n): [NodeJS.Platform, NativeExtensionArch] => {\n const separator = target.lastIndexOf(\"-\");\n return [\n target.slice(0, separator) as NodeJS.Platform,\n target.slice(separator + 1) as NativeExtensionArch,\n ];\n};\n\nconst resolveAccessibleLibrary = async (\n path: string,\n target: NativeExtensionTarget,\n packageName?: string\n): Promise<string> => {\n try {\n return await realpath(path);\n } catch (cause) {\n throw new NativeExtensionArtifactResolutionError(\n `native extension library is not accessible at ${path}`,\n target,\n {\n cause,\n ...(packageName === undefined ? {} : { packageName }),\n }\n );\n }\n};\n","import {\n PROTOCOL_VERSION,\n type AppEvent,\n type ClientFrame,\n type ClientRequestFrame,\n type AppIdentity,\n type AppIcon,\n type ExtensionEnvelope,\n type ExtOperationPayload,\n type Icon,\n type Menu,\n type RequestId,\n type ServerFrame,\n type Tooltip,\n type TrayBoundsResult,\n type TrayEvent,\n type TrayId,\n type TrayOptions,\n} from \"@opentray/spec\";\nimport {\n normalizeAppIcon,\n selectAppIconVariant,\n validateAppIcon,\n} from \"./app-icon\";\n\nimport {\n resolveNativeExtensionArtifact,\n type NativeExtensionArtifact,\n} from \"./native-extension-artifact\";\n\n/**\n * Optional per-call transport budget (W1, harden-transport-robustness): a\n * transport that enforces deadlines settles the call with a typed\n * `TransportTimeoutError` when no correlated reply arrives within\n * `deadlineMs`. The parameter is also the teardown-class marking channel\n * later phases read to keep caller-initiated teardown out of recovery — the\n * budget class, not a new protocol flag, distinguishes the call.\n */\nexport interface TransportRequestOptions {\n /** Per-call deadline budget in milliseconds; transports default to the interactive class. */\n deadlineMs?: number;\n}\n\nexport interface OpenTrayTransport {\n request(frame: ClientRequestFrame, options?: TransportRequestOptions): Promise<ServerFrame>;\n}\n\n/**\n * Default per-call deadline classes (W1, harden-transport-robustness;\n * field-validated against the pnpm-pub silent-wedge incident): interactive\n * calls settle or reject within 5 s, teardown-class frames within 2 s, and\n * bootstrap-class round-trips (connection init and first bring-up) within\n * 10 s. They live beside `OpenTrayTransport` because they are part of the\n * generic transport call contract, not of one broker implementation.\n */\nexport const INTERACTIVE_CALL_DEADLINE_MS = 5_000;\nexport const TEARDOWN_CALL_DEADLINE_MS = 2_000;\nexport const BOOTSTRAP_CALL_DEADLINE_MS = 10_000;\n\n/**\n * Typed per-call deadline rejection: the transport's budget for one\n * round-trip expired without a correlated reply. This is the third\n * rejection class, distinct from transport-lost (the plain\n * `BROKER_CONNECTION_CLOSED_MESSAGE` sentinel family, or the typed\n * `extension_transport_closed` for accepted deferred operations) and from\n * broker-rejected (`BrokerServerError` / `ExtensionOperationError`). An\n * expiry settles exactly one call; it never declares the transport dead —\n * death stays a socket-close/error (and, later, heartbeat) verdict.\n */\nexport class TransportTimeoutError extends Error {\n readonly requestId: RequestId;\n readonly deadlineMs: number;\n\n constructor(requestId: RequestId, deadlineMs: number) {\n super(`transport call deadline expired after ${deadlineMs}ms: ${requestId}`);\n this.name = \"TransportTimeoutError\";\n this.requestId = requestId;\n this.deadlineMs = deadlineMs;\n }\n}\n\nexport type OpenTrayEventFrame = Extract<\n ServerFrame,\n { type: \"event\" | \"app-event\" | \"ext-event\" }\n>;\n\n/**\n * Supervision state vocabulary (W6 Tier 1, harden-transport-robustness):\n * `healthy` (a live generation is serving), `recovering` (uninvited death was\n * declared and in-process recovery is running), `abandoned` (terminal — the\n * recovery budget is exhausted and every later call fails fast with the\n * typed `TransportAbandonedError`). Edge-triggered through\n * `onTransportStateChange`; the initial `healthy` state never fires.\n */\nexport type TransportState = \"healthy\" | \"recovering\" | \"abandoned\";\n\n/**\n * Context handed to a facade rebuild callback after a supervised recovery\n * (W4): the fresh generation number and the new generation's broker session\n * id, so extension facades can re-create session-attributed native state\n * against the live session instead of the dead one.\n */\nexport interface TransportRebuildContext {\n readonly generation: number;\n readonly sessionId: string | undefined;\n}\n\nexport interface OpenTrayEventSource {\n onEvent(listener: (frame: OpenTrayEventFrame) => void): () => void;\n}\n\nexport interface OpenTrayConnection\n extends OpenTrayTransport,\n OpenTrayEventSource {}\n\nexport interface OpenTrayClient {\n createTray(options: TrayOptions): Promise<TrayHandle>;\n}\n\n/**\n * Public result contract of one extension request (add-ext-dialog section\n * 5.1 / section 5.7 ruling #8): immediate commands settle with the response\n * envelopes; deferred commands settle with exactly one terminal frame, whose\n * `result` payload value is surfaced as `value` (an `error` terminal rejects\n * with `ExtensionOperationError` before this type is produced).\n */\nexport type ExtensionRequestResult<TValue = unknown> =\n | { kind: \"immediate\"; events: ExtensionEnvelope[] }\n | { kind: \"terminal\"; operationId: string; value: TValue };\n\n/**\n * Typed rejection for synchronous broker error frames: carries the wire\n * `code`, the structured `details` payload when the error family freezes one,\n * and the transport cause when relevant. Consumers match on `code`; the human\n * `message` is not a contract. The deferred-operation rejection counterpart\n * is `ExtensionOperationError` (same `{ code, message, details }` family).\n */\nexport class BrokerServerError extends Error {\n readonly code: string;\n readonly details?: unknown;\n\n constructor(\n code: string,\n message: string,\n options: { details?: unknown; cause?: unknown } = {}\n ) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = \"BrokerServerError\";\n this.code = code;\n if (options.details !== undefined) {\n this.details = options.details;\n }\n }\n}\n\nexport interface OpenTrayEventfulClient extends OpenTrayClient {\n createTray(options: TrayOptions): Promise<EventfulTrayHandle>;\n}\n\nexport interface TrayHandle {\n trayId: TrayId;\n app: AppHandle;\n getBounds(): Promise<TrayBoundsResult>;\n setMenu(menu: Menu): Promise<void>;\n setTooltip(tooltip: Tooltip): Promise<void>;\n setIcon(icon: Icon): Promise<void>;\n loadExtension(options: ExtensionLoadOptions): Promise<void>;\n commandExtension(ext: string, data: unknown): Promise<void>;\n requestExtension<TValue = unknown>(\n ext: string,\n data: unknown\n ): Promise<ExtensionRequestResult<TValue>>;\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions\n ): TrayHandle & TCapability;\n destroy(): Promise<void>;\n}\n\nexport interface AppHandle {\n readonly appId: string;\n getName(): Promise<string>;\n setName(name: string): Promise<string>;\n getAppIcon(): Promise<AppIcon | null>;\n getAppIconVariant(): Promise<string | null>;\n setAppIcon(iconOrVariant: AppIcon | string | null): Promise<void>;\n}\n\nexport type TrayScopedEvent = Exclude<TrayEvent, { type: \"ready\" }>;\nexport type TrayEventType = TrayScopedEvent[\"type\"];\nexport type TrayEventByType<TEvent extends TrayEventType> = Extract<\n TrayScopedEvent,\n { type: TEvent }\n>;\n\nexport interface EventfulTrayHandle extends TrayHandle {\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions\n ): EventfulTrayHandle & TCapability;\n listenExtension<TData = unknown>(\n ext: string,\n handler: (event: ExtensionEnvelope<TData>) => void\n ): () => void;\n listen<TEvent extends TrayEventType>(\n event: TEvent,\n handler: (event: TrayEventByType<TEvent>) => void\n ): () => void;\n onMenuClick(\n handler: (event: TrayEventByType<\"menuClick\">) => void\n ): () => void;\n onTrayClick(\n handler: (event: TrayEventByType<\"trayClick\">) => void\n ): () => void;\n onTrayDoubleClick(\n handler: (event: TrayEventByType<\"trayDoubleClick\">) => void\n ): () => void;\n onAppReopenRequested(\n handler: (event: Extract<AppEvent, { type: \"reopenRequested\" }>) => void\n ): () => void;\n /**\n * Terminal broker-connection-death notification (D3,\n * harden-lifecycle-ownership). Present when the transport publishes its own\n * death signal (the local broker connection always does); fires exactly\n * once, after which pending requests have rejected, event delivery has\n * stopped, and every later request rejects instead of hanging.\n */\n onConnectionDead?(handler: (error: Error) => void): () => void;\n /**\n * Tier 1 transport-supervision state projection (W6,\n * harden-transport-robustness). Present when the underlying transport is\n * supervised (the `createTray` runtime path always supervises): fires\n * edge-triggered `healthy | recovering | abandoned` transitions across\n * connection generations; the current value is not replayed.\n */\n onTransportStateChange?(handler: (state: TransportState) => void): () => void;\n /**\n * Facade rebuild registration (W4, harden-transport-robustness). Present\n * on supervised transports: extension facades register one callback that\n * re-creates their declarative native state (windows, styles,\n * subscriptions) after the supervisor recovered a fresh generation.\n * Callbacks run in registration order after the core journal replay.\n */\n registerTransportRebuild?(\n rebuild: (context: TransportRebuildContext) => Promise<void>\n ): void;\n}\n\nexport interface ExtensionLoadOptions {\n name: string;\n artifact: NativeExtensionArtifact;\n mountId?: string;\n}\n\nexport interface TrayExtensionMountSpec {\n name?: string;\n artifact?: NativeExtensionArtifact;\n mountId?: string;\n}\n\nexport interface TrayExtensionContext {\n readonly appId: string;\n readonly trayId: TrayId;\n /**\n * Broker session identity extracted from the connection's Ready frame,\n * when the transport publishes one (the local broker connection sets it\n * after the handshake). Extensions attribute session-owned native state\n * with it — e.g. `@opentray/ext-webview` window owner tuples. Transports\n * without the field stay unattributed and keep legacy semantics.\n */\n readonly sessionId?: string;\n readonly name: string;\n readonly artifact: NativeExtensionArtifact;\n readonly mountId: string;\n ensureLoaded(): Promise<void>;\n command(data: unknown): Promise<void>;\n request<TValue = unknown>(data: unknown): Promise<ExtensionRequestResult<TValue>>;\n}\n\nexport interface TrayExtension<\n TCapability extends object,\n TOptions = undefined\n> {\n readonly name: string;\n readonly artifact: NativeExtensionArtifact;\n resolveMount?(options: TOptions | undefined): TrayExtensionMountSpec;\n extend(\n tray: TrayHandle,\n context: TrayExtensionContext,\n options: TOptions | undefined\n ): TCapability;\n}\n\nexport const createInitFrame = (clientVersion: string): ClientFrame => ({\n type: \"init\",\n protocolVersion: PROTOCOL_VERSION,\n clientVersion,\n});\n\nexport interface CreateClientOptions {\n requestIdPrefix?: string;\n appOptions?: {\n name?: string;\n appIcon?: AppIcon;\n };\n}\n\nexport function createClient(\n transport: OpenTrayConnection,\n options?: CreateClientOptions\n): OpenTrayEventfulClient;\nexport function createClient(\n transport: OpenTrayTransport,\n options?: CreateClientOptions\n): OpenTrayClient;\nexport function createClient(\n transport: OpenTrayTransport,\n options: CreateClientOptions = {}\n): OpenTrayClient | OpenTrayEventfulClient {\n const nextRequestId = createRequestIdFactory(\n options.requestIdPrefix ?? \"opentray\"\n );\n let appPromise: Promise<{ app: { appId: string }; handle: AppHandle }> | undefined;\n\n const ensureApp = async (\n trayOptions: TrayOptions\n ): Promise<{ app: { appId: string }; handle: AppHandle }> => {\n appPromise ??= (async () => {\n const app = await resolveDefaultAppRef(transport, nextRequestId);\n const handle = createAppHandle(transport, app.appId, nextRequestId);\n const configured = options.appOptions;\n if (configured?.name !== undefined) {\n await handle.setName(configured.name);\n }\n if (configured?.appIcon !== undefined) {\n await handle.setAppIcon(configured.appIcon);\n }\n return { app, handle };\n })().catch((error: unknown) => {\n appPromise = undefined;\n throw error;\n });\n return appPromise;\n };\n\n return {\n async createTray(options: TrayOptions): Promise<TrayHandle> {\n const { app } = await ensureApp(options);\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"create-tray\",\n requestId,\n app,\n tray: options,\n });\n const frame = expectResponse(response, requestId, \"tray-created\");\n return createTrayHandle(\n transport,\n app.appId,\n frame.trayId ?? options.id,\n nextRequestId\n );\n },\n };\n}\n\nexport function createTrayHandle(\n transport: OpenTrayConnection,\n appId: string,\n trayId: TrayId,\n nextRequestId?: () => RequestId\n): EventfulTrayHandle;\nexport function createTrayHandle(\n transport: OpenTrayTransport,\n appId: string,\n trayId: TrayId,\n nextRequestId?: () => RequestId\n): TrayHandle;\nexport function createTrayHandle(\n transport: OpenTrayTransport,\n appId: string,\n trayId: TrayId,\n nextRequestId: () => RequestId = createRequestIdFactory(\"opentray\")\n): TrayHandle | EventfulTrayHandle {\n // The local broker connection publishes the Ready frame's session id on\n // the transport itself (after init); read it once here so extension\n // contexts can attribute session-owned state (ext-webview owner tuples).\n const sessionId = readTransportSessionId(transport);\n let nextMountOrdinal = 1;\n const nextMountId = (extensionName: string): string => {\n const mountId = `${formatMountIdComponent(\n extensionName\n )}.${formatMountIdComponent(trayId)}.${nextMountOrdinal}`;\n nextMountOrdinal += 1;\n return mountId;\n };\n const handle: TrayHandle = {\n trayId,\n app: createAppHandle(transport, appId, nextRequestId),\n async getBounds(): Promise<TrayBoundsResult> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"get-tray-bounds\",\n requestId,\n appId,\n trayId,\n });\n return expectResponse(response, requestId, \"tray-bounds\").bounds;\n },\n async setMenu(menu: Menu): Promise<void> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-tray-menu\",\n requestId,\n appId,\n trayId,\n menu,\n });\n expectResponse(response, requestId, \"ack\");\n },\n async setTooltip(tooltip: Tooltip): Promise<void> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-tray-tooltip\",\n requestId,\n appId,\n trayId,\n tooltip,\n });\n expectResponse(response, requestId, \"ack\");\n },\n async setIcon(icon: Icon): Promise<void> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-tray-icon\",\n requestId,\n appId,\n trayId,\n icon,\n });\n expectResponse(response, requestId, \"ack\");\n },\n async loadExtension(options): Promise<void> {\n const requestId = nextRequestId();\n const resolved = await resolveNativeExtensionArtifact(options.artifact);\n const response = await transport.request({\n type: \"load-ext\",\n requestId,\n appId,\n name: options.name,\n path: resolved.path,\n expectedIdentity: resolved.expectedIdentity,\n ...(options.mountId === undefined ? {} : { mountId: options.mountId }),\n });\n expectResponse(response, requestId, \"ack\");\n },\n async commandExtension(ext: string, data: unknown): Promise<void> {\n await this.requestExtension(ext, data);\n },\n async requestExtension<TValue = unknown>(\n ext: string,\n data: unknown\n ): Promise<ExtensionRequestResult<TValue>> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"ext-command\",\n requestId,\n appId,\n trayId,\n ext,\n data,\n });\n if (response.type === \"ack\") {\n expectResponse(response, requestId, \"ack\");\n return { kind: \"immediate\", events: [] };\n }\n // A successful deferred terminal settles here: the transport correlates\n // the terminal through the operation map (no requestId on the wire) and\n // an `error` terminal has already rejected with ExtensionOperationError.\n if (response.type === \"ext-operation-terminal\") {\n const payload: ExtOperationPayload = response.payload;\n if (payload.kind !== \"result\") {\n // Defensive only: transports reject error terminals themselves, so a\n // typed error payload reaching this branch is a transport contract\n // violation, not a user-visible deferred failure.\n throw new Error(\n `transport settled a deferred request with an error terminal for ${requestId}`\n );\n }\n return { kind: \"terminal\", operationId: response.operationId, value: payload.value as TValue };\n }\n const result = expectResponse(response, requestId, \"ext-command-result\");\n return { kind: \"immediate\", events: result.events };\n },\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions\n ): TrayHandle & TCapability {\n const context = createTrayExtensionContext(\n handle,\n appId,\n extension,\n options,\n nextMountId,\n sessionId\n );\n const capability = extension.extend(handle, context, options);\n return Object.assign({}, handle, capability);\n },\n async destroy(): Promise<void> {\n const requestId = nextRequestId();\n // Teardown-class budget (W3, harden-transport-robustness): the\n // transport-level deadline bounds this round-trip so a wedged broker can\n // never wedge consumer shutdown; no application-layer race wraps it.\n // `deadlineMs` doubles as the teardown-class marker later phases read to\n // keep caller-initiated teardown from ever triggering recovery.\n const response = await transport.request(\n {\n type: \"destroy-tray\",\n requestId,\n appId,\n trayId,\n },\n { deadlineMs: TEARDOWN_CALL_DEADLINE_MS },\n );\n expectResponse(response, requestId, \"ack\");\n },\n };\n if (!isOpenTrayEventSource(transport)) {\n return handle;\n }\n return attachEventfulTrayHandle(handle, transport, appId, nextMountId, sessionId);\n};\n\nconst attachEventfulTrayHandle = (\n handle: TrayHandle,\n source: OpenTrayEventSource,\n appId: string,\n nextMountId: (extensionName: string) => string,\n sessionId: string | undefined\n): EventfulTrayHandle => {\n const listen: EventfulTrayHandle[\"listen\"] = (event, handler) =>\n source.onEvent((frame) => {\n if (frame.type !== \"event\" || frame.event.type !== event) {\n return;\n }\n if (!isOwnedTrayEvent(frame.event, appId, handle.trayId)) {\n return;\n }\n handler(frame.event as TrayEventByType<typeof event>);\n });\n\n // D3: surface the transport's terminal death signal when it publishes one,\n // so eventful consumers and extensions observe broker death instead of\n // silently losing delivery.\n const onConnectionDead = isConnectionDeadSource(source)\n ? (handler: (error: Error) => void) => source.onConnectionDead(handler)\n : undefined;\n\n // W6/W4: surface the supervision state projection and the facade rebuild\n // registration when the transport is supervised (the createTray runtime\n // path always is). Same structural-capability pattern as onConnectionDead.\n const transportSupervision = isTransportSupervisionSource(source)\n ? {\n onTransportStateChange: (handler: (state: TransportState) => void) =>\n source.onTransportStateChange(handler),\n registerTransportRebuild: (rebuild: (context: TransportRebuildContext) => Promise<void>) =>\n source.registerTransportRebuild(rebuild),\n }\n : undefined;\n\n const eventful: EventfulTrayHandle = {\n ...handle,\n ...(onConnectionDead === undefined ? {} : { onConnectionDead }),\n ...(transportSupervision === undefined ? {} : transportSupervision),\n listenExtension<TData = unknown>(\n ext: string,\n handler: (event: ExtensionEnvelope<TData>) => void\n ) {\n return source.onEvent((frame) => {\n if (frame.type !== \"ext-event\" || frame.ext !== ext) {\n return;\n }\n if (frame.appId !== appId || frame.trayId !== handle.trayId) {\n return;\n }\n handler({\n scope: { appId: frame.appId, trayId: frame.trayId, ext: frame.ext },\n data: frame.data as TData,\n });\n });\n },\n listen,\n onMenuClick(handler) {\n return listen(\"menuClick\", handler);\n },\n onTrayClick(handler) {\n return listen(\"trayClick\", handler);\n },\n onTrayDoubleClick(handler) {\n return listen(\"trayDoubleClick\", handler);\n },\n onAppReopenRequested(handler) {\n return source.onEvent((frame) => {\n if (\n frame.type === \"app-event\" &&\n frame.event.type === \"reopenRequested\" &&\n frame.event.appId === appId\n ) {\n handler(frame.event);\n }\n });\n },\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions\n ): EventfulTrayHandle & TCapability {\n const context = createTrayExtensionContext(\n eventful,\n appId,\n extension,\n options,\n nextMountId,\n sessionId\n );\n const capability = extension.extend(eventful, context, options);\n return Object.assign({}, eventful, capability);\n },\n };\n return eventful;\n};\n\nconst isOwnedTrayEvent = (\n event: TrayEvent,\n appId: string,\n trayId: string\n): event is TrayScopedEvent =>\n event.type !== \"ready\" && event.appId === appId && event.trayId === trayId;\n\nconst isOpenTrayEventSource = (\n transport: OpenTrayTransport\n): transport is OpenTrayConnection =>\n \"onEvent\" in transport && typeof transport.onEvent === \"function\";\n\n/** Structural view of transports that publish a terminal death signal (D3). */\ninterface ConnectionDeadSourceTransport {\n onConnectionDead(handler: (error: Error) => void): () => void;\n}\n\nconst isConnectionDeadSource = (\n transport: OpenTrayEventSource\n): transport is OpenTrayEventSource & ConnectionDeadSourceTransport =>\n \"onConnectionDead\" in transport &&\n typeof transport.onConnectionDead === \"function\";\n\n/** Structural view of supervised transports (W4/W6 supervision seams). */\ninterface TransportSupervisionSourceTransport {\n onTransportStateChange(handler: (state: TransportState) => void): () => void;\n registerTransportRebuild(\n rebuild: (context: TransportRebuildContext) => Promise<void>\n ): void;\n}\n\nconst isTransportSupervisionSource = (\n transport: OpenTrayEventSource\n): transport is OpenTrayEventSource & TransportSupervisionSourceTransport =>\n \"onTransportStateChange\" in transport &&\n typeof transport.onTransportStateChange === \"function\" &&\n \"registerTransportRebuild\" in transport &&\n typeof transport.registerTransportRebuild === \"function\";\n\nconst resolveDefaultAppRef = async (\n transport: OpenTrayTransport,\n nextRequestId: () => RequestId\n): Promise<{ appId: string }> => {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"resolve-default-app\",\n requestId,\n });\n return expectResponse(response, requestId, \"default-app\").app;\n};\n\nconst createAppHandle = (\n transport: OpenTrayTransport,\n appId: string,\n nextRequestId: () => RequestId\n): AppHandle => {\n const requestIdentity = async (): Promise<AppIdentity> => {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"get-app-identity\",\n requestId,\n appId,\n });\n return expectResponse(response, requestId, \"app-identity\").identity;\n };\n return {\n appId,\n async getName(): Promise<string> {\n return (await requestIdentity()).appName;\n },\n async setName(name: string): Promise<string> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-app-name\",\n requestId,\n appId,\n name,\n });\n expectResponse(response, requestId, \"ack\");\n return (await requestIdentity()).appName;\n },\n async getAppIcon(): Promise<AppIcon | null> {\n return (await requestIdentity()).appIcon ?? null;\n },\n async getAppIconVariant(): Promise<string | null> {\n return (await requestIdentity()).appIconVariant ?? null;\n },\n async setAppIcon(iconOrVariant: AppIcon | string | null): Promise<void> {\n if (typeof iconOrVariant === \"string\") {\n const identity = await requestIdentity();\n if (identity.appIcon === undefined) {\n selectAppIconVariant([], iconOrVariant);\n } else {\n selectAppIconVariant(identity.appIcon, iconOrVariant);\n }\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-app-icon-variant\",\n requestId,\n appId,\n variant: iconOrVariant,\n });\n expectResponse(response, requestId, \"ack\");\n return;\n }\n if (iconOrVariant !== null) await validateAppIcon(iconOrVariant);\n const appIcon =\n iconOrVariant === null ? null : normalizeAppIcon(iconOrVariant);\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-app-icon\",\n requestId,\n appId,\n appIcon,\n });\n expectResponse(response, requestId, \"ack\");\n },\n };\n};\n\nconst createTrayExtensionContext = <TCapability extends object, TOptions>(\n tray: TrayHandle,\n appId: string,\n extension: TrayExtension<TCapability, TOptions>,\n options: TOptions | undefined,\n nextMountId: (extensionName: string) => string,\n sessionId?: string\n): TrayExtensionContext => {\n const mount = extension.resolveMount?.(options) ?? {};\n const name = mount.name ?? extension.name;\n const artifact = mount.artifact ?? extension.artifact;\n const mountId = mount.mountId ?? nextMountId(name);\n let loadPromise: Promise<void> | undefined;\n\n const ensureLoaded = async (): Promise<void> => {\n if (loadPromise === undefined) {\n // Package-manager resolution stays in Node; the broker receives one exact file.\n loadPromise = tray\n .loadExtension({ name, artifact, mountId })\n .catch((error: unknown) => {\n loadPromise = undefined;\n throw error;\n });\n }\n await loadPromise;\n };\n\n return {\n appId,\n trayId: tray.trayId,\n ...(sessionId === undefined ? {} : { sessionId }),\n name,\n artifact,\n mountId,\n ensureLoaded,\n async command(data: unknown): Promise<void> {\n await ensureLoaded();\n await tray.commandExtension(mountId, data);\n },\n async request<TValue = unknown>(\n data: unknown\n ): Promise<ExtensionRequestResult<TValue>> {\n await ensureLoaded();\n return tray.requestExtension<TValue>(mountId, data);\n },\n };\n};\n\n/** Structural view of transports that publish the Ready frame's session id. */\ninterface SessionIdBearingTransport {\n readonly sessionId?: unknown;\n}\n\nconst readTransportSessionId = (\n transport: OpenTrayTransport\n): string | undefined => {\n const { sessionId } = transport as SessionIdBearingTransport;\n return typeof sessionId === \"string\" && sessionId.length > 0 ? sessionId : undefined;\n};\n\nconst formatMountIdComponent = (value: string): string => {\n const formatted = value.replaceAll(/[^a-zA-Z0-9._+-]/g, \"_\");\n return formatted.length > 0 ? formatted : \"ext\";\n};\n\nconst createRequestIdFactory = (prefix: string): (() => RequestId) => {\n let next = 1;\n return () => {\n const requestId = `${prefix}-${next}`;\n next += 1;\n return requestId;\n };\n};\n\nconst expectResponse = <TType extends ServerFrame[\"type\"]>(\n frame: ServerFrame,\n requestId: RequestId,\n type: TType\n): Extract<ServerFrame, { type: TType }> => {\n if (frame.type === \"error\") {\n // Synchronous broker errors share the typed `{ code, message, details }`\n // family with deferred terminal errors (add-ext-dialog section 7.5).\n throw new BrokerServerError(frame.code, frame.message, {\n details: frame.details,\n });\n }\n if (frame.type !== type) {\n throw new Error(\n `expected ${type} for ${requestId}, received ${frame.type}`\n );\n }\n if (requestIdOf(frame) !== requestId) {\n throw new Error(\n `expected response for ${requestId}, received ${\n requestIdOf(frame) ?? \"none\"\n }`\n );\n }\n return frame as Extract<ServerFrame, { type: TType }>;\n};\n\nconst requestIdOf = (frame: ServerFrame): RequestId | undefined => {\n switch (frame.type) {\n case \"app-created\":\n case \"default-app\":\n case \"app-identity\":\n case \"tray-created\":\n case \"tray-bounds\":\n case \"ack\":\n case \"ext-command-result\":\n case \"runtime-host-health\":\n return frame.requestId;\n case \"error\":\n return frame.requestId;\n // Deferred-transaction frames never correlate through requestId here:\n // acceptance settles nothing and the terminal frame has no requestId\n // (the local broker connection correlates it through the operation map).\n case \"ext-command-accepted\":\n case \"ext-operation-terminal\":\n case \"ready\":\n case \"event\":\n case \"app-event\":\n case \"ext-event\":\n return undefined;\n }\n};\n","import { basename } from \"node:path\";\n\nimport { sanitizeCallerLabel } from \"@opentray/spec\";\n\nexport interface CallerLabelSources {\n /** Explicit developer-provided label, highest precedence. */\n readonly explicit?: string;\n /**\n * Caller-supplied app identity (`createTray` runtime `appId`). Endpoint\n * identity for app-style consumers: same app, same broker, every launch\n * method. Normalized to the same filesystem-safe slug space as the other\n * sources. Display names (`appName`) never participate (D4,\n * harden-lifecycle-ownership).\n */\n readonly appId?: string;\n /** `npm_package_name` environment value. */\n readonly npmPackageName?: string;\n /** Script path resolved from `process.argv[1]` or equivalent. */\n readonly scriptPath?: string;\n}\n\nexport interface ResolveCallerLabelOptions extends Partial<CallerLabelSources> {\n env?: NodeJS.ProcessEnv;\n argv?: readonly string[];\n}\n\n/**\n * Derives a caller label using the precedence: explicit > appId slug >\n * npm_package_name > script basename > neutral default. The result is always\n * sanitized to a filesystem- and process-safe component, so callers can use it\n * directly in endpoint identity, runtime directories, and process titles.\n */\nexport const resolveCallerLabel = (options: ResolveCallerLabelOptions = {}): string => {\n const env = options.env ?? process.env;\n const argv = options.argv ?? process.argv;\n\n const candidates: string[] = [];\n if (options.explicit !== undefined && options.explicit.length > 0) {\n candidates.push(options.explicit);\n }\n if (options.appId !== undefined && options.appId.length > 0) {\n candidates.push(options.appId);\n }\n const npmName = options.npmPackageName ?? env.npm_package_name;\n if (typeof npmName === \"string\" && npmName.length > 0) {\n candidates.push(npmName);\n }\n const scriptPath = options.scriptPath ?? argv[1];\n if (typeof scriptPath === \"string\" && scriptPath.length > 0) {\n candidates.push(basename(scriptPath));\n }\n\n for (const candidate of candidates) {\n const sanitized = sanitizeCallerLabel(candidate);\n if (sanitized.length > 0) {\n return sanitized;\n }\n }\n\n return sanitizeCallerLabel(undefined);\n};\n","import type { BrokerArtifactTarget } from \"@opentray/spec\";\n\nexport type BrokerPackageOs = \"darwin\" | \"linux\" | \"windows\";\nexport type BrokerArch = \"arm64\" | \"x64\";\n\nexport interface BrokerNativeTarget {\n packageName: string;\n binaryRelativePath: string;\n carrierTemplateRelativePath?: string;\n}\n\nexport const resolveBrokerNativeTarget = (\n platform: string = process.platform,\n arch: string = process.arch,\n): BrokerNativeTarget => {\n const packageOs = platformToPackageOs(platform);\n const nativeArch = normalizeArch(arch);\n return {\n packageName: `@opentray/${packageOs}-${nativeArch}`,\n binaryRelativePath: `bin/${packageOs === \"windows\" ? \"opentray.exe\" : \"opentray\"}`,\n ...(packageOs === \"darwin\"\n ? { carrierTemplateRelativePath: \"app/Info.plist\" }\n : {}),\n };\n};\n\nexport const resolveBrokerArtifactTarget = (\n platform: string = process.platform,\n arch: string = process.arch,\n): BrokerArtifactTarget => {\n const packageOs = platformToPackageOs(platform);\n return {\n os: packageOs === \"windows\" ? \"win32\" : packageOs,\n arch: normalizeArch(arch),\n };\n};\n\nconst platformToPackageOs = (platform: string): BrokerPackageOs => {\n switch (platform) {\n case \"darwin\":\n case \"linux\":\n return platform;\n case \"win32\":\n return \"windows\";\n default:\n throw new MissingPlatformBrokerBinaryError(\n `unsupported OpenTray broker platform: ${platform}`,\n platform,\n process.arch,\n );\n }\n};\n\nconst normalizeArch = (arch: string): BrokerArch => {\n switch (arch) {\n case \"arm64\":\n case \"x64\":\n return arch;\n default:\n throw new MissingPlatformBrokerBinaryError(\n `unsupported OpenTray broker architecture: ${arch}`,\n process.platform,\n arch,\n );\n }\n};\n\nexport class MissingPlatformBrokerBinaryError extends Error {\n readonly code = \"OPENTRAY_MISSING_PLATFORM_BROKER_BINARY\";\n readonly platform: string;\n readonly arch: string;\n readonly packageName: string | undefined;\n readonly binaryPath: string | undefined;\n\n constructor(\n message: string,\n platform: string,\n arch: string,\n options: {\n packageName?: string;\n binaryPath?: string;\n cause?: unknown;\n } = {},\n ) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = \"MissingPlatformBrokerBinaryError\";\n this.platform = platform;\n this.arch = arch;\n this.packageName = options.packageName;\n this.binaryPath = options.binaryPath;\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { access, appendFile, mkdir, readFile, realpath } from \"node:fs/promises\";\nimport { constants } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { spawn } from \"node:child_process\";\n\nimport type { BrokerArtifactIdentity } from \"@opentray/spec\";\nimport type { AppIcon } from \"@opentray/spec\";\nimport { generateDefaultAppIcon } from \"@opentray/icon\";\nimport {\n ensureDarwinAppBundle,\n type OpenTrayAppBundleOptions,\n type OpenTrayPackageIdentity,\n} from \"@opentray/packaging\";\n\nimport type { DaemonPaths } from \"./paths\";\nimport {\n type BrokerNativeTarget,\n MissingPlatformBrokerBinaryError,\n resolveBrokerArtifactTarget,\n resolveBrokerNativeTarget,\n} from \"./native-target\";\n\nexport interface BrokerCommand {\n command: string;\n args: string[];\n cwd?: string;\n}\n\nexport interface ResolvedBrokerArtifact extends BrokerCommand {\n executablePath: string;\n artifactIdentity: BrokerArtifactIdentity;\n}\n\nconst sourceUrl = import.meta.url;\nconst requireFromSource = createRequire(sourceUrl);\n\nexport interface InstalledBrokerBinaryResolution {\n binary?: string;\n binaryPath?: string;\n carrierTemplate?: string;\n carrierTemplatePath?: string;\n}\n\nexport interface ResolveInstalledBrokerBinaryOptions {\n platform?: NodeJS.Platform;\n resolvePackageJson?: (specifier: string) => string;\n assertBinaryAccessible?: (binaryPath: string, platform: NodeJS.Platform) => Promise<void>;\n assertCarrierAccessible?: (carrierPath: string) => Promise<void>;\n}\n\nexport interface ResolveBrokerCommandOptions {\n env?: NodeJS.ProcessEnv;\n platform?: NodeJS.Platform;\n arch?: string;\n sourceDir?: string;\n resolveInstalledBrokerBinary?: (\n target: BrokerNativeTarget,\n options: ResolveInstalledBrokerBinaryOptions,\n ) => Promise<InstalledBrokerBinaryResolution>;\n findWorkspaceRoot?: (start: string) => Promise<string | undefined>;\n ensureDevBrokerBinary?: (\n workspaceRoot: string,\n paths: DaemonPaths,\n platform: NodeJS.Platform,\n ) => Promise<string>;\n ensureDevDarwinCarrierTemplate?: (\n workspaceRoot: string,\n paths: DaemonPaths,\n ) => Promise<string>;\n appBundle?: OpenTrayAppBundleOptions & { readonly path: string };\n appIcon?: AppIcon;\n packageIdentity?: OpenTrayPackageIdentity;\n}\n\nexport interface ResolveBrokerArtifactOptions extends ResolveBrokerCommandOptions {\n resolveExecutablePath?: (path: string) => Promise<string>;\n readExecutable?: (path: string) => Promise<Uint8Array>;\n}\n\nexport const resolveBrokerArtifact = async (\n paths: DaemonPaths,\n options: ResolveBrokerArtifactOptions = {},\n): Promise<ResolvedBrokerArtifact> => {\n const command = await resolveBrokerCommand(paths, options);\n const executablePath = await (options.resolveExecutablePath ?? realpath)(command.command);\n const bytes = await (options.readExecutable ?? readFile)(executablePath);\n const executableHash = createHash(\"sha256\").update(bytes).digest(\"hex\");\n const artifactIdentity: BrokerArtifactIdentity = {\n packageVersion: paths.packageVersion,\n target: resolveBrokerArtifactTarget(\n options.platform ?? process.platform,\n options.arch ?? process.arch,\n ),\n executableHash,\n buildIdentity: `sha256:${executableHash.slice(0, 16)}`,\n };\n return {\n ...command,\n command: executablePath,\n args: [\n ...command.args,\n \"--broker-executable-path\",\n executablePath,\n \"--broker-artifact-identity\",\n JSON.stringify(artifactIdentity),\n ],\n executablePath,\n artifactIdentity,\n };\n};\n\nexport const resolveBrokerCommand = async (\n paths: DaemonPaths,\n options: ResolveBrokerCommandOptions = {},\n): Promise<BrokerCommand> => {\n const env = options.env ?? process.env;\n const platform = options.platform ?? process.platform;\n const arch = options.arch ?? process.arch;\n const explicit = env.OPENTRAY_BROKER_BIN;\n if (explicit !== undefined && explicit.length > 0) {\n if (platform !== \"darwin\" || options.appBundle === undefined) {\n return commandForBinary(explicit, paths);\n }\n const templatePath = await resolveExplicitDarwinCarrierTemplate(paths, options, platform, arch);\n const binary = await ensureDarwinBundle(options, paths, explicit, templatePath);\n return commandForBinary(binary, paths);\n }\n\n const target = resolveBrokerNativeTarget(platform, arch);\n const installed = await (options.resolveInstalledBrokerBinary ?? resolveInstalledBrokerBinary)(\n target,\n { platform },\n );\n if (installed.binary !== undefined) {\n if (platform !== \"darwin\") return commandForBinary(installed.binary, paths);\n if (options.appBundle === undefined) return commandForBinary(installed.binary, paths);\n if (installed.carrierTemplate === undefined) {\n throw missingDarwinCarrierError(target, installed, arch);\n }\n const binary = await ensureDarwinBundle(options, paths, installed.binary, installed.carrierTemplate);\n return commandForBinary(binary, paths);\n }\n\n const sourceDir = options.sourceDir ?? dirname(fileURLToPath(sourceUrl));\n const workspaceRoot = await (options.findWorkspaceRoot ?? findWorkspaceRoot)(sourceDir);\n if (workspaceRoot !== undefined) {\n const binary = await (options.ensureDevBrokerBinary ?? ensureDevBrokerBinary)(\n workspaceRoot,\n paths,\n platform,\n );\n if (platform !== \"darwin\") return commandForBinary(binary, paths);\n const carrierBinary =\n options.appBundle === undefined\n ? binary\n : await ensureDarwinBundle(\n options,\n paths,\n binary,\n await (\n options.ensureDevDarwinCarrierTemplate ?? ensureDevDarwinCarrierTemplate\n )(workspaceRoot, paths),\n );\n return commandForBinary(carrierBinary, paths);\n }\n\n throw new MissingPlatformBrokerBinaryError(\n installed.binaryPath === undefined\n ? `unable to resolve OpenTray broker binary for ${platform}/${arch}; install \"${target.packageName}\" for this platform or set OPENTRAY_BROKER_BIN`\n : `unable to resolve OpenTray broker binary for ${platform}/${arch}; package \"${target.packageName}\" was found but binary \"${installed.binaryPath}\" is not accessible; restage the runtime package or set OPENTRAY_BROKER_BIN`,\n platform,\n arch,\n {\n packageName: target.packageName,\n ...(installed.binaryPath === undefined ? {} : { binaryPath: installed.binaryPath }),\n },\n );\n};\n\nconst resolveExplicitDarwinCarrierTemplate = async (\n paths: DaemonPaths,\n options: ResolveBrokerCommandOptions,\n platform: NodeJS.Platform,\n arch: string,\n): Promise<string> => {\n const sourceDir = options.sourceDir ?? dirname(fileURLToPath(sourceUrl));\n const workspaceRoot = await (options.findWorkspaceRoot ?? findWorkspaceRoot)(sourceDir);\n if (workspaceRoot !== undefined) {\n return (\n options.ensureDevDarwinCarrierTemplate ?? ensureDevDarwinCarrierTemplate\n )(workspaceRoot, paths);\n }\n\n const target = resolveBrokerNativeTarget(platform, arch);\n const installed = await (options.resolveInstalledBrokerBinary ?? resolveInstalledBrokerBinary)(\n target,\n { platform },\n );\n if (installed.carrierTemplate !== undefined) {\n return installed.carrierTemplate;\n }\n throw missingDarwinCarrierError(target, installed, arch);\n};\n\nexport const resolveInstalledBrokerBinary = async (\n target: BrokerNativeTarget,\n options: ResolveInstalledBrokerBinaryOptions = {},\n): Promise<InstalledBrokerBinaryResolution> => {\n const platform = options.platform ?? process.platform;\n let packageJsonPath: string;\n try {\n packageJsonPath = (\n options.resolvePackageJson ?? requireFromSource.resolve.bind(requireFromSource)\n )(`${target.packageName}/package.json`);\n } catch (error) {\n if (isNodeError(error) && error.code === \"MODULE_NOT_FOUND\") {\n return {};\n }\n throw error;\n }\n\n const binaryPath = join(dirname(packageJsonPath), target.binaryRelativePath);\n const carrierTemplatePath =\n target.carrierTemplateRelativePath === undefined\n ? undefined\n : join(dirname(packageJsonPath), target.carrierTemplateRelativePath);\n let carrierTemplate: string | undefined;\n if (carrierTemplatePath !== undefined) {\n try {\n await (options.assertCarrierAccessible ?? assertInstalledCarrierAccessible)(\n carrierTemplatePath,\n );\n carrierTemplate = carrierTemplatePath;\n } catch (error) {\n if (\n !isNodeError(error) ||\n (error.code !== \"ENOENT\" && error.code !== \"EACCES\" && error.code !== \"EPERM\")\n ) {\n throw error;\n }\n }\n }\n try {\n await (options.assertBinaryAccessible ?? assertInstalledBrokerBinaryAccessible)(\n binaryPath,\n platform,\n );\n return {\n binary: binaryPath,\n binaryPath,\n ...(carrierTemplatePath === undefined ? {} : { carrierTemplatePath }),\n ...(carrierTemplate === undefined ? {} : { carrierTemplate }),\n };\n } catch (error) {\n if (\n isNodeError(error) &&\n (error.code === \"ENOENT\" || error.code === \"EACCES\" || error.code === \"EPERM\")\n ) {\n return {\n binaryPath,\n ...(carrierTemplatePath === undefined ? {} : { carrierTemplatePath }),\n ...(carrierTemplate === undefined ? {} : { carrierTemplate }),\n };\n }\n throw error;\n }\n};\n\nconst commandForBinary = (binary: string, paths: DaemonPaths, cwd?: string): BrokerCommand => {\n const command: BrokerCommand = {\n command: binary,\n args: [\n \"broker\",\n \"--endpoint\",\n paths.endpoint,\n \"--ready-file\",\n paths.readyFile,\n \"--package-version\",\n paths.packageVersion,\n \"--protocol-version\",\n `${paths.protocolVersion}`,\n \"--app-id\",\n paths.appId,\n \"--app-name\",\n paths.appName,\n \"--caller-label\",\n paths.callerLabel,\n ],\n };\n if (cwd !== undefined) {\n command.cwd = cwd;\n }\n return command;\n};\n\nconst findWorkspaceRoot = async (start: string): Promise<string | undefined> => {\n let current = start;\n while (true) {\n if (await exists(join(current, \"Cargo.toml\"))) {\n if (await exists(join(current, \"crates\", \"opentray-bin\", \"Cargo.toml\"))) {\n return current;\n }\n }\n\n const parent = dirname(current);\n if (parent === current) {\n return undefined;\n }\n current = parent;\n }\n};\n\nexport const resolveDevBrokerBinaryPath = (\n workspaceRoot: string,\n platform: NodeJS.Platform = process.platform,\n callerLabel = \"opentray\",\n): string =>\n join(\n resolveDevBrokerTargetDir(workspaceRoot, platform, callerLabel),\n \"debug\",\n platform === \"win32\" ? \"opentray.exe\" : \"opentray\",\n );\n\nconst resolveDevBrokerTargetDir = (\n workspaceRoot: string,\n platform: NodeJS.Platform,\n callerLabel: string,\n): string =>\n platform === \"win32\"\n ? join(workspaceRoot, \"target\", \"opentray-source\", callerLabel)\n : join(workspaceRoot, \"target\");\n\nconst ensureDevBrokerBinary = async (\n workspaceRoot: string,\n paths: DaemonPaths,\n platform: NodeJS.Platform,\n): Promise<string> => {\n const targetDir = resolveDevBrokerTargetDir(workspaceRoot, platform, paths.callerLabel);\n const binary = resolveDevBrokerBinaryPath(workspaceRoot, platform, paths.callerLabel);\n await runCargoBuild(workspaceRoot, platform === \"win32\" ? targetDir : undefined);\n return binary;\n};\n\nconst ensureDevDarwinCarrierTemplate = async (\n workspaceRoot: string,\n _paths: DaemonPaths,\n): Promise<string> => {\n return join(workspaceRoot, \"packages/darwin-app-carrier/Info.plist\");\n};\n\nconst ensureDarwinBundle = async (\n options: ResolveBrokerCommandOptions,\n paths: DaemonPaths,\n brokerPath: string,\n templatePath: string,\n): Promise<string> => {\n const appBundle = options.appBundle;\n if (appBundle === undefined) return brokerPath;\n const arch = options.arch ?? process.arch;\n if (arch !== \"arm64\" && arch !== \"x64\") {\n throw new Error(`unsupported Darwin app bundle architecture: ${arch}`);\n }\n const defaultAppIcon = await synthesizeDefaultAppIcon(options, appBundle, paths);\n return ensureDarwinAppBundle({\n bundlePath: appBundle.path,\n packageName: options.packageIdentity?.name ?? paths.callerLabel,\n appId: paths.appId,\n appName: paths.appName,\n target: { os: \"darwin\", arch },\n brokerPath,\n templatePath,\n ...(defaultAppIcon === undefined && options.appIcon === undefined\n ? {}\n : { appIcon: (options.appIcon ?? defaultAppIcon)! }),\n ...(appBundle.reinitialize === undefined ? {} : { reinitialize: appBundle.reinitialize }),\n });\n};\n\n/**\n * The synthesized glyph default (shared-icon-kernel plan D6/D7/D8): a carrier\n * materialization concern, never Core App identity. Only synthesized when the\n * caller declared no `appIcon`, did not opt out, and the runtime owns bundle\n * generation (`reinitialize: false` keeps a prebuilt bundle read-only).\n * Failure falls back to the pre-change behavior (no icon) with a diagnostic\n * line in the runtime's stable broker log — it must never block a start.\n */\nconst synthesizeDefaultAppIcon = async (\n options: ResolveBrokerCommandOptions,\n appBundle: OpenTrayAppBundleOptions & { readonly path: string },\n paths: DaemonPaths,\n): Promise<AppIcon | undefined> => {\n if (options.appIcon !== undefined) return undefined;\n if (appBundle.defaultAppIcon === false) return undefined;\n if (appBundle.reinitialize === false) return undefined;\n try {\n const generated = await generateDefaultAppIcon({\n appName: paths.appName,\n outputDir: join(paths.runtimeDir, \"app-icon\"),\n });\n if (generated.degraded) {\n // The name's script is not covered by this host's fonts; the neutral\n // terminal mark is used. Diagnosed, never blocking.\n await appendFile(\n paths.brokerLog,\n `[opentray:icon] default app icon degraded to the neutral mark: no font in the ladder covers the first character of ${JSON.stringify(paths.appName)}\\n`,\n ).catch(() => {});\n }\n return generated.appIcon;\n } catch (error) {\n try {\n // Embedded callers may reach bundle resolution before the runtime\n // directory exists; diagnostics must never block materialization.\n await mkdir(dirname(paths.brokerLog), { recursive: true });\n await appendFile(\n paths.brokerLog,\n `[opentray:icon] default app icon synthesis failed; materializing without an icon: ${String(error)}\\n`,\n );\n } catch {\n // Diagnostics must never turn an icon fallback into a start failure.\n }\n return undefined;\n }\n};\n\nconst runCargoBuild = (workspaceRoot: string, targetDir?: string): Promise<void> =>\n runProcess(\n \"cargo\",\n [\n \"build\",\n \"-p\",\n \"opentray-bin\",\n ...(targetDir === undefined ? [] : [\"--target-dir\", targetDir]),\n ],\n workspaceRoot,\n process.env.OPENTRAY_BROKER_BUILD_LOGS === \"1\" ? \"inherit\" : \"ignore\",\n );\n\nconst runProcess = (\n command: string,\n args: readonly string[],\n cwd: string,\n stdio: \"ignore\" | \"inherit\" = \"ignore\",\n): Promise<void> =>\n new Promise((resolve, reject) => {\n const child = spawn(command, [...args], { cwd, stdio });\n child.once(\"error\", reject);\n child.once(\"exit\", (code) => {\n if (code === 0) {\n resolve();\n return;\n }\n reject(new Error(`${command} ${args.join(\" \")} failed with code ${code ?? \"unknown\"}`));\n });\n });\n\nconst exists = async (path: string): Promise<boolean> => {\n try {\n await access(path, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n};\n\nconst binaryAccessMode = (platform: NodeJS.Platform): number =>\n platform === \"win32\" ? constants.F_OK : constants.X_OK;\n\nconst assertInstalledBrokerBinaryAccessible = async (\n binaryPath: string,\n platform: NodeJS.Platform,\n): Promise<void> => {\n await access(binaryPath, binaryAccessMode(platform));\n};\n\nconst assertInstalledCarrierAccessible = async (carrierPath: string): Promise<void> => {\n await access(carrierPath, constants.F_OK);\n};\n\nconst missingDarwinCarrierError = (\n target: BrokerNativeTarget,\n resolution: InstalledBrokerBinaryResolution,\n arch: string,\n): MissingPlatformBrokerBinaryError =>\n new MissingPlatformBrokerBinaryError(\n `unable to resolve OpenTray Darwin app bundle template for ${target.packageName}; expected ${resolution.carrierTemplatePath ?? target.carrierTemplateRelativePath ?? \"app/Info.plist\"}`,\n \"darwin\",\n arch,\n {\n packageName: target.packageName,\n ...(resolution.carrierTemplatePath === undefined\n ? {}\n : { binaryPath: resolution.carrierTemplatePath }),\n },\n );\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error;\n}\n","// Orthogonal intents (updated 2026-07-21; original user requests: detached\n// brokers must be caller-scoped, artifact-coherent, and diagnosable by default):\n// 1. Start, inspect, restart, and stop one caller-scoped broker under a lock.\n// 2. Reject liveness-only reuse through exact ready artifact identity.\n// 3. Preserve Darwin stable-bundle live-owner protection.\n// 4. Persist detached broker output and early exit identity unless explicitly overridden.\n// 5. Bound native cold-start readiness and recover caller locks left by dead processes.\n\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { constants } from \"node:fs\";\nimport {\n access,\n appendFile,\n link,\n mkdir,\n open,\n readFile,\n rm,\n stat,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { spawn } from \"node:child_process\";\nimport { isAbsolute } from \"node:path\";\n\nimport {\n brokerArtifactIdentityEquals,\n isBrokerArtifactIdentity,\n type BrokerReadyMetadata,\n} from \"@opentray/spec\";\n\nimport { resolveBrokerArtifact, type ResolvedBrokerArtifact } from \"./broker-command\";\nimport type { DaemonPaths } from \"./paths\";\nimport type { AppIcon } from \"@opentray/spec\";\nimport type { OpenTrayAppBundleOptions, OpenTrayPackageIdentity } from \"@opentray/packaging\";\nimport { clearDarwinAppBundleOwner, writeDarwinAppBundleOwner } from \"@opentray/packaging\";\n\nconst DAEMON_STDIO_ENV = \"OPENTRAY_DAEMON_STDIO\";\nconst DAEMON_POLL_INTERVAL_MS = 50;\nconst DEFAULT_DAEMON_READY_TIMEOUT_MS = 10_000;\nconst DEFAULT_DAEMON_LOCK_TIMEOUT_MS = DEFAULT_DAEMON_READY_TIMEOUT_MS + 5_000;\nconst ABANDONED_RECLAIM_CLAIM_MS = 1_000;\n\nexport type DaemonStartResult =\n | {\n status: \"started\";\n pid: number;\n paths: DaemonPaths;\n broker: ResolvedBrokerArtifact;\n }\n | {\n status: \"already-running\";\n pid: number;\n paths: DaemonPaths;\n broker: ResolvedBrokerArtifact;\n };\n\nexport type DaemonStopResult =\n | { status: \"stopped\"; pid: number; paths: DaemonPaths }\n | { status: \"not-running\"; paths: DaemonPaths };\n\nexport type DaemonInspectResult =\n | { status: \"running\"; pid: number; paths: DaemonPaths }\n | { status: \"not-running\"; paths: DaemonPaths; stalePid?: number };\n\nexport interface DaemonDriver {\n resolveBroker(paths: DaemonPaths): Promise<ResolvedBrokerArtifact>;\n isAlive(pid: number): Promise<boolean>;\n spawnBroker(paths: DaemonPaths, broker: ResolvedBrokerArtifact): Promise<number>;\n stop(pid: number): Promise<void>;\n}\n\nexport interface StartDaemonOptions {\n paths: DaemonPaths;\n driver: DaemonDriver;\n lockTimeoutMs?: number;\n readinessTimeoutMs?: number;\n}\n\nexport interface StopDaemonOptions {\n paths: DaemonPaths;\n driver: DaemonDriver;\n}\n\nexport interface InspectDaemonOptions {\n paths: DaemonPaths;\n driver: DaemonDriver;\n}\n\nexport interface NodeDaemonDriverOptions {\n readonly appBundle?: OpenTrayAppBundleOptions & { readonly path: string };\n readonly appIcon?: AppIcon;\n readonly packageIdentity?: OpenTrayPackageIdentity;\n readonly env?: NodeJS.ProcessEnv;\n}\n\nexport const createNodeDaemonDriver = (\n cliEntrypoint: string,\n options: NodeDaemonDriverOptions = {},\n): DaemonDriver => ({\n async resolveBroker(paths) {\n return resolveBrokerArtifact(paths, {\n ...(options.appBundle === undefined ? {} : { appBundle: options.appBundle }),\n ...(options.appIcon === undefined ? {} : { appIcon: options.appIcon }),\n ...(options.packageIdentity === undefined\n ? {}\n : { packageIdentity: options.packageIdentity }),\n });\n },\n async isAlive(pid) {\n return isProcessAlive(pid);\n },\n async spawnBroker(paths, broker) {\n // The caller label flows to the broker via both a CLI flag and an env var.\n // The broker uses it to bind the per-caller endpoint and to set its own\n // process title so task managers show the owning application.\n const env = options.env ?? process.env;\n const stdio = resolveBrokerStdio(env[DAEMON_STDIO_ENV]);\n if (stdio === \"log\") await mkdir(paths.runtimeDir, { recursive: true });\n const logHandle = stdio === \"log\" ? await open(paths.brokerLog, \"a\") : undefined;\n if (logHandle !== undefined) {\n await logHandle.appendFile(\n `${JSON.stringify({\n timestamp: new Date().toISOString(),\n event: \"broker-spawn\",\n command: broker.command,\n cwd: broker.cwd ?? process.cwd(),\n appId: paths.appId,\n appName: paths.appName,\n })}\\n`,\n \"utf8\",\n );\n }\n if (isAbsolute(broker.command)) {\n try {\n await access(\n broker.command,\n process.platform === \"win32\" ? constants.F_OK : constants.X_OK,\n );\n } catch (error) {\n if (stdio === \"log\") {\n await appendFile(\n paths.brokerLog,\n `${JSON.stringify({\n timestamp: new Date().toISOString(),\n event: \"broker-spawn-error\",\n command: broker.command,\n error: error instanceof Error ? error.message : String(error),\n })}\\n`,\n \"utf8\",\n ).catch(() => undefined);\n }\n await logHandle?.close();\n return 0;\n }\n }\n let child: ReturnType<typeof spawn>;\n try {\n child = spawn(broker.command, broker.args, {\n cwd: broker.cwd,\n detached: true,\n env: {\n ...env,\n OPENTRAY_DAEMON_HOME: paths.homeDir,\n OPENTRAY_DAEMON_PACKAGE_VERSION: paths.packageVersion,\n OPENTRAY_DAEMON_CLI_ENTRYPOINT: cliEntrypoint,\n OPENTRAY_DAEMON_APP_ID: paths.appId,\n OPENTRAY_DAEMON_APP_NAME: paths.appName,\n OPENTRAY_DAEMON_CALLER_LABEL: paths.callerLabel,\n },\n stdio:\n logHandle === undefined\n ? stdio === \"log\"\n ? \"ignore\"\n : stdio\n : [\"ignore\", logHandle.fd, logHandle.fd],\n });\n } finally {\n await logHandle?.close();\n }\n\n child.on(\"error\", (error) => {\n if (stdio !== \"log\") return;\n void appendFile(\n paths.brokerLog,\n `${JSON.stringify({\n timestamp: new Date().toISOString(),\n event: \"broker-spawn-error\",\n command: broker.command,\n error: error.message,\n })}\\n`,\n \"utf8\",\n ).catch(() => undefined);\n });\n child.once(\"exit\", (code, signal) => {\n if (stdio !== \"log\") return;\n void appendFile(\n paths.brokerLog,\n `${JSON.stringify({\n timestamp: new Date().toISOString(),\n event: \"broker-exit\",\n command: broker.command,\n code,\n signal,\n })}\\n`,\n \"utf8\",\n ).catch(() => undefined);\n });\n\n child.unref();\n const pid = child.pid ?? 0;\n if (process.platform === \"darwin\" && options.appBundle !== undefined && pid > 0) {\n await writeDarwinAppBundleOwner(\n options.appBundle.path,\n pid,\n broker.artifactIdentity.executableHash,\n );\n }\n return pid;\n },\n async stop(pid) {\n process.kill(pid, \"SIGTERM\");\n if (process.platform === \"darwin\" && options.appBundle !== undefined) {\n await clearDarwinAppBundleOwner(options.appBundle.path, pid);\n }\n },\n});\n\nexport const resolveBrokerStdio = (value: string | undefined): \"log\" | \"ignore\" | \"inherit\" => {\n if (value === \"inherit\") return \"inherit\";\n if (value === \"ignore\") return \"ignore\";\n return \"log\";\n};\n\nexport const startDaemon = async ({\n paths,\n driver,\n lockTimeoutMs = DEFAULT_DAEMON_LOCK_TIMEOUT_MS,\n readinessTimeoutMs = DEFAULT_DAEMON_READY_TIMEOUT_MS,\n}: StartDaemonOptions): Promise<DaemonStartResult> => {\n await mkdir(paths.runtimeDir, { recursive: true });\n\n const lock = await acquireDaemonLock(paths.lockFile, lockTimeoutMs);\n try {\n const existingPid = await readPid(paths.pidFile);\n let existingAlive = existingPid !== undefined && (await driver.isAlive(existingPid));\n let broker: ResolvedBrokerArtifact;\n try {\n // Darwin bundle materialization is part of broker resolution. The bundle owner marker\n // rejects an incompatible live owner before any managed file is replaced.\n broker = await driver.resolveBroker(paths);\n } catch (error) {\n if (existingAlive && isBundleInUseError(error) && existingPid !== undefined) {\n await driver.stop(existingPid);\n if (!(await waitUntilStopped(driver, existingPid))) {\n throw new Error(\n `incompatible daemon broker did not stop within the bounded shutdown window: pid=${existingPid}`,\n );\n }\n existingAlive = false;\n broker = await driver.resolveBroker(paths);\n } else {\n throw error;\n }\n }\n if (existingPid !== undefined && existingAlive) {\n const ready = await readReadyMetadata(paths.readyFile);\n // Liveness is not compatibility: only the exact resolved executable may win reuse.\n if (readyMatchesBroker(ready, paths, existingPid, broker)) {\n return {\n status: \"already-running\",\n pid: existingPid,\n paths,\n broker,\n };\n }\n await driver.stop(existingPid);\n if (!(await waitUntilStopped(driver, existingPid))) {\n throw new Error(\n `incompatible daemon broker did not stop within the bounded shutdown window: pid=${existingPid}`,\n );\n }\n }\n\n await cleanupRuntimeFiles(paths);\n const pid = await driver.spawnBroker(paths, broker);\n if (!Number.isInteger(pid) || pid <= 0) {\n throw new Error(\"daemon broker process did not expose a valid pid\");\n }\n await writeFile(paths.pidFile, `${pid}\\n`, \"utf8\");\n try {\n await waitForReadyFile(paths, driver, pid, broker, readinessTimeoutMs);\n } catch (error) {\n if (await driver.isAlive(pid)) {\n await driver.stop(pid);\n await waitUntilStopped(driver, pid);\n }\n await cleanupRuntimeFiles(paths);\n throw error;\n }\n return { status: \"started\", pid, paths, broker };\n } finally {\n await lock.release();\n }\n};\n\nexport const stopDaemon = async ({\n paths,\n driver,\n}: StopDaemonOptions): Promise<DaemonStopResult> => {\n const pid = await readPid(paths.pidFile);\n if (pid === undefined || !(await driver.isAlive(pid))) {\n await cleanupRuntimeFiles(paths);\n return { status: \"not-running\", paths };\n }\n\n await driver.stop(pid);\n if (!(await waitUntilStopped(driver, pid))) {\n throw new Error(`daemon broker did not stop within the bounded shutdown window: pid=${pid}`);\n }\n await cleanupRuntimeFiles(paths);\n return { status: \"stopped\", pid, paths };\n};\n\nexport const restartDaemon = async (options: StartDaemonOptions): Promise<DaemonStartResult> => {\n await stopDaemon({ paths: options.paths, driver: options.driver });\n return startDaemon(options);\n};\n\nexport const inspectDaemon = async ({\n paths,\n driver,\n}: InspectDaemonOptions): Promise<DaemonInspectResult> => {\n const pid = await readPid(paths.pidFile);\n if (pid !== undefined && (await driver.isAlive(pid))) {\n return { status: \"running\", pid, paths };\n }\n\n await cleanupRuntimeFiles(paths);\n return pid === undefined\n ? { status: \"not-running\", paths }\n : { status: \"not-running\", paths, stalePid: pid };\n};\n\nconst readPid = async (pidFile: string): Promise<number | undefined> => {\n try {\n const content = await readFile(pidFile, \"utf8\");\n const pid = Number.parseInt(content.trim(), 10);\n return Number.isInteger(pid) && pid > 0 ? pid : undefined;\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n};\n\nconst cleanupRuntimeFiles = async (paths: DaemonPaths): Promise<void> => {\n await rm(paths.readyFile, { force: true });\n await rm(paths.pidFile, { force: true });\n if (process.platform !== \"win32\") {\n await rm(paths.endpoint, { force: true });\n }\n};\n\nconst waitUntilStopped = async (driver: DaemonDriver, pid: number): Promise<boolean> => {\n for (let attempt = 0; attempt < 20; attempt += 1) {\n if (!(await driver.isAlive(pid))) {\n return true;\n }\n await sleep(DAEMON_POLL_INTERVAL_MS);\n }\n return false;\n};\n\nconst waitForReadyFile = async (\n paths: DaemonPaths,\n driver: DaemonDriver,\n pid: number,\n broker: ResolvedBrokerArtifact,\n timeoutMs: number,\n): Promise<void> => {\n const deadline = Date.now() + timeoutMs;\n while (true) {\n const ready = await readReadyMetadata(paths.readyFile);\n if (readyMatchesBroker(ready, paths, pid, broker)) {\n return;\n }\n if (ready !== undefined) {\n throw new Error(\n `daemon readiness artifact identity mismatch: expected=${JSON.stringify(broker.artifactIdentity)} actual=${JSON.stringify(ready.brokerArtifactIdentity)}`,\n );\n }\n if (!(await driver.isAlive(pid))) {\n throw new Error(\n `daemon broker exited before readiness: pid=${pid}; readyFile=${paths.readyFile}; brokerLog=${paths.brokerLog}; set ${DAEMON_STDIO_ENV}=inherit to mirror broker stderr`,\n );\n }\n const remainingMs = deadline - Date.now();\n if (remainingMs <= 0) break;\n await sleep(Math.min(DAEMON_POLL_INTERVAL_MS, remainingMs));\n }\n\n throw new Error(\n `timed out waiting for daemon readiness after ${timeoutMs}ms: pid=${pid}; readyFile=${paths.readyFile}; brokerLog=${paths.brokerLog}; set ${DAEMON_STDIO_ENV}=inherit to mirror broker stderr`,\n );\n};\n\nconst readReadyMetadata = async (readyFile: string): Promise<BrokerReadyMetadata | undefined> => {\n let value: unknown;\n try {\n value = JSON.parse(await readFile(readyFile, \"utf8\"));\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return undefined;\n }\n if (error instanceof SyntaxError) {\n return undefined;\n }\n throw error;\n }\n if (\n !isRecord(value) ||\n !Number.isInteger(value.pid) ||\n typeof value.pid !== \"number\" ||\n typeof value.endpoint !== \"string\" ||\n typeof value.packageVersion !== \"string\" ||\n typeof value.protocolVersion !== \"number\" ||\n typeof value.appId !== \"string\" ||\n typeof value.appName !== \"string\" ||\n typeof value.callerLabel !== \"string\" ||\n typeof value.executablePath !== \"string\" ||\n !isBrokerArtifactIdentity(value.brokerArtifactIdentity)\n ) {\n return undefined;\n }\n return {\n pid: value.pid,\n endpoint: value.endpoint,\n packageVersion: value.packageVersion,\n protocolVersion: value.protocolVersion,\n appId: value.appId,\n appName: value.appName,\n callerLabel: value.callerLabel,\n executablePath: value.executablePath,\n brokerArtifactIdentity: value.brokerArtifactIdentity,\n };\n};\n\nconst readyMatchesBroker = (\n ready: BrokerReadyMetadata | undefined,\n paths: DaemonPaths,\n pid: number,\n broker: ResolvedBrokerArtifact,\n): boolean =>\n ready !== undefined &&\n ready.pid === pid &&\n ready.endpoint === paths.endpoint &&\n ready.packageVersion === paths.packageVersion &&\n ready.protocolVersion === paths.protocolVersion &&\n ready.appId === paths.appId &&\n ready.appName === paths.appName &&\n ready.callerLabel === paths.callerLabel &&\n executablePathsEqual(ready.executablePath, broker.executablePath) &&\n brokerArtifactIdentityEquals(ready.brokerArtifactIdentity, broker.artifactIdentity);\n\nconst isBundleInUseError = (error: unknown): boolean =>\n error instanceof Error && \"code\" in error && error.code === \"bundle_in_use\";\n\nexport const executablePathsEqual = (\n left: string,\n right: string,\n platform: NodeJS.Platform = process.platform,\n): boolean => {\n if (platform !== \"win32\") {\n return left === right;\n }\n\n const normalize = (value: string): string =>\n value\n .replaceAll(\"\\\\\", \"/\")\n .replace(/^\\/\\/?\\?\\//u, \"\")\n .toLowerCase();\n return normalize(left) === normalize(right);\n};\n\nexport const acquireDaemonLock = async (\n lockFile: string,\n timeoutMs: number,\n): Promise<{\n release(): Promise<void>;\n}> => {\n const deadline = Date.now() + timeoutMs;\n const owner = `${JSON.stringify({ pid: process.pid, token: randomUUID() })}\\n`;\n while (Date.now() <= deadline) {\n try {\n const handle = await open(\n lockFile,\n constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY,\n );\n await handle.writeFile(owner, \"utf8\");\n return {\n async release() {\n await handle.close();\n if ((await readLockSource(lockFile)) !== owner) return;\n await unlink(lockFile).catch((error: unknown) => {\n if (!isNodeError(error) || error.code !== \"ENOENT\") {\n throw error;\n }\n });\n },\n };\n } catch (error) {\n if (isNodeError(error) && error.code === \"EEXIST\") {\n if (await reclaimDeadLockOwner(lockFile)) continue;\n await sleep(25);\n continue;\n }\n throw error;\n }\n }\n\n throw new Error(`timed out acquiring daemon lock: ${lockFile}`);\n};\n\nconst reclaimDeadLockOwner = async (lockFile: string): Promise<boolean> => {\n const observed = await readLockSource(lockFile);\n if (observed === undefined) return true;\n const owner = parseLockOwner(observed);\n if (owner === undefined || isProcessAlive(owner.pid)) return false;\n\n const claimFile = `${lockFile}.reclaim-${createHash(\"sha256\").update(observed).digest(\"hex\").slice(0, 16)}`;\n try {\n await link(lockFile, claimFile);\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") return true;\n if (isNodeError(error) && error.code === \"EEXIST\") {\n await clearAbandonedReclaimClaim(claimFile);\n return false;\n }\n throw error;\n }\n\n try {\n // Only the hard-link claim winner may remove this exact dead owner inode.\n if ((await readLockSource(lockFile)) !== observed || isProcessAlive(owner.pid)) return false;\n try {\n await unlink(lockFile);\n return true;\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") return true;\n throw error;\n }\n } finally {\n await unlink(claimFile).catch((error: unknown) => {\n if (!isNodeError(error) || error.code !== \"ENOENT\") throw error;\n });\n }\n};\n\nconst clearAbandonedReclaimClaim = async (claimFile: string): Promise<void> => {\n try {\n const claim = await stat(claimFile);\n if (Date.now() - claim.ctimeMs < ABANDONED_RECLAIM_CLAIM_MS) return;\n await unlink(claimFile);\n } catch (error) {\n if (!isNodeError(error) || error.code !== \"ENOENT\") throw error;\n }\n};\n\nconst readLockSource = async (lockFile: string): Promise<string | undefined> => {\n try {\n return await readFile(lockFile, \"utf8\");\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") return undefined;\n throw error;\n }\n};\n\nconst parseLockOwner = (source: string): { readonly pid: number } | undefined => {\n const legacyPid = Number(source.trim());\n if (Number.isInteger(legacyPid) && legacyPid > 0) return { pid: legacyPid };\n\n let value: unknown;\n try {\n value = JSON.parse(source);\n } catch {\n return undefined;\n }\n if (\n !isRecord(value) ||\n typeof value.pid !== \"number\" ||\n !Number.isInteger(value.pid) ||\n value.pid <= 0 ||\n typeof value.token !== \"string\" ||\n value.token.length === 0\n ) {\n return undefined;\n }\n return { pid: value.pid };\n};\n\nconst isProcessAlive = (pid: number): boolean => {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return !(isNodeError(error) && error.code === \"ESRCH\");\n }\n};\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst isNodeError = (error: unknown): error is NodeJS.ErrnoException =>\n error instanceof Error && \"code\" in error;\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n","import { readFile } from \"node:fs/promises\";\n\nexport const readPackageVersion = async (packageJsonUrl: URL): Promise<string> => {\n const value: unknown = JSON.parse(await readFile(packageJsonUrl, \"utf8\"));\n if (!isPackageJsonWithVersion(value)) {\n throw new Error(`package.json is missing a string version: ${packageJsonUrl.href}`);\n }\n\n return value.version;\n};\n\nconst isPackageJsonWithVersion = (value: unknown): value is { version: string } =>\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n \"version\" in value &&\n typeof value.version === \"string\";\n","import {\n createBrokerEndpointIdentity,\n formatUnixSocketPath,\n formatWindowsPipeName,\n} from \"@opentray/spec\";\n\nexport interface DaemonPathOptions {\n homeDir: string;\n packageVersion: string;\n callerLabel?: string;\n appId?: string;\n appName?: string;\n platform?: NodeJS.Platform;\n}\n\nexport interface DaemonPaths {\n homeDir: string;\n packageVersion: string;\n callerLabel: string;\n appId: string;\n appName: string;\n protocolVersion: number;\n stateRoot: string;\n runtimeDir: string;\n endpoint: string;\n pidFile: string;\n lockFile: string;\n readyFile: string;\n brokerLog: string;\n}\n\nexport const resolveDaemonPaths = ({\n homeDir,\n packageVersion,\n callerLabel,\n appId,\n appName,\n platform = process.platform,\n}: DaemonPathOptions): DaemonPaths => {\n const identity = createBrokerEndpointIdentity(\n callerLabel === undefined ? { packageVersion } : { packageVersion, callerLabel },\n );\n const resolvedAppId = normalizeAppIdentityField(appId, identity.callerLabel);\n const resolvedAppName = normalizeAppIdentityField(appName, identity.callerLabel);\n const normalizedHome = homeDir.replace(/[\\\\/]+$/u, \"\");\n const stateRoot = `${normalizedHome}/.opentray/${identity.packageVersion}/${identity.callerLabel}`;\n const runtimeDir = `${stateRoot}/runtime`;\n const endpoint =\n platform === \"win32\"\n ? formatWindowsPipeName(identity)\n : formatUnixSocketPath(normalizedHome, identity);\n\n return {\n homeDir: normalizedHome,\n packageVersion: identity.packageVersion,\n callerLabel: identity.callerLabel,\n appId: resolvedAppId,\n appName: resolvedAppName,\n protocolVersion: identity.protocolVersion,\n stateRoot,\n runtimeDir,\n endpoint,\n pidFile: `${runtimeDir}/broker.pid`,\n lockFile: `${runtimeDir}/broker.lock`,\n readyFile: `${runtimeDir}/ready.json`,\n brokerLog: `${runtimeDir}/broker.log`,\n };\n};\n\nconst normalizeAppIdentityField = (value: string | undefined, fallback: string): string => {\n const trimmed = value?.trim();\n return trimmed === undefined || trimmed.length === 0 ? fallback : trimmed;\n};\n","// Orthogonal intents (2026-07-21; original user requests: a normal install\n// yields one coherent local runtime; the last app launch command is committed\n// only after a successful broker handshake):\n// 1. Resolve caller identity, endpoint, package graph, and stable Darwin bundle.\n// 2. Start/reuse one compatible caller-scoped broker and validate its identity.\n// 3. Own request/event transport and deterministic connection teardown.\n// 4. Commit mutable Darwin launch state after runtime initialization succeeds.\n\nimport { createConnection, type Socket } from \"node:net\";\nimport { homedir } from \"node:os\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { appendFile, mkdir } from \"node:fs/promises\";\n\nimport {\n PROTOCOL_VERSION,\n brokerArtifactIdentityEquals,\n parseServerFrame,\n type BrokerArtifactIdentity,\n type BrokerEndpointIdentityOptions,\n type ClientRequestFrame,\n type ExtOperationPayload,\n type RequestId,\n type ServerFrame,\n} from \"@opentray/spec\";\nimport type { OpenTrayAppBundleOptions, OpenTrayAppLaunchDescriptor } from \"@opentray/packaging\";\nimport {\n resolveDefaultDarwinAppBundlePath,\n convergeDarwinAppBundleIdentity,\n resolveOpenTrayPackageIdentity,\n updateDarwinAppLaunchDescriptor,\n type OpenTrayPackageIdentity,\n} from \"@opentray/packaging\";\n\nimport type { OpenTrayTransport, TransportRequestOptions } from \"./client\";\nimport {\n BOOTSTRAP_CALL_DEADLINE_MS,\n INTERACTIVE_CALL_DEADLINE_MS,\n TEARDOWN_CALL_DEADLINE_MS,\n TransportTimeoutError,\n BrokerServerError,\n} from \"./client\";\nimport { resolveCallerLabel } from \"./daemon/caller-label\";\nimport { createNodeDaemonDriver, startDaemon, type DaemonDriver } from \"./daemon/lifecycle\";\nimport { readPackageVersion } from \"./daemon/package-version\";\nimport { resolveDaemonPaths } from \"./daemon/paths\";\nimport type { DaemonPaths } from \"./daemon/paths\";\n\nconst packageJsonUrl = new URL(\"../package.json\", import.meta.url);\n\nexport type LocalRuntimeEventFrame = Extract<\n ServerFrame,\n { type: \"event\" | \"app-event\" | \"ext-event\" }\n>;\n\n/**\n * Transport-close sentinel every pending request rejects with when the\n * broker socket closes (the broker exits once its last session closes, so a\n * caller racing its own teardown against that exit sees this message).\n * Exported so the tray-handle destroy path can treat it as the desired end\n * state instead of a failure (P3.6 quit-path finding, 2026-09-12).\n */\nexport const BROKER_CONNECTION_CLOSED_MESSAGE = \"broker connection closed\";\n\n/**\n * Generic transport-close rejection code for every pending deferred operation\n * (add-ext-dialog section 5.1 frozen): the core client carries no extension-specific\n * branch. Extension facades map this shared code onto their public surface\n * (e.g. ext-dialog's `dialog_transport_closed`) - that mapping is facade work,\n * never core work.\n */\nexport const EXTENSION_TRANSPORT_CLOSED_CODE = \"extension_transport_closed\";\n\n/**\n * Typed rejection every deferred operation settles with: the `error` payload\n * branch of an `ext-operation-terminal` frame, or the generic\n * `extension_transport_closed` rejection when the transport dies while an\n * operation is pending. Consumers match on `code`; the human `message` is not\n * a contract. `details` carries the wire error's structured payload when the\n * extension supplied one.\n */\nexport class ExtensionOperationError extends Error {\n readonly code: string;\n readonly details?: unknown;\n\n constructor(\n code: string,\n message: string,\n options: { details?: unknown; cause?: unknown } = {}\n ) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = \"ExtensionOperationError\";\n this.code = code;\n if (options.details !== undefined) {\n this.details = options.details;\n }\n }\n}\n\nconst extensionTransportClosedError = (cause: Error): ExtensionOperationError =>\n new ExtensionOperationError(\n EXTENSION_TRANSPORT_CLOSED_CODE,\n \"the broker transport closed while a deferred extension operation was pending\",\n { cause }\n );\n\n/**\n * Correlation label the bootstrap deadline reports under: the init frame\n * carries no requestId on the wire, so the typed timeout names the call class\n * itself.\n */\nconst INIT_REQUEST_ID = \"init\";\n\n/**\n * Typed handshake rejection for a Ready frame whose protocol version does not\n * equal the version this client sent in its Init frame: a structurally valid\n * Ready frame alone must never accept the session (add-ext-dialog batch A\n * review P1-9). The message names both sides; consumers may match\n * `instanceof` or the two numeric fields.\n */\nexport class BrokerProtocolVersionError extends Error {\n readonly clientProtocolVersion: number;\n readonly brokerProtocolVersion: number;\n\n constructor(clientProtocolVersion: number, brokerProtocolVersion: number) {\n super(\n `broker protocol version mismatch: client=${clientProtocolVersion} broker=${brokerProtocolVersion}`\n );\n this.name = \"BrokerProtocolVersionError\";\n this.clientProtocolVersion = clientProtocolVersion;\n this.brokerProtocolVersion = brokerProtocolVersion;\n }\n}\n\nexport interface LocalBrokerClient extends OpenTrayTransport {\n readonly endpoint: string;\n readonly callerLabel: string;\n readonly sessionId: string;\n /**\n * Terminal connection-death state (D3, harden-lifecycle-ownership): true\n * once the broker socket errored or closed. Pending and future requests\n * reject; event delivery has stopped.\n */\n readonly connectionDead: boolean;\n /**\n * Terminal connection-death notification; fires exactly once, either for a\n * transport error or the transport-close sentinel, and also after a\n * caller-initiated graceful `close()` completes.\n */\n onConnectionDead(listener: (error: Error) => void): () => void;\n /**\n * Internal deadline-expiry observation seam (W1, harden-transport-robustness):\n * not consumer API. A supervision layer (Phase C heartbeat) subscribes to\n * attribute probe failures — an expiry settles one call and never declares\n * the transport dead, but it counts as one liveness-failure signal.\n */\n onDeadlineExpiry(listener: (expiry: TransportDeadlineExpiry) => void): () => void;\n onEvent(listener: (frame: LocalRuntimeEventFrame) => void): () => void;\n close(): Promise<void>;\n}\n\n/** Payload of the internal deadline-expiry seam: which call class budget expired. */\nexport interface TransportDeadlineExpiry {\n readonly requestId: RequestId;\n readonly deadlineMs: number;\n}\n\nexport interface ConnectLocalBrokerOptions extends Partial<BrokerEndpointIdentityOptions> {\n endpoint?: string;\n homeDir?: string;\n appId?: string;\n appName?: string;\n clientVersion?: string;\n autoStart?: boolean;\n daemonDriver?: DaemonDriver;\n cliEntrypoint?: string;\n callerLabel?: string;\n expectedBrokerArtifactIdentity?: BrokerArtifactIdentity;\n appIcon?: import(\"@opentray/spec\").AppIcon;\n appBundle?: OpenTrayAppBundleOptions;\n appLaunch?: OpenTrayAppLaunchDescriptor;\n packageName?: string;\n packageRoot?: string;\n}\n\ninterface PendingRequest {\n resolve(frame: ServerFrame): void;\n reject(error: Error): void;\n /**\n * Per-call deadline timer (W1): unref'd so library callers' process exit is\n * never held open by an outstanding call; cleared on every settle path.\n */\n deadlineTimer?: ReturnType<typeof setTimeout> | undefined;\n /**\n * Set when the matching `ext-command-accepted` frame arrives (add-ext-dialog\n * section 5.1 pending-until-final): the promise stays pending until exactly one\n * `ext-operation-terminal` settles it, and a transport death rejects it with\n * the generic typed `extension_transport_closed` instead of the plain\n * transport sentinel. Acceptance clears the deadline (two-phase law): the\n * deadline bounds dispatch→acceptance — the transport round-trip the client\n * owns — while the accepted operation awaits native completion that can be\n * legitimately user-paced (a held modal dialog) and is bounded only by\n * transport liveness, never by a transport deadline.\n */\n deferredOperation?: string;\n}\n\n/**\n * Minimal structural socket the connection needs; exported so in-repo tests\n * can drive the transport against deterministic fake sockets (never-answering\n * brokers, wedged graceful ends) instead of timing-dependent real ones.\n */\nexport interface BrokerSocket {\n setEncoding(encoding: BufferEncoding): void;\n on(event: \"data\", listener: (chunk: Buffer | string) => void): void;\n on(event: \"error\", listener: (error: Error) => void): void;\n on(event: \"close\", listener: () => void): void;\n once(event: \"connect\", listener: () => void): void;\n once(event: \"error\", listener: (error: Error) => void): void;\n off(event: \"error\", listener: (error: Error) => void): void;\n write(data: string): void;\n end(callback: () => void): void;\n destroy(): void;\n}\n\nexport const connectLocalBroker = async (\n options: ConnectLocalBrokerOptions = {},\n): Promise<LocalBrokerClient> => {\n const packageVersion = options.packageVersion ?? (await readPackageVersion(packageJsonUrl));\n const clientVersion = options.clientVersion ?? packageVersion;\n const appId = normalizeAppIdentityField(options.appId);\n const appName = normalizeAppIdentityField(options.appName);\n // Endpoint identity precedence (D4, harden-lifecycle-ownership): internal\n // diagnostic override > appId slug > tool fallbacks. `appName` never\n // participates: display names are not filesystem-safe endpoint segments.\n const callerLabel =\n options.callerLabel ?? resolveCallerLabel(appId === undefined ? {} : { appId });\n const paths = resolveDaemonPaths({\n homeDir: options.homeDir ?? process.env.OPENTRAY_HOME ?? homedir(),\n packageVersion,\n callerLabel,\n ...(appId === undefined ? {} : { appId }),\n ...(appName === undefined ? {} : { appName }),\n });\n const endpoint = options.endpoint ?? paths.endpoint;\n const autoStart = options.autoStart ?? endpoint === paths.endpoint;\n if (autoStart && endpoint !== paths.endpoint) {\n throw new Error(\"local broker autoStart requires the derived same-version endpoint\");\n }\n const cliEntrypoint = options.cliEntrypoint ?? resolveCliEntrypoint();\n const packageIdentity =\n process.platform === \"darwin\" && autoStart\n ? await resolveOpenTrayPackageIdentity({\n ...(options.packageName === undefined ? {} : { packageName: options.packageName }),\n ...(options.packageRoot === undefined ? {} : { packageRoot: options.packageRoot }),\n })\n : undefined;\n const appBundle =\n process.platform === \"darwin\" && autoStart\n ? resolveDarwinAppBundleOptions(options.appBundle, paths, packageIdentity)\n : undefined;\n const driver =\n options.daemonDriver ??\n createNodeDaemonDriver(cliEntrypoint, {\n ...(appBundle === undefined ? {} : { appBundle }),\n ...(options.appIcon === undefined ? {} : { appIcon: options.appIcon }),\n ...(packageIdentity === undefined ? {} : { packageIdentity }),\n });\n const expectedBrokerArtifactIdentity = autoStart\n ? (await startDaemon({ paths, driver })).broker.artifactIdentity\n : (options.expectedBrokerArtifactIdentity ??\n (await driver.resolveBroker(paths)).artifactIdentity);\n const socket = await connectSocket(endpoint);\n const connection = new LocalBrokerConnection(socket, endpoint, callerLabel);\n\n try {\n await connection.init(\n clientVersion,\n options.protocolVersion ?? PROTOCOL_VERSION,\n expectedBrokerArtifactIdentity,\n );\n if (appBundle !== undefined && options.appLaunch !== undefined) {\n await updateDarwinAppLaunchDescriptor(appBundle.path, options.appLaunch);\n const convergence = await convergeDarwinAppBundleIdentity({\n currentBundlePath: appBundle.path,\n appId: paths.appId,\n managedAppsRoot: resolve(paths.homeDir, \".opentray/apps\"),\n legacyRuntimeRoot: resolve(paths.homeDir, \".opentray\"),\n legacyBundlePaths: [resolve(paths.runtimeDir, \"darwin-carrier/OpenTray.app\")],\n });\n await appendBrokerDiagnostic(paths.brokerLog, {\n event: \"bundle-identity-convergence\",\n removed: convergence.removed,\n skippedLiveOwner: convergence.skippedLiveOwner,\n failedUnregister: convergence.failedUnregister,\n });\n }\n } catch (error) {\n await connection.close();\n throw error;\n }\n return connection;\n};\n\nconst appendBrokerDiagnostic = async (\n path: string,\n value: Readonly<Record<string, unknown>>,\n): Promise<void> => {\n try {\n await mkdir(dirname(path), { recursive: true });\n await appendFile(\n path,\n `${JSON.stringify({ timestamp: new Date().toISOString(), ...value })}\\n`,\n \"utf8\",\n );\n } catch {\n // Diagnostics must never turn a successful tray connection into a failure.\n }\n};\n\nconst resolveDarwinAppBundleOptions = (\n configured: OpenTrayAppBundleOptions | undefined,\n paths: DaemonPaths,\n packageIdentity: OpenTrayPackageIdentity | undefined,\n): OpenTrayAppBundleOptions & { readonly path: string } => {\n if (packageIdentity === undefined) {\n throw new Error(\"Darwin app bundle resolution requires the caller package identity\");\n }\n const configuredPath = configured?.path;\n const path =\n configuredPath === undefined\n ? resolveDefaultDarwinAppBundlePath({\n homeDir: paths.homeDir,\n packageName: packageIdentity.name,\n appName: paths.appName,\n })\n : typeof configuredPath === \"string\"\n ? isAbsolute(configuredPath)\n ? configuredPath\n : resolve(packageIdentity.root, configuredPath)\n : configuredPath.protocol === \"file:\"\n ? fileURLToPath(configuredPath)\n : (() => {\n throw new Error(`Darwin appBundle.path must be a file URL: ${configuredPath.href}`);\n })();\n return {\n path,\n ...(configured?.reinitialize === undefined ? {} : { reinitialize: configured.reinitialize }),\n };\n};\n\nconst normalizeAppIdentityField = (value: string | undefined): string | undefined => {\n const trimmed = value?.trim();\n return trimmed === undefined || trimmed.length === 0 ? undefined : trimmed;\n};\n\nexport class LocalBrokerConnection implements LocalBrokerClient {\n readonly endpoint: string;\n readonly callerLabel: string;\n sessionId = \"\";\n\n private buffer = \"\";\n private readonly listeners = new Set<(frame: LocalRuntimeEventFrame) => void>();\n private readonly pending = new Map<RequestId, PendingRequest>();\n /** operationId -> requestId of accepted-but-unsettled deferred operations. */\n private readonly deferredOperations = new Map<string, RequestId>();\n private readonly deadListeners = new Set<(error: Error) => void>();\n private readonly deadlineExpiryListeners = new Set<(expiry: TransportDeadlineExpiry) => void>();\n private deadError: Error | undefined;\n private ready:\n | {\n resolve(frame: Extract<ServerFrame, { type: \"ready\" }>): void;\n reject(error: Error): void;\n }\n | undefined;\n\n constructor(\n private readonly socket: BrokerSocket,\n endpoint: string,\n callerLabel: string,\n ) {\n this.endpoint = endpoint;\n this.callerLabel = callerLabel;\n socket.setEncoding(\"utf8\");\n socket.on(\"data\", (chunk: Buffer | string) => {\n this.consume(String(chunk));\n });\n socket.on(\"error\", (error) => {\n // Transport errors race the close event per platform (Linux delivers\n // ECONNRESET before close; macOS close-first). The terminal surface is\n // the stable classification message — the underlying transport error\n // stays observable as `cause` for diagnostics, so both orderings\n // expose identical public behavior.\n this.markDead(\n new Error(BROKER_CONNECTION_CLOSED_MESSAGE, { cause: error }),\n );\n });\n socket.on(\"close\", () => {\n this.markDead(new Error(BROKER_CONNECTION_CLOSED_MESSAGE));\n });\n }\n\n get connectionDead(): boolean {\n return this.deadError !== undefined;\n }\n\n onConnectionDead(listener: (error: Error) => void): () => void {\n this.deadListeners.add(listener);\n return () => {\n this.deadListeners.delete(listener);\n };\n }\n\n onDeadlineExpiry(listener: (expiry: TransportDeadlineExpiry) => void): () => void {\n this.deadlineExpiryListeners.add(listener);\n return () => {\n this.deadlineExpiryListeners.delete(listener);\n };\n }\n\n async init(\n clientVersion: string,\n protocolVersion: number,\n expectedBrokerArtifactIdentity: BrokerArtifactIdentity,\n ): Promise<void> {\n const ready = new Promise<Extract<ServerFrame, { type: \"ready\" }>>((resolve, reject) => {\n this.ready = { resolve, reject };\n });\n this.write({\n type: \"init\",\n protocolVersion,\n clientVersion,\n });\n const frame = await this.raceBootstrapDeadline(ready);\n // A structurally valid Ready frame is not session authority: the broker\n // must speak exactly the protocol version this client announced (direct\n // connections have no daemon-readiness metadata protecting them).\n if (frame.protocolVersion !== protocolVersion) {\n throw new BrokerProtocolVersionError(protocolVersion, frame.protocolVersion);\n }\n if (\n !brokerArtifactIdentityEquals(frame.brokerArtifactIdentity, expectedBrokerArtifactIdentity)\n ) {\n throw new Error(\n `broker artifact identity mismatch: expected=${JSON.stringify(expectedBrokerArtifactIdentity)} actual=${JSON.stringify(frame.brokerArtifactIdentity)}`,\n );\n }\n this.sessionId = frame.sessionId;\n }\n\n async request(\n frame: ClientRequestFrame,\n options: TransportRequestOptions = {},\n ): Promise<ServerFrame> {\n if (this.pending.has(frame.requestId)) {\n throw new Error(`duplicate requestId: ${frame.requestId}`);\n }\n // Requests issued after transport death reject immediately: a destroyed\n // socket swallows writes without a terminal event, so the request map\n // would otherwise hold them forever (F2 zombie-entry finding, 2026-09-14:\n // post-death getUrl/destroy stayed pending indefinitely in both Node and\n // Bun because write-after-close only returns false).\n if (this.deadError !== undefined) {\n throw new Error(this.deadError.message);\n }\n\n // Per-call budget (W1, harden-transport-robustness): a half-open transport\n // where both processes stay alive but neither direction is delivered would\n // otherwise hold this entry forever. Expiry settles exactly this call with\n // the typed timeout rejection and removes the entry, so a late reply finds\n // no owner; it never marks the transport dead.\n const deadlineMs = options.deadlineMs ?? INTERACTIVE_CALL_DEADLINE_MS;\n const response = new Promise<ServerFrame>((resolve, reject) => {\n const deadlineTimer = setTimeout(() => {\n this.expireRequest(frame.requestId, deadlineMs);\n }, deadlineMs);\n // Library semantics: an outstanding call must never keep the host\n // process alive on its own.\n deadlineTimer.unref();\n this.pending.set(frame.requestId, { resolve, reject, deadlineTimer });\n });\n this.write(frame);\n return response;\n }\n\n onEvent(listener: (frame: LocalRuntimeEventFrame) => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n async close(): Promise<void> {\n if (this.deadError !== undefined) {\n // The transport already reached its terminal state; there is nothing\n // left to end. Resolving keeps explicit teardown paths (e.g. generated\n // app Quit after broker death) finite.\n return;\n }\n this.write({ type: \"exit\" });\n // Wall-clock-bounded graceful teardown (W3): a peer that never completes\n // the half-close must not wedge consumer shutdown. `end` completing late\n // degrades to `destroy`; either way close itself resolves — it never\n // rejects with a timeout, keeping the graceful-close sentinel semantics\n // (the subsequent socket close reports through the existing death path).\n await new Promise<void>((resolve) => {\n const degrade = setTimeout(() => {\n this.socket.destroy();\n resolve();\n }, TEARDOWN_CALL_DEADLINE_MS);\n degrade.unref();\n this.socket.end(() => {\n clearTimeout(degrade);\n resolve();\n });\n });\n }\n\n private consume(chunk: string): void {\n this.buffer += chunk;\n while (true) {\n const newline = this.buffer.indexOf(\"\\n\");\n if (newline < 0) {\n return;\n }\n\n const line = this.buffer.slice(0, newline).trim();\n this.buffer = this.buffer.slice(newline + 1);\n if (line.length > 0) {\n this.dispatchLine(line);\n }\n }\n }\n\n private dispatchLine(line: string): void {\n const parsed = parseServerFrame(line);\n if (!parsed.ok || parsed.frame === undefined) {\n this.rejectAll(new Error(`${parsed.error ?? \"invalid server frame\"}: ${line}`));\n return;\n }\n\n this.dispatchFrame(parsed.frame);\n }\n\n private dispatchFrame(frame: ServerFrame): void {\n if (frame.type === \"ready\") {\n this.ready?.resolve(frame);\n this.ready = undefined;\n return;\n }\n\n if (frame.type === \"error\") {\n // Synchronous server errors keep the typed `{ code, message, details }`\n // family (add-ext-dialog section 7.5): the same shape a deferred\n // terminal error rejects with, so consumers match one contract.\n const error = new BrokerServerError(frame.code, frame.message, {\n details: frame.details,\n });\n if (frame.requestId !== undefined) {\n this.takePending(frame.requestId)?.reject(error);\n return;\n }\n // An error with no requestId could not be correlated to a specific request.\n // If the handshake is still pending, reject it; otherwise reject every\n // pending request so callers fail loudly instead of hanging indefinitely.\n // (See issue #3: createTray never resolves on a malformed frame.)\n if (this.ready) {\n this.ready.reject(error);\n this.ready = undefined;\n return;\n }\n this.rejectAll(error);\n return;\n }\n\n if (frame.type === \"ext-command-accepted\") {\n this.acceptDeferredOperation(frame.requestId, frame.operationId);\n return;\n }\n\n if (frame.type === \"ext-operation-terminal\") {\n this.settleDeferredOperation(frame.operationId, frame.payload);\n return;\n }\n\n const requestId = responseRequestId(frame);\n if (requestId !== undefined) {\n // Request responses and broker events are separate streams even on one\n // socket. A reply arriving after its deadline finds no entry — the\n // stateless late-settlement discard (W1) — and settles nothing.\n this.takePending(requestId)?.resolve(frame);\n return;\n }\n\n if (\n frame.type === \"event\" ||\n frame.type === \"app-event\" ||\n frame.type === \"ext-event\"\n ) {\n for (const listener of this.listeners) {\n listener(frame);\n }\n }\n }\n\n private write(frame: unknown): void {\n this.socket.write(`${JSON.stringify(frame)}\\n`);\n }\n\n /**\n * Pending-until-final acceptance (add-ext-dialog section 5.1): acceptance never\n * settles the request. The broker's owner loop guarantees exactly one\n * terminal per operation; a second acceptance for the same request or an\n * already-bound operationId is defensively ignored, never a second\n * registration. Acceptance also stops the call's deadline: dispatch was the\n * bounded transport phase the client owns, and the accepted operation now\n * awaits a native terminal that can be legitimately user-paced (a held modal\n * dialog), bounded only by transport liveness.\n */\n private acceptDeferredOperation(requestId: RequestId, operationId: string): void {\n const entry = this.pending.get(requestId);\n if (entry === undefined || entry.deferredOperation !== undefined) {\n return;\n }\n if (this.deferredOperations.has(operationId)) {\n return;\n }\n entry.deferredOperation = operationId;\n this.deferredOperations.set(operationId, requestId);\n this.clearDeadline(entry);\n }\n\n /**\n * The single terminal settlement: resolves the still-pending request with\n * the terminal frame (`payload.kind === \"result\"`), or rejects it with the\n * typed wire error (`\"error\"`). Terminals for unknown or already-settled\n * operationIds are silently dropped - the broker side already settles\n * through a one-shot CAS; the client mirrors that stateless drop instead of\n * guessing an owner. A terminal arriving after the call's deadline expired\n * is the same stateless drop (W1).\n */\n private settleDeferredOperation(operationId: string, payload: ExtOperationPayload): void {\n const requestId = this.deferredOperations.get(operationId);\n if (requestId === undefined) {\n return;\n }\n const entry = this.takePending(requestId);\n if (entry === undefined) {\n this.deferredOperations.delete(operationId);\n return;\n }\n if (payload.kind === \"result\") {\n // The terminal frame is the correlated server-frame settlement of the\n // original request; its payload carries the deferred value.\n const terminal: Extract<ServerFrame, { type: \"ext-operation-terminal\" }> = {\n type: \"ext-operation-terminal\",\n operationId,\n payload,\n };\n entry.resolve(terminal);\n return;\n }\n const wireError = payload.error;\n entry.reject(\n new ExtensionOperationError(wireError.code, wireError.message, {\n details: wireError.details,\n }),\n );\n }\n\n /**\n * Removes and fully cleans one pending entry: clears its deadline timer and\n * the deferred-operation reverse mapping, so every settle path (response,\n * correlated error, deferred terminal, expiry) leaves no timer or mapping\n * behind.\n */\n private takePending(requestId: RequestId): PendingRequest | undefined {\n const entry = this.pending.get(requestId);\n if (entry === undefined) {\n return undefined;\n }\n this.pending.delete(requestId);\n this.clearDeadline(entry);\n if (entry.deferredOperation !== undefined) {\n this.deferredOperations.delete(entry.deferredOperation);\n }\n return entry;\n }\n\n private clearDeadline(entry: PendingRequest): void {\n if (entry.deadlineTimer !== undefined) {\n clearTimeout(entry.deadlineTimer);\n entry.deadlineTimer = undefined;\n }\n }\n\n /**\n * Deadline expiry (W1): settles exactly this call with the typed timeout\n * rejection and removes its entries, so a late reply or terminal finds no\n * owner. Deliberately NOT `markDead` — an unanswered call is one liveness\n * signal, not a death verdict; the connection stays usable and the death\n * listeners stay silent. The expiry is reported through the internal seam\n * for the Phase C heartbeat's failure classification.\n */\n private expireRequest(requestId: RequestId, deadlineMs: number): void {\n const entry = this.pending.get(requestId);\n if (entry === undefined) {\n return;\n }\n this.takePending(requestId);\n this.notifyDeadlineExpiry({ requestId, deadlineMs });\n entry.reject(new TransportTimeoutError(requestId, deadlineMs));\n }\n\n /**\n * Bootstrap-class budget (W1): the Ready frame must arrive within\n * `BOOTSTRAP_CALL_DEADLINE_MS` or init settles with the typed timeout\n * rejection. Like per-call expiry this never marks the transport dead —\n * `connectLocalBroker`'s error path performs the bounded close.\n */\n private raceBootstrapDeadline(\n ready: Promise<Extract<ServerFrame, { type: \"ready\" }>>,\n ): Promise<Extract<ServerFrame, { type: \"ready\" }>> {\n return new Promise((resolve, reject) => {\n let bootstrapTimer: ReturnType<typeof setTimeout> | undefined = setTimeout(() => {\n bootstrapTimer = undefined;\n this.notifyDeadlineExpiry({\n requestId: INIT_REQUEST_ID,\n deadlineMs: BOOTSTRAP_CALL_DEADLINE_MS,\n });\n reject(new TransportTimeoutError(INIT_REQUEST_ID, BOOTSTRAP_CALL_DEADLINE_MS));\n }, BOOTSTRAP_CALL_DEADLINE_MS);\n bootstrapTimer.unref();\n const settle = (settleFn: () => void): void => {\n if (bootstrapTimer !== undefined) {\n clearTimeout(bootstrapTimer);\n bootstrapTimer = undefined;\n }\n settleFn();\n };\n ready.then(\n (frame) => settle(() => resolve(frame)),\n (error) => settle(() => reject(error)),\n );\n });\n }\n\n private notifyDeadlineExpiry(expiry: TransportDeadlineExpiry): void {\n for (const listener of [...this.deadlineExpiryListeners]) {\n try {\n listener(expiry);\n } catch {\n // A throwing seam listener must not block expiry propagation to the\n // remaining listeners.\n }\n }\n }\n\n private rejectAll(error: Error): void {\n this.ready?.reject(error);\n this.ready = undefined;\n for (const pending of this.pending.values()) {\n this.clearDeadline(pending);\n pending.reject(error);\n }\n this.pending.clear();\n this.deferredOperations.clear();\n }\n\n /**\n * Terminal connection-death transition (D3): first socket error/close wins,\n * rejects everything pending, and notifies every terminal listener exactly\n * once. Later terminal events are no-ops.\n *\n * Pending-until-final (add-ext-dialog section 5.1): accepted deferred operations\n * reject with the generic typed `extension_transport_closed` (the core\n * client has no extension-name branch); every ordinary pending request\n * keeps the plain transport sentinel.\n */\n private markDead(error: Error): void {\n if (this.deadError !== undefined) {\n return;\n }\n this.deadError = error;\n this.ready?.reject(error);\n this.ready = undefined;\n for (const pending of this.pending.values()) {\n this.clearDeadline(pending);\n pending.reject(\n pending.deferredOperation === undefined ? error : extensionTransportClosedError(error),\n );\n }\n this.pending.clear();\n this.deferredOperations.clear();\n for (const listener of [...this.deadListeners]) {\n try {\n listener(error);\n } catch {\n // A throwing terminal listener must not block death propagation to\n // the remaining listeners.\n }\n }\n }\n}\n\nconst connectSocket = (endpoint: string): Promise<BrokerSocket> =>\n new Promise((resolve, reject) => {\n const socket = createConnection(endpoint);\n socket.once(\"connect\", () => {\n socket.off(\"error\", reject);\n resolve(socket);\n });\n socket.once(\"error\", reject);\n });\n\nconst responseRequestId = (frame: ServerFrame): RequestId | undefined => {\n switch (frame.type) {\n case \"app-created\":\n case \"default-app\":\n case \"app-identity\":\n case \"tray-created\":\n case \"tray-bounds\":\n case \"ack\":\n case \"ext-command-result\":\n case \"runtime-host-health\":\n return frame.requestId;\n // Acceptance never settles a request (handled before correlation), and a\n // terminal frame carries no requestId at all: both are routed through the\n // deferred-operation map in `dispatchFrame`.\n case \"ext-command-accepted\":\n case \"ext-operation-terminal\":\n case \"ready\":\n case \"event\":\n case \"app-event\":\n case \"ext-event\":\n case \"error\":\n return undefined;\n }\n};\n\nconst resolveCliEntrypoint = (): string => {\n const suffix = fileURLToPath(import.meta.url).endsWith(\".ts\") ? \"cli.ts\" : \"cli.mjs\";\n return fileURLToPath(new URL(`./${suffix}`, import.meta.url));\n};\n","// Orthogonal intents (2026-09-20; harden-transport-robustness Phase C/D,\n// original user request: broker death must surface as a bounded event and\n// recover with zero consumer code):\n// 1. Supervise exactly one live broker connection per generation; never\n// resurrect a dead connection (its D3 single-flight death contract stays\n// per-connection truth).\n// 2. Detect uninvited death through socket close/error plus an idle-gated\n// health-probe heartbeat (Phase A deadline machinery bounds each probe).\n// 3. Recover by reconnecting through the caller's original connect options\n// (identity gates and lock reclaim live in connectLocalBroker), replaying\n// a declarative journal, and re-running registered facade rebuild\n// callbacks in registration order.\n// 4. Bound recovery with an in-process sliding-window budget; exhaustion is\n// the terminal `abandoned` state with typed fail-fast calls.\n// 5. Keep caller-initiated teardown recovery-free and wall-clock bounded\n// (the Phase A teardown budget class is the caller-intent marker).\n\nimport type {\n AppIcon,\n AppRef,\n ClientRequestFrame,\n ExpectedExtensionIdentity,\n Icon,\n Menu,\n RequestId,\n ServerFrame,\n Tooltip,\n TrayId,\n TrayOptions,\n} from \"@opentray/spec\";\n\nimport {\n BROKER_CONNECTION_CLOSED_MESSAGE,\n type LocalBrokerClient,\n} from \"./local-broker\";\nimport {\n BOOTSTRAP_CALL_DEADLINE_MS,\n TEARDOWN_CALL_DEADLINE_MS,\n BrokerServerError,\n type OpenTrayEventFrame,\n type TransportRebuildContext,\n type TransportRequestOptions,\n type TransportState,\n} from \"./client\";\n\n/**\n * Default heartbeat cadence (W2; field-validated numbers from the pnpm-pub\n * silent-wedge reference implementation): probe only after 30 s of silence,\n * settle each probe within 3 s, declare death after 3 consecutive failures.\n */\nexport const DEFAULT_HEARTBEAT_INTERVAL_MS = 30_000;\nexport const DEFAULT_PROBE_DEADLINE_MS = 3_000;\nexport const DEFAULT_HEARTBEAT_FAILURE_THRESHOLD = 3;\n\n/**\n * Default recovery budget (W5): 3 respawn attempts per 10-minute window,\n * 1 s initial cooldown with exponential backoff (factor 2, capped at 30 s).\n * In-memory per supervisor — a fresh `createTray` is a fresh budget,\n * matching \"a manual process restart resets the budget\".\n */\nexport const DEFAULT_RECOVERY_MAX_RESTARTS = 3;\nexport const DEFAULT_RECOVERY_WINDOW_MS = 600_000;\nexport const DEFAULT_RECOVERY_COOLDOWN_MS = 1_000;\nexport const DEFAULT_RECOVERY_BACKOFF_FACTOR = 2;\nexport const DEFAULT_RECOVERY_BACKOFF_CAP_MS = 30_000;\n\n/**\n * Typed fail-fast rejection for every call issued after supervision reached\n * its terminal `abandoned` state: the recovery budget is exhausted and the\n * runtime stays headless by design (the consumer process keeps running).\n * Consumers match on `code` (`transport_abandoned`); `details` carries the\n * budget facts `{ recoveries, windowMs }`.\n */\nexport class TransportAbandonedError extends Error {\n readonly code = \"transport_abandoned\";\n readonly details: { readonly recoveries: number; readonly windowMs: number };\n\n constructor(recoveries: number, windowMs: number) {\n super(\n `transport abandoned: ${recoveries} recovery attempts within ${windowMs}ms exhausted the budget; every later call fails fast`,\n );\n this.name = \"TransportAbandonedError\";\n this.details = { recoveries, windowMs };\n }\n}\n\n/**\n * Tier 0/2 recovery policy (W6). Every key has a working default; the whole\n * object is optional — not configuring it means full default protection.\n * Policy stays in the app; mechanism stays in the SDK.\n */\nexport interface TransportRecoveryOptions {\n /**\n * Master switch (default `true`). `false` degrades supervision to today's\n * behavior plus heartbeat death detection: declared death stays terminal\n * per connection, no respawn, no `recovering`/`abandoned` transitions.\n */\n enabled?: boolean;\n /** Recovery attempts allowed per sliding `windowMs` (default 3). */\n maxRestarts?: number;\n /** Sliding budget window in milliseconds (default 600_000 = 10 min). */\n windowMs?: number;\n /** Cooldown before the first respawn attempt (default 1_000). */\n cooldownMs?: number;\n /** Multiplier applied to the cooldown after each failed attempt (default 2). */\n backoffFactor?: number;\n /** Backoff ceiling in milliseconds (default 30_000). */\n backoffCapMs?: number;\n /**\n * Tier 2 hand-over (default: absent). When provided, an uninvited death\n * performs a bounded teardown, invokes this callback exactly once, and goes\n * terminal — the supervisor never performs in-process rebuild and never\n * loops. The SDK never embeds app-process restart vectors itself.\n */\n restartApp?: () => void | Promise<void>;\n}\n\n/** Constructor tuning for {@link createTransportSupervisor}. */\nexport interface CreateTransportSupervisorOptions {\n /**\n * Establishes one broker connection generation. Production callers close\n * over `connectLocalBroker` with the caller's original options so a\n * respawn is exactly a reconnect: daemon lifecycle, identity gates, and\n * lock reclaim all reapply unchanged.\n */\n connect(): Promise<LocalBrokerClient>;\n /** Idle gap before a health probe is sent (default 30 s). */\n heartbeatIntervalMs?: number;\n /** Per-probe deadline budget (default 3 s). */\n probeDeadlineMs?: number;\n /** Consecutive probe failures that declare death (default 3). */\n heartbeatFailureThreshold?: number;\n /** Recovery policy; every key defaulted (Tier 0). */\n recovery?: TransportRecoveryOptions;\n}\n\n/**\n * Declarative state snapshot recorded from successfully settled mutating\n * frames (Tier 0's zero-API journal). One ordered list; keyed entries\n * (tray/app mutations, extension mounts) replace in place at first-occurrence\n * position, `create-tray` entries append in creation order. Only frames that\n * settled successfully are recorded — a rejected mutation never became\n * broker state.\n */\ntype JournalEntry =\n | { kind: \"resolve-default-app\"; appId: string }\n | { kind: \"create-tray\"; app: AppRef; tray: TrayOptions; trayId: TrayId }\n | {\n kind: \"set-tray-menu\";\n appId: string;\n trayId: TrayId;\n menu: Menu;\n }\n | { kind: \"set-tray-icon\"; appId: string; trayId: TrayId; icon: Icon }\n | {\n kind: \"set-tray-tooltip\";\n appId: string;\n trayId: TrayId;\n tooltip: Tooltip;\n }\n | { kind: \"set-app-name\"; appId: string; name: string }\n | { kind: \"set-app-icon\"; appId: string; appIcon: AppIcon | null }\n | { kind: \"set-app-icon-variant\"; appId: string; variant: string }\n | {\n kind: \"load-ext\";\n appId: string;\n name: string;\n path: string;\n expectedIdentity: ExpectedExtensionIdentity;\n mountId?: string;\n };\n\nconst journalKeyOf = (entry: JournalEntry): string | undefined => {\n switch (entry.kind) {\n case \"resolve-default-app\":\n return \"resolve-default-app\";\n case \"create-tray\":\n return undefined;\n case \"set-tray-menu\":\n case \"set-tray-icon\":\n case \"set-tray-tooltip\":\n return `${entry.kind}:${entry.appId}:${entry.trayId}`;\n case \"set-app-name\":\n case \"set-app-icon\":\n case \"set-app-icon-variant\":\n return `${entry.kind}:${entry.appId}`;\n case \"load-ext\":\n return `load-ext:${entry.appId}:${entry.mountId ?? entry.name}`;\n }\n};\n\n/** Structural view of connections publishing Phase A's expiry seam. */\ninterface DeadlineExpirySource {\n onDeadlineExpiry(listener: (expiry: { requestId: RequestId; deadlineMs: number }) => void): () => void;\n}\n\nconst isDeadlineExpirySource = (\n connection: LocalBrokerClient,\n): connection is LocalBrokerClient & DeadlineExpirySource =>\n \"onDeadlineExpiry\" in connection && typeof connection.onDeadlineExpiry === \"function\";\n\n/** Structural view of connections publishing their terminal death signal. */\ninterface ConnectionDeadSource {\n onConnectionDead(handler: (error: Error) => void): () => void;\n}\n\nconst isConnectionDeadSource = (\n connection: LocalBrokerClient,\n): connection is LocalBrokerClient & ConnectionDeadSource =>\n \"onConnectionDead\" in connection && typeof connection.onConnectionDead === \"function\";\n\nconst sleepUnref = (ms: number): Promise<void> =>\n new Promise((resolve) => {\n const timer = setTimeout(resolve, ms);\n timer.unref();\n });\n\n/**\n * Supervised transport (W2/W4/W5/W6): a stable `OpenTrayConnection`-shaped\n * proxy for the layers above (createClient, tray handles) that owns one\n * broker connection per generation underneath. Consumer event subscriptions\n * and the supervision state machine survive generation changes;\n * per-connection surfaces (`onConnectionDead`) stay per-generation truth.\n */\nexport class SupervisedLocalBrokerConnection {\n private readonly heartbeatIntervalMs: number;\n private readonly probeDeadlineMs: number;\n private readonly heartbeatFailureThreshold: number;\n private readonly recoveryEnabled: boolean;\n private readonly maxRestarts: number;\n private readonly recoveryWindowMs: number;\n private readonly cooldownMs: number;\n private readonly backoffFactor: number;\n private readonly backoffCapMs: number;\n private readonly restartApp: (() => void | Promise<void>) | undefined;\n\n private connection: LocalBrokerClient | undefined;\n private generation = 0;\n private state: TransportState = \"healthy\";\n private journal: JournalEntry[] = [];\n private readonly eventListeners = new Set<(frame: OpenTrayEventFrame) => void>();\n private readonly deadListeners = new Set<(error: Error) => void>();\n private readonly stateListeners = new Set<(state: TransportState) => void>();\n private readonly rebuildCallbacks: Array<\n (context: TransportRebuildContext) => Promise<void>\n > = [];\n private unwireGeneration: () => void = noop;\n private heartbeatTimer: ReturnType<typeof setInterval> | undefined;\n private heartbeatOrdinal = 0;\n private consecutiveHeartbeatFailures = 0;\n private lastSettledAt = 0;\n private restartTimestamps: number[] = [];\n private callerInitiated = false;\n private shutdownPromise: Promise<void> | undefined;\n\n constructor(\n private readonly connectFactory: () => Promise<LocalBrokerClient>,\n options: CreateTransportSupervisorOptions,\n ) {\n this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;\n this.probeDeadlineMs = options.probeDeadlineMs ?? DEFAULT_PROBE_DEADLINE_MS;\n this.heartbeatFailureThreshold =\n options.heartbeatFailureThreshold ?? DEFAULT_HEARTBEAT_FAILURE_THRESHOLD;\n const recovery = options.recovery ?? {};\n this.recoveryEnabled = recovery.enabled ?? true;\n this.maxRestarts = recovery.maxRestarts ?? DEFAULT_RECOVERY_MAX_RESTARTS;\n this.recoveryWindowMs = recovery.windowMs ?? DEFAULT_RECOVERY_WINDOW_MS;\n this.cooldownMs = recovery.cooldownMs ?? DEFAULT_RECOVERY_COOLDOWN_MS;\n this.backoffFactor = recovery.backoffFactor ?? DEFAULT_RECOVERY_BACKOFF_FACTOR;\n this.backoffCapMs = recovery.backoffCapMs ?? DEFAULT_RECOVERY_BACKOFF_CAP_MS;\n this.restartApp = recovery.restartApp;\n }\n\n /** Current supervision state; edge events go to {@link onTransportStateChange}. */\n get transportState(): TransportState {\n return this.state;\n }\n\n /** Monotonic generation counter; each respawn/replay increments it once. */\n get transportGeneration(): number {\n return this.generation;\n }\n\n /** Current generation's endpoint (proxy; absent before the first connect). */\n get endpoint(): string {\n return this.connection?.endpoint ?? \"\";\n }\n\n /** Current generation's caller label (proxy; absent before the first connect). */\n get callerLabel(): string {\n return this.connection?.callerLabel ?? \"\";\n }\n\n /**\n * Current generation's broker session id. Read dynamically so extension\n * contexts and rebuild callbacks can attribute session-owned state to the\n * live generation (the id changes on every respawn).\n */\n get sessionId(): string {\n return this.connection?.sessionId ?? \"\";\n }\n\n /** True once the current generation's connection died (or none exists). */\n get connectionDead(): boolean {\n return this.connection === undefined || this.connection.connectionDead;\n }\n\n /**\n * Establishes generation 0. A failure here propagates to the caller\n * unchanged — supervision (heartbeat, recovery) only guards a connection\n * that once existed; an app that never started is a plain startup failure.\n */\n async connect(): Promise<void> {\n const connection = await this.connectFactory();\n this.connection = connection;\n this.unwireGeneration = this.wireGeneration(connection);\n this.lastSettledAt = Date.now();\n this.consecutiveHeartbeatFailures = 0;\n this.startHeartbeat();\n }\n\n /**\n * Forwards one request to the current generation. After the terminal\n * `abandoned` state every call fails fast with {@link TransportAbandonedError}.\n * A teardown-budget call (`deadlineMs === TEARDOWN_CALL_DEADLINE_MS`) marks\n * the supervision caller-initiated: Phase A froze the budget class as the\n * caller-intent channel, so a socket close racing caller-initiated destroy\n * can never be misread as uninvited death.\n */\n async request(\n frame: ClientRequestFrame,\n options: TransportRequestOptions = {},\n ): Promise<ServerFrame> {\n if (this.state === \"abandoned\") {\n throw new TransportAbandonedError(this.restartTimestamps.length, this.recoveryWindowMs);\n }\n if (options.deadlineMs === TEARDOWN_CALL_DEADLINE_MS) {\n this.callerInitiated = true;\n }\n const connection = this.connection;\n if (connection === undefined) {\n throw new Error(BROKER_CONNECTION_CLOSED_MESSAGE);\n }\n const candidate = journalCandidateFrom(frame);\n const response = await connection.request(frame, options);\n this.noteSuccessfulSettlement();\n if (candidate !== undefined) {\n this.commitJournalEntry(candidate, response);\n }\n if (frame.type === \"destroy-tray\") {\n // A successfully destroyed tray must not resurrect on recovery: the\n // journal mirrors declarative broker state, so teardown evicts it.\n this.evictJournalTray(frame.appId, frame.trayId);\n }\n return response;\n }\n\n /**\n * Consumer event subscription that survives generation changes: each new\n * generation's event stream fans out to the same listeners.\n */\n onEvent(listener: (frame: OpenTrayEventFrame) => void): () => void {\n this.eventListeners.add(listener);\n return () => {\n this.eventListeners.delete(listener);\n };\n }\n\n /**\n * Per-connection death notification, forwarded for every generation (D3\n * semantics preserved: consumers using it for per-connection cleanup keep\n * working; the supervision state machine is the new higher-level truth).\n */\n onConnectionDead(listener: (error: Error) => void): () => void {\n this.deadListeners.add(listener);\n return () => {\n this.deadListeners.delete(listener);\n };\n }\n\n /**\n * Tier 1 health projection (W6): edge-triggered `healthy | recovering |\n * abandoned` transitions. The initial `healthy` state never fires —\n * consumers reading the current state use `transportState`.\n */\n onTransportStateChange(listener: (state: TransportState) => void): () => void {\n this.stateListeners.add(listener);\n return () => {\n this.stateListeners.delete(listener);\n };\n }\n\n /**\n * Registers one facade rebuild callback (W4). Callbacks run in\n * registration order after the core journal replay on every successful\n * recovery, receiving the fresh generation number and session id so\n * session-attributed native state can be re-created against the live\n * broker session.\n */\n registerTransportRebuild(\n rebuild: (context: TransportRebuildContext) => Promise<void>,\n ): void {\n this.rebuildCallbacks.push(rebuild);\n }\n\n /**\n * Graceful teardown channel (W4/W3): idempotent, marks the supervision\n * caller-initiated synchronously (so the close-driven death event can\n * never trigger recovery), stops the heartbeat, then closes the current\n * generation within its bounded graceful-close budget.\n */\n async shutdown(): Promise<void> {\n this.callerInitiated = true;\n this.shutdownPromise ??= (async () => {\n this.stopHeartbeat();\n this.unwireGeneration();\n this.unwireGeneration = noop;\n const connection = this.connection;\n this.connection = undefined;\n if (connection !== undefined) {\n await connection.close().catch(noopAsync);\n }\n })();\n await this.shutdownPromise;\n }\n\n /** LocalBrokerClient structural compatibility: graceful close == shutdown. */\n close(): Promise<void> {\n return this.shutdown();\n }\n\n private startHeartbeat(): void {\n if (this.heartbeatTimer !== undefined) {\n return;\n }\n this.heartbeatTimer = setInterval(() => {\n void this.heartbeatTick();\n }, this.heartbeatIntervalMs);\n // Library semantics: supervision must never keep the host process alive.\n this.heartbeatTimer.unref();\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer !== undefined) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = undefined;\n }\n }\n\n /**\n * Idle-gated heartbeat (W2): a transport that keeps settling requests\n * proves its own liveness, so the probe budget is spent only on silence.\n * A probe failure of any rejection class (typed timeout, transport-lost,\n * broker error frame) counts; a successful settlement resets the streak.\n */\n private async heartbeatTick(): Promise<void> {\n const connection = this.connection;\n if (\n connection === undefined ||\n this.state !== \"healthy\" ||\n this.callerInitiated\n ) {\n return;\n }\n if (Date.now() - this.lastSettledAt < this.heartbeatIntervalMs) {\n return;\n }\n const requestId = `supervisor-heartbeat-${this.generation}-${(this.heartbeatOrdinal += 1)}`;\n try {\n await connection.request(\n { type: \"health\", requestId },\n { deadlineMs: this.probeDeadlineMs },\n );\n this.consecutiveHeartbeatFailures = 0;\n this.noteSuccessfulSettlement();\n } catch (error) {\n this.consecutiveHeartbeatFailures += 1;\n if (this.consecutiveHeartbeatFailures < this.heartbeatFailureThreshold) {\n return;\n }\n // Declared death: settle the verdict through the sentinel family so\n // consumers matching the message keep working; the cause carries the\n // probe accounting for diagnostics.\n const death = new Error(BROKER_CONNECTION_CLOSED_MESSAGE, {\n cause: `heartbeat declared death after ${this.consecutiveHeartbeatFailures} consecutive probe failures (${String(error)})`,\n });\n // The death funnel runs first and unwires this generation; the bounded\n // close then rejects the half-open socket's pending entries through\n // the real destroy path without a second death notification.\n this.handleGenerationDeath(death);\n void connection.close().catch(noopAsync);\n }\n }\n\n private noteSuccessfulSettlement(): void {\n this.lastSettledAt = Date.now();\n this.consecutiveHeartbeatFailures = 0;\n }\n\n /**\n * Subscribes this supervisor's stable listener sets to one generation.\n * Event fanout and the death/expiry seams are wired before the generation\n * becomes `this.connection` (recovery candidates are wired before replay)\n * so no observable event window opens between adoption steps.\n */\n private wireGeneration(connection: LocalBrokerClient): () => void {\n const unwires: Array<() => void> = [];\n const unlistenEvents = connection.onEvent((frame) => {\n for (const listener of [...this.eventListeners]) {\n try {\n listener(frame);\n } catch {\n // A throwing consumer listener must not block fan-out.\n }\n }\n });\n unwires.push(unlistenEvents);\n // Structural capability tap (repo pattern): transports without a\n // death signal keep every other supervision feature and simply never\n // declare socket-close deaths — the real local broker connection always\n // publishes one, test fakes may not.\n if (isConnectionDeadSource(connection)) {\n const unlistenDead = connection.onConnectionDead((error) => {\n this.handleGenerationDeath(error);\n });\n unwires.push(unlistenDead);\n }\n if (isDeadlineExpirySource(connection)) {\n const unlistenExpiry = connection.onDeadlineExpiry((expiry) => {\n // Probe expiries are attributed by the probe's own rejection; every\n // other expiry is one liveness-failure signal (W1: an expiry never\n // declares death by itself).\n if (expiry.requestId.startsWith(\"supervisor-heartbeat-\")) {\n return;\n }\n this.consecutiveHeartbeatFailures += 1;\n if (\n this.consecutiveHeartbeatFailures >= this.heartbeatFailureThreshold &&\n this.state === \"healthy\" &&\n !this.callerInitiated\n ) {\n const connectionAtDeath = this.connection;\n // Death funnel first (unwires), bounded close second: same ordering\n // guarantee as the probe-failure path above.\n this.handleGenerationDeath(\n new Error(BROKER_CONNECTION_CLOSED_MESSAGE, {\n cause: `heartbeat declared death after ${this.consecutiveHeartbeatFailures} consecutive deadline expiries`,\n }),\n );\n if (connectionAtDeath !== undefined) {\n void connectionAtDeath.close().catch(noopAsync);\n }\n }\n });\n unwires.push(unlistenExpiry);\n }\n return () => {\n for (const unwire of unwires.splice(0)) {\n unwire();\n }\n };\n }\n\n /**\n * Death funnel: forwards the per-connection event first (D3 truth), stops\n * this generation's wiring, then decides the supervision reaction. The\n * state guard makes the reaction single-flight — deaths of candidates\n * during an ongoing recovery only forward, they never nest recoveries.\n */\n private handleGenerationDeath(error: Error): void {\n for (const listener of [...this.deadListeners]) {\n try {\n listener(error);\n } catch {\n // A throwing terminal listener must not block death propagation.\n }\n }\n if (this.callerInitiated || this.state !== \"healthy\") {\n return;\n }\n this.unwireGeneration();\n this.unwireGeneration = noop;\n if (this.restartApp !== undefined) {\n void this.handOverToRestartApp();\n return;\n }\n if (!this.recoveryEnabled) {\n // Tier-off: declared death stays terminal per connection (today's\n // behavior + heartbeat); no state transitions, no respawn.\n return;\n }\n void this.runRecovery();\n }\n\n /**\n * Tier 2 hand-over: bounded teardown of the current generation, the app's\n * restart vector invoked exactly once, then terminal. No in-process\n * rebuild, no loop — restart ownership belongs to the callback.\n */\n private async handOverToRestartApp(): Promise<void> {\n this.setState(\"recovering\");\n // Suppress every further supervision reaction first: our own teardown\n // fires the generation's death event, and the restart vector is the\n // app's policy from here on.\n this.callerInitiated = true;\n this.stopHeartbeat();\n const connection = this.connection;\n if (connection !== undefined && !connection.connectionDead) {\n await connection.close().catch(noopAsync);\n }\n try {\n await this.restartApp?.();\n } catch (error) {\n // The callback is app policy: surface the failure, never re-enter\n // supervision with it, and still settle the terminal state.\n console.error(\"OpenTray recovery.restartApp callback failed:\", error);\n }\n this.setState(\"abandoned\");\n }\n\n /**\n * In-process recovery (W4/W5): cooldown backoff → reconnect through the\n * original connect options → journal replay → facade rebuilds → healthy.\n * Every attempt consumes budget up front; a failed attempt (connect,\n * replay, or rebuild — including artifact identity mismatches) retries\n * inside the remaining budget until exhaustion abandons the runtime.\n */\n private async runRecovery(): Promise<void> {\n this.setState(\"recovering\");\n let backoffOrdinal = 0;\n while (true) {\n if (this.callerInitiated) {\n // Consumer teardown raced the recovery; the graceful path wins.\n return;\n }\n if (!this.consumeRestartBudget()) {\n this.setState(\"abandoned\");\n return;\n }\n await sleepUnref(this.cooldownForBackoff(backoffOrdinal));\n if (this.callerInitiated) {\n return;\n }\n try {\n const candidate = await this.connectFactory();\n await this.adoptGeneration(candidate);\n this.setState(\"healthy\");\n return;\n } catch {\n backoffOrdinal += 1;\n }\n }\n }\n\n private cooldownForBackoff(backoffOrdinal: number): number {\n return Math.min(\n this.cooldownMs * this.backoffFactor ** backoffOrdinal,\n this.backoffCapMs,\n );\n }\n\n /**\n * Sliding-window budget: one timestamp per respawn attempt (successful or\n * not — both are respawns the consumer experienced). In-memory per\n * supervisor by ruling; a fresh `createTray` starts a fresh budget.\n */\n private consumeRestartBudget(): boolean {\n const windowStart = Date.now() - this.recoveryWindowMs;\n this.restartTimestamps = this.restartTimestamps.filter(\n (timestamp) => timestamp > windowStart,\n );\n if (this.restartTimestamps.length >= this.maxRestarts) {\n return false;\n }\n this.restartTimestamps.push(Date.now());\n return true;\n }\n\n /**\n * Wires the candidate generation, replays the journal, and runs the\n * facade rebuild callbacks. `this.connection` is committed only after the\n * full sequence succeeds: consumer calls during recovery keep failing\n * fast against the dead generation instead of racing a half-replayed\n * broker. A failing candidate is unwired and closed (bounded) before the\n * attempt is reported failed.\n */\n private async adoptGeneration(candidate: LocalBrokerClient): Promise<void> {\n this.generation += 1;\n this.unwireGeneration = this.wireGeneration(candidate);\n try {\n await this.replayJournal(candidate);\n for (const rebuild of [...this.rebuildCallbacks]) {\n await rebuild({\n generation: this.generation,\n sessionId: candidate.sessionId.length > 0 ? candidate.sessionId : undefined,\n });\n }\n } catch (error) {\n this.unwireGeneration();\n this.unwireGeneration = noop;\n await candidate.close().catch(noopAsync);\n throw error;\n }\n this.connection = candidate;\n this.consecutiveHeartbeatFailures = 0;\n this.noteSuccessfulSettlement();\n }\n\n /**\n * Replays the declarative journal in record order with fresh request ids\n * under the bootstrap deadline class. The resolved default app of the new\n * generation becomes the appId authority: replayed frames are rewritten\n * onto it, so app-scoped state follows broker truth instead of a stale\n * generation's identity.\n */\n private async replayJournal(connection: LocalBrokerClient): Promise<void> {\n let ordinal = 0;\n const appIdRewrites = new Map<string, string>();\n const rewriteAppId = (appId: string): string => appIdRewrites.get(appId) ?? appId;\n for (const entry of this.journal) {\n ordinal += 1;\n const requestId: RequestId = `supervisor-replay-${this.generation}-${ordinal}`;\n let frame: ClientRequestFrame;\n switch (entry.kind) {\n case \"resolve-default-app\":\n frame = { type: \"resolve-default-app\", requestId };\n break;\n case \"create-tray\":\n frame = {\n type: \"create-tray\",\n requestId,\n app: { appId: rewriteAppId(entry.app.appId) },\n // Inject the originally resolved trayId: handle identity must\n // stay stable across generations even when the caller omitted a\n // tray id and the first broker assigned one.\n tray: { ...entry.tray, id: entry.trayId },\n };\n break;\n case \"set-tray-menu\":\n frame = {\n type: \"set-tray-menu\",\n requestId,\n appId: rewriteAppId(entry.appId),\n trayId: entry.trayId,\n menu: entry.menu,\n };\n break;\n case \"set-tray-icon\":\n frame = {\n type: \"set-tray-icon\",\n requestId,\n appId: rewriteAppId(entry.appId),\n trayId: entry.trayId,\n icon: entry.icon,\n };\n break;\n case \"set-tray-tooltip\":\n frame = {\n type: \"set-tray-tooltip\",\n requestId,\n appId: rewriteAppId(entry.appId),\n trayId: entry.trayId,\n tooltip: entry.tooltip,\n };\n break;\n case \"set-app-name\":\n frame = {\n type: \"set-app-name\",\n requestId,\n appId: rewriteAppId(entry.appId),\n name: entry.name,\n };\n break;\n case \"set-app-icon\":\n frame = {\n type: \"set-app-icon\",\n requestId,\n appId: rewriteAppId(entry.appId),\n appIcon: entry.appIcon,\n };\n break;\n case \"set-app-icon-variant\":\n frame = {\n type: \"set-app-icon-variant\",\n requestId,\n appId: rewriteAppId(entry.appId),\n variant: entry.variant,\n };\n break;\n case \"load-ext\":\n frame = {\n type: \"load-ext\",\n requestId,\n appId: rewriteAppId(entry.appId),\n name: entry.name,\n path: entry.path,\n expectedIdentity: entry.expectedIdentity,\n ...(entry.mountId === undefined ? {} : { mountId: entry.mountId }),\n };\n break;\n }\n const response = await connection.request(frame, {\n deadlineMs: BOOTSTRAP_CALL_DEADLINE_MS,\n });\n if (response.type === \"error\") {\n throw new BrokerServerError(response.code, response.message, {\n details: response.details,\n });\n }\n if (entry.kind === \"resolve-default-app\" && response.type === \"default-app\") {\n appIdRewrites.set(entry.appId, response.app.appId);\n }\n }\n }\n\n private setState(state: TransportState): void {\n if (this.state === state) {\n return;\n }\n this.state = state;\n if (state === \"abandoned\") {\n // Terminal: no heartbeat is ever useful again.\n this.stopHeartbeat();\n }\n for (const listener of [...this.stateListeners]) {\n try {\n listener(state);\n } catch {\n // A throwing state listener must not block the transition.\n }\n }\n }\n\n private commitJournalEntry(frame: ClientRequestFrame, response: ServerFrame): void {\n switch (frame.type) {\n case \"resolve-default-app\":\n if (response.type === \"default-app\") {\n this.upsertJournal({\n kind: \"resolve-default-app\",\n appId: response.app.appId,\n });\n }\n return;\n case \"create-tray\": {\n const trayId: TrayId =\n response.type === \"tray-created\" && typeof response.trayId === \"string\"\n ? response.trayId\n : frame.tray.id;\n this.journal.push({\n kind: \"create-tray\",\n app: frame.app,\n tray: frame.tray,\n trayId,\n });\n return;\n }\n case \"set-tray-menu\":\n this.upsertJournal({\n kind: \"set-tray-menu\",\n appId: frame.appId,\n trayId: frame.trayId,\n menu: frame.menu,\n });\n return;\n case \"set-tray-icon\":\n this.upsertJournal({\n kind: \"set-tray-icon\",\n appId: frame.appId,\n trayId: frame.trayId,\n icon: frame.icon,\n });\n return;\n case \"set-tray-tooltip\":\n this.upsertJournal({\n kind: \"set-tray-tooltip\",\n appId: frame.appId,\n trayId: frame.trayId,\n tooltip: frame.tooltip,\n });\n return;\n case \"set-app-name\":\n this.upsertJournal({ kind: \"set-app-name\", appId: frame.appId, name: frame.name });\n return;\n case \"set-app-icon\":\n this.upsertJournal({\n kind: \"set-app-icon\",\n appId: frame.appId,\n appIcon: frame.appIcon,\n });\n return;\n case \"set-app-icon-variant\":\n this.upsertJournal({\n kind: \"set-app-icon-variant\",\n appId: frame.appId,\n variant: frame.variant,\n });\n return;\n case \"load-ext\":\n this.upsertJournal({\n kind: \"load-ext\",\n appId: frame.appId,\n name: frame.name,\n path: frame.path,\n expectedIdentity: frame.expectedIdentity,\n ...(frame.mountId === undefined ? {} : { mountId: frame.mountId }),\n });\n return;\n default:\n return;\n }\n }\n\n /**\n * Keyed entries replace in place at first-occurrence position (last-write-\n * wins value, stable ordering); first occurrences append. Tray creations\n * and mount declarations keep their creation order by construction.\n */\n private upsertJournal(entry: JournalEntry): void {\n const key = journalKeyOf(entry);\n if (key === undefined) {\n this.journal.push(entry);\n return;\n }\n const existing = this.journal.findIndex(\n (candidate) => journalKeyOf(candidate) === key,\n );\n if (existing < 0) {\n this.journal.push(entry);\n return;\n }\n this.journal[existing] = entry;\n }\n\n private evictJournalTray(appId: string, trayId: TrayId): void {\n this.journal = this.journal.filter((entry) => {\n switch (entry.kind) {\n case \"create-tray\":\n return !(entry.app.appId === appId && entry.trayId === trayId);\n case \"set-tray-menu\":\n case \"set-tray-icon\":\n case \"set-tray-tooltip\":\n return !(entry.appId === appId && entry.trayId === trayId);\n default:\n return true;\n }\n });\n }\n}\n\n/**\n * Snapshot candidate for the declarative journal: a defensive clone of every\n * journalable mutating frame, taken before the await so later caller\n * mutation of the frame object cannot corrupt the recorded state. The entry\n * is committed only after the frame settles successfully.\n */\nconst journalCandidateFrom = (frame: ClientRequestFrame): ClientRequestFrame | undefined => {\n switch (frame.type) {\n case \"resolve-default-app\":\n case \"create-tray\":\n case \"set-tray-menu\":\n case \"set-tray-icon\":\n case \"set-tray-tooltip\":\n case \"set-app-name\":\n case \"set-app-icon\":\n case \"set-app-icon-variant\":\n case \"load-ext\":\n return structuredClone(frame);\n default:\n return undefined;\n }\n};\n\n/** Constructs a supervised transport around one connect factory. */\nexport const createTransportSupervisor = (\n options: CreateTransportSupervisorOptions,\n): SupervisedLocalBrokerConnection =>\n new SupervisedLocalBrokerConnection(options.connect, options);\n\nconst noop = (): void => {};\nconst noopAsync = (): void => {};\n","import type { Menu, MenuItem, MenuItemId } from \"@opentray/spec\";\n\nimport type { TrayEventByType } from \"./client\";\n\nexport type CreateTrayMenuClickHandler = (\n event: TrayEventByType<\"menuClick\">\n) => void;\n\n/** App-facing menu input accepted by top-level createTray and setMenu. */\nexport type CreateTrayMenu = {\n items: CreateTrayMenuItem[];\n};\n\n/** Menu item shorthand normalized to protocol MenuItem before runtime transport. */\nexport type CreateTrayMenuItem =\n | string\n | readonly [title: string, items: readonly CreateTrayMenuItem[]]\n | CreateTrayItem\n | CreateTrayCheckItem\n | CreateTrayRadioItem\n | CreateTraySeparatorItem\n | CreateTraySubmenuItem;\n\nexport type CreateTrayItem = {\n type?: \"item\";\n id?: MenuItemId;\n title: string;\n primaryEvent?: boolean;\n enabled?: boolean;\n shortcut?: string;\n onMenuClick?: CreateTrayMenuClickHandler;\n};\n\nexport type CreateTrayCheckItem = {\n type: \"check\";\n id?: MenuItemId;\n title: string;\n enabled?: boolean;\n checked?: boolean;\n onMenuClick?: CreateTrayMenuClickHandler;\n};\n\nexport type CreateTrayRadioItem = {\n type: \"radio\";\n id?: MenuItemId;\n title: string;\n enabled?: boolean;\n checked?: boolean;\n group: number;\n onMenuClick?: CreateTrayMenuClickHandler;\n};\n\nexport type CreateTraySeparatorItem = {\n type: \"separator\";\n};\n\nexport type CreateTraySubmenuItem = {\n type: \"submenu\";\n title: string;\n enabled?: boolean;\n items: readonly CreateTrayMenuItem[];\n};\n\nexport interface NormalizedCreateTrayMenu {\n menu: Menu;\n handlers: Map<MenuItemId, CreateTrayMenuClickHandler[]>;\n}\n\nexport const normalizeCreateTrayMenu = (\n menu: CreateTrayMenu\n): NormalizedCreateTrayMenu => {\n const state: NormalizeState = {\n usedIds: collectExplicitMenuIds(menu.items),\n nextId: 1,\n handlers: new Map(),\n };\n return {\n menu: {\n items: menu.items.map((item) => normalizeCreateTrayMenuItem(item, state)),\n },\n handlers: state.handlers,\n };\n};\n\nconst normalizeCreateTrayMenuItem = (\n item: CreateTrayMenuItem,\n state: NormalizeState\n): MenuItem => {\n if (typeof item === \"string\") {\n if (isSeparatorShortcut(item)) {\n return { type: \"separator\" };\n }\n return normalizePlainItem({ title: item }, state);\n }\n if (isSubmenuTuple(item)) {\n const [title, items] = item;\n return {\n type: \"submenu\",\n title,\n items: items.map((child) => normalizeCreateTrayMenuItem(child, state)),\n };\n }\n switch (item.type) {\n case undefined:\n case \"item\":\n return normalizePlainItem(item, state);\n case \"check\":\n return normalizeCheckItem(item, state);\n case \"radio\":\n return normalizeRadioItem(item, state);\n case \"separator\":\n return item;\n case \"submenu\":\n return {\n type: \"submenu\",\n title: item.title,\n ...(item.enabled === undefined ? {} : { enabled: item.enabled }),\n items: item.items.map((child) =>\n normalizeCreateTrayMenuItem(child, state)\n ),\n };\n }\n throw new Error(\"unsupported menu item\");\n};\n\nconst normalizeClickableItem = (\n item: {\n id?: MenuItemId;\n onMenuClick?: CreateTrayMenuClickHandler;\n },\n state: NormalizeState\n): MenuItemId => {\n const id = item.id ?? allocateMenuItemId(state);\n registerClickId(state, id);\n if (item.onMenuClick !== undefined) {\n const handlers = state.handlers.get(id) ?? [];\n handlers.push(item.onMenuClick);\n state.handlers.set(id, handlers);\n }\n return id;\n};\n\nconst normalizePlainItem = (\n item: CreateTrayItem,\n state: NormalizeState\n): Extract<MenuItem, { type: \"item\" }> => {\n const id = normalizeClickableItem(item, state);\n return {\n type: \"item\",\n id,\n title: item.title,\n ...(item.primaryEvent === undefined\n ? {}\n : { primaryEvent: item.primaryEvent }),\n ...(item.enabled === undefined ? {} : { enabled: item.enabled }),\n ...(item.shortcut === undefined ? {} : { shortcut: item.shortcut }),\n };\n};\n\nconst normalizeCheckItem = (\n item: CreateTrayCheckItem,\n state: NormalizeState\n): Extract<MenuItem, { type: \"check\" }> => {\n const id = normalizeClickableItem(item, state);\n return {\n type: \"check\",\n id,\n title: item.title,\n ...(item.enabled === undefined ? {} : { enabled: item.enabled }),\n ...(item.checked === undefined ? {} : { checked: item.checked }),\n };\n};\n\nconst normalizeRadioItem = (\n item: CreateTrayRadioItem,\n state: NormalizeState\n): Extract<MenuItem, { type: \"radio\" }> => {\n const id = normalizeClickableItem(item, state);\n return {\n type: \"radio\",\n id,\n title: item.title,\n ...(item.enabled === undefined ? {} : { enabled: item.enabled }),\n ...(item.checked === undefined ? {} : { checked: item.checked }),\n group: item.group,\n };\n};\n\nconst allocateMenuItemId = (state: NormalizeState): MenuItemId => {\n while (state.usedIds.has(state.nextId)) {\n state.nextId += 1;\n }\n const id = state.nextId;\n state.usedIds.add(id);\n state.nextId += 1;\n return id;\n};\n\nconst collectExplicitMenuIds = (\n items: readonly CreateTrayMenuItem[]\n): Set<MenuItemId> => {\n const ids = new Set<MenuItemId>();\n for (const item of items) {\n if (typeof item === \"string\") {\n continue;\n }\n if (isSubmenuTuple(item)) {\n for (const id of collectExplicitMenuIds(item[1])) {\n ids.add(id);\n }\n continue;\n }\n switch (item.type) {\n case undefined:\n case \"item\":\n case \"check\":\n case \"radio\":\n if (item.id !== undefined) {\n ids.add(item.id);\n }\n break;\n case \"submenu\":\n for (const id of collectExplicitMenuIds(item.items)) {\n ids.add(id);\n }\n break;\n case \"separator\":\n break;\n }\n }\n return ids;\n};\n\nconst isSeparatorShortcut = (value: string): boolean => /^-+$/.test(value);\n\nconst isSubmenuTuple = (\n item: CreateTrayMenuItem\n): item is readonly [title: string, items: readonly CreateTrayMenuItem[]] =>\n Array.isArray(item);\n\nconst registerClickId = (state: NormalizeState, id: MenuItemId): void => {\n const seen = state.seenClickIds ?? new Set<MenuItemId>();\n if (seen.has(id)) {\n throw new Error(`duplicate menu item id: ${id}`);\n }\n seen.add(id);\n state.seenClickIds = seen;\n};\n\ninterface NormalizeState {\n usedIds: Set<MenuItemId>;\n nextId: MenuItemId;\n handlers: Map<MenuItemId, CreateTrayMenuClickHandler[]>;\n seenClickIds?: Set<MenuItemId>;\n}\n","// Orthogonal intents (2026-07-20; original user request: an empty launch\n// setting reuses the current process invocation and explicit scripts are allowed):\n// 1. Normalize caller-facing launch options into a durable executable vector.\n// 2. Resolve cwd and path-like commands without invoking a shell.\n// 3. Keep environment variables out of the persisted descriptor.\n\nimport { isAbsolute, resolve } from \"node:path\";\n\nimport type { OpenTrayAppLaunchDescriptor, OpenTrayAppLaunchOptions } from \"@opentray/packaging\";\n\nexport const normalizeAppLaunch = (\n configured: OpenTrayAppLaunchOptions | null | undefined,\n context: {\n readonly execPath?: string;\n readonly argv?: readonly string[];\n readonly cwd?: string;\n } = {},\n): OpenTrayAppLaunchDescriptor => {\n const currentCwd = context.cwd ?? process.cwd();\n if (configured === undefined || configured === null) {\n return {\n schemaVersion: 1,\n command: validateRequiredText(context.execPath ?? process.execPath, \"process.execPath\"),\n args: [...(context.argv ?? process.argv).slice(1)].map((arg, index) =>\n validateArg(arg, `process.argv[${index + 1}]`),\n ),\n cwd: validateRequiredText(currentCwd, \"process.cwd()\"),\n };\n }\n const command = validateRequiredText(configured.command, \"appLaunch.command\");\n const configuredCwd =\n configured.cwd === undefined\n ? currentCwd\n : validateRequiredText(configured.cwd, \"appLaunch.cwd\");\n const cwd = resolve(currentCwd, configuredCwd);\n const args = [...(configured.args ?? [])].map((arg, index) =>\n validateArg(arg, `appLaunch.args[${index}]`),\n );\n return {\n schemaVersion: 1,\n command: resolvePathLikeCommand(command, currentCwd),\n args,\n cwd,\n };\n};\n\nconst resolvePathLikeCommand = (command: string, cwd: string): string => {\n if (isAbsolute(command) || command.includes(\"/\") || command.includes(\"\\\\\")) {\n return resolve(cwd, command);\n }\n return command;\n};\n\nconst validateRequiredText = (value: string, field: string): string => {\n if (value.trim().length === 0 || value.includes(\"\\u0000\")) {\n throw new Error(`${field} must be a non-empty string without NUL`);\n }\n return value;\n};\n\nconst validateArg = (value: string, field: string): string => {\n if (value.includes(\"\\u0000\")) {\n throw new Error(`${field} must be a string without NUL`);\n }\n return value;\n};\n","// Orthogonal intents (maintained 2026-07-21; original user requests: pnpm\n// install must be sufficient; an empty App launch command must remember the\n// current process.argv invocation for the next stable-bundle launch):\n// 1. Expose one direct, ergonomic createTray entrypoint.\n// 2. Normalize app-facing menu shorthand into the protocol model.\n// 3. Make the returned handle own and deterministically close its broker session.\n// 4. Snapshot caller launch intent before initializing the local runtime.\n\nimport type { AppIcon, Icon, Tooltip, TrayOptions } from \"@opentray/spec\";\nimport type {\n OpenTrayAppBundleOptions,\n OpenTrayAppLaunchOptions,\n} from \"@opentray/packaging\";\n\nimport {\n createClient,\n type EventfulTrayHandle,\n type TrayExtension,\n} from \"./client\";\nimport { connectLocalBroker, BROKER_CONNECTION_CLOSED_MESSAGE } from \"./local-broker\";\nimport {\n createTransportSupervisor,\n type TransportRecoveryOptions,\n} from \"./transport-supervision\";\nimport {\n normalizeCreateTrayMenu,\n type CreateTrayMenu,\n type CreateTrayMenuClickHandler,\n} from \"./menu-input\";\nimport { normalizeAppIcon, validateAppIcon } from \"./app-icon\";\nimport { normalizeAppLaunch } from \"./app-launch\";\n\nexport interface OpenTrayRuntimeOptions {\n endpoint?: string;\n homeDir?: string;\n packageVersion?: string;\n protocolVersion?: number;\n clientVersion?: string;\n appId?: string;\n appName?: string;\n appIcon?: AppIcon;\n appBundle?: OpenTrayAppBundleOptions;\n /** Stable app-entry launch vector. Omitted/null snapshots the current invocation. */\n appLaunch?: OpenTrayAppLaunchOptions | null;\n autoStart?: boolean;\n /**\n * Optional transport supervision policy (Tier 0/2,\n * harden-transport-robustness). Every key has a working default; omitting\n * the object entirely means full default protection: heartbeat death\n * detection, automatic in-process recovery with journal replay, and a\n * bounded restart budget. `enabled: false` keeps death detection but\n * degrades to today's fail-fast behavior.\n */\n recovery?: TransportRecoveryOptions;\n}\n\n/** App-facing tray options accepted by top-level createTray. */\nexport interface CreateTrayOptions {\n id: string;\n tooltip?: Tooltip;\n icon?: Icon;\n menu?: CreateTrayMenu;\n}\n\n/** Tray handle returned by top-level createTray with ergonomic menu and session ownership. */\nexport interface CreateTrayHandle\n extends Omit<EventfulTrayHandle, \"setMenu\" | \"extend\" | \"destroy\"> {\n setMenu(menu: CreateTrayMenu): Promise<void>;\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions\n ): CreateTrayHandle & TCapability;\n destroy(): Promise<void>;\n}\n\nexport const createTray = async (\n options: CreateTrayOptions,\n runtimeOptions: OpenTrayRuntimeOptions = {}\n): Promise<CreateTrayHandle> => {\n if (runtimeOptions.appIcon !== undefined) {\n await validateAppIcon(runtimeOptions.appIcon);\n }\n const appIcon =\n runtimeOptions.appIcon === undefined\n ? undefined\n : normalizeAppIcon(runtimeOptions.appIcon);\n const normalized = normalizeCreateTrayOptions(options);\n const appLaunch = normalizeAppLaunch(runtimeOptions.appLaunch);\n const { recovery, ...brokerOptions } = runtimeOptions;\n // The supervisor owns the broker connection from here on: it presents the\n // stable transport surface to createClient/handles while holding one\n // LocalBrokerConnection per generation underneath. A respawn is exactly a\n // reconnect through the original options — daemon lifecycle, identity\n // gates, and lock reclaim all reapply unchanged.\n const supervisor = createTransportSupervisor({\n connect: () =>\n connectLocalBroker({\n ...brokerOptions,\n ...(appIcon === undefined ? {} : { appIcon }),\n appLaunch,\n }),\n ...(recovery === undefined ? {} : { recovery }),\n });\n try {\n await supervisor.connect();\n const tray = await createClient(supervisor, {\n appOptions: {\n ...(runtimeOptions.appName === undefined\n ? {}\n : { name: runtimeOptions.appName }),\n ...(appIcon === undefined ? {} : { appIcon }),\n },\n }).createTray(normalized.options);\n return wrapCreateTrayHandle(tray, {\n shutdown: () => supervisor.shutdown(),\n destroyPromise: undefined,\n menuUnsubscribe: bindMenuClickHandlers(tray, normalized.menuHandlers),\n });\n } catch (error) {\n await supervisor.shutdown().catch(noop);\n throw error;\n }\n};\n\nconst normalizeCreateTrayOptions = (\n options: CreateTrayOptions\n): NormalizedCreateTrayOptions => {\n const protocolOptions: Omit<TrayOptions, \"menu\"> = {\n id: options.id,\n ...(options.tooltip === undefined ? {} : { tooltip: options.tooltip }),\n ...(options.icon === undefined ? {} : { icon: options.icon }),\n };\n if (options.menu === undefined) {\n return { options: protocolOptions, menuHandlers: new Map() };\n }\n const normalized = normalizeCreateTrayMenu(options.menu);\n return {\n options: {\n ...protocolOptions,\n menu: normalized.menu,\n },\n menuHandlers: normalized.handlers,\n };\n};\n\nconst wrapCreateTrayHandle = (\n tray: EventfulTrayHandle,\n state: CreateTrayHandleState\n): CreateTrayHandle => {\n const handle: CreateTrayHandle = {\n ...tray,\n async setMenu(menu: CreateTrayMenu): Promise<void> {\n const normalized = normalizeCreateTrayMenu(menu);\n await tray.setMenu(normalized.menu);\n state.menuUnsubscribe();\n state.menuUnsubscribe = bindMenuClickHandlers(tray, normalized.handlers);\n },\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions\n ): CreateTrayHandle & TCapability {\n const extended = tray.extend(extension, options);\n return wrapCreateTrayHandle(extended, state) as CreateTrayHandle &\n TCapability;\n },\n async destroy(): Promise<void> {\n state.destroyPromise ??= (async () => {\n state.menuUnsubscribe();\n state.menuUnsubscribe = noop;\n // The broker tears its transport down as soon as its last session\n // closes, so the destroy request can race the broker-side socket\n // close. Both the destroy frame and the connection close rejecting\n // with the transport-close sentinel is the requested end state, not\n // a failure — a generated app's Quit must exit cleanly when the\n // broker exits first (P3.6 quit-path finding, 2026-09-12).\n // The destroy frame carries the teardown budget class (W3), which\n // the supervisor reads as the caller-initiated marker — so this\n // close race can never be misread as uninvited death and never\n // triggers recovery.\n const isTransportClosed = (error: unknown): boolean =>\n error instanceof Error &&\n error.message === BROKER_CONNECTION_CLOSED_MESSAGE;\n try {\n await tray.destroy();\n } catch (error) {\n if (!isTransportClosed(error)) {\n throw error;\n }\n } finally {\n try {\n await state.shutdown();\n } catch (error) {\n if (!isTransportClosed(error)) {\n throw error;\n }\n }\n }\n })();\n await state.destroyPromise;\n },\n };\n return handle;\n};\n\nconst bindMenuClickHandlers = (\n tray: EventfulTrayHandle,\n handlers: Map<number, CreateTrayMenuClickHandler[]>\n): (() => void) => {\n if (handlers.size === 0) {\n return noop;\n }\n return tray.onMenuClick((event) => {\n for (const handler of handlers.get(event.itemId) ?? []) {\n handler(event);\n }\n });\n};\n\nconst noop = (): void => {};\n\ninterface NormalizedCreateTrayOptions {\n options: TrayOptions;\n menuHandlers: Map<number, CreateTrayMenuClickHandler[]>;\n}\n\ninterface CreateTrayHandleState {\n /** Graceful supervised teardown: marks caller-initiated and closes the generation. */\n shutdown: () => Promise<void>;\n destroyPromise: Promise<void> | undefined;\n menuUnsubscribe: () => void;\n}\n"],"mappings":";;;;;;;;;;;;;AAgBA,MAAa,2BAA2B;AACxC,MAAM,2BAA2B;AAEjC,IAAa,sBAAb,cAAyC,MAAM;CAC7C,OAAgB;CAChB;CAEA,YAAY,QAAgB,WAA4B,QAAQ,UAAU;EACxE,MAAM,uBAAuB,SAAS,IAAI,QAAQ;EAClD,KAAK,OAAO;EACZ,KAAK,SAAS;CAChB;AACF;AAEA,IAAa,8BAAb,cAAiD,MAAM;CACrD,OAAgB;CAChB;CAEA,YAAY,SAAiB,WAA4B,QAAQ,UAAU;EACzE,MAAM,mBAAmB,QAAQ,sBAAsB,UAAU;EACjE,KAAK,OAAO;EACZ,KAAK,UAAU;CACjB;AACF;;AAGA,MAAa,kBAAkB,OAC7B,MACA,WAA4B,QAAQ,aAClB;CAClB,IAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,KAAK,WAAW,GAC1C,MAAM,IAAI,oBACR,qCACA,QACF;CAGF,MAAM,mCAAmB,IAAI,IAAkC;CAC/D,MAAM,6BAAa,IAAI,IAAY;CACnC,MAAM,8BAAc,IAAI,IAAY;CACpC,MAAM,oCAAoB,IAAI,IAAY;CAC1C,MAAM,+BAAe,IAAI,IAAY;CACrC,KAAK,MAAM,SAAS,MAAM;EACxB,IAAI,CAACA,WAAS,KAAK,GACjB,MAAM,IAAI,oBAAoB,2BAA2B,QAAQ;EAEnE,MAAM,gBAAgB,MAAM;EAC5B,MAAM,SAAS,MAAM;EACrB,MAAM,WAAW,qBAAqB,MAAM,SAAS,QAAQ;EAC7D,IAAI,kBAAkB,YAAY,WAAW,QAAQ;GACnD,gBACE,OACA;IAAC;IAAY;IAAU;GAAQ,GAC/B,UACA,CAAC,SAAS,CACZ;GACA,wBAAwB,YAAY,UAAU,UAAU,QAAQ;GAChE,MAAM,eAAe,MAAM,QAAQ,QAAQ,QAAQ;GACnD,uBAAuB,kBAAkB,UAAU,QAAQ;GAC3D;EACF;EACA,IAAI,kBAAkB,aAAa,WAAW,OAAO;GACnD,gBACE,OACA;IAAC;IAAY;IAAU;GAAQ,GAC/B,UACA,CAAC,SAAS,CACZ;GACA,wBAAwB,aAAa,UAAU,WAAW,QAAQ;GAClE,MAAM,eAAe,MAAM,QAAQ,OAAO,QAAQ;GAClD,uBAAuB,kBAAkB,UAAU,SAAS;GAC5D;EACF;EACA,IAAI,kBAAkB,WAAW,WAAW,OAAO;GACjD,gBACE,OACA;IAAC;IAAY;IAAU;IAAQ;GAAQ,GACvC,UACA,CAAC,SAAS,CACZ;GACA,IACE,CAAC,OAAO,UAAU,MAAM,IAAI,KAC5B,OAAO,MAAM,SAAS,YACtB,MAAM,QAAQ,GAEd,MAAM,IAAI,oBACR,oDACA,QACF;GAEF,KAAK,MAAM,WAAW,UAAU;IAC9B,MAAM,MAAM,GAAG,QAAQ,IAAI,MAAM;IACjC,IAAI,kBAAkB,IAAI,GAAG,GAC3B,MAAM,IAAI,oBACR,4BAA4B,MAAM,KAAK,eAAe,WACtD,QACF;IAEF,kBAAkB,IAAI,GAAG;GAC3B;GACA,MAAM,eAAe,MAAM,QAAQ,OAAO,QAAQ;GAClD,uBAAuB,kBAAkB,UAAU,OAAO;GAC1D;EACF;EACA,IAAI,kBAAkB,WAAW,WAAW,OAAO;GACjD,gBACE,OACA;IAAC;IAAY;IAAU;GAAQ,GAC/B,UACA,CAAC,SAAS,CACZ;GACA,wBAAwB,cAAc,UAAU,aAAa,QAAQ;GACrE,MAAM,eAAe,MAAM,QAAQ,OAAO,QAAQ;GAClD,uBAAuB,kBAAkB,UAAU,OAAO;GAC1D;EACF;EACA,MAAM,IAAI,oBACR,oCAAoC,OAAO,aAAa,EAAE,GAAG,OAC3D,MACF,KACA,QACF;CACF;CAEA,MAAM,kBAAkB,kBAAkB,QAAQ;CAClD,IAAI,oBAAoB,KAAA,GAAW;EACjC,IAAI,CAAC,iBAAiB,IAAA,SAA4B,CAAC,EAAE,IAAI,eAAe,GACtE,MAAM,IAAI,oBACR,MAAM,gBAAgB,GAAG,yBAAyB,sBAClD,QACF;EAEF,KAAK,MAAM,CAAC,SAAS,cAAc,kBACjC,IAAI,CAAC,UAAU,IAAI,eAAe,GAChC,MAAM,IAAI,oBACR,WAAW,QAAQ,UAAU,gBAAgB,SAC7C,QACF;CAGN;AACF;;AAGA,MAAa,oBAAoB,SAC/B,KAAK,KAAK,UAAU;CAClB,MAAM,SAAS,gBAAgB,MAAM,MAAM;CAC3C,MAAM,UAAU,iBAAiB,MAAM,OAAO;CAC9C,IAAI,MAAM,aAAa,UAAU,OAAO;EAAE,GAAG;EAAO;EAAS;CAAO;CACpE,IAAI,MAAM,aAAa,WAAW,OAAO;EAAE,GAAG;EAAO;EAAS;CAAO;CACrE,IAAI,MAAM,WAAW,OAAO,OAAO;EAAE,GAAG;EAAO;EAAS;CAAO;CAC/D,OAAO;EAAE,GAAG;EAAO;EAAS;CAAO;AACrC,CAAC;;AAGH,MAAa,wBACX,MACA,SACA,WAA4B,QAAQ,aACxB;CACZ,oBAAoB,SAAS,QAAQ;CACrC,MAAM,WAAW,KAAK,QAAQ,UAC5B,uBAAuB,MAAM,OAAO,CAAC,CAAC,SAAS,OAAO,CACxD;CACA,MAAM,kBAAkB,kBAAkB,QAAQ;CAClD,IACE,SAAS,WAAW,KACnB,oBAAoB,KAAA,KACnB,CAAC,SAAS,MAAM,UAAU,MAAM,aAAa,eAAe,GAE9D,MAAM,IAAI,4BAA4B,SAAS,QAAQ;CAEzD,OAAO;AACT;AAEA,MAAM,mBAAmB,WACvB,OAAO,SAAS,YACZ;CAAE,MAAM;CAAW,MAAM,MAAM,KAAK,OAAO,IAAI;AAAE,IACjD;CAAE,MAAM;CAAQ,MAAM,QAAQ,OAAO,IAAI;AAAE;AAEjD,MAAM,oBACJ,YAEA,YAAY,KAAA,IACR,2BACA,OAAO,YAAY,WACjB,UACA,CAAC,GAAG,OAAO;AAEnB,MAAM,0BACJ,YAEA,YAAY,KAAA,IACR,CAAC,wBAAwB,IACzB,OAAO,YAAY,WACjB,CAAC,OAAO,IACR;AAER,MAAM,wBACJ,SACA,aACsB;CACtB,MAAM,QACJ,YAAY,KAAA,IACR,CAAC,wBAAwB,IACzB,OAAO,YAAY,WACjB,CAAC,OAAO,IACR,MAAM,QAAQ,OAAO,IACnB,UACA,CAAC;CACX,IAAI,MAAM,WAAW,GACnB,MAAM,IAAI,oBACR,kDACA,QACF;CAEF,MAAM,uBAAO,IAAI,IAAY;CAC7B,KAAK,MAAM,QAAQ,OAAO;EACxB,oBAAoB,MAAM,QAAQ;EAClC,IAAI,KAAK,IAAI,IAAI,GACf,MAAM,IAAI,oBACR,0BAA0B,KAAK,gBAC/B,QACF;EAEF,KAAK,IAAI,IAAI;CACf;CACA,OAAO;AACT;AAEA,SAAS,oBACP,SACA,UAC2B;CAC3B,IAAI,OAAO,YAAY,YAAY,CAAC,yBAAyB,KAAK,OAAO,GACvE,MAAM,IAAI,oBACR,sBAAsB,4BACtB,QACF;AAEJ;AAEA,MAAM,2BACJ,MACA,UACA,OACA,iBACS;CACT,KAAK,MAAM,WAAW,UAAU;EAC9B,IAAI,KAAK,IAAI,OAAO,GAClB,MAAM,IAAI,oBACR,aAAa,MAAM,qBAAqB,WACxC,YACF;EAEF,KAAK,IAAI,OAAO;CAClB;AACF;AAEA,MAAM,0BACJ,UACA,OACA,aACS;CACT,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,YAAY,SAAS,IAAI,IAAI,qBAAK,IAAI,IAAqB;EACjE,UAAU,IAAI,QAAQ;EACtB,SAAS,IAAI,MAAM,SAAS;CAC9B;AACF;AAEA,MAAM,iBAAiB,OACrB,QACA,QACA,aACkB;CAClB,IAAI,CAACA,WAAS,MAAM,GAClB,MAAM,IAAI,oBACR,kDACA,QACF;CAEF,IAAI;CACJ,IAAI,OAAO,SAAS,QAAQ;EAC1B,gBAAgB,QAAQ,CAAC,QAAQ,MAAM,GAAG,QAAQ;EAClD,IAAI,OAAO,OAAO,SAAS,YAAY,OAAO,KAAK,KAAK,CAAC,CAAC,WAAW,GACnE,MAAM,IAAI,oBACR,sCACA,QACF;EAEF,IAAI;GACF,QAAQ,MAAM,SAAS,OAAO,IAAI;EACpC,SAAS,OAAO;GACd,MAAM,IAAI,oBACR,kBAAkB,OAAO,KAAK,IAAI,aAAa,KAAK,KACpD,QACF;EACF;CACF,OAAO,IAAI,OAAO,SAAS,WAAW;EACpC,gBAAgB,QAAQ,CAAC,QAAQ,MAAM,GAAG,QAAQ;EAClD,QAAQ,aAAa,OAAO,MAAM,QAAQ;CAC5C,OACE,MAAM,IAAI,oBAAoB,oCAAoC,QAAQ;CAE5E,IAAI,CAAC,cAAc,OAAO,MAAM,GAC9B,MAAM,IAAI,oBACR,uCAAuC,OAAO,YAAY,EAAE,SAC5D,QACF;AAEJ;AAEA,MAAM,gBAAgB,MAAe,aAA0C;CAC7E,IAAI,gBAAgB,cAAc,KAAK,aAAa,GAAG,OAAO;CAC9D,IACE,MAAM,QAAQ,IAAI,KAClB,KAAK,SAAS,KACd,KAAK,OAAO,UAAU,OAAO,UAAU,KAAK,KAAK,SAAS,KAAK,SAAS,GAAG,GAE3E,OAAO,WAAW,KAAK,IAAI;CAE7B,MAAM,IAAI,oBACR,qEACA,QACF;AACF;AAEA,MAAM,iBACJ,OACA,WACY;CACZ,IAAI,WAAW,QAAQ,OAAO,UAAU,OAAO;EAAC;EAAM;EAAM;EAAM;CAAI,CAAC;CACvE,IAAI,WAAW,OACb,OACE,MAAM,UAAU,KAAK,UAAU,OAAO;EAAC;EAAG;EAAG;EAAG;CAAC,CAAC,KAAK,MAAM,OAAO;CAGxE,IAAI,WAAW,OACb,OAAO,UAAU,OAAO;EAAC;EAAK;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;CAAE,CAAC;CAE3D,MAAM,SAAS,IAAI,YAAY,CAAC,CAC7B,OAAO,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAC/B,QAAQ,WAAW,EAAE;CACxB,OAAO,yDAAyD,KAC9D,OAAO,UAAU,CACnB;AACF;AAEA,MAAM,aAAa,OAAmB,WACpC,MAAM,UAAU,OAAO,UACvB,OAAO,OAAO,MAAM,UAAU,MAAM,WAAW,IAAI;AAErD,MAAM,mBACJ,QACA,UACA,UACA,WAA8B,CAAC,MACtB;CACT,MAAM,SAAS,OAAO,KAAK,MAAM;CACjC,MAAM,0BAAU,IAAI,IAAI,CAAC,GAAG,UAAU,GAAG,QAAQ,CAAC;CAClD,MAAM,aAAa,OAAO,MAAM,QAAQ,CAAC,QAAQ,IAAI,GAAG,CAAC;CACzD,IAAI,eAAe,KAAA,GACjB,MAAM,IAAI,oBACR,0BAA0B,cAC1B,QACF;CAEF,MAAM,UAAU,SAAS,MAAM,QAAQ,EAAE,OAAO,OAAO;CACvD,IAAI,YAAY,KAAA,GACd,MAAM,IAAI,oBAAoB,uBAAuB,WAAW,QAAQ;AAE5E;AAEA,MAAMA,cAAY,UAChB,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAErE,MAAM,gBAAgB,UACpB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAEvD,MAAM,qBACJ,aACgC;CAChC,IAAI,aAAa,UAAU,OAAO;CAClC,IAAI,aAAa,SAAS,OAAO;CACjC,IAAI,aAAa,SAAS,OAAO;AAEnC;;;;;;;;;;;ACrWA,MAAa,0CAA0C;CACrD;CACA;CACA;CACA;AACF;AAwDA,IAAa,yCAAb,cAA4D,MAAM;CAOrD;CANX,OAAgB;CAChB;CACA;CAEA,YACE,SACA,QACA,UAGI,CAAC,GACL;EACA,MAAM,SAAS,OAAO;EANb,KAAA,SAAA;EAOT,KAAK,OAAO;EACZ,IAAI,QAAQ,gBAAgB,KAAA,GAC1B,KAAK,cAAc,QAAQ;EAE7B,IAAI,QAAQ,yBAAyB,KAAA,GACnC,KAAK,uBAAuB,QAAQ;CAExC;AACF;;AAcA,MAAa,wCAGT;CACF,sBAAsB;CACtB,uBAAuB;CACvB,oBAAoB;CACpB,sBAAsB;AACxB;AAEA,IAAa,uCAAb,cAA0D,MAAM;CAC9D;CACA;CACA;CACA;CAEA,YACE,QACA,SACA,SAIA;EACA,MAAM,SAAS,OAAO;EACtB,KAAK,OAAO;EACZ,KAAK,SAAS;EACd,KAAK,OAAO,sCAAsC;EAClD,KAAK,SAAS,QAAQ;EACtB,IAAI,QAAQ,yBAAyB,KAAA,GACnC,KAAK,uBAAuB,QAAQ;CAExC;AACF;;AAGA,MAAa,iCAAiC,OAC5C,UACA,WAA4B,QAAQ,UACpC,OAAe,QAAQ,SACsB;CAC7C,MAAM,SAAS,sBAAsB,UAAU,IAAI;CACnD,IAAI,SAAS,SAAS,QACpB,OAAO;EACL,MAAM,MAAM,yBAAyB,SAAS,MAAM,MAAM;EAC1D,kBACE,SAAS,oBACR,MAAM,wBAAwB,SAAS,gBAAgB,MAAM;EAChE;CACF;CAGF,IAAI,SAAS,SAAS,YACpB,OAAO,iCAAiC,UAAU,MAAM;CAG1D,MAAM,gBAAgB,SAAS,QAAQ;CACvC,IAAI,kBAAkB,KAAA,GACpB,MAAM,IAAI,uCACR,4CAA4C,UAC5C,MACF;CAGF,MAAM,mBAAmB,MAAM,wBAAwB,UAAU,MAAM;CAEvE,MAAM,oBAAoB,cAAc,SAAS,cAAc;CAC/D,IAAI;CACJ,IAAI;EACF,0BAA0B,kBAAkB,QAC1C,GAAG,cAAc,YAAY,cAC/B;CACF,SAAS,OAAO;EACd,MAAM,IAAI,uCACR,+CAA+C,cAAc,YAAY,QAAQ,OAAO,QAAQ,SAAS,kBACzG,QACA;GACE;GACA,aAAa,cAAc;GAC3B,sBAAsB,SAAS;EACjC,CACF;CACF;CAEA,MAAM,WAAW,MAAM,4BACrB,yBACA,QACA,cAAc,WAChB;CACA,MAAM,cAAc,KAAK,QAAQ,uBAAuB,GAAG,cAAc,WAAW;CACpF,OAAO;EACL,MAAM,MAAM,yBAAyB,aAAa,QAAQ,cAAc,WAAW;EACnF,aAAa,cAAc;EAC3B,gBAAgB,SAAS;EACzB;EACA;CACF;AACF;AAEA,MAAM,0BAA0B,OAC9B,QACA,WAC6C;CAC7C,MAAM,CAAC,gBAAgB,oBAAoB,MAAM,QAAQ,IAAI,CAC3D,0BAA0B,OAAO,gBAAgB,MAAM,GACvD,8BAA8B,OAAO,qBAAqB,MAAM,CAClE,CAAC;CACD,MAAM,CAAC,IAAI,QAAQ,YAAY,MAAM;CACrC,OAAO;EACL,eAAe,iBAAiB;EAChC,oBAAoB,eAAe;EACnC,qBAAqB,iBAAiB;EACtC,QAAQ;GAAE;GAAI;EAAK;CACrB;AACF;;AAaA,MAAa,iCAAiC;AAc9C,MAAM,mBAAmB;AAEzB,MAAM,0BACJ,WAEC,wCAA8D,SAAS,MAAM;AAEhF,MAAM,oBAAoB,MAAc,cAA+B;CACrE,MAAM,MAAM,SAAS,MAAM,SAAS;CACpC,IAAI,IAAI,WAAW,GACjB,OAAO;CAET,OAAO,EAAE,QAAQ,QAAQ,IAAI,WAAW,KAAK,KAAK,KAAK,WAAW,GAAG;AACvE;AAEA,MAAM,mCAAmC,OACvC,UACA,WAC6C;CAC7C,MAAM,uBAAuB,SAAS;CACtC,MAAM,iBACJ,QACA,SACA,UAA+B,CAAC,MAEhC,IAAI,qCAAqC,QAAQ,SAAS;EACxD;EACA;EACA,GAAI,QAAQ,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,QAAQ,MAAM;CAChE,CAAC;CAIH,IAAI,CAAC,uBAAuB,MAAM,GAChC,MAAM,cACJ,sBACA,sEAAsE,wCAAwC,KAAK,IAAI,EAAE,KAAK,OAAO,eACvI;CAEF,MAAM,iBAAiB,SAAS,QAAQ;CACxC,IAAI,mBAAmB,KAAA,GAGrB,MAAM,cACJ,sBACA,qDAAqD,QACvD;CAGF,MAAM,aAAa,QAAQ,cAAc,IAAI,IAAI,oBAAoB,CAAC,CAAC;CAIvE,IAAI,WAAW,eAAe,WAAW,GACvC,MAAM,cACJ,uBACA,sEAAsE,eAAe,aACvF;CAEF,MAAM,gBAAgB,QAAQ,YAAY,eAAe,WAAW;CACpE,IAAI,CAAC,iBAAiB,YAAY,aAAa,GAC7C,MAAM,cACJ,uBACA,0DAA0D,eAAe,aAC3E;CAKF,MAAM,CAAC,gBAAgB,oBAAoB,MAAM,QAAQ,IAAI,CAC3D,iBAAiB,sBAAsB,aAAa,CAAC,CAAC,MAAM,WAAW;EACrE,IAAI,CAAC,wBAAwB,MAAM,GACjC,MAAM,cACJ,oBACA,kDAAkD,sBACpD;EAEF,OAAO;CACT,CAAC,GACD,iBAAiB,SAAS,qBAAqB,aAAa,CAAC,CAAC,MAAM,WAAW;EAC7E,IAAI,CAAC,4BAA4B,MAAM,GACrC,MAAM,cACJ,oBACA,sDAAsD,SAAS,qBACjE;EAEF,OAAO;CACT,CAAC,CACH,CAAC;CAED,MAAM,eAAe,KAAK,YAAY,8BAA8B;CACpE,MAAM,WAAW,MAAM,iBACrB,cAAc,YAAY,CAAC,CAAC,MAC5B,aACF,CAAC,CAAC,MAAM,WAAW;EACjB,IAAI,CAAC,0BAA0B,MAAM,GACnC,MAAM,cACJ,oBACA,2CAA2C,cAC7C;EAEF,OAAO;CACT,CAAC;CAED,IAAI,SAAS,kBAAkB,eAAe,SAC5C,MAAM,cACJ,oBACA,4CAA4C,SAAS,cAAc,yCAAyC,eAAe,SAC7H;CAEF,IAAI,SAAS,wBAAwB,iBAAiB,qBACpD,MAAM,cACJ,oBACA,0FAA0F,SAAS,qBACrG;CAKF,KAAK,MAAM,gBAAgB,yCACzB,IAAI,SAAS,QAAQ,kBAAkB,KAAA,GACrC,MAAM,cACJ,oBACA,+DAA+D,cACjE;CAGJ,KAAK,MAAM,kBAAkB,OAAO,KAAK,SAAS,OAAO,GAAG;EAC1D,IAAI,CAAC,uBAAuB,cAAuC,GACjE,MAAM,cACJ,oBACA,6CAA6C,eAAe,mCAC9D;EAEF,IACE,SAAS,QAAQ,oBACjB,KAAA,GAEA,MAAM,cACJ,oBACA,wDAAwD,gBAC1D;CAEJ;CACA,MAAM,gBAAgB,SAAS,QAAQ;CACvC,IAAI,kBAAkB,KAAA,GACpB,MAAM,cACJ,oBACA,qDAAqD,QACvD;CAGF,IAAI,WAAW,cAAc,IAAI,GAC/B,MAAM,cACJ,uBACA,uFAAuF,cAAc,MACvG;CAEF,MAAM,sBAAsB,QAAQ,YAAY,cAAc,IAAI;CAClE,IAAI,CAAC,iBAAiB,YAAY,mBAAmB,GACnD,MAAM,cACJ,uBACA,2EAA2E,cAAc,MAC3F;CAEF,IAAI,wBAAwB,eAC1B,MAAM,cACJ,oBACA,kCAAkC,cAAc,KAAK,4CAA4C,eAAe,YAAY,cAAc,QAC5I;CAKF,MAAM,WAAW,MAAM,SAAS,UAAU,CAAC,CAAC,YAAY,UAAU;CAClE,IAAI;CACJ,IAAI;EACF,gBAAgB,MAAM,SAAS,aAAa;CAC9C,SAAS,OAAO;EACd,MAAM,cACJ,sBACA,0DAA0D,iBAC1D,EAAE,MAAM,CACV;CACF;CACA,IAAI,CAAC,iBAAiB,UAAU,aAAa,GAC3C,MAAM,cACJ,uBACA,8DAA8D,eAAe,aAC/E;CAKF,IAAI;CACJ,IAAI;EACF,eAAe,MAAM,SAAS,aAAa;CAC7C,SAAS,OAAO;EACd,MAAM,cACJ,sBACA,wDAAwD,iBACxD,EAAE,MAAM,CACV;CACF;CACA,MAAM,SAAS,WAAW,QAAQ,CAAC,CAAC,OAAO,YAAY,CAAC,CAAC,OAAO,KAAK;CACrE,IAAI,WAAW,cAAc,QAC3B,MAAM,cACJ,oBACA,+EAA+E,QACjF;CAGF,MAAM,CAAC,IAAI,QAAQ,YAAY,MAAM;CACrC,MAAM,mBAAoD;EACxD,eAAe,iBAAiB;EAChC,oBAAoB,eAAe;EACnC,qBAAqB,iBAAiB;EACtC,QAAQ;GAAE;GAAI;EAAK;EACnB;EACA,eAAe,cAAc;CAC/B;CACA,OAAO;EAAE,MAAM;EAAe;EAAkB;CAAO;AACzD;AAEA,MAAM,mBAAmB,OACvB,KACA,kBAKqB;CACrB,IAAI;EACF,OAAO,KAAK,MAAM,MAAM,SAAS,IAAI,IAAI,GAAG,GAAG,MAAM,CAAC;CACxD,SAAS,OAAO;EACd,MAAM,cACJ,oBACA,sDAAsD,OACtD,EAAE,MAAM,CACV;CACF;AACF;AAEA,MAAM,6BACJ,UACqC;CACrC,IAAI,CAAC,aAAa,KAAK,KAAK,CAAC,aAAa,MAAM,OAAO,GACrD,OAAO;CAET,IACE,OAAO,MAAM,kBAAkB,YAC/B,OAAO,MAAM,wBAAwB,UAErC,OAAO;CAET,KAAK,MAAM,SAAS,OAAO,OAAO,MAAM,OAAO,GAC7C,IACE,CAAC,aAAa,KAAK,KACnB,OAAO,MAAM,SAAS,YACtB,OAAO,MAAM,WAAW,YACxB,CAAC,iBAAiB,KAAK,MAAM,MAAM,KACnC,OAAO,MAAM,kBAAkB,YAC/B,MAAM,cAAc,WAAW,GAE/B,OAAO;CAGX,OAAO;AACT;AAEA,MAAM,gBAAgB,UACpB,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAErE,MAAM,yBACJ,UACA,SAC0B;CAC1B,IAAI,SAAS,WAAW,SAAS,OAC/B,MAAM,IAAI,MAAM,8CAA8C,MAAM;CAEtE,OAAO,GAAG,SAAS,GAAG;AACxB;AAmBA,MAAM,4BAA4B,OAChC,gBACA,WACmC;CACnC,MAAM,SAAS,MAAM,YAAY,gBAAgB,QAAQ,yBAAyB;CAClF,IAAI,CAAC,wBAAwB,MAAM,GACjC,MAAM,IAAI,uCACR,kDAAkD,kBAClD,QACA,EAAE,sBAAsB,eAAe,CACzC;CAEF,OAAO;AACT;AAEA,MAAM,gCAAgC,OACpC,qBACA,WACuC;CACvC,MAAM,SAAS,MAAM,YACnB,qBACA,QACA,6BACF;CACA,IAAI,CAAC,4BAA4B,MAAM,GACrC,MAAM,IAAI,uCACR,oDAAoD,uBACpD,MACF;CAEF,OAAO;AACT;AAEA,MAAM,cAAc,OAClB,KACA,QACA,UACqB;CACrB,IAAI;EACF,OAAO,KAAK,MAAM,MAAM,SAAS,IAAI,IAAI,GAAG,GAAG,MAAM,CAAC;CACxD,SAAS,OAAO;EACd,MAAM,IAAI,uCACR,kBAAkB,MAAM,MAAM,OAC9B,QACA,EAAE,MAAM,CACV;CACF;AACF;AAEA,MAAM,8BAA8B,OAClC,iBACA,QACA,gBACqC;CACrC,IAAI;CACJ,IAAI;EACF,SAAS,KAAK,MAAM,MAAM,SAAS,iBAAiB,MAAM,CAAC;CAC7D,SAAS,OAAO;EACd,MAAM,IAAI,uCACR,uDAAuD,mBACvD,QACA;GAAE;GAAO;EAAY,CACvB;CACF;CACA,IAAI,CAAC,0BAA0B,MAAM,KAAK,OAAO,SAAS,aACxD,MAAM,IAAI,uCACR,wCAAwC,gBAAgB,qBAAqB,eAC7E,QACA,EAAE,YAAY,CAChB;CAEF,MAAM,CAAC,UAAU,QAAQ,YAAY,MAAM;CAC3C,IAAI,OAAO,OAAO,KAAA,KAAa,CAAC,OAAO,GAAG,SAAS,QAAQ,GACzD,MAAM,IAAI,uCACR,4BAA4B,YAAY,uBAAuB,YAC/D,QACA,EAAE,YAAY,CAChB;CAEF,IAAI,OAAO,QAAQ,KAAA,KAAa,CAAC,OAAO,IAAI,SAAS,IAAI,GACvD,MAAM,IAAI,uCACR,4BAA4B,YAAY,wBAAwB,QAChE,QACA,EAAE,YAAY,CAChB;CAEF,OAAO;AACT;AAEA,MAAM,6BACJ,UAEA,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,OAAO,MAAM,SAAS,YACtB,aAAa,SACb,OAAO,MAAM,YAAY,aACxB,EAAE,QAAQ,UACR,MAAM,QAAQ,MAAM,EAAE,KAAK,MAAM,GAAG,OAAO,SAAS,OAAO,SAAS,QAAQ,OAC9E,EAAE,SAAS,UACT,MAAM,QAAQ,MAAM,GAAG,KAAK,MAAM,IAAI,OAAO,SAAS,OAAO,SAAS,QAAQ;AAEnF,MAAM,2BAA2B,UAC/B,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,OAAO,MAAM,SAAS,YACtB,aAAa,SACb,OAAO,MAAM,YAAY;AAE3B,MAAM,+BACJ,UAEA,OAAO,UAAU,YACjB,UAAU,QACV,mBAAmB,SACnB,OAAO,MAAM,kBAAkB,YAC/B,yBAAyB,SACzB,OAAO,MAAM,wBAAwB;AAEvC,MAAM,eACJ,WAC2C;CAC3C,MAAM,YAAY,OAAO,YAAY,GAAG;CACxC,OAAO,CACL,OAAO,MAAM,GAAG,SAAS,GACzB,OAAO,MAAM,YAAY,CAAC,CAC5B;AACF;AAEA,MAAM,2BAA2B,OAC/B,MACA,QACA,gBACoB;CACpB,IAAI;EACF,OAAO,MAAM,SAAS,IAAI;CAC5B,SAAS,OAAO;EACd,MAAM,IAAI,uCACR,iDAAiD,QACjD,QACA;GACE;GACA,GAAI,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,YAAY;EACrD,CACF;CACF;AACF;;;;;;;;;;;ACrqBA,MAAa,+BAA+B;AAC5C,MAAa,4BAA4B;AACzC,MAAa,6BAA6B;;;;;;;;;;;AAY1C,IAAa,wBAAb,cAA2C,MAAM;CAC/C;CACA;CAEA,YAAY,WAAsB,YAAoB;EACpD,MAAM,yCAAyC,WAAW,MAAM,WAAW;EAC3E,KAAK,OAAO;EACZ,KAAK,YAAY;EACjB,KAAK,aAAa;CACpB;AACF;;;;;;;;AA0DA,IAAa,oBAAb,cAAuC,MAAM;CAC3C;CACA;CAEA,YACE,MACA,SACA,UAAkD,CAAC,GACnD;EACA,MAAM,SAAS,QAAQ,UAAU,KAAA,IAAY,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,CAAC;EACjF,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,IAAI,QAAQ,YAAY,KAAA,GACtB,KAAK,UAAU,QAAQ;CAE3B;AACF;AA4IA,MAAa,mBAAmB,mBAAwC;CACtE,MAAM;CACN,iBAAiBC;CACjB;AACF;AAkBA,SAAgB,aACd,WACA,UAA+B,CAAC,GACS;CACzC,MAAM,gBAAgB,uBACpB,QAAQ,mBAAmB,UAC7B;CACA,IAAI;CAEJ,MAAM,YAAY,OAChB,gBAC2D;EAC3D,gBAAgB,YAAY;GAC1B,MAAM,MAAM,MAAM,qBAAqB,WAAW,aAAa;GAC/D,MAAM,SAAS,gBAAgB,WAAW,IAAI,OAAO,aAAa;GAClE,MAAM,aAAa,QAAQ;GAC3B,IAAI,YAAY,SAAS,KAAA,GACvB,MAAM,OAAO,QAAQ,WAAW,IAAI;GAEtC,IAAI,YAAY,YAAY,KAAA,GAC1B,MAAM,OAAO,WAAW,WAAW,OAAO;GAE5C,OAAO;IAAE;IAAK;GAAO;EACvB,EAAA,CAAG,CAAC,CAAC,OAAO,UAAmB;GAC7B,aAAa,KAAA;GACb,MAAM;EACR,CAAC;EACD,OAAO;CACT;CAEA,OAAO,EACL,MAAM,WAAW,SAA2C;EAC1D,MAAM,EAAE,QAAQ,MAAM,UAAU,OAAO;EACvC,MAAM,YAAY,cAAc;EAChC,MAAM,WAAW,MAAM,UAAU,QAAQ;GACvC,MAAM;GACN;GACA;GACA,MAAM;EACR,CAAC;EACD,MAAM,QAAQ,eAAe,UAAU,WAAW,cAAc;EAChE,OAAO,iBACL,WACA,IAAI,OACJ,MAAM,UAAU,QAAQ,IACxB,aACF;CACF,EACF;AACF;AAcA,SAAgB,iBACd,WACA,OACA,QACA,gBAAiC,uBAAuB,UAAU,GACjC;CAIjC,MAAM,YAAY,uBAAuB,SAAS;CAClD,IAAI,mBAAmB;CACvB,MAAM,eAAe,kBAAkC;EACrD,MAAM,UAAU,GAAG,uBACjB,aACF,EAAE,GAAG,uBAAuB,MAAM,EAAE,GAAG;EACvC,oBAAoB;EACpB,OAAO;CACT;CACA,MAAM,SAAqB;EACzB;EACA,KAAK,gBAAgB,WAAW,OAAO,aAAa;EACpD,MAAM,YAAuC;GAC3C,MAAM,YAAY,cAAc;GAChC,MAAM,WAAW,MAAM,UAAU,QAAQ;IACvC,MAAM;IACN;IACA;IACA;GACF,CAAC;GACD,OAAO,eAAe,UAAU,WAAW,aAAa,CAAC,CAAC;EAC5D;EACA,MAAM,QAAQ,MAA2B;GACvC,MAAM,YAAY,cAAc;GAChC,MAAM,WAAW,MAAM,UAAU,QAAQ;IACvC,MAAM;IACN;IACA;IACA;IACA;GACF,CAAC;GACD,eAAe,UAAU,WAAW,KAAK;EAC3C;EACA,MAAM,WAAW,SAAiC;GAChD,MAAM,YAAY,cAAc;GAChC,MAAM,WAAW,MAAM,UAAU,QAAQ;IACvC,MAAM;IACN;IACA;IACA;IACA;GACF,CAAC;GACD,eAAe,UAAU,WAAW,KAAK;EAC3C;EACA,MAAM,QAAQ,MAA2B;GACvC,MAAM,YAAY,cAAc;GAChC,MAAM,WAAW,MAAM,UAAU,QAAQ;IACvC,MAAM;IACN;IACA;IACA;IACA;GACF,CAAC;GACD,eAAe,UAAU,WAAW,KAAK;EAC3C;EACA,MAAM,cAAc,SAAwB;GAC1C,MAAM,YAAY,cAAc;GAChC,MAAM,WAAW,MAAM,+BAA+B,QAAQ,QAAQ;GACtE,MAAM,WAAW,MAAM,UAAU,QAAQ;IACvC,MAAM;IACN;IACA;IACA,MAAM,QAAQ;IACd,MAAM,SAAS;IACf,kBAAkB,SAAS;IAC3B,GAAI,QAAQ,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,QAAQ,QAAQ;GACtE,CAAC;GACD,eAAe,UAAU,WAAW,KAAK;EAC3C;EACA,MAAM,iBAAiB,KAAa,MAA8B;GAChE,MAAM,KAAK,iBAAiB,KAAK,IAAI;EACvC;EACA,MAAM,iBACJ,KACA,MACyC;GACzC,MAAM,YAAY,cAAc;GAChC,MAAM,WAAW,MAAM,UAAU,QAAQ;IACvC,MAAM;IACN;IACA;IACA;IACA;IACA;GACF,CAAC;GACD,IAAI,SAAS,SAAS,OAAO;IAC3B,eAAe,UAAU,WAAW,KAAK;IACzC,OAAO;KAAE,MAAM;KAAa,QAAQ,CAAC;IAAE;GACzC;GAIA,IAAI,SAAS,SAAS,0BAA0B;IAC9C,MAAM,UAA+B,SAAS;IAC9C,IAAI,QAAQ,SAAS,UAInB,MAAM,IAAI,MACR,mEAAmE,WACrE;IAEF,OAAO;KAAE,MAAM;KAAY,aAAa,SAAS;KAAa,OAAO,QAAQ;IAAgB;GAC/F;GAEA,OAAO;IAAE,MAAM;IAAa,QADb,eAAe,UAAU,WAAW,oBACV,CAAC,CAAC;GAAO;EACpD;EACA,OACE,WACA,SAC0B;GAC1B,MAAM,UAAU,2BACd,QACA,OACA,WACA,SACA,aACA,SACF;GACA,MAAM,aAAa,UAAU,OAAO,QAAQ,SAAS,OAAO;GAC5D,OAAO,OAAO,OAAO,CAAC,GAAG,QAAQ,UAAU;EAC7C;EACA,MAAM,UAAyB;GAC7B,MAAM,YAAY,cAAc;GAMhC,MAAM,WAAW,MAAM,UAAU,QAC/B;IACE,MAAM;IACN;IACA;IACA;GACF,GACA,EAAE,YAAY,0BAA0B,CAC1C;GACA,eAAe,UAAU,WAAW,KAAK;EAC3C;CACF;CACA,IAAI,CAAC,sBAAsB,SAAS,GAClC,OAAO;CAET,OAAO,yBAAyB,QAAQ,WAAW,OAAO,aAAa,SAAS;AAClF;AAEA,MAAM,4BACJ,QACA,QACA,OACA,aACA,cACuB;CACvB,MAAM,UAAwC,OAAO,YACnD,OAAO,SAAS,UAAU;EACxB,IAAI,MAAM,SAAS,WAAW,MAAM,MAAM,SAAS,OACjD;EAEF,IAAI,CAAC,iBAAiB,MAAM,OAAO,OAAO,OAAO,MAAM,GACrD;EAEF,QAAQ,MAAM,KAAsC;CACtD,CAAC;CAKH,MAAM,mBAAmBC,yBAAuB,MAAM,KACjD,YAAoC,OAAO,iBAAiB,OAAO,IACpE,KAAA;CAKJ,MAAM,uBAAuB,6BAA6B,MAAM,IAC5D;EACE,yBAAyB,YACvB,OAAO,uBAAuB,OAAO;EACvC,2BAA2B,YACzB,OAAO,yBAAyB,OAAO;CAC3C,IACA,KAAA;CAEJ,MAAM,WAA+B;EACnC,GAAG;EACH,GAAI,qBAAqB,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB;EAC7D,GAAI,yBAAyB,KAAA,IAAY,CAAC,IAAI;EAC9C,gBACE,KACA,SACA;GACA,OAAO,OAAO,SAAS,UAAU;IAC/B,IAAI,MAAM,SAAS,eAAe,MAAM,QAAQ,KAC9C;IAEF,IAAI,MAAM,UAAU,SAAS,MAAM,WAAW,OAAO,QACnD;IAEF,QAAQ;KACN,OAAO;MAAE,OAAO,MAAM;MAAO,QAAQ,MAAM;MAAQ,KAAK,MAAM;KAAI;KAClE,MAAM,MAAM;IACd,CAAC;GACH,CAAC;EACH;EACA;EACA,YAAY,SAAS;GACnB,OAAO,OAAO,aAAa,OAAO;EACpC;EACA,YAAY,SAAS;GACnB,OAAO,OAAO,aAAa,OAAO;EACpC;EACA,kBAAkB,SAAS;GACzB,OAAO,OAAO,mBAAmB,OAAO;EAC1C;EACA,qBAAqB,SAAS;GAC5B,OAAO,OAAO,SAAS,UAAU;IAC/B,IACE,MAAM,SAAS,eACf,MAAM,MAAM,SAAS,qBACrB,MAAM,MAAM,UAAU,OAEtB,QAAQ,MAAM,KAAK;GAEvB,CAAC;EACH;EACA,OACE,WACA,SACkC;GAClC,MAAM,UAAU,2BACd,UACA,OACA,WACA,SACA,aACA,SACF;GACA,MAAM,aAAa,UAAU,OAAO,UAAU,SAAS,OAAO;GAC9D,OAAO,OAAO,OAAO,CAAC,GAAG,UAAU,UAAU;EAC/C;CACF;CACA,OAAO;AACT;AAEA,MAAM,oBACJ,OACA,OACA,WAEA,MAAM,SAAS,WAAW,MAAM,UAAU,SAAS,MAAM,WAAW;AAEtE,MAAM,yBACJ,cAEA,aAAa,aAAa,OAAO,UAAU,YAAY;AAOzD,MAAMA,4BACJ,cAEA,sBAAsB,aACtB,OAAO,UAAU,qBAAqB;AAUxC,MAAM,gCACJ,cAEA,4BAA4B,aAC5B,OAAO,UAAU,2BAA2B,cAC5C,8BAA8B,aAC9B,OAAO,UAAU,6BAA6B;AAEhD,MAAM,uBAAuB,OAC3B,WACA,kBAC+B;CAC/B,MAAM,YAAY,cAAc;CAChC,MAAM,WAAW,MAAM,UAAU,QAAQ;EACvC,MAAM;EACN;CACF,CAAC;CACD,OAAO,eAAe,UAAU,WAAW,aAAa,CAAC,CAAC;AAC5D;AAEA,MAAM,mBACJ,WACA,OACA,kBACc;CACd,MAAM,kBAAkB,YAAkC;EACxD,MAAM,YAAY,cAAc;EAChC,MAAM,WAAW,MAAM,UAAU,QAAQ;GACvC,MAAM;GACN;GACA;EACF,CAAC;EACD,OAAO,eAAe,UAAU,WAAW,cAAc,CAAC,CAAC;CAC7D;CACA,OAAO;EACL;EACA,MAAM,UAA2B;GAC/B,QAAQ,MAAM,gBAAgB,EAAA,CAAG;EACnC;EACA,MAAM,QAAQ,MAA+B;GAC3C,MAAM,YAAY,cAAc;GAChC,MAAM,WAAW,MAAM,UAAU,QAAQ;IACvC,MAAM;IACN;IACA;IACA;GACF,CAAC;GACD,eAAe,UAAU,WAAW,KAAK;GACzC,QAAQ,MAAM,gBAAgB,EAAA,CAAG;EACnC;EACA,MAAM,aAAsC;GAC1C,QAAQ,MAAM,gBAAgB,EAAA,CAAG,WAAW;EAC9C;EACA,MAAM,oBAA4C;GAChD,QAAQ,MAAM,gBAAgB,EAAA,CAAG,kBAAkB;EACrD;EACA,MAAM,WAAW,eAAuD;GACtE,IAAI,OAAO,kBAAkB,UAAU;IACrC,MAAM,WAAW,MAAM,gBAAgB;IACvC,IAAI,SAAS,YAAY,KAAA,GACvB,qBAAqB,CAAC,GAAG,aAAa;SAEtC,qBAAqB,SAAS,SAAS,aAAa;IAEtD,MAAM,YAAY,cAAc;IAChC,MAAM,WAAW,MAAM,UAAU,QAAQ;KACvC,MAAM;KACN;KACA;KACA,SAAS;IACX,CAAC;IACD,eAAe,UAAU,WAAW,KAAK;IACzC;GACF;GACA,IAAI,kBAAkB,MAAM,MAAM,gBAAgB,aAAa;GAC/D,MAAM,UACJ,kBAAkB,OAAO,OAAO,iBAAiB,aAAa;GAChE,MAAM,YAAY,cAAc;GAChC,MAAM,WAAW,MAAM,UAAU,QAAQ;IACvC,MAAM;IACN;IACA;IACA;GACF,CAAC;GACD,eAAe,UAAU,WAAW,KAAK;EAC3C;CACF;AACF;AAEA,MAAM,8BACJ,MACA,OACA,WACA,SACA,aACA,cACyB;CACzB,MAAM,QAAQ,UAAU,eAAe,OAAO,KAAK,CAAC;CACpD,MAAM,OAAO,MAAM,QAAQ,UAAU;CACrC,MAAM,WAAW,MAAM,YAAY,UAAU;CAC7C,MAAM,UAAU,MAAM,WAAW,YAAY,IAAI;CACjD,IAAI;CAEJ,MAAM,eAAe,YAA2B;EAC9C,IAAI,gBAAgB,KAAA,GAElB,cAAc,KACX,cAAc;GAAE;GAAM;GAAU;EAAQ,CAAC,CAAC,CAC1C,OAAO,UAAmB;GACzB,cAAc,KAAA;GACd,MAAM;EACR,CAAC;EAEL,MAAM;CACR;CAEA,OAAO;EACL;EACA,QAAQ,KAAK;EACb,GAAI,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU;EAC/C;EACA;EACA;EACA;EACA,MAAM,QAAQ,MAA8B;GAC1C,MAAM,aAAa;GACnB,MAAM,KAAK,iBAAiB,SAAS,IAAI;EAC3C;EACA,MAAM,QACJ,MACyC;GACzC,MAAM,aAAa;GACnB,OAAO,KAAK,iBAAyB,SAAS,IAAI;EACpD;CACF;AACF;AAOA,MAAM,0BACJ,cACuB;CACvB,MAAM,EAAE,cAAc;CACtB,OAAO,OAAO,cAAc,YAAY,UAAU,SAAS,IAAI,YAAY,KAAA;AAC7E;AAEA,MAAM,0BAA0B,UAA0B;CACxD,MAAM,YAAY,MAAM,WAAW,qBAAqB,GAAG;CAC3D,OAAO,UAAU,SAAS,IAAI,YAAY;AAC5C;AAEA,MAAM,0BAA0B,WAAsC;CACpE,IAAI,OAAO;CACX,aAAa;EACX,MAAM,YAAY,GAAG,OAAO,GAAG;EAC/B,QAAQ;EACR,OAAO;CACT;AACF;AAEA,MAAM,kBACJ,OACA,WACA,SAC0C;CAC1C,IAAI,MAAM,SAAS,SAGjB,MAAM,IAAI,kBAAkB,MAAM,MAAM,MAAM,SAAS,EACrD,SAAS,MAAM,QACjB,CAAC;CAEH,IAAI,MAAM,SAAS,MACjB,MAAM,IAAI,MACR,YAAY,KAAK,OAAO,UAAU,aAAa,MAAM,MACvD;CAEF,IAAI,YAAY,KAAK,MAAM,WACzB,MAAM,IAAI,MACR,yBAAyB,UAAU,aACjC,YAAY,KAAK,KAAK,QAE1B;CAEF,OAAO;AACT;AAEA,MAAM,eAAe,UAA8C;CACjE,QAAQ,MAAM,MAAd;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,uBACH,OAAO,MAAM;EACf,KAAK,SACH,OAAO,MAAM;EAIf,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,aACH;CACJ;AACF;;;;;;;;;AC70BA,MAAa,sBAAsB,UAAqC,CAAC,MAAc;CACrF,MAAM,MAAM,QAAQ,OAAO,QAAQ;CACnC,MAAM,OAAO,QAAQ,QAAQ,QAAQ;CAErC,MAAM,aAAuB,CAAC;CAC9B,IAAI,QAAQ,aAAa,KAAA,KAAa,QAAQ,SAAS,SAAS,GAC9D,WAAW,KAAK,QAAQ,QAAQ;CAElC,IAAI,QAAQ,UAAU,KAAA,KAAa,QAAQ,MAAM,SAAS,GACxD,WAAW,KAAK,QAAQ,KAAK;CAE/B,MAAM,UAAU,QAAQ,kBAAkB,IAAI;CAC9C,IAAI,OAAO,YAAY,YAAY,QAAQ,SAAS,GAClD,WAAW,KAAK,OAAO;CAEzB,MAAM,aAAa,QAAQ,cAAc,KAAK;CAC9C,IAAI,OAAO,eAAe,YAAY,WAAW,SAAS,GACxD,WAAW,KAAK,SAAS,UAAU,CAAC;CAGtC,KAAK,MAAM,aAAa,YAAY;EAClC,MAAM,YAAY,oBAAoB,SAAS;EAC/C,IAAI,UAAU,SAAS,GACrB,OAAO;CAEX;CAEA,OAAO,oBAAoB,KAAA,CAAS;AACtC;;;ACjDA,MAAa,6BACX,WAAmB,QAAQ,UAC3B,OAAe,QAAQ,SACA;CACvB,MAAM,YAAY,oBAAoB,QAAQ;CAE9C,OAAO;EACL,aAAa,aAAa,UAAU,GAFnB,cAAc,IAEiB;EAChD,oBAAoB,OAAO,cAAc,YAAY,iBAAiB;EACtE,GAAI,cAAc,WACd,EAAE,6BAA6B,iBAAiB,IAChD,CAAC;CACP;AACF;AAEA,MAAa,+BACX,WAAmB,QAAQ,UAC3B,OAAe,QAAQ,SACE;CACzB,MAAM,YAAY,oBAAoB,QAAQ;CAC9C,OAAO;EACL,IAAI,cAAc,YAAY,UAAU;EACxC,MAAM,cAAc,IAAI;CAC1B;AACF;AAEA,MAAM,uBAAuB,aAAsC;CACjE,QAAQ,UAAR;EACE,KAAK;EACL,KAAK,SACH,OAAO;EACT,KAAK,SACH,OAAO;EACT,SACE,MAAM,IAAI,iCACR,yCAAyC,YACzC,UACA,QAAQ,IACV;CACJ;AACF;AAEA,MAAM,iBAAiB,SAA6B;CAClD,QAAQ,MAAR;EACE,KAAK;EACL,KAAK,OACH,OAAO;EACT,SACE,MAAM,IAAI,iCACR,6CAA6C,QAC7C,QAAQ,UACR,IACF;CACJ;AACF;AAEA,IAAa,mCAAb,cAAsD,MAAM;CAC1D,OAAgB;CAChB;CACA;CACA;CACA;CAEA,YACE,SACA,UACA,MACA,UAII,CAAC,GACL;EACA,MAAM,SAAS,QAAQ,UAAU,KAAA,IAAY,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,CAAC;EACjF,KAAK,OAAO;EACZ,KAAK,WAAW;EAChB,KAAK,OAAO;EACZ,KAAK,cAAc,QAAQ;EAC3B,KAAK,aAAa,QAAQ;CAC5B;AACF;;;ACvDA,MAAM,YAAY,OAAO,KAAK;AAC9B,MAAM,oBAAoB,cAAc,SAAS;AA6CjD,MAAa,wBAAwB,OACnC,OACA,UAAwC,CAAC,MACL;CACpC,MAAM,UAAU,MAAM,qBAAqB,OAAO,OAAO;CACzD,MAAM,iBAAiB,OAAO,QAAQ,yBAAyB,SAAA,CAAU,QAAQ,OAAO;CACxF,MAAM,QAAQ,OAAO,QAAQ,kBAAkB,SAAA,CAAU,cAAc;CACvE,MAAM,iBAAiB,WAAW,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,KAAK;CACtE,MAAM,mBAA2C;EAC/C,gBAAgB,MAAM;EACtB,QAAQ,4BACN,QAAQ,YAAY,QAAQ,UAC5B,QAAQ,QAAQ,QAAQ,IAC1B;EACA;EACA,eAAe,UAAU,eAAe,MAAM,GAAG,EAAE;CACrD;CACA,OAAO;EACL,GAAG;EACH,SAAS;EACT,MAAM;GACJ,GAAG,QAAQ;GACX;GACA;GACA;GACA,KAAK,UAAU,gBAAgB;EACjC;EACA;EACA;CACF;AACF;AAEA,MAAa,uBAAuB,OAClC,OACA,UAAuC,CAAC,MACb;CAC3B,MAAM,MAAM,QAAQ,OAAO,QAAQ;CACnC,MAAM,WAAW,QAAQ,YAAY,QAAQ;CAC7C,MAAM,OAAO,QAAQ,QAAQ,QAAQ;CACrC,MAAM,WAAW,IAAI;CACrB,IAAI,aAAa,KAAA,KAAa,SAAS,SAAS,GAAG;EACjD,IAAI,aAAa,YAAY,QAAQ,cAAc,KAAA,GACjD,OAAO,iBAAiB,UAAU,KAAK;EAEzC,MAAM,eAAe,MAAM,qCAAqC,OAAO,SAAS,UAAU,IAAI;EAC9F,MAAM,SAAS,MAAM,mBAAmB,SAAS,OAAO,UAAU,YAAY;EAC9E,OAAO,iBAAiB,QAAQ,KAAK;CACvC;CAEA,MAAM,SAAS,0BAA0B,UAAU,IAAI;CACvD,MAAM,YAAY,OAAO,QAAQ,gCAAgC,6BAAA,CAC/D,QACA,EAAE,SAAS,CACb;CACA,IAAI,UAAU,WAAW,KAAA,GAAW;EAClC,IAAI,aAAa,UAAU,OAAO,iBAAiB,UAAU,QAAQ,KAAK;EAC1E,IAAI,QAAQ,cAAc,KAAA,GAAW,OAAO,iBAAiB,UAAU,QAAQ,KAAK;EACpF,IAAI,UAAU,oBAAoB,KAAA,GAChC,MAAM,0BAA0B,QAAQ,WAAW,IAAI;EAEzD,MAAM,SAAS,MAAM,mBAAmB,SAAS,OAAO,UAAU,QAAQ,UAAU,eAAe;EACnG,OAAO,iBAAiB,QAAQ,KAAK;CACvC;CAEA,MAAM,YAAY,QAAQ,aAAa,QAAQ,cAAc,SAAS,CAAC;CACvE,MAAM,gBAAgB,OAAO,QAAQ,qBAAqB,kBAAA,CAAmB,SAAS;CACtF,IAAI,kBAAkB,KAAA,GAAW;EAC/B,MAAM,SAAS,OAAO,QAAQ,yBAAyB,sBAAA,CACrD,eACA,OACA,QACF;EACA,IAAI,aAAa,UAAU,OAAO,iBAAiB,QAAQ,KAAK;EAChE,MAAM,gBACJ,QAAQ,cAAc,KAAA,IAClB,SACA,MAAM,mBACJ,SACA,OACA,QACA,OACE,QAAQ,kCAAkC,+BAAA,CAC1C,eAAe,KAAK,CACxB;EACN,OAAO,iBAAiB,eAAe,KAAK;CAC9C;CAEA,MAAM,IAAI,iCACR,UAAU,eAAe,KAAA,IACrB,gDAAgD,SAAS,GAAG,KAAK,aAAa,OAAO,YAAY,kDACjG,gDAAgD,SAAS,GAAG,KAAK,aAAa,OAAO,YAAY,0BAA0B,UAAU,WAAW,8EACpJ,UACA,MACA;EACE,aAAa,OAAO;EACpB,GAAI,UAAU,eAAe,KAAA,IAAY,CAAC,IAAI,EAAE,YAAY,UAAU,WAAW;CACnF,CACF;AACF;AAEA,MAAM,uCAAuC,OAC3C,OACA,SACA,UACA,SACoB;CACpB,MAAM,YAAY,QAAQ,aAAa,QAAQ,cAAc,SAAS,CAAC;CACvE,MAAM,gBAAgB,OAAO,QAAQ,qBAAqB,kBAAA,CAAmB,SAAS;CACtF,IAAI,kBAAkB,KAAA,GACpB,QACE,QAAQ,kCAAkC,+BAAA,CAC1C,eAAe,KAAK;CAGxB,MAAM,SAAS,0BAA0B,UAAU,IAAI;CACvD,MAAM,YAAY,OAAO,QAAQ,gCAAgC,6BAAA,CAC/D,QACA,EAAE,SAAS,CACb;CACA,IAAI,UAAU,oBAAoB,KAAA,GAChC,OAAO,UAAU;CAEnB,MAAM,0BAA0B,QAAQ,WAAW,IAAI;AACzD;AAEA,MAAa,+BAA+B,OAC1C,QACA,UAA+C,CAAC,MACH;CAC7C,MAAM,WAAW,QAAQ,YAAY,QAAQ;CAC7C,IAAI;CACJ,IAAI;EACF,mBACE,QAAQ,sBAAsB,kBAAkB,QAAQ,KAAK,iBAAiB,EAAA,CAC9E,GAAG,OAAO,YAAY,cAAc;CACxC,SAAS,OAAO;EACd,IAAIC,cAAY,KAAK,KAAK,MAAM,SAAS,oBACvC,OAAO,CAAC;EAEV,MAAM;CACR;CAEA,MAAM,aAAa,KAAK,QAAQ,eAAe,GAAG,OAAO,kBAAkB;CAC3E,MAAM,sBACJ,OAAO,gCAAgC,KAAA,IACnC,KAAA,IACA,KAAK,QAAQ,eAAe,GAAG,OAAO,2BAA2B;CACvE,IAAI;CACJ,IAAI,wBAAwB,KAAA,GAC1B,IAAI;EACF,OAAO,QAAQ,2BAA2B,iCAAA,CACxC,mBACF;EACA,kBAAkB;CACpB,SAAS,OAAO;EACd,IACE,CAACA,cAAY,KAAK,KACjB,MAAM,SAAS,YAAY,MAAM,SAAS,YAAY,MAAM,SAAS,SAEtE,MAAM;CAEV;CAEF,IAAI;EACF,OAAO,QAAQ,0BAA0B,sCAAA,CACvC,YACA,QACF;EACA,OAAO;GACL,QAAQ;GACR;GACA,GAAI,wBAAwB,KAAA,IAAY,CAAC,IAAI,EAAE,oBAAoB;GACnE,GAAI,oBAAoB,KAAA,IAAY,CAAC,IAAI,EAAE,gBAAgB;EAC7D;CACF,SAAS,OAAO;EACd,IACEA,cAAY,KAAK,MAChB,MAAM,SAAS,YAAY,MAAM,SAAS,YAAY,MAAM,SAAS,UAEtE,OAAO;GACL;GACA,GAAI,wBAAwB,KAAA,IAAY,CAAC,IAAI,EAAE,oBAAoB;GACnE,GAAI,oBAAoB,KAAA,IAAY,CAAC,IAAI,EAAE,gBAAgB;EAC7D;EAEF,MAAM;CACR;AACF;AAEA,MAAM,oBAAoB,QAAgB,OAAoB,QAAgC;CAC5F,MAAM,UAAyB;EAC7B,SAAS;EACT,MAAM;GACJ;GACA;GACA,MAAM;GACN;GACA,MAAM;GACN;GACA,MAAM;GACN;GACA,GAAG,MAAM;GACT;GACA,MAAM;GACN;GACA,MAAM;GACN;GACA,MAAM;EACR;CACF;CACA,IAAI,QAAQ,KAAA,GACV,QAAQ,MAAM;CAEhB,OAAO;AACT;AAEA,MAAM,oBAAoB,OAAO,UAA+C;CAC9E,IAAI,UAAU;CACd,OAAO,MAAM;EACX,IAAI,MAAM,OAAO,KAAK,SAAS,YAAY,CAAC;OACtC,MAAM,OAAO,KAAK,SAAS,UAAU,gBAAgB,YAAY,CAAC,GACpE,OAAO;EAAA;EAIX,MAAM,SAAS,QAAQ,OAAO;EAC9B,IAAI,WAAW,SACb;EAEF,UAAU;CACZ;AACF;AAEA,MAAa,8BACX,eACA,WAA4B,QAAQ,UACpC,cAAc,eAEd,KACE,0BAA0B,eAAe,UAAU,WAAW,GAC9D,SACA,aAAa,UAAU,iBAAiB,UAC1C;AAEF,MAAM,6BACJ,eACA,UACA,gBAEA,aAAa,UACT,KAAK,eAAe,UAAU,mBAAmB,WAAW,IAC5D,KAAK,eAAe,QAAQ;AAElC,MAAM,wBAAwB,OAC5B,eACA,OACA,aACoB;CACpB,MAAM,YAAY,0BAA0B,eAAe,UAAU,MAAM,WAAW;CACtF,MAAM,SAAS,2BAA2B,eAAe,UAAU,MAAM,WAAW;CACpF,MAAM,cAAc,eAAe,aAAa,UAAU,YAAY,KAAA,CAAS;CAC/E,OAAO;AACT;AAEA,MAAM,iCAAiC,OACrC,eACA,WACoB;CACpB,OAAO,KAAK,eAAe,wCAAwC;AACrE;AAEA,MAAM,qBAAqB,OACzB,SACA,OACA,YACA,iBACoB;CACpB,MAAM,YAAY,QAAQ;CAC1B,IAAI,cAAc,KAAA,GAAW,OAAO;CACpC,MAAM,OAAO,QAAQ,QAAQ,QAAQ;CACrC,IAAI,SAAS,WAAW,SAAS,OAC/B,MAAM,IAAI,MAAM,+CAA+C,MAAM;CAEvE,MAAM,iBAAiB,MAAM,yBAAyB,SAAS,WAAW,KAAK;CAC/E,OAAO,sBAAsB;EAC3B,YAAY,UAAU;EACtB,aAAa,QAAQ,iBAAiB,QAAQ,MAAM;EACpD,OAAO,MAAM;EACb,SAAS,MAAM;EACf,QAAQ;GAAE,IAAI;GAAU;EAAK;EAC7B;EACA;EACA,GAAI,mBAAmB,KAAA,KAAa,QAAQ,YAAY,KAAA,IACpD,CAAC,IACD,EAAE,SAAU,QAAQ,WAAW,eAAiB;EACpD,GAAI,UAAU,iBAAiB,KAAA,IAAY,CAAC,IAAI,EAAE,cAAc,UAAU,aAAa;CACzF,CAAC;AACH;;;;;;;;;AAUA,MAAM,2BAA2B,OAC/B,SACA,WACA,UACiC;CACjC,IAAI,QAAQ,YAAY,KAAA,GAAW,OAAO,KAAA;CAC1C,IAAI,UAAU,mBAAmB,OAAO,OAAO,KAAA;CAC/C,IAAI,UAAU,iBAAiB,OAAO,OAAO,KAAA;CAC7C,IAAI;EACF,MAAM,YAAY,MAAM,uBAAuB;GAC7C,SAAS,MAAM;GACf,WAAW,KAAK,MAAM,YAAY,UAAU;EAC9C,CAAC;EACD,IAAI,UAAU,UAGZ,MAAM,WACJ,MAAM,WACN,sHAAsH,KAAK,UAAU,MAAM,OAAO,EAAE,GACtJ,CAAC,CAAC,YAAY,CAAC,CAAC;EAElB,OAAO,UAAU;CACnB,SAAS,OAAO;EACd,IAAI;GAGF,MAAM,MAAM,QAAQ,MAAM,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;GACzD,MAAM,WACJ,MAAM,WACN,qFAAqF,OAAO,KAAK,EAAE,GACrG;EACF,QAAQ,CAER;EACA;CACF;AACF;AAEA,MAAM,iBAAiB,eAAuB,cAC5C,WACE,SACA;CACE;CACA;CACA;CACA,GAAI,cAAc,KAAA,IAAY,CAAC,IAAI,CAAC,gBAAgB,SAAS;AAC/D,GACA,eACA,QAAQ,IAAI,+BAA+B,MAAM,YAAY,QAC/D;AAEF,MAAM,cACJ,SACA,MACA,KACA,QAA8B,aAE9B,IAAI,SAAS,SAAS,WAAW;CAC/B,MAAM,QAAQ,MAAM,SAAS,CAAC,GAAG,IAAI,GAAG;EAAE;EAAK;CAAM,CAAC;CACtD,MAAM,KAAK,SAAS,MAAM;CAC1B,MAAM,KAAK,SAAS,SAAS;EAC3B,IAAI,SAAS,GAAG;GACd,QAAQ;GACR;EACF;EACA,uBAAO,IAAI,MAAM,GAAG,QAAQ,GAAG,KAAK,KAAK,GAAG,EAAE,oBAAoB,QAAQ,WAAW,CAAC;CACxF,CAAC;AACH,CAAC;AAEH,MAAM,SAAS,OAAO,SAAmC;CACvD,IAAI;EACF,MAAM,OAAO,MAAM,UAAU,IAAI;EACjC,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;AAEA,MAAM,oBAAoB,aACxB,aAAa,UAAU,UAAU,OAAO,UAAU;AAEpD,MAAM,wCAAwC,OAC5C,YACA,aACkB;CAClB,MAAM,OAAO,YAAY,iBAAiB,QAAQ,CAAC;AACrD;AAEA,MAAM,mCAAmC,OAAO,gBAAuC;CACrF,MAAM,OAAO,aAAa,UAAU,IAAI;AAC1C;AAEA,MAAM,6BACJ,QACA,YACA,SAEA,IAAI,iCACF,6DAA6D,OAAO,YAAY,aAAa,WAAW,uBAAuB,OAAO,+BAA+B,oBACrK,UACA,MACA;CACE,aAAa,OAAO;CACpB,GAAI,WAAW,wBAAwB,KAAA,IACnC,CAAC,IACD,EAAE,YAAY,WAAW,oBAAoB;AACnD,CACF;AAEF,SAASA,cAAY,OAAgD;CACnE,OAAO,iBAAiB,SAAS,UAAU;AAC7C;;;AC/cA,MAAM,mBAAmB;AACzB,MAAM,0BAA0B;AAChC,MAAM,kCAAkC;AACxC,MAAM,iCAAiC;AACvC,MAAM,6BAA6B;AAuDnC,MAAa,0BACX,eACA,UAAmC,CAAC,OAClB;CAClB,MAAM,cAAc,OAAO;EACzB,OAAO,sBAAsB,OAAO;GAClC,GAAI,QAAQ,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,QAAQ,UAAU;GAC1E,GAAI,QAAQ,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,QAAQ,QAAQ;GACpE,GAAI,QAAQ,oBAAoB,KAAA,IAC5B,CAAC,IACD,EAAE,iBAAiB,QAAQ,gBAAgB;EACjD,CAAC;CACH;CACA,MAAM,QAAQ,KAAK;EACjB,OAAO,eAAe,GAAG;CAC3B;CACA,MAAM,YAAY,OAAO,QAAQ;EAI/B,MAAM,MAAM,QAAQ,OAAO,QAAQ;EACnC,MAAM,QAAQ,mBAAmB,IAAI,iBAAiB;EACtD,IAAI,UAAU,OAAO,MAAM,MAAM,MAAM,YAAY,EAAE,WAAW,KAAK,CAAC;EACtE,MAAM,YAAY,UAAU,QAAQ,MAAM,KAAK,MAAM,WAAW,GAAG,IAAI,KAAA;EACvE,IAAI,cAAc,KAAA,GAChB,MAAM,UAAU,WACd,GAAG,KAAK,UAAU;GAChB,4BAAW,IAAI,KAAK,EAAA,CAAE,YAAY;GAClC,OAAO;GACP,SAAS,OAAO;GAChB,KAAK,OAAO,OAAO,QAAQ,IAAI;GAC/B,OAAO,MAAM;GACb,SAAS,MAAM;EACjB,CAAC,EAAE,KACH,MACF;EAEF,IAAI,WAAW,OAAO,OAAO,GAC3B,IAAI;GACF,MAAM,OACJ,OAAO,SACP,QAAQ,aAAa,UAAU,UAAU,OAAO,UAAU,IAC5D;EACF,SAAS,OAAO;GACd,IAAI,UAAU,OACZ,MAAM,WACJ,MAAM,WACN,GAAG,KAAK,UAAU;IAChB,4BAAW,IAAI,KAAK,EAAA,CAAE,YAAY;IAClC,OAAO;IACP,SAAS,OAAO;IAChB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAC9D,CAAC,EAAE,KACH,MACF,CAAC,CAAC,YAAY,KAAA,CAAS;GAEzB,MAAM,WAAW,MAAM;GACvB,OAAO;EACT;EAEF,IAAI;EACJ,IAAI;GACF,QAAQ,MAAM,OAAO,SAAS,OAAO,MAAM;IACzC,KAAK,OAAO;IACZ,UAAU;IACV,KAAK;KACH,GAAG;KACH,sBAAsB,MAAM;KAC5B,iCAAiC,MAAM;KACvC,gCAAgC;KAChC,wBAAwB,MAAM;KAC9B,0BAA0B,MAAM;KAChC,8BAA8B,MAAM;IACtC;IACA,OACE,cAAc,KAAA,IACV,UAAU,QACR,WACA,QACF;KAAC;KAAU,UAAU;KAAI,UAAU;IAAE;GAC7C,CAAC;EACH,UAAU;GACR,MAAM,WAAW,MAAM;EACzB;EAEA,MAAM,GAAG,UAAU,UAAU;GAC3B,IAAI,UAAU,OAAO;GACrB,WACE,MAAM,WACN,GAAG,KAAK,UAAU;IAChB,4BAAW,IAAI,KAAK,EAAA,CAAE,YAAY;IAClC,OAAO;IACP,SAAS,OAAO;IAChB,OAAO,MAAM;GACf,CAAC,EAAE,KACH,MACF,CAAC,CAAC,YAAY,KAAA,CAAS;EACzB,CAAC;EACD,MAAM,KAAK,SAAS,MAAM,WAAW;GACnC,IAAI,UAAU,OAAO;GACrB,WACE,MAAM,WACN,GAAG,KAAK,UAAU;IAChB,4BAAW,IAAI,KAAK,EAAA,CAAE,YAAY;IAClC,OAAO;IACP,SAAS,OAAO;IAChB;IACA;GACF,CAAC,EAAE,KACH,MACF,CAAC,CAAC,YAAY,KAAA,CAAS;EACzB,CAAC;EAED,MAAM,MAAM;EACZ,MAAM,MAAM,MAAM,OAAO;EACzB,IAAI,QAAQ,aAAa,YAAY,QAAQ,cAAc,KAAA,KAAa,MAAM,GAC5E,MAAM,0BACJ,QAAQ,UAAU,MAClB,KACA,OAAO,iBAAiB,cAC1B;EAEF,OAAO;CACT;CACA,MAAM,KAAK,KAAK;EACd,QAAQ,KAAK,KAAK,SAAS;EAC3B,IAAI,QAAQ,aAAa,YAAY,QAAQ,cAAc,KAAA,GACzD,MAAM,0BAA0B,QAAQ,UAAU,MAAM,GAAG;CAE/D;AACF;AAEA,MAAa,sBAAsB,UAA4D;CAC7F,IAAI,UAAU,WAAW,OAAO;CAChC,IAAI,UAAU,UAAU,OAAO;CAC/B,OAAO;AACT;AAEA,MAAa,cAAc,OAAO,EAChC,OACA,QACA,gBAAgB,gCAChB,qBAAqB,sCAC+B;CACpD,MAAM,MAAM,MAAM,YAAY,EAAE,WAAW,KAAK,CAAC;CAEjD,MAAM,OAAO,MAAM,kBAAkB,MAAM,UAAU,aAAa;CAClE,IAAI;EACF,MAAM,cAAc,MAAM,QAAQ,MAAM,OAAO;EAC/C,IAAI,gBAAgB,gBAAgB,KAAA,KAAc,MAAM,OAAO,QAAQ,WAAW;EAClF,IAAI;EACJ,IAAI;GAGF,SAAS,MAAM,OAAO,cAAc,KAAK;EAC3C,SAAS,OAAO;GACd,IAAI,iBAAiB,mBAAmB,KAAK,KAAK,gBAAgB,KAAA,GAAW;IAC3E,MAAM,OAAO,KAAK,WAAW;IAC7B,IAAI,CAAE,MAAM,iBAAiB,QAAQ,WAAW,GAC9C,MAAM,IAAI,MACR,mFAAmF,aACrF;IAEF,gBAAgB;IAChB,SAAS,MAAM,OAAO,cAAc,KAAK;GAC3C,OACE,MAAM;EAEV;EACA,IAAI,gBAAgB,KAAA,KAAa,eAAe;GAC9C,MAAM,QAAQ,MAAM,kBAAkB,MAAM,SAAS;GAErD,IAAI,mBAAmB,OAAO,OAAO,aAAa,MAAM,GACtD,OAAO;IACL,QAAQ;IACR,KAAK;IACL;IACA;GACF;GAEF,MAAM,OAAO,KAAK,WAAW;GAC7B,IAAI,CAAE,MAAM,iBAAiB,QAAQ,WAAW,GAC9C,MAAM,IAAI,MACR,mFAAmF,aACrF;EAEJ;EAEA,MAAM,oBAAoB,KAAK;EAC/B,MAAM,MAAM,MAAM,OAAO,YAAY,OAAO,MAAM;EAClD,IAAI,CAAC,OAAO,UAAU,GAAG,KAAK,OAAO,GACnC,MAAM,IAAI,MAAM,kDAAkD;EAEpE,MAAM,UAAU,MAAM,SAAS,GAAG,IAAI,KAAK,MAAM;EACjD,IAAI;GACF,MAAM,iBAAiB,OAAO,QAAQ,KAAK,QAAQ,kBAAkB;EACvE,SAAS,OAAO;GACd,IAAI,MAAM,OAAO,QAAQ,GAAG,GAAG;IAC7B,MAAM,OAAO,KAAK,GAAG;IACrB,MAAM,iBAAiB,QAAQ,GAAG;GACpC;GACA,MAAM,oBAAoB,KAAK;GAC/B,MAAM;EACR;EACA,OAAO;GAAE,QAAQ;GAAW;GAAK;GAAO;EAAO;CACjD,UAAU;EACR,MAAM,KAAK,QAAQ;CACrB;AACF;AAwCA,MAAM,UAAU,OAAO,YAAiD;CACtE,IAAI;EACF,MAAM,UAAU,MAAM,SAAS,SAAS,MAAM;EAC9C,MAAM,MAAM,OAAO,SAAS,QAAQ,KAAK,GAAG,EAAE;EAC9C,OAAO,OAAO,UAAU,GAAG,KAAK,MAAM,IAAI,MAAM,KAAA;CAClD,SAAS,OAAO;EACd,IAAI,YAAY,KAAK,KAAK,MAAM,SAAS,UACvC;EAEF,MAAM;CACR;AACF;AAEA,MAAM,sBAAsB,OAAO,UAAsC;CACvE,MAAM,GAAG,MAAM,WAAW,EAAE,OAAO,KAAK,CAAC;CACzC,MAAM,GAAG,MAAM,SAAS,EAAE,OAAO,KAAK,CAAC;CACvC,IAAI,QAAQ,aAAa,SACvB,MAAM,GAAG,MAAM,UAAU,EAAE,OAAO,KAAK,CAAC;AAE5C;AAEA,MAAM,mBAAmB,OAAO,QAAsB,QAAkC;CACtF,KAAK,IAAI,UAAU,GAAG,UAAU,IAAI,WAAW,GAAG;EAChD,IAAI,CAAE,MAAM,OAAO,QAAQ,GAAG,GAC5B,OAAO;EAET,MAAM,MAAM,uBAAuB;CACrC;CACA,OAAO;AACT;AAEA,MAAM,mBAAmB,OACvB,OACA,QACA,KACA,QACA,cACkB;CAClB,MAAM,WAAW,KAAK,IAAI,IAAI;CAC9B,OAAO,MAAM;EACX,MAAM,QAAQ,MAAM,kBAAkB,MAAM,SAAS;EACrD,IAAI,mBAAmB,OAAO,OAAO,KAAK,MAAM,GAC9C;EAEF,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MACR,yDAAyD,KAAK,UAAU,OAAO,gBAAgB,EAAE,UAAU,KAAK,UAAU,MAAM,sBAAsB,GACxJ;EAEF,IAAI,CAAE,MAAM,OAAO,QAAQ,GAAG,GAC5B,MAAM,IAAI,MACR,8CAA8C,IAAI,cAAc,MAAM,UAAU,cAAc,MAAM,UAAU,QAAQ,iBAAiB,iCACzI;EAEF,MAAM,cAAc,WAAW,KAAK,IAAI;EACxC,IAAI,eAAe,GAAG;EACtB,MAAM,MAAM,KAAK,IAAI,yBAAyB,WAAW,CAAC;CAC5D;CAEA,MAAM,IAAI,MACR,gDAAgD,UAAU,UAAU,IAAI,cAAc,MAAM,UAAU,cAAc,MAAM,UAAU,QAAQ,iBAAiB,iCAC/J;AACF;AAEA,MAAM,oBAAoB,OAAO,cAAgE;CAC/F,IAAI;CACJ,IAAI;EACF,QAAQ,KAAK,MAAM,MAAM,SAAS,WAAW,MAAM,CAAC;CACtD,SAAS,OAAO;EACd,IAAI,YAAY,KAAK,KAAK,MAAM,SAAS,UACvC;EAEF,IAAI,iBAAiB,aACnB;EAEF,MAAM;CACR;CACA,IACE,CAAC,SAAS,KAAK,KACf,CAAC,OAAO,UAAU,MAAM,GAAG,KAC3B,OAAO,MAAM,QAAQ,YACrB,OAAO,MAAM,aAAa,YAC1B,OAAO,MAAM,mBAAmB,YAChC,OAAO,MAAM,oBAAoB,YACjC,OAAO,MAAM,UAAU,YACvB,OAAO,MAAM,YAAY,YACzB,OAAO,MAAM,gBAAgB,YAC7B,OAAO,MAAM,mBAAmB,YAChC,CAAC,yBAAyB,MAAM,sBAAsB,GAEtD;CAEF,OAAO;EACL,KAAK,MAAM;EACX,UAAU,MAAM;EAChB,gBAAgB,MAAM;EACtB,iBAAiB,MAAM;EACvB,OAAO,MAAM;EACb,SAAS,MAAM;EACf,aAAa,MAAM;EACnB,gBAAgB,MAAM;EACtB,wBAAwB,MAAM;CAChC;AACF;AAEA,MAAM,sBACJ,OACA,OACA,KACA,WAEA,UAAU,KAAA,KACV,MAAM,QAAQ,OACd,MAAM,aAAa,MAAM,YACzB,MAAM,mBAAmB,MAAM,kBAC/B,MAAM,oBAAoB,MAAM,mBAChC,MAAM,UAAU,MAAM,SACtB,MAAM,YAAY,MAAM,WACxB,MAAM,gBAAgB,MAAM,eAC5B,qBAAqB,MAAM,gBAAgB,OAAO,cAAc,KAChE,6BAA6B,MAAM,wBAAwB,OAAO,gBAAgB;AAEpF,MAAM,sBAAsB,UAC1B,iBAAiB,SAAS,UAAU,SAAS,MAAM,SAAS;AAE9D,MAAa,wBACX,MACA,OACA,WAA4B,QAAQ,aACxB;CACZ,IAAI,aAAa,SACf,OAAO,SAAS;CAGlB,MAAM,aAAa,UACjB,MACG,WAAW,MAAM,GAAG,CAAC,CACrB,QAAQ,eAAe,EAAE,CAAC,CAC1B,YAAY;CACjB,OAAO,UAAU,IAAI,MAAM,UAAU,KAAK;AAC5C;AAEA,MAAa,oBAAoB,OAC/B,UACA,cAGI;CACJ,MAAM,WAAW,KAAK,IAAI,IAAI;CAC9B,MAAM,QAAQ,GAAG,KAAK,UAAU;EAAE,KAAK,QAAQ;EAAK,OAAO,WAAW;CAAE,CAAC,EAAE;CAC3E,OAAO,KAAK,IAAI,KAAK,UACnB,IAAI;EACF,MAAM,SAAS,MAAM,KACnB,UACA,UAAU,UAAU,UAAU,SAAS,UAAU,QACnD;EACA,MAAM,OAAO,UAAU,OAAO,MAAM;EACpC,OAAO,EACL,MAAM,UAAU;GACd,MAAM,OAAO,MAAM;GACnB,IAAK,MAAM,eAAe,QAAQ,MAAO,OAAO;GAChD,MAAM,OAAO,QAAQ,CAAC,CAAC,OAAO,UAAmB;IAC/C,IAAI,CAAC,YAAY,KAAK,KAAK,MAAM,SAAS,UACxC,MAAM;GAEV,CAAC;EACH,EACF;CACF,SAAS,OAAO;EACd,IAAI,YAAY,KAAK,KAAK,MAAM,SAAS,UAAU;GACjD,IAAI,MAAM,qBAAqB,QAAQ,GAAG;GAC1C,MAAM,MAAM,EAAE;GACd;EACF;EACA,MAAM;CACR;CAGF,MAAM,IAAI,MAAM,oCAAoC,UAAU;AAChE;AAEA,MAAM,uBAAuB,OAAO,aAAuC;CACzE,MAAM,WAAW,MAAM,eAAe,QAAQ;CAC9C,IAAI,aAAa,KAAA,GAAW,OAAO;CACnC,MAAM,QAAQ,eAAe,QAAQ;CACrC,IAAI,UAAU,KAAA,KAAa,eAAe,MAAM,GAAG,GAAG,OAAO;CAE7D,MAAM,YAAY,GAAG,SAAS,WAAW,WAAW,QAAQ,CAAC,CAAC,OAAO,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE;CACxG,IAAI;EACF,MAAM,KAAK,UAAU,SAAS;CAChC,SAAS,OAAO;EACd,IAAI,YAAY,KAAK,KAAK,MAAM,SAAS,UAAU,OAAO;EAC1D,IAAI,YAAY,KAAK,KAAK,MAAM,SAAS,UAAU;GACjD,MAAM,2BAA2B,SAAS;GAC1C,OAAO;EACT;EACA,MAAM;CACR;CAEA,IAAI;EAEF,IAAK,MAAM,eAAe,QAAQ,MAAO,YAAY,eAAe,MAAM,GAAG,GAAG,OAAO;EACvF,IAAI;GACF,MAAM,OAAO,QAAQ;GACrB,OAAO;EACT,SAAS,OAAO;GACd,IAAI,YAAY,KAAK,KAAK,MAAM,SAAS,UAAU,OAAO;GAC1D,MAAM;EACR;CACF,UAAU;EACR,MAAM,OAAO,SAAS,CAAC,CAAC,OAAO,UAAmB;GAChD,IAAI,CAAC,YAAY,KAAK,KAAK,MAAM,SAAS,UAAU,MAAM;EAC5D,CAAC;CACH;AACF;AAEA,MAAM,6BAA6B,OAAO,cAAqC;CAC7E,IAAI;EACF,MAAM,QAAQ,MAAM,KAAK,SAAS;EAClC,IAAI,KAAK,IAAI,IAAI,MAAM,UAAU,4BAA4B;EAC7D,MAAM,OAAO,SAAS;CACxB,SAAS,OAAO;EACd,IAAI,CAAC,YAAY,KAAK,KAAK,MAAM,SAAS,UAAU,MAAM;CAC5D;AACF;AAEA,MAAM,iBAAiB,OAAO,aAAkD;CAC9E,IAAI;EACF,OAAO,MAAM,SAAS,UAAU,MAAM;CACxC,SAAS,OAAO;EACd,IAAI,YAAY,KAAK,KAAK,MAAM,SAAS,UAAU,OAAO,KAAA;EAC1D,MAAM;CACR;AACF;AAEA,MAAM,kBAAkB,WAAyD;CAC/E,MAAM,YAAY,OAAO,OAAO,KAAK,CAAC;CACtC,IAAI,OAAO,UAAU,SAAS,KAAK,YAAY,GAAG,OAAO,EAAE,KAAK,UAAU;CAE1E,IAAI;CACJ,IAAI;EACF,QAAQ,KAAK,MAAM,MAAM;CAC3B,QAAQ;EACN;CACF;CACA,IACE,CAAC,SAAS,KAAK,KACf,OAAO,MAAM,QAAQ,YACrB,CAAC,OAAO,UAAU,MAAM,GAAG,KAC3B,MAAM,OAAO,KACb,OAAO,MAAM,UAAU,YACvB,MAAM,MAAM,WAAW,GAEvB;CAEF,OAAO,EAAE,KAAK,MAAM,IAAI;AAC1B;AAEA,MAAM,kBAAkB,QAAyB;CAC/C,IAAI;EACF,QAAQ,KAAK,KAAK,CAAC;EACnB,OAAO;CACT,SAAS,OAAO;EACd,OAAO,EAAE,YAAY,KAAK,KAAK,MAAM,SAAS;CAChD;AACF;AAEA,MAAM,SAAS,OAA8B,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;AAE7F,MAAM,eAAe,UACnB,iBAAiB,SAAS,UAAU;AAEtC,MAAM,YAAY,UAChB,OAAO,UAAU,YAAY,UAAU;;;ACvmBzC,MAAa,qBAAqB,OAAO,mBAAyC;CAChF,MAAM,QAAiB,KAAK,MAAM,MAAM,SAAS,gBAAgB,MAAM,CAAC;CACxE,IAAI,CAAC,yBAAyB,KAAK,GACjC,MAAM,IAAI,MAAM,6CAA6C,eAAe,MAAM;CAGpF,OAAO,MAAM;AACf;AAEA,MAAM,4BAA4B,UAChC,OAAO,UAAU,YACjB,UAAU,QACV,CAAC,MAAM,QAAQ,KAAK,KACpB,aAAa,SACb,OAAO,MAAM,YAAY;;;ACe3B,MAAa,sBAAsB,EACjC,SACA,gBACA,aACA,OACA,SACA,WAAW,QAAQ,eACiB;CACpC,MAAM,WAAWC,+BACf,gBAAgB,KAAA,IAAY,EAAE,eAAe,IAAI;EAAE;EAAgB;CAAY,CACjF;CACA,MAAM,gBAAgBC,4BAA0B,OAAO,SAAS,WAAW;CAC3E,MAAM,kBAAkBA,4BAA0B,SAAS,SAAS,WAAW;CAC/E,MAAM,iBAAiB,QAAQ,QAAQ,YAAY,EAAE;CACrD,MAAM,YAAY,GAAG,eAAe,aAAa,SAAS,eAAe,GAAG,SAAS;CACrF,MAAM,aAAa,GAAG,UAAU;CAChC,MAAM,WACJ,aAAa,UACTC,wBAAsB,QAAQ,IAC9BC,uBAAqB,gBAAgB,QAAQ;CAEnD,OAAO;EACL,SAAS;EACT,gBAAgB,SAAS;EACzB,aAAa,SAAS;EACtB,OAAO;EACP,SAAS;EACT,iBAAiB,SAAS;EAC1B;EACA;EACA;EACA,SAAS,GAAG,WAAW;EACvB,UAAU,GAAG,WAAW;EACxB,WAAW,GAAG,WAAW;EACzB,WAAW,GAAG,WAAW;CAC3B;AACF;AAEA,MAAMF,+BAA6B,OAA2B,aAA6B;CACzF,MAAM,UAAU,OAAO,KAAK;CAC5B,OAAO,YAAY,KAAA,KAAa,QAAQ,WAAW,IAAI,WAAW;AACpE;;;ACxBA,MAAM,iBAAiB,IAAI,IAAI,mBAAmB,OAAO,KAAK,GAAG;;;;;;;;AAcjE,MAAa,mCAAmC;;;;;;;;AAShD,MAAa,kCAAkC;;;;;;;;;AAU/C,IAAa,0BAAb,cAA6C,MAAM;CACjD;CACA;CAEA,YACE,MACA,SACA,UAAkD,CAAC,GACnD;EACA,MAAM,SAAS,QAAQ,UAAU,KAAA,IAAY,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,CAAC;EACjF,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,IAAI,QAAQ,YAAY,KAAA,GACtB,KAAK,UAAU,QAAQ;CAE3B;AACF;AAEA,MAAM,iCAAiC,UACrC,IAAI,wBACF,iCACA,gFACA,EAAE,MAAM,CACV;;;;;;AAOF,MAAM,kBAAkB;;;;;;;;AASxB,IAAa,6BAAb,cAAgD,MAAM;CACpD;CACA;CAEA,YAAY,uBAA+B,uBAA+B;EACxE,MACE,4CAA4C,sBAAsB,UAAU,uBAC9E;EACA,KAAK,OAAO;EACZ,KAAK,wBAAwB;EAC7B,KAAK,wBAAwB;CAC/B;AACF;AA6FA,MAAa,qBAAqB,OAChC,UAAqC,CAAC,MACP;CAC/B,MAAM,iBAAiB,QAAQ,kBAAmB,MAAM,mBAAmB,cAAc;CACzF,MAAM,gBAAgB,QAAQ,iBAAiB;CAC/C,MAAM,QAAQ,0BAA0B,QAAQ,KAAK;CACrD,MAAM,UAAU,0BAA0B,QAAQ,OAAO;CAIzD,MAAM,cACJ,QAAQ,eAAe,mBAAmB,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,CAAC;CAChF,MAAM,QAAQ,mBAAmB;EAC/B,SAAS,QAAQ,WAAW,QAAQ,IAAI,iBAAiB,QAAQ;EACjE;EACA;EACA,GAAI,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM;EACvC,GAAI,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ;CAC7C,CAAC;CACD,MAAM,WAAW,QAAQ,YAAY,MAAM;CAC3C,MAAM,YAAY,QAAQ,aAAa,aAAa,MAAM;CAC1D,IAAI,aAAa,aAAa,MAAM,UAClC,MAAM,IAAI,MAAM,mEAAmE;CAErF,MAAM,gBAAgB,QAAQ,iBAAiB,qBAAqB;CACpE,MAAM,kBACJ,QAAQ,aAAa,YAAY,YAC7B,MAAM,+BAA+B;EACnC,GAAI,QAAQ,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,QAAQ,YAAY;EAChF,GAAI,QAAQ,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,QAAQ,YAAY;CAClF,CAAC,IACD,KAAA;CACN,MAAM,YACJ,QAAQ,aAAa,YAAY,YAC7B,8BAA8B,QAAQ,WAAW,OAAO,eAAe,IACvE,KAAA;CACN,MAAM,SACJ,QAAQ,gBACR,uBAAuB,eAAe;EACpC,GAAI,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU;EAC/C,GAAI,QAAQ,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,QAAQ,QAAQ;EACpE,GAAI,oBAAoB,KAAA,IAAY,CAAC,IAAI,EAAE,gBAAgB;CAC7D,CAAC;CACH,MAAM,iCAAiC,aAClC,MAAM,YAAY;EAAE;EAAO;CAAO,CAAC,EAAA,CAAG,OAAO,mBAC7C,QAAQ,mCACR,MAAM,OAAO,cAAc,KAAK,EAAA,CAAG;CAExC,MAAM,aAAa,IAAI,sBAAsB,MADxB,cAAc,QAAQ,GACU,UAAU,WAAW;CAE1E,IAAI;EACF,MAAM,WAAW,KACf,eACA,QAAQ,mBAAmBG,oBAC3B,8BACF;EACA,IAAI,cAAc,KAAA,KAAa,QAAQ,cAAc,KAAA,GAAW;GAC9D,MAAM,gCAAgC,UAAU,MAAM,QAAQ,SAAS;GACvE,MAAM,cAAc,MAAM,gCAAgC;IACxD,mBAAmB,UAAU;IAC7B,OAAO,MAAM;IACb,iBAAiB,QAAQ,MAAM,SAAS,gBAAgB;IACxD,mBAAmB,QAAQ,MAAM,SAAS,WAAW;IACrD,mBAAmB,CAAC,QAAQ,MAAM,YAAY,6BAA6B,CAAC;GAC9E,CAAC;GACD,MAAM,uBAAuB,MAAM,WAAW;IAC5C,OAAO;IACP,SAAS,YAAY;IACrB,kBAAkB,YAAY;IAC9B,kBAAkB,YAAY;GAChC,CAAC;EACH;CACF,SAAS,OAAO;EACd,MAAM,WAAW,MAAM;EACvB,MAAM;CACR;CACA,OAAO;AACT;AAEA,MAAM,yBAAyB,OAC7B,MACA,UACkB;CAClB,IAAI;EACF,MAAM,MAAM,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;EAC9C,MAAM,WACJ,MACA,GAAG,KAAK,UAAU;GAAE,4BAAW,IAAI,KAAK,EAAA,CAAE,YAAY;GAAG,GAAG;EAAM,CAAC,EAAE,KACrE,MACF;CACF,QAAQ,CAER;AACF;AAEA,MAAM,iCACJ,YACA,OACA,oBACyD;CACzD,IAAI,oBAAoB,KAAA,GACtB,MAAM,IAAI,MAAM,mEAAmE;CAErF,MAAM,iBAAiB,YAAY;CAiBnC,OAAO;EACL,MAhBA,mBAAmB,KAAA,IACf,kCAAkC;GAChC,SAAS,MAAM;GACf,aAAa,gBAAgB;GAC7B,SAAS,MAAM;EACjB,CAAC,IACD,OAAO,mBAAmB,WACxB,WAAW,cAAc,IACvB,iBACA,QAAQ,gBAAgB,MAAM,cAAc,IAC9C,eAAe,aAAa,UAC1B,cAAc,cAAc,WACrB;GACL,MAAM,IAAI,MAAM,6CAA6C,eAAe,MAAM;EACpF,EAAA,CAAG;EAGX,GAAI,YAAY,iBAAiB,KAAA,IAAY,CAAC,IAAI,EAAE,cAAc,WAAW,aAAa;CAC5F;AACF;AAEA,MAAM,6BAA6B,UAAkD;CACnF,MAAM,UAAU,OAAO,KAAK;CAC5B,OAAO,YAAY,KAAA,KAAa,QAAQ,WAAW,IAAI,KAAA,IAAY;AACrE;AAEA,IAAa,wBAAb,MAAgE;CAqB3C;CApBnB;CACA;CACA,YAAY;CAEZ,SAAiB;CACjB,4BAA6B,IAAI,IAA6C;CAC9E,0BAA2B,IAAI,IAA+B;;CAE9D,qCAAsC,IAAI,IAAuB;CACjE,gCAAiC,IAAI,IAA4B;CACjE,0CAA2C,IAAI,IAA+C;CAC9F;CACA;CAOA,YACE,QACA,UACA,aACA;EAHiB,KAAA,SAAA;EAIjB,KAAK,WAAW;EAChB,KAAK,cAAc;EACnB,OAAO,YAAY,MAAM;EACzB,OAAO,GAAG,SAAS,UAA2B;GAC5C,KAAK,QAAQ,OAAO,KAAK,CAAC;EAC5B,CAAC;EACD,OAAO,GAAG,UAAU,UAAU;GAM5B,KAAK,SACH,IAAI,MAAM,kCAAkC,EAAE,OAAO,MAAM,CAAC,CAC9D;EACF,CAAC;EACD,OAAO,GAAG,eAAe;GACvB,KAAK,yBAAS,IAAI,MAAM,gCAAgC,CAAC;EAC3D,CAAC;CACH;CAEA,IAAI,iBAA0B;EAC5B,OAAO,KAAK,cAAc,KAAA;CAC5B;CAEA,iBAAiB,UAA8C;EAC7D,KAAK,cAAc,IAAI,QAAQ;EAC/B,aAAa;GACX,KAAK,cAAc,OAAO,QAAQ;EACpC;CACF;CAEA,iBAAiB,UAAiE;EAChF,KAAK,wBAAwB,IAAI,QAAQ;EACzC,aAAa;GACX,KAAK,wBAAwB,OAAO,QAAQ;EAC9C;CACF;CAEA,MAAM,KACJ,eACA,iBACA,gCACe;EACf,MAAM,QAAQ,IAAI,SAAkD,SAAS,WAAW;GACtF,KAAK,QAAQ;IAAE;IAAS;GAAO;EACjC,CAAC;EACD,KAAK,MAAM;GACT,MAAM;GACN;GACA;EACF,CAAC;EACD,MAAM,QAAQ,MAAM,KAAK,sBAAsB,KAAK;EAIpD,IAAI,MAAM,oBAAoB,iBAC5B,MAAM,IAAI,2BAA2B,iBAAiB,MAAM,eAAe;EAE7E,IACE,CAAC,6BAA6B,MAAM,wBAAwB,8BAA8B,GAE1F,MAAM,IAAI,MACR,+CAA+C,KAAK,UAAU,8BAA8B,EAAE,UAAU,KAAK,UAAU,MAAM,sBAAsB,GACrJ;EAEF,KAAK,YAAY,MAAM;CACzB;CAEA,MAAM,QACJ,OACA,UAAmC,CAAC,GACd;EACtB,IAAI,KAAK,QAAQ,IAAI,MAAM,SAAS,GAClC,MAAM,IAAI,MAAM,wBAAwB,MAAM,WAAW;EAO3D,IAAI,KAAK,cAAc,KAAA,GACrB,MAAM,IAAI,MAAM,KAAK,UAAU,OAAO;EAQxC,MAAM,aAAa,QAAQ,cAAA;EAC3B,MAAM,WAAW,IAAI,SAAsB,SAAS,WAAW;GAC7D,MAAM,gBAAgB,iBAAiB;IACrC,KAAK,cAAc,MAAM,WAAW,UAAU;GAChD,GAAG,UAAU;GAGb,cAAc,MAAM;GACpB,KAAK,QAAQ,IAAI,MAAM,WAAW;IAAE;IAAS;IAAQ;GAAc,CAAC;EACtE,CAAC;EACD,KAAK,MAAM,KAAK;EAChB,OAAO;CACT;CAEA,QAAQ,UAA+D;EACrE,KAAK,UAAU,IAAI,QAAQ;EAC3B,aAAa;GACX,KAAK,UAAU,OAAO,QAAQ;EAChC;CACF;CAEA,MAAM,QAAuB;EAC3B,IAAI,KAAK,cAAc,KAAA,GAIrB;EAEF,KAAK,MAAM,EAAE,MAAM,OAAO,CAAC;EAM3B,MAAM,IAAI,SAAe,YAAY;GACnC,MAAM,UAAU,iBAAiB;IAC/B,KAAK,OAAO,QAAQ;IACpB,QAAQ;GACV,GAAG,yBAAyB;GAC5B,QAAQ,MAAM;GACd,KAAK,OAAO,UAAU;IACpB,aAAa,OAAO;IACpB,QAAQ;GACV,CAAC;EACH,CAAC;CACH;CAEA,QAAgB,OAAqB;EACnC,KAAK,UAAU;EACf,OAAO,MAAM;GACX,MAAM,UAAU,KAAK,OAAO,QAAQ,IAAI;GACxC,IAAI,UAAU,GACZ;GAGF,MAAM,OAAO,KAAK,OAAO,MAAM,GAAG,OAAO,CAAC,CAAC,KAAK;GAChD,KAAK,SAAS,KAAK,OAAO,MAAM,UAAU,CAAC;GAC3C,IAAI,KAAK,SAAS,GAChB,KAAK,aAAa,IAAI;EAE1B;CACF;CAEA,aAAqB,MAAoB;EACvC,MAAM,SAAS,iBAAiB,IAAI;EACpC,IAAI,CAAC,OAAO,MAAM,OAAO,UAAU,KAAA,GAAW;GAC5C,KAAK,0BAAU,IAAI,MAAM,GAAG,OAAO,SAAS,uBAAuB,IAAI,MAAM,CAAC;GAC9E;EACF;EAEA,KAAK,cAAc,OAAO,KAAK;CACjC;CAEA,cAAsB,OAA0B;EAC9C,IAAI,MAAM,SAAS,SAAS;GAC1B,KAAK,OAAO,QAAQ,KAAK;GACzB,KAAK,QAAQ,KAAA;GACb;EACF;EAEA,IAAI,MAAM,SAAS,SAAS;GAI1B,MAAM,QAAQ,IAAI,kBAAkB,MAAM,MAAM,MAAM,SAAS,EAC7D,SAAS,MAAM,QACjB,CAAC;GACD,IAAI,MAAM,cAAc,KAAA,GAAW;IACjC,KAAK,YAAY,MAAM,SAAS,CAAC,EAAE,OAAO,KAAK;IAC/C;GACF;GAKA,IAAI,KAAK,OAAO;IACd,KAAK,MAAM,OAAO,KAAK;IACvB,KAAK,QAAQ,KAAA;IACb;GACF;GACA,KAAK,UAAU,KAAK;GACpB;EACF;EAEA,IAAI,MAAM,SAAS,wBAAwB;GACzC,KAAK,wBAAwB,MAAM,WAAW,MAAM,WAAW;GAC/D;EACF;EAEA,IAAI,MAAM,SAAS,0BAA0B;GAC3C,KAAK,wBAAwB,MAAM,aAAa,MAAM,OAAO;GAC7D;EACF;EAEA,MAAM,YAAY,kBAAkB,KAAK;EACzC,IAAI,cAAc,KAAA,GAAW;GAI3B,KAAK,YAAY,SAAS,CAAC,EAAE,QAAQ,KAAK;GAC1C;EACF;EAEA,IACE,MAAM,SAAS,WACf,MAAM,SAAS,eACf,MAAM,SAAS,aAEf,KAAK,MAAM,YAAY,KAAK,WAC1B,SAAS,KAAK;CAGpB;CAEA,MAAc,OAAsB;EAClC,KAAK,OAAO,MAAM,GAAG,KAAK,UAAU,KAAK,EAAE,GAAG;CAChD;;;;;;;;;;;CAYA,wBAAgC,WAAsB,aAA2B;EAC/E,MAAM,QAAQ,KAAK,QAAQ,IAAI,SAAS;EACxC,IAAI,UAAU,KAAA,KAAa,MAAM,sBAAsB,KAAA,GACrD;EAEF,IAAI,KAAK,mBAAmB,IAAI,WAAW,GACzC;EAEF,MAAM,oBAAoB;EAC1B,KAAK,mBAAmB,IAAI,aAAa,SAAS;EAClD,KAAK,cAAc,KAAK;CAC1B;;;;;;;;;;CAWA,wBAAgC,aAAqB,SAAoC;EACvF,MAAM,YAAY,KAAK,mBAAmB,IAAI,WAAW;EACzD,IAAI,cAAc,KAAA,GAChB;EAEF,MAAM,QAAQ,KAAK,YAAY,SAAS;EACxC,IAAI,UAAU,KAAA,GAAW;GACvB,KAAK,mBAAmB,OAAO,WAAW;GAC1C;EACF;EACA,IAAI,QAAQ,SAAS,UAAU;GAG7B,MAAM,WAAqE;IACzE,MAAM;IACN;IACA;GACF;GACA,MAAM,QAAQ,QAAQ;GACtB;EACF;EACA,MAAM,YAAY,QAAQ;EAC1B,MAAM,OACJ,IAAI,wBAAwB,UAAU,MAAM,UAAU,SAAS,EAC7D,SAAS,UAAU,QACrB,CAAC,CACH;CACF;;;;;;;CAQA,YAAoB,WAAkD;EACpE,MAAM,QAAQ,KAAK,QAAQ,IAAI,SAAS;EACxC,IAAI,UAAU,KAAA,GACZ;EAEF,KAAK,QAAQ,OAAO,SAAS;EAC7B,KAAK,cAAc,KAAK;EACxB,IAAI,MAAM,sBAAsB,KAAA,GAC9B,KAAK,mBAAmB,OAAO,MAAM,iBAAiB;EAExD,OAAO;CACT;CAEA,cAAsB,OAA6B;EACjD,IAAI,MAAM,kBAAkB,KAAA,GAAW;GACrC,aAAa,MAAM,aAAa;GAChC,MAAM,gBAAgB,KAAA;EACxB;CACF;;;;;;;;;CAUA,cAAsB,WAAsB,YAA0B;EACpE,MAAM,QAAQ,KAAK,QAAQ,IAAI,SAAS;EACxC,IAAI,UAAU,KAAA,GACZ;EAEF,KAAK,YAAY,SAAS;EAC1B,KAAK,qBAAqB;GAAE;GAAW;EAAW,CAAC;EACnD,MAAM,OAAO,IAAI,sBAAsB,WAAW,UAAU,CAAC;CAC/D;;;;;;;CAQA,sBACE,OACkD;EAClD,OAAO,IAAI,SAAS,SAAS,WAAW;GACtC,IAAI,iBAA4D,iBAAiB;IAC/E,iBAAiB,KAAA;IACjB,KAAK,qBAAqB;KACxB,WAAW;KACX,YAAY;IACd,CAAC;IACD,OAAO,IAAI,sBAAsB,iBAAiB,0BAA0B,CAAC;GAC/E,GAAG,0BAA0B;GAC7B,eAAe,MAAM;GACrB,MAAM,UAAU,aAA+B;IAC7C,IAAI,mBAAmB,KAAA,GAAW;KAChC,aAAa,cAAc;KAC3B,iBAAiB,KAAA;IACnB;IACA,SAAS;GACX;GACA,MAAM,MACH,UAAU,aAAa,QAAQ,KAAK,CAAC,IACrC,UAAU,aAAa,OAAO,KAAK,CAAC,CACvC;EACF,CAAC;CACH;CAEA,qBAA6B,QAAuC;EAClE,KAAK,MAAM,YAAY,CAAC,GAAG,KAAK,uBAAuB,GACrD,IAAI;GACF,SAAS,MAAM;EACjB,QAAQ,CAGR;CAEJ;CAEA,UAAkB,OAAoB;EACpC,KAAK,OAAO,OAAO,KAAK;EACxB,KAAK,QAAQ,KAAA;EACb,KAAK,MAAM,WAAW,KAAK,QAAQ,OAAO,GAAG;GAC3C,KAAK,cAAc,OAAO;GAC1B,QAAQ,OAAO,KAAK;EACtB;EACA,KAAK,QAAQ,MAAM;EACnB,KAAK,mBAAmB,MAAM;CAChC;;;;;;;;;;;CAYA,SAAiB,OAAoB;EACnC,IAAI,KAAK,cAAc,KAAA,GACrB;EAEF,KAAK,YAAY;EACjB,KAAK,OAAO,OAAO,KAAK;EACxB,KAAK,QAAQ,KAAA;EACb,KAAK,MAAM,WAAW,KAAK,QAAQ,OAAO,GAAG;GAC3C,KAAK,cAAc,OAAO;GAC1B,QAAQ,OACN,QAAQ,sBAAsB,KAAA,IAAY,QAAQ,8BAA8B,KAAK,CACvF;EACF;EACA,KAAK,QAAQ,MAAM;EACnB,KAAK,mBAAmB,MAAM;EAC9B,KAAK,MAAM,YAAY,CAAC,GAAG,KAAK,aAAa,GAC3C,IAAI;GACF,SAAS,KAAK;EAChB,QAAQ,CAGR;CAEJ;AACF;AAEA,MAAM,iBAAiB,aACrB,IAAI,SAAS,SAAS,WAAW;CAC/B,MAAM,SAAS,iBAAiB,QAAQ;CACxC,OAAO,KAAK,iBAAiB;EAC3B,OAAO,IAAI,SAAS,MAAM;EAC1B,QAAQ,MAAM;CAChB,CAAC;CACD,OAAO,KAAK,SAAS,MAAM;AAC7B,CAAC;AAEH,MAAM,qBAAqB,UAA8C;CACvE,QAAQ,MAAM,MAAd;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,uBACH,OAAO,MAAM;EAIf,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,SACH;CACJ;AACF;AAEA,MAAM,6BAAqC;CACzC,MAAM,SAAS,cAAc,OAAO,KAAK,GAAG,CAAC,CAAC,SAAS,KAAK,IAAI,WAAW;CAC3E,OAAO,cAAc,IAAI,IAAI,KAAK,UAAU,OAAO,KAAK,GAAG,CAAC;AAC9D;;;;;;;;AClwBA,IAAa,0BAAb,cAA6C,MAAM;CACjD,OAAgB;CAChB;CAEA,YAAY,YAAoB,UAAkB;EAChD,MACE,wBAAwB,WAAW,4BAA4B,SAAS,qDAC1E;EACA,KAAK,OAAO;EACZ,KAAK,UAAU;GAAE;GAAY;EAAS;CACxC;AACF;AAwFA,MAAM,gBAAgB,UAA4C;CAChE,QAAQ,MAAM,MAAd;EACE,KAAK,uBACH,OAAO;EACT,KAAK,eACH;EACF,KAAK;EACL,KAAK;EACL,KAAK,oBACH,OAAO,GAAG,MAAM,KAAK,GAAG,MAAM,MAAM,GAAG,MAAM;EAC/C,KAAK;EACL,KAAK;EACL,KAAK,wBACH,OAAO,GAAG,MAAM,KAAK,GAAG,MAAM;EAChC,KAAK,YACH,OAAO,YAAY,MAAM,MAAM,GAAG,MAAM,WAAW,MAAM;CAC7D;AACF;AAOA,MAAM,0BACJ,eAEA,sBAAsB,cAAc,OAAO,WAAW,qBAAqB;AAO7E,MAAM,0BACJ,eAEA,sBAAsB,cAAc,OAAO,WAAW,qBAAqB;AAE7E,MAAM,cAAc,OAClB,IAAI,SAAS,YAAY;CAEvB,WADyB,SAAS,EAC9B,CAAC,CAAC,MAAM;AACd,CAAC;;;;;;;;AASH,IAAa,kCAAb,MAA6C;CAgCxB;CA/BnB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA,aAAqB;CACrB,QAAgC;CAChC,UAAkC,CAAC;CACnC,iCAAkC,IAAI,IAAyC;CAC/E,gCAAiC,IAAI,IAA4B;CACjE,iCAAkC,IAAI,IAAqC;CAC3E,mBAEI,CAAC;CACL,mBAAuCC;CACvC;CACA,mBAA2B;CAC3B,+BAAuC;CACvC,gBAAwB;CACxB,oBAAsC,CAAC;CACvC,kBAA0B;CAC1B;CAEA,YACE,gBACA,SACA;EAFiB,KAAA,iBAAA;EAGjB,KAAK,sBAAsB,QAAQ,uBAAA;EACnC,KAAK,kBAAkB,QAAQ,mBAAA;EAC/B,KAAK,4BACH,QAAQ,6BAAA;EACV,MAAM,WAAW,QAAQ,YAAY,CAAC;EACtC,KAAK,kBAAkB,SAAS,WAAW;EAC3C,KAAK,cAAc,SAAS,eAAA;EAC5B,KAAK,mBAAmB,SAAS,YAAA;EACjC,KAAK,aAAa,SAAS,cAAA;EAC3B,KAAK,gBAAgB,SAAS,iBAAA;EAC9B,KAAK,eAAe,SAAS,gBAAA;EAC7B,KAAK,aAAa,SAAS;CAC7B;;CAGA,IAAI,iBAAiC;EACnC,OAAO,KAAK;CACd;;CAGA,IAAI,sBAA8B;EAChC,OAAO,KAAK;CACd;;CAGA,IAAI,WAAmB;EACrB,OAAO,KAAK,YAAY,YAAY;CACtC;;CAGA,IAAI,cAAsB;EACxB,OAAO,KAAK,YAAY,eAAe;CACzC;;;;;;CAOA,IAAI,YAAoB;EACtB,OAAO,KAAK,YAAY,aAAa;CACvC;;CAGA,IAAI,iBAA0B;EAC5B,OAAO,KAAK,eAAe,KAAA,KAAa,KAAK,WAAW;CAC1D;;;;;;CAOA,MAAM,UAAyB;EAC7B,MAAM,aAAa,MAAM,KAAK,eAAe;EAC7C,KAAK,aAAa;EAClB,KAAK,mBAAmB,KAAK,eAAe,UAAU;EACtD,KAAK,gBAAgB,KAAK,IAAI;EAC9B,KAAK,+BAA+B;EACpC,KAAK,eAAe;CACtB;;;;;;;;;CAUA,MAAM,QACJ,OACA,UAAmC,CAAC,GACd;EACtB,IAAI,KAAK,UAAU,aACjB,MAAM,IAAI,wBAAwB,KAAK,kBAAkB,QAAQ,KAAK,gBAAgB;EAExF,IAAI,QAAQ,eAAA,KACV,KAAK,kBAAkB;EAEzB,MAAM,aAAa,KAAK;EACxB,IAAI,eAAe,KAAA,GACjB,MAAM,IAAI,MAAM,gCAAgC;EAElD,MAAM,YAAY,qBAAqB,KAAK;EAC5C,MAAM,WAAW,MAAM,WAAW,QAAQ,OAAO,OAAO;EACxD,KAAK,yBAAyB;EAC9B,IAAI,cAAc,KAAA,GAChB,KAAK,mBAAmB,WAAW,QAAQ;EAE7C,IAAI,MAAM,SAAS,gBAGjB,KAAK,iBAAiB,MAAM,OAAO,MAAM,MAAM;EAEjD,OAAO;CACT;;;;;CAMA,QAAQ,UAA2D;EACjE,KAAK,eAAe,IAAI,QAAQ;EAChC,aAAa;GACX,KAAK,eAAe,OAAO,QAAQ;EACrC;CACF;;;;;;CAOA,iBAAiB,UAA8C;EAC7D,KAAK,cAAc,IAAI,QAAQ;EAC/B,aAAa;GACX,KAAK,cAAc,OAAO,QAAQ;EACpC;CACF;;;;;;CAOA,uBAAuB,UAAuD;EAC5E,KAAK,eAAe,IAAI,QAAQ;EAChC,aAAa;GACX,KAAK,eAAe,OAAO,QAAQ;EACrC;CACF;;;;;;;;CASA,yBACE,SACM;EACN,KAAK,iBAAiB,KAAK,OAAO;CACpC;;;;;;;CAQA,MAAM,WAA0B;EAC9B,KAAK,kBAAkB;EACvB,KAAK,qBAAqB,YAAY;GACpC,KAAK,cAAc;GACnB,KAAK,iBAAiB;GACtB,KAAK,mBAAmBA;GACxB,MAAM,aAAa,KAAK;GACxB,KAAK,aAAa,KAAA;GAClB,IAAI,eAAe,KAAA,GACjB,MAAM,WAAW,MAAM,CAAC,CAAC,MAAM,SAAS;EAE5C,EAAA,CAAG;EACH,MAAM,KAAK;CACb;;CAGA,QAAuB;EACrB,OAAO,KAAK,SAAS;CACvB;CAEA,iBAA+B;EAC7B,IAAI,KAAK,mBAAmB,KAAA,GAC1B;EAEF,KAAK,iBAAiB,kBAAkB;GACtC,KAAU,cAAc;EAC1B,GAAG,KAAK,mBAAmB;EAE3B,KAAK,eAAe,MAAM;CAC5B;CAEA,gBAA8B;EAC5B,IAAI,KAAK,mBAAmB,KAAA,GAAW;GACrC,cAAc,KAAK,cAAc;GACjC,KAAK,iBAAiB,KAAA;EACxB;CACF;;;;;;;CAQA,MAAc,gBAA+B;EAC3C,MAAM,aAAa,KAAK;EACxB,IACE,eAAe,KAAA,KACf,KAAK,UAAU,aACf,KAAK,iBAEL;EAEF,IAAI,KAAK,IAAI,IAAI,KAAK,gBAAgB,KAAK,qBACzC;EAEF,MAAM,YAAY,wBAAwB,KAAK,WAAW,GAAI,KAAK,oBAAoB;EACvF,IAAI;GACF,MAAM,WAAW,QACf;IAAE,MAAM;IAAU;GAAU,GAC5B,EAAE,YAAY,KAAK,gBAAgB,CACrC;GACA,KAAK,+BAA+B;GACpC,KAAK,yBAAyB;EAChC,SAAS,OAAO;GACd,KAAK,gCAAgC;GACrC,IAAI,KAAK,+BAA+B,KAAK,2BAC3C;GAKF,MAAM,QAAQ,IAAI,MAAM,kCAAkC,EACxD,OAAO,kCAAkC,KAAK,6BAA6B,+BAA+B,OAAO,KAAK,EAAE,GAC1H,CAAC;GAID,KAAK,sBAAsB,KAAK;GAChC,WAAgB,MAAM,CAAC,CAAC,MAAM,SAAS;EACzC;CACF;CAEA,2BAAyC;EACvC,KAAK,gBAAgB,KAAK,IAAI;EAC9B,KAAK,+BAA+B;CACtC;;;;;;;CAQA,eAAuB,YAA2C;EAChE,MAAM,UAA6B,CAAC;EACpC,MAAM,iBAAiB,WAAW,SAAS,UAAU;GACnD,KAAK,MAAM,YAAY,CAAC,GAAG,KAAK,cAAc,GAC5C,IAAI;IACF,SAAS,KAAK;GAChB,QAAQ,CAER;EAEJ,CAAC;EACD,QAAQ,KAAK,cAAc;EAK3B,IAAI,uBAAuB,UAAU,GAAG;GACtC,MAAM,eAAe,WAAW,kBAAkB,UAAU;IAC1D,KAAK,sBAAsB,KAAK;GAClC,CAAC;GACD,QAAQ,KAAK,YAAY;EAC3B;EACA,IAAI,uBAAuB,UAAU,GAAG;GACtC,MAAM,iBAAiB,WAAW,kBAAkB,WAAW;IAI7D,IAAI,OAAO,UAAU,WAAW,uBAAuB,GACrD;IAEF,KAAK,gCAAgC;IACrC,IACE,KAAK,gCAAgC,KAAK,6BAC1C,KAAK,UAAU,aACf,CAAC,KAAK,iBACN;KACA,MAAM,oBAAoB,KAAK;KAG/B,KAAK,sBACH,IAAI,MAAM,kCAAkC,EAC1C,OAAO,kCAAkC,KAAK,6BAA6B,gCAC7E,CAAC,CACH;KACA,IAAI,sBAAsB,KAAA,GACxB,kBAAuB,MAAM,CAAC,CAAC,MAAM,SAAS;IAElD;GACF,CAAC;GACD,QAAQ,KAAK,cAAc;EAC7B;EACA,aAAa;GACX,KAAK,MAAM,UAAU,QAAQ,OAAO,CAAC,GACnC,OAAO;EAEX;CACF;;;;;;;CAQA,sBAA8B,OAAoB;EAChD,KAAK,MAAM,YAAY,CAAC,GAAG,KAAK,aAAa,GAC3C,IAAI;GACF,SAAS,KAAK;EAChB,QAAQ,CAER;EAEF,IAAI,KAAK,mBAAmB,KAAK,UAAU,WACzC;EAEF,KAAK,iBAAiB;EACtB,KAAK,mBAAmBA;EACxB,IAAI,KAAK,eAAe,KAAA,GAAW;GACjC,KAAU,qBAAqB;GAC/B;EACF;EACA,IAAI,CAAC,KAAK,iBAGR;EAEF,KAAU,YAAY;CACxB;;;;;;CAOA,MAAc,uBAAsC;EAClD,KAAK,SAAS,YAAY;EAI1B,KAAK,kBAAkB;EACvB,KAAK,cAAc;EACnB,MAAM,aAAa,KAAK;EACxB,IAAI,eAAe,KAAA,KAAa,CAAC,WAAW,gBAC1C,MAAM,WAAW,MAAM,CAAC,CAAC,MAAM,SAAS;EAE1C,IAAI;GACF,MAAM,KAAK,aAAa;EAC1B,SAAS,OAAO;GAGd,QAAQ,MAAM,iDAAiD,KAAK;EACtE;EACA,KAAK,SAAS,WAAW;CAC3B;;;;;;;;CASA,MAAc,cAA6B;EACzC,KAAK,SAAS,YAAY;EAC1B,IAAI,iBAAiB;EACrB,OAAO,MAAM;GACX,IAAI,KAAK,iBAEP;GAEF,IAAI,CAAC,KAAK,qBAAqB,GAAG;IAChC,KAAK,SAAS,WAAW;IACzB;GACF;GACA,MAAM,WAAW,KAAK,mBAAmB,cAAc,CAAC;GACxD,IAAI,KAAK,iBACP;GAEF,IAAI;IACF,MAAM,YAAY,MAAM,KAAK,eAAe;IAC5C,MAAM,KAAK,gBAAgB,SAAS;IACpC,KAAK,SAAS,SAAS;IACvB;GACF,QAAQ;IACN,kBAAkB;GACpB;EACF;CACF;CAEA,mBAA2B,gBAAgC;EACzD,OAAO,KAAK,IACV,KAAK,aAAa,KAAK,iBAAiB,gBACxC,KAAK,YACP;CACF;;;;;;CAOA,uBAAwC;EACtC,MAAM,cAAc,KAAK,IAAI,IAAI,KAAK;EACtC,KAAK,oBAAoB,KAAK,kBAAkB,QAC7C,cAAc,YAAY,WAC7B;EACA,IAAI,KAAK,kBAAkB,UAAU,KAAK,aACxC,OAAO;EAET,KAAK,kBAAkB,KAAK,KAAK,IAAI,CAAC;EACtC,OAAO;CACT;;;;;;;;;CAUA,MAAc,gBAAgB,WAA6C;EACzE,KAAK,cAAc;EACnB,KAAK,mBAAmB,KAAK,eAAe,SAAS;EACrD,IAAI;GACF,MAAM,KAAK,cAAc,SAAS;GAClC,KAAK,MAAM,WAAW,CAAC,GAAG,KAAK,gBAAgB,GAC7C,MAAM,QAAQ;IACZ,YAAY,KAAK;IACjB,WAAW,UAAU,UAAU,SAAS,IAAI,UAAU,YAAY,KAAA;GACpE,CAAC;EAEL,SAAS,OAAO;GACd,KAAK,iBAAiB;GACtB,KAAK,mBAAmBA;GACxB,MAAM,UAAU,MAAM,CAAC,CAAC,MAAM,SAAS;GACvC,MAAM;EACR;EACA,KAAK,aAAa;EAClB,KAAK,+BAA+B;EACpC,KAAK,yBAAyB;CAChC;;;;;;;;CASA,MAAc,cAAc,YAA8C;EACxE,IAAI,UAAU;EACd,MAAM,gCAAgB,IAAI,IAAoB;EAC9C,MAAM,gBAAgB,UAA0B,cAAc,IAAI,KAAK,KAAK;EAC5E,KAAK,MAAM,SAAS,KAAK,SAAS;GAChC,WAAW;GACX,MAAM,YAAuB,qBAAqB,KAAK,WAAW,GAAG;GACrE,IAAI;GACJ,QAAQ,MAAM,MAAd;IACE,KAAK;KACH,QAAQ;MAAE,MAAM;MAAuB;KAAU;KACjD;IACF,KAAK;KACH,QAAQ;MACN,MAAM;MACN;MACA,KAAK,EAAE,OAAO,aAAa,MAAM,IAAI,KAAK,EAAE;MAI5C,MAAM;OAAE,GAAG,MAAM;OAAM,IAAI,MAAM;MAAO;KAC1C;KACA;IACF,KAAK;KACH,QAAQ;MACN,MAAM;MACN;MACA,OAAO,aAAa,MAAM,KAAK;MAC/B,QAAQ,MAAM;MACd,MAAM,MAAM;KACd;KACA;IACF,KAAK;KACH,QAAQ;MACN,MAAM;MACN;MACA,OAAO,aAAa,MAAM,KAAK;MAC/B,QAAQ,MAAM;MACd,MAAM,MAAM;KACd;KACA;IACF,KAAK;KACH,QAAQ;MACN,MAAM;MACN;MACA,OAAO,aAAa,MAAM,KAAK;MAC/B,QAAQ,MAAM;MACd,SAAS,MAAM;KACjB;KACA;IACF,KAAK;KACH,QAAQ;MACN,MAAM;MACN;MACA,OAAO,aAAa,MAAM,KAAK;MAC/B,MAAM,MAAM;KACd;KACA;IACF,KAAK;KACH,QAAQ;MACN,MAAM;MACN;MACA,OAAO,aAAa,MAAM,KAAK;MAC/B,SAAS,MAAM;KACjB;KACA;IACF,KAAK;KACH,QAAQ;MACN,MAAM;MACN;MACA,OAAO,aAAa,MAAM,KAAK;MAC/B,SAAS,MAAM;KACjB;KACA;IACF,KAAK;KACH,QAAQ;MACN,MAAM;MACN;MACA,OAAO,aAAa,MAAM,KAAK;MAC/B,MAAM,MAAM;MACZ,MAAM,MAAM;MACZ,kBAAkB,MAAM;MACxB,GAAI,MAAM,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,MAAM,QAAQ;KAClE;KACA;GACJ;GACA,MAAM,WAAW,MAAM,WAAW,QAAQ,OAAO,EAC/C,YAAY,2BACd,CAAC;GACD,IAAI,SAAS,SAAS,SACpB,MAAM,IAAI,kBAAkB,SAAS,MAAM,SAAS,SAAS,EAC3D,SAAS,SAAS,QACpB,CAAC;GAEH,IAAI,MAAM,SAAS,yBAAyB,SAAS,SAAS,eAC5D,cAAc,IAAI,MAAM,OAAO,SAAS,IAAI,KAAK;EAErD;CACF;CAEA,SAAiB,OAA6B;EAC5C,IAAI,KAAK,UAAU,OACjB;EAEF,KAAK,QAAQ;EACb,IAAI,UAAU,aAEZ,KAAK,cAAc;EAErB,KAAK,MAAM,YAAY,CAAC,GAAG,KAAK,cAAc,GAC5C,IAAI;GACF,SAAS,KAAK;EAChB,QAAQ,CAER;CAEJ;CAEA,mBAA2B,OAA2B,UAA6B;EACjF,QAAQ,MAAM,MAAd;GACE,KAAK;IACH,IAAI,SAAS,SAAS,eACpB,KAAK,cAAc;KACjB,MAAM;KACN,OAAO,SAAS,IAAI;IACtB,CAAC;IAEH;GACF,KAAK,eAAe;IAClB,MAAM,SACJ,SAAS,SAAS,kBAAkB,OAAO,SAAS,WAAW,WAC3D,SAAS,SACT,MAAM,KAAK;IACjB,KAAK,QAAQ,KAAK;KAChB,MAAM;KACN,KAAK,MAAM;KACX,MAAM,MAAM;KACZ;IACF,CAAC;IACD;GACF;GACA,KAAK;IACH,KAAK,cAAc;KACjB,MAAM;KACN,OAAO,MAAM;KACb,QAAQ,MAAM;KACd,MAAM,MAAM;IACd,CAAC;IACD;GACF,KAAK;IACH,KAAK,cAAc;KACjB,MAAM;KACN,OAAO,MAAM;KACb,QAAQ,MAAM;KACd,MAAM,MAAM;IACd,CAAC;IACD;GACF,KAAK;IACH,KAAK,cAAc;KACjB,MAAM;KACN,OAAO,MAAM;KACb,QAAQ,MAAM;KACd,SAAS,MAAM;IACjB,CAAC;IACD;GACF,KAAK;IACH,KAAK,cAAc;KAAE,MAAM;KAAgB,OAAO,MAAM;KAAO,MAAM,MAAM;IAAK,CAAC;IACjF;GACF,KAAK;IACH,KAAK,cAAc;KACjB,MAAM;KACN,OAAO,MAAM;KACb,SAAS,MAAM;IACjB,CAAC;IACD;GACF,KAAK;IACH,KAAK,cAAc;KACjB,MAAM;KACN,OAAO,MAAM;KACb,SAAS,MAAM;IACjB,CAAC;IACD;GACF,KAAK;IACH,KAAK,cAAc;KACjB,MAAM;KACN,OAAO,MAAM;KACb,MAAM,MAAM;KACZ,MAAM,MAAM;KACZ,kBAAkB,MAAM;KACxB,GAAI,MAAM,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,MAAM,QAAQ;IAClE,CAAC;IACD;GACF,SACE;EACJ;CACF;;;;;;CAOA,cAAsB,OAA2B;EAC/C,MAAM,MAAM,aAAa,KAAK;EAC9B,IAAI,QAAQ,KAAA,GAAW;GACrB,KAAK,QAAQ,KAAK,KAAK;GACvB;EACF;EACA,MAAM,WAAW,KAAK,QAAQ,WAC3B,cAAc,aAAa,SAAS,MAAM,GAC7C;EACA,IAAI,WAAW,GAAG;GAChB,KAAK,QAAQ,KAAK,KAAK;GACvB;EACF;EACA,KAAK,QAAQ,YAAY;CAC3B;CAEA,iBAAyB,OAAe,QAAsB;EAC5D,KAAK,UAAU,KAAK,QAAQ,QAAQ,UAAU;GAC5C,QAAQ,MAAM,MAAd;IACE,KAAK,eACH,OAAO,EAAE,MAAM,IAAI,UAAU,SAAS,MAAM,WAAW;IACzD,KAAK;IACL,KAAK;IACL,KAAK,oBACH,OAAO,EAAE,MAAM,UAAU,SAAS,MAAM,WAAW;IACrD,SACE,OAAO;GACX;EACF,CAAC;CACH;AACF;;;;;;;AAQA,MAAM,wBAAwB,UAA8D;CAC1F,QAAQ,MAAM,MAAd;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,YACH,OAAO,gBAAgB,KAAK;EAC9B,SACE;CACJ;AACF;;AAGA,MAAa,6BACX,YAEA,IAAI,gCAAgC,QAAQ,SAAS,OAAO;AAE9D,MAAMA,eAAmB,CAAC;AAC1B,MAAM,kBAAwB,CAAC;;;AC/4B/B,MAAa,2BACX,SAC6B;CAC7B,MAAM,QAAwB;EAC5B,SAAS,uBAAuB,KAAK,KAAK;EAC1C,QAAQ;EACR,0BAAU,IAAI,IAAI;CACpB;CACA,OAAO;EACL,MAAM,EACJ,OAAO,KAAK,MAAM,KAAK,SAAS,4BAA4B,MAAM,KAAK,CAAC,EAC1E;EACA,UAAU,MAAM;CAClB;AACF;AAEA,MAAM,+BACJ,MACA,UACa;CACb,IAAI,OAAO,SAAS,UAAU;EAC5B,IAAI,oBAAoB,IAAI,GAC1B,OAAO,EAAE,MAAM,YAAY;EAE7B,OAAO,mBAAmB,EAAE,OAAO,KAAK,GAAG,KAAK;CAClD;CACA,IAAI,eAAe,IAAI,GAAG;EACxB,MAAM,CAAC,OAAO,SAAS;EACvB,OAAO;GACL,MAAM;GACN;GACA,OAAO,MAAM,KAAK,UAAU,4BAA4B,OAAO,KAAK,CAAC;EACvE;CACF;CACA,QAAQ,KAAK,MAAb;EACE,KAAK,KAAA;EACL,KAAK,QACH,OAAO,mBAAmB,MAAM,KAAK;EACvC,KAAK,SACH,OAAO,mBAAmB,MAAM,KAAK;EACvC,KAAK,SACH,OAAO,mBAAmB,MAAM,KAAK;EACvC,KAAK,aACH,OAAO;EACT,KAAK,WACH,OAAO;GACL,MAAM;GACN,OAAO,KAAK;GACZ,GAAI,KAAK,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,KAAK,QAAQ;GAC9D,OAAO,KAAK,MAAM,KAAK,UACrB,4BAA4B,OAAO,KAAK,CAC1C;EACF;CACJ;CACA,MAAM,IAAI,MAAM,uBAAuB;AACzC;AAEA,MAAM,0BACJ,MAIA,UACe;CACf,MAAM,KAAK,KAAK,MAAM,mBAAmB,KAAK;CAC9C,gBAAgB,OAAO,EAAE;CACzB,IAAI,KAAK,gBAAgB,KAAA,GAAW;EAClC,MAAM,WAAW,MAAM,SAAS,IAAI,EAAE,KAAK,CAAC;EAC5C,SAAS,KAAK,KAAK,WAAW;EAC9B,MAAM,SAAS,IAAI,IAAI,QAAQ;CACjC;CACA,OAAO;AACT;AAEA,MAAM,sBACJ,MACA,UACwC;CAExC,OAAO;EACL,MAAM;EACN,IAHS,uBAAuB,MAAM,KAGrC;EACD,OAAO,KAAK;EACZ,GAAI,KAAK,iBAAiB,KAAA,IACtB,CAAC,IACD,EAAE,cAAc,KAAK,aAAa;EACtC,GAAI,KAAK,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,KAAK,QAAQ;EAC9D,GAAI,KAAK,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,KAAK,SAAS;CACnE;AACF;AAEA,MAAM,sBACJ,MACA,UACyC;CAEzC,OAAO;EACL,MAAM;EACN,IAHS,uBAAuB,MAAM,KAGrC;EACD,OAAO,KAAK;EACZ,GAAI,KAAK,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,KAAK,QAAQ;EAC9D,GAAI,KAAK,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,KAAK,QAAQ;CAChE;AACF;AAEA,MAAM,sBACJ,MACA,UACyC;CAEzC,OAAO;EACL,MAAM;EACN,IAHS,uBAAuB,MAAM,KAGrC;EACD,OAAO,KAAK;EACZ,GAAI,KAAK,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,KAAK,QAAQ;EAC9D,GAAI,KAAK,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,KAAK,QAAQ;EAC9D,OAAO,KAAK;CACd;AACF;AAEA,MAAM,sBAAsB,UAAsC;CAChE,OAAO,MAAM,QAAQ,IAAI,MAAM,MAAM,GACnC,MAAM,UAAU;CAElB,MAAM,KAAK,MAAM;CACjB,MAAM,QAAQ,IAAI,EAAE;CACpB,MAAM,UAAU;CAChB,OAAO;AACT;AAEA,MAAM,0BACJ,UACoB;CACpB,MAAM,sBAAM,IAAI,IAAgB;CAChC,KAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,OAAO,SAAS,UAClB;EAEF,IAAI,eAAe,IAAI,GAAG;GACxB,KAAK,MAAM,MAAM,uBAAuB,KAAK,EAAE,GAC7C,IAAI,IAAI,EAAE;GAEZ;EACF;EACA,QAAQ,KAAK,MAAb;GACE,KAAK,KAAA;GACL,KAAK;GACL,KAAK;GACL,KAAK;IACH,IAAI,KAAK,OAAO,KAAA,GACd,IAAI,IAAI,KAAK,EAAE;IAEjB;GACF,KAAK;IACH,KAAK,MAAM,MAAM,uBAAuB,KAAK,KAAK,GAChD,IAAI,IAAI,EAAE;IAEZ;GACF,KAAK,aACH;EACJ;CACF;CACA,OAAO;AACT;AAEA,MAAM,uBAAuB,UAA2B,OAAO,KAAK,KAAK;AAEzE,MAAM,kBACJ,SAEA,MAAM,QAAQ,IAAI;AAEpB,MAAM,mBAAmB,OAAuB,OAAyB;CACvE,MAAM,OAAO,MAAM,gCAAgB,IAAI,IAAgB;CACvD,IAAI,KAAK,IAAI,EAAE,GACb,MAAM,IAAI,MAAM,2BAA2B,IAAI;CAEjD,KAAK,IAAI,EAAE;CACX,MAAM,eAAe;AACvB;;;AC7OA,MAAa,sBACX,YACA,UAII,CAAC,MAC2B;CAChC,MAAM,aAAa,QAAQ,OAAO,QAAQ,IAAI;CAC9C,IAAI,eAAe,KAAA,KAAa,eAAe,MAC7C,OAAO;EACL,eAAe;EACf,SAAS,qBAAqB,QAAQ,YAAY,QAAQ,UAAU,kBAAkB;EACtF,MAAM,CAAC,IAAI,QAAQ,QAAQ,QAAQ,KAAA,CAAM,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,UAC3D,YAAY,KAAK,gBAAgB,QAAQ,EAAE,EAAE,CAC/C;EACA,KAAK,qBAAqB,YAAY,eAAe;CACvD;CAEF,MAAM,UAAU,qBAAqB,WAAW,SAAS,mBAAmB;CAK5E,MAAM,MAAM,QAAQ,YAHlB,WAAW,QAAQ,KAAA,IACf,aACA,qBAAqB,WAAW,KAAK,eAAe,CACb;CAC7C,MAAM,OAAO,CAAC,GAAI,WAAW,QAAQ,CAAC,CAAE,CAAC,CAAC,KAAK,KAAK,UAClD,YAAY,KAAK,kBAAkB,MAAM,EAAE,CAC7C;CACA,OAAO;EACL,eAAe;EACf,SAAS,uBAAuB,SAAS,UAAU;EACnD;EACA;CACF;AACF;AAEA,MAAM,0BAA0B,SAAiB,QAAwB;CACvE,IAAI,WAAW,OAAO,KAAK,QAAQ,SAAS,GAAG,KAAK,QAAQ,SAAS,IAAI,GACvE,OAAO,QAAQ,KAAK,OAAO;CAE7B,OAAO;AACT;AAEA,MAAM,wBAAwB,OAAe,UAA0B;CACrE,IAAI,MAAM,KAAK,CAAC,CAAC,WAAW,KAAK,MAAM,SAAS,IAAQ,GACtD,MAAM,IAAI,MAAM,GAAG,MAAM,wCAAwC;CAEnE,OAAO;AACT;AAEA,MAAM,eAAe,OAAe,UAA0B;CAC5D,IAAI,MAAM,SAAS,IAAQ,GACzB,MAAM,IAAI,MAAM,GAAG,MAAM,8BAA8B;CAEzD,OAAO;AACT;;;ACUA,MAAa,aAAa,OACxB,SACA,iBAAyC,CAAC,MACZ;CAC9B,IAAI,eAAe,YAAY,KAAA,GAC7B,MAAM,gBAAgB,eAAe,OAAO;CAE9C,MAAM,UACJ,eAAe,YAAY,KAAA,IACvB,KAAA,IACA,iBAAiB,eAAe,OAAO;CAC7C,MAAM,aAAa,2BAA2B,OAAO;CACrD,MAAM,YAAY,mBAAmB,eAAe,SAAS;CAC7D,MAAM,EAAE,UAAU,GAAG,kBAAkB;CAMvC,MAAM,aAAa,0BAA0B;EAC3C,eACE,mBAAmB;GACjB,GAAG;GACH,GAAI,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ;GAC3C;EACF,CAAC;EACH,GAAI,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS;CAC/C,CAAC;CACD,IAAI;EACF,MAAM,WAAW,QAAQ;EACzB,MAAM,OAAO,MAAM,aAAa,YAAY,EAC1C,YAAY;GACV,GAAI,eAAe,YAAY,KAAA,IAC3B,CAAC,IACD,EAAE,MAAM,eAAe,QAAQ;GACnC,GAAI,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ;EAC7C,EACF,CAAC,CAAC,CAAC,WAAW,WAAW,OAAO;EAChC,OAAO,qBAAqB,MAAM;GAChC,gBAAgB,WAAW,SAAS;GACpC,gBAAgB,KAAA;GAChB,iBAAiB,sBAAsB,MAAM,WAAW,YAAY;EACtE,CAAC;CACH,SAAS,OAAO;EACd,MAAM,WAAW,SAAS,CAAC,CAAC,MAAM,IAAI;EACtC,MAAM;CACR;AACF;AAEA,MAAM,8BACJ,YACgC;CAChC,MAAM,kBAA6C;EACjD,IAAI,QAAQ;EACZ,GAAI,QAAQ,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,QAAQ,QAAQ;EACpE,GAAI,QAAQ,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,QAAQ,KAAK;CAC7D;CACA,IAAI,QAAQ,SAAS,KAAA,GACnB,OAAO;EAAE,SAAS;EAAiB,8BAAc,IAAI,IAAI;CAAE;CAE7D,MAAM,aAAa,wBAAwB,QAAQ,IAAI;CACvD,OAAO;EACL,SAAS;GACP,GAAG;GACH,MAAM,WAAW;EACnB;EACA,cAAc,WAAW;CAC3B;AACF;AAEA,MAAM,wBACJ,MACA,UACqB;CAqDrB,OAAO;EAnDL,GAAG;EACH,MAAM,QAAQ,MAAqC;GACjD,MAAM,aAAa,wBAAwB,IAAI;GAC/C,MAAM,KAAK,QAAQ,WAAW,IAAI;GAClC,MAAM,gBAAgB;GACtB,MAAM,kBAAkB,sBAAsB,MAAM,WAAW,QAAQ;EACzE;EACA,OACE,WACA,SACgC;GAChC,MAAM,WAAW,KAAK,OAAO,WAAW,OAAO;GAC/C,OAAO,qBAAqB,UAAU,KAAK;EAE7C;EACA,MAAM,UAAyB;GAC7B,MAAM,oBAAoB,YAAY;IACpC,MAAM,gBAAgB;IACtB,MAAM,kBAAkB;IAWxB,MAAM,qBAAqB,UACzB,iBAAiB,SACjB,MAAM,YAAA;IACR,IAAI;KACF,MAAM,KAAK,QAAQ;IACrB,SAAS,OAAO;KACd,IAAI,CAAC,kBAAkB,KAAK,GAC1B,MAAM;IAEV,UAAU;KACR,IAAI;MACF,MAAM,MAAM,SAAS;KACvB,SAAS,OAAO;MACd,IAAI,CAAC,kBAAkB,KAAK,GAC1B,MAAM;KAEV;IACF;GACF,EAAA,CAAG;GACH,MAAM,MAAM;EACd;CAEU;AACd;AAEA,MAAM,yBACJ,MACA,aACiB;CACjB,IAAI,SAAS,SAAS,GACpB,OAAO;CAET,OAAO,KAAK,aAAa,UAAU;EACjC,KAAK,MAAM,WAAW,SAAS,IAAI,MAAM,MAAM,KAAK,CAAC,GACnD,QAAQ,KAAK;CAEjB,CAAC;AACH;AAEA,MAAM,aAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["isRecord","PROTOCOL_VERSION","isConnectionDeadSource","isNodeError","createBrokerEndpointIdentity","normalizeAppIdentityField","formatWindowsPipeName","formatUnixSocketPath","PROTOCOL_VERSION","noop"],"sources":["../src/app-icon.ts","../src/native-extension-artifact.ts","../src/client.ts","../src/daemon/caller-label.ts","../src/daemon/native-target.ts","../src/daemon/broker-command.ts","../src/daemon/lifecycle.ts","../src/daemon/package-version.ts","../src/daemon/paths.ts","../src/local-broker.ts","../src/transport-supervision.ts","../src/menu-input.ts","../src/app-launch.ts","../src/sdk.ts"],"sourcesContent":["// Orthogonal intents (maintained 2026-07-20; original user request: appIcon\n// must be a strict platform-standard asset array distinct from trayIcon):\n// 1. Validate platform coverage and uniqueness before broker startup.\n// 2. Prove declared native formats against source bytes.\n// 3. Reject every tray-oriented, remote, text, template, and raw RGBA shape.\n\nimport { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport type {\n AppIcon,\n AppIconSource,\n AppIconVariant,\n} from \"@opentray/spec\";\n\nexport type AppIconPlatform = \"darwin\" | \"windows\" | \"linux\";\nexport const DEFAULT_APP_ICON_VARIANT = \"default\" as const;\nconst APP_ICON_VARIANT_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;\n\nexport class InvalidAppIconError extends Error {\n readonly code = \"OPENTRAY_INVALID_APP_ICON\";\n readonly reason: string;\n\n constructor(reason: string, platform: NodeJS.Platform = process.platform) {\n super(`invalid appIcon for ${platform}: ${reason}`);\n this.name = \"InvalidAppIconError\";\n this.reason = reason;\n }\n}\n\nexport class AppIconVariantNotFoundError extends Error {\n readonly code = \"OPENTRAY_APP_ICON_VARIANT_NOT_FOUND\";\n readonly variant: string;\n\n constructor(variant: string, platform: NodeJS.Platform = process.platform) {\n super(`appIcon variant ${variant} is unavailable for ${platform}`);\n this.name = \"AppIconVariantNotFoundError\";\n this.variant = variant;\n }\n}\n\n/** Validate an explicit AppIcon, including native file signatures, before broker startup. */\nexport const validateAppIcon = async (\n icon: unknown,\n platform: NodeJS.Platform = process.platform\n): Promise<void> => {\n if (!Array.isArray(icon) || icon.length === 0) {\n throw new InvalidAppIconError(\n \"the asset array must not be empty\",\n platform\n );\n }\n\n const variantPlatforms = new Map<string, Set<AppIconPlatform>>();\n const seenDarwin = new Set<string>();\n const seenWindows = new Set<string>();\n const seenLinuxPngSizes = new Set<string>();\n const seenLinuxSvg = new Set<string>();\n for (const asset of icon) {\n if (!isRecord(asset)) {\n throw new InvalidAppIconError(\"asset must be an object\", platform);\n }\n const assetPlatform = asset.platform;\n const format = asset.format;\n const variants = validateVariantNames(asset.variant, platform);\n if (assetPlatform === \"darwin\" && format === \"icns\") {\n assertExactKeys(\n asset,\n [\"platform\", \"format\", \"source\"],\n platform,\n [\"variant\"]\n );\n rejectDuplicateVariants(seenDarwin, variants, \"darwin\", platform);\n await validateSource(asset.source, \"icns\", platform);\n recordVariantPlatforms(variantPlatforms, variants, \"darwin\");\n continue;\n }\n if (assetPlatform === \"windows\" && format === \"ico\") {\n assertExactKeys(\n asset,\n [\"platform\", \"format\", \"source\"],\n platform,\n [\"variant\"]\n );\n rejectDuplicateVariants(seenWindows, variants, \"windows\", platform);\n await validateSource(asset.source, \"ico\", platform);\n recordVariantPlatforms(variantPlatforms, variants, \"windows\");\n continue;\n }\n if (assetPlatform === \"linux\" && format === \"png\") {\n assertExactKeys(\n asset,\n [\"platform\", \"format\", \"size\", \"source\"],\n platform,\n [\"variant\"]\n );\n if (\n !Number.isInteger(asset.size) ||\n typeof asset.size !== \"number\" ||\n asset.size <= 0\n ) {\n throw new InvalidAppIconError(\n \"Linux PNG assets require a positive integer size\",\n platform\n );\n }\n for (const variant of variants) {\n const key = `${variant}\\0${asset.size}`;\n if (seenLinuxPngSizes.has(key)) {\n throw new InvalidAppIconError(\n `duplicate Linux PNG size ${asset.size} for variant ${variant}`,\n platform\n );\n }\n seenLinuxPngSizes.add(key);\n }\n await validateSource(asset.source, \"png\", platform);\n recordVariantPlatforms(variantPlatforms, variants, \"linux\");\n continue;\n }\n if (assetPlatform === \"linux\" && format === \"svg\") {\n assertExactKeys(\n asset,\n [\"platform\", \"format\", \"source\"],\n platform,\n [\"variant\"]\n );\n rejectDuplicateVariants(seenLinuxSvg, variants, \"Linux SVG\", platform);\n await validateSource(asset.source, \"svg\", platform);\n recordVariantPlatforms(variantPlatforms, variants, \"linux\");\n continue;\n }\n throw new InvalidAppIconError(\n `unsupported platform/format pair ${String(assetPlatform)}/${String(\n format\n )}`,\n platform\n );\n }\n\n const currentPlatform = normalizePlatform(platform);\n if (currentPlatform !== undefined) {\n if (!variantPlatforms.get(DEFAULT_APP_ICON_VARIANT)?.has(currentPlatform)) {\n throw new InvalidAppIconError(\n `no ${currentPlatform} ${DEFAULT_APP_ICON_VARIANT} asset was provided`,\n platform\n );\n }\n for (const [variant, platforms] of variantPlatforms) {\n if (!platforms.has(currentPlatform)) {\n throw new InvalidAppIconError(\n `variant ${variant} has no ${currentPlatform} asset`,\n platform\n );\n }\n }\n }\n};\n\n/** Normalize encoded sources into JSON array bytes for the Rust wire protocol. */\nexport const normalizeAppIcon = (icon: AppIcon): AppIcon =>\n icon.map((asset) => {\n const source = normalizeSource(asset.source);\n const variant = normalizeVariant(asset.variant);\n if (asset.platform === \"darwin\") return { ...asset, variant, source };\n if (asset.platform === \"windows\") return { ...asset, variant, source };\n if (asset.format === \"png\") return { ...asset, variant, source };\n return { ...asset, variant, source };\n });\n\n/** Select one semantic variant while retaining every platform's matching native asset. */\nexport const selectAppIconVariant = (\n icon: AppIcon,\n variant: string,\n platform: NodeJS.Platform = process.platform\n): AppIcon => {\n validateVariantName(variant, platform);\n const selected = icon.filter((asset) =>\n normalizedVariantNames(asset.variant).includes(variant)\n );\n const currentPlatform = normalizePlatform(platform);\n if (\n selected.length === 0 ||\n (currentPlatform !== undefined &&\n !selected.some((asset) => asset.platform === currentPlatform))\n ) {\n throw new AppIconVariantNotFoundError(variant, platform);\n }\n return selected;\n};\n\nconst normalizeSource = (source: AppIconSource): AppIconSource =>\n source.type === \"encoded\"\n ? { type: \"encoded\", data: Array.from(source.data) }\n : { type: \"file\", path: resolve(source.path) };\n\nconst normalizeVariant = (\n variant: AppIconVariant | undefined\n): AppIconVariant =>\n variant === undefined\n ? DEFAULT_APP_ICON_VARIANT\n : typeof variant === \"string\"\n ? variant\n : [...variant];\n\nconst normalizedVariantNames = (\n variant: AppIconVariant | undefined\n): readonly string[] =>\n variant === undefined\n ? [DEFAULT_APP_ICON_VARIANT]\n : typeof variant === \"string\"\n ? [variant]\n : variant;\n\nconst validateVariantNames = (\n variant: unknown,\n platform: NodeJS.Platform\n): readonly string[] => {\n const names =\n variant === undefined\n ? [DEFAULT_APP_ICON_VARIANT]\n : typeof variant === \"string\"\n ? [variant]\n : Array.isArray(variant)\n ? variant\n : [];\n if (names.length === 0) {\n throw new InvalidAppIconError(\n \"variant must be a name or non-empty name array\",\n platform\n );\n }\n const seen = new Set<string>();\n for (const name of names) {\n validateVariantName(name, platform);\n if (seen.has(name)) {\n throw new InvalidAppIconError(\n `duplicate variant name ${name} on one asset`,\n platform\n );\n }\n seen.add(name);\n }\n return names;\n};\n\nfunction validateVariantName(\n variant: unknown,\n platform: NodeJS.Platform\n): asserts variant is string {\n if (typeof variant !== \"string\" || !APP_ICON_VARIANT_PATTERN.test(variant)) {\n throw new InvalidAppIconError(\n `variant must match ${APP_ICON_VARIANT_PATTERN}`,\n platform\n );\n }\n}\n\nconst rejectDuplicateVariants = (\n seen: Set<string>,\n variants: readonly string[],\n label: string,\n hostPlatform: NodeJS.Platform\n): void => {\n for (const variant of variants) {\n if (seen.has(variant)) {\n throw new InvalidAppIconError(\n `duplicate ${label} asset for variant ${variant}`,\n hostPlatform\n );\n }\n seen.add(variant);\n }\n};\n\nconst recordVariantPlatforms = (\n variants: Map<string, Set<AppIconPlatform>>,\n names: readonly string[],\n platform: AppIconPlatform\n): void => {\n for (const name of names) {\n const platforms = variants.get(name) ?? new Set<AppIconPlatform>();\n platforms.add(platform);\n variants.set(name, platforms);\n }\n};\n\nconst validateSource = async (\n source: unknown,\n format: \"icns\" | \"ico\" | \"png\" | \"svg\",\n platform: NodeJS.Platform\n): Promise<void> => {\n if (!isRecord(source)) {\n throw new InvalidAppIconError(\n \"asset source must be a file or encoded payload\",\n platform\n );\n }\n let bytes: Uint8Array;\n if (source.type === \"file\") {\n assertExactKeys(source, [\"type\", \"path\"], platform);\n if (typeof source.path !== \"string\" || source.path.trim().length === 0) {\n throw new InvalidAppIconError(\n \"file source path must not be empty\",\n platform\n );\n }\n try {\n bytes = await readFile(source.path);\n } catch (error) {\n throw new InvalidAppIconError(\n `unable to read ${source.path}: ${errorMessage(error)}`,\n platform\n );\n }\n } else if (source.type === \"encoded\") {\n assertExactKeys(source, [\"type\", \"data\"], platform);\n bytes = encodedBytes(source.data, platform);\n } else {\n throw new InvalidAppIconError(\"unsupported app icon source type\", platform);\n }\n if (!matchesFormat(bytes, format)) {\n throw new InvalidAppIconError(\n `source bytes do not contain a valid ${format.toUpperCase()} asset`,\n platform\n );\n }\n};\n\nconst encodedBytes = (data: unknown, platform: NodeJS.Platform): Uint8Array => {\n if (data instanceof Uint8Array && data.byteLength > 0) return data;\n if (\n Array.isArray(data) &&\n data.length > 0 &&\n data.every((value) => Number.isInteger(value) && value >= 0 && value <= 255)\n ) {\n return Uint8Array.from(data);\n }\n throw new InvalidAppIconError(\n \"encoded source must contain one or more bytes in the range 0..255\",\n platform\n );\n};\n\nconst matchesFormat = (\n bytes: Uint8Array,\n format: \"icns\" | \"ico\" | \"png\" | \"svg\"\n): boolean => {\n if (format === \"icns\") return hasPrefix(bytes, [0x69, 0x63, 0x6e, 0x73]);\n if (format === \"ico\") {\n return (\n bytes.length >= 6 && hasPrefix(bytes, [0, 0, 1, 0]) && bytes[4] !== 0\n );\n }\n if (format === \"png\") {\n return hasPrefix(bytes, [137, 80, 78, 71, 13, 10, 26, 10]);\n }\n const source = new TextDecoder()\n .decode(bytes.subarray(0, 4096))\n .replace(/^\\uFEFF/, \"\");\n return /<(?:\\?xml[^>]*>\\s*)?(?:!--[\\s\\S]*?-->\\s*)*svg(?:\\s|>)/i.test(\n source.trimStart()\n );\n};\n\nconst hasPrefix = (bytes: Uint8Array, prefix: readonly number[]): boolean =>\n bytes.length >= prefix.length &&\n prefix.every((byte, index) => bytes[index] === byte);\n\nconst assertExactKeys = (\n record: Record<string, unknown>,\n expected: readonly string[],\n platform: NodeJS.Platform,\n optional: readonly string[] = []\n): void => {\n const actual = Object.keys(record);\n const allowed = new Set([...expected, ...optional]);\n const unexpected = actual.find((key) => !allowed.has(key));\n if (unexpected !== undefined) {\n throw new InvalidAppIconError(\n `unexpected asset field ${unexpected}`,\n platform\n );\n }\n const missing = expected.find((key) => !(key in record));\n if (missing !== undefined) {\n throw new InvalidAppIconError(`missing asset field ${missing}`, platform);\n }\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst errorMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\nconst normalizePlatform = (\n platform: NodeJS.Platform\n): AppIconPlatform | undefined => {\n if (platform === \"darwin\") return \"darwin\";\n if (platform === \"win32\") return \"windows\";\n if (platform === \"linux\") return \"linux\";\n return undefined;\n};\n","// Orthogonal intents (2026-07-19; original user request: pnpm install must be sufficient):\n// 1. Describe package-owned and exact-file native extension artifacts without importing binaries.\n// 2. Resolve platform packages from the declaring facade's dependency closure.\n// 3. Reject missing targets, invalid package metadata, and inaccessible native libraries precisely.\n// 4. Resolve embedded per-target libraries through the staging manifest identity chain with\n// root containment and adversarial rejection (add-ext-dialog section 6.1/section 6.4).\n\nimport { createHash } from \"node:crypto\";\nimport { readFile, realpath } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport type { ExpectedExtensionIdentity } from \"@opentray/spec\";\n\nexport type NativeExtensionArch = \"arm64\" | \"x64\";\nexport type NativeExtensionTarget = `${NodeJS.Platform}-${NativeExtensionArch}`;\n\nexport interface NativeExtensionPackageTarget {\n packageName: string;\n libraryPath: string;\n}\n\nexport interface NativeExtensionIdentitySource {\n packageJsonUrl: string;\n contractManifestUrl: string;\n}\n\nexport interface NativeExtensionPackageArtifact\n extends NativeExtensionIdentitySource {\n kind: \"package\";\n targets: Partial<Record<NativeExtensionTarget, NativeExtensionPackageTarget>>;\n}\n\n/** One embedded per-target library, relative to the facade package root (add-ext-dialog section 6.1). */\nexport interface NativeExtensionEmbeddedTarget {\n libraryPath: string;\n}\n\n/**\n * Frozen embedded staging matrix (add-ext-dialog section 6.4): a facade that\n * embeds platform binaries stages exactly these four targets. The runtime\n * resolver requires the staging manifest to be complete over this matrix\n * (release staging enforces the same set before anything is packed); one\n * missing cell is a manifest-invalid artifact, never a silently thinner\n * catalog.\n */\nexport const NATIVE_EXTENSION_EMBEDDED_TARGET_MATRIX = [\n \"darwin-arm64\",\n \"darwin-x64\",\n \"win32-arm64\",\n \"win32-x64\",\n] as const;\n\n/** One cell of the frozen embedded staging matrix. */\nexport type NativeExtensionEmbeddedMatrixTarget =\n (typeof NATIVE_EXTENSION_EMBEDDED_TARGET_MATRIX)[number];\n\n/**\n * Facade package that ships its platform libraries inside its own tarball via\n * `platforms/<target>/` plus the root-contained staging manifest\n * `platforms/manifest.json` (add-ext-dialog section 6.4 identity chain). No\n * optionalDependencies platform packages are involved. The declared catalog\n * is complete over the frozen matrix: an incomplete embedded catalog is not\n * representable, and the runtime manifest check carries the same\n * completeness rule for untyped consumers.\n */\nexport interface NativeExtensionEmbeddedArtifact\n extends NativeExtensionIdentitySource {\n kind: \"embedded\";\n targets: Record<\n NativeExtensionEmbeddedMatrixTarget,\n NativeExtensionEmbeddedTarget\n >;\n}\n\ninterface NativeExtensionFileArtifactBase {\n kind: \"file\";\n path: string;\n}\n\nexport type NativeExtensionFileArtifact = NativeExtensionFileArtifactBase &\n (\n | {\n expectedIdentity: NativeExtensionExpectedIdentity;\n identitySource?: never;\n }\n | {\n expectedIdentity?: never;\n identitySource: NativeExtensionIdentitySource;\n }\n );\n\nexport type NativeExtensionArtifact =\n | NativeExtensionPackageArtifact\n | NativeExtensionFileArtifact\n | NativeExtensionEmbeddedArtifact;\n\nexport type NativeExtensionExpectedIdentity = ExpectedExtensionIdentity;\n\nexport interface ResolvedNativeExtensionArtifact {\n path: string;\n packageName?: string;\n packageVersion?: string;\n expectedIdentity: NativeExtensionExpectedIdentity;\n target: NativeExtensionTarget;\n}\n\nexport class NativeExtensionArtifactResolutionError extends Error {\n readonly code = \"OPENTRAY_NATIVE_EXTENSION_ARTIFACT_RESOLUTION_FAILED\";\n readonly packageName?: string;\n readonly facadePackageJsonUrl?: string;\n\n constructor(\n message: string,\n readonly target: NativeExtensionTarget,\n options: ErrorOptions & {\n packageName?: string;\n facadePackageJsonUrl?: string;\n } = {}\n ) {\n super(message, options);\n this.name = \"NativeExtensionArtifactResolutionError\";\n if (options.packageName !== undefined) {\n this.packageName = options.packageName;\n }\n if (options.facadePackageJsonUrl !== undefined) {\n this.facadePackageJsonUrl = options.facadePackageJsonUrl;\n }\n }\n}\n\n/**\n * Structured embedded-artifact rejection reasons (add-ext-dialog section 6.1): the\n * four-class replacement of a single resolution-failed error. Consumers match\n * on `reason`/`code`; the human message is not a contract.\n */\nexport type NativeExtensionEmbeddedErrorReason =\n | \"target-unsupported\"\n | \"path-outside-facade\"\n | \"manifest-invalid\"\n | \"library-unreadable\";\n\n/** Stable machine code per embedded rejection reason (same family style as the resolution error). */\nexport const NATIVE_EXTENSION_EMBEDDED_ERROR_CODES: Record<\n NativeExtensionEmbeddedErrorReason,\n string\n> = {\n \"target-unsupported\": \"OPENTRAY_NATIVE_EXTENSION_TARGET_UNSUPPORTED\",\n \"path-outside-facade\": \"OPENTRAY_NATIVE_EXTENSION_PATH_OUTSIDE_FACADE\",\n \"manifest-invalid\": \"OPENTRAY_NATIVE_EXTENSION_MANIFEST_INVALID\",\n \"library-unreadable\": \"OPENTRAY_NATIVE_EXTENSION_LIBRARY_UNREADABLE\",\n};\n\nexport class NativeExtensionEmbeddedArtifactError extends Error {\n readonly reason: NativeExtensionEmbeddedErrorReason;\n readonly code: string;\n readonly target: NativeExtensionTarget;\n readonly facadePackageJsonUrl?: string;\n\n constructor(\n reason: NativeExtensionEmbeddedErrorReason,\n message: string,\n options: ErrorOptions & {\n target: NativeExtensionTarget;\n facadePackageJsonUrl?: string;\n }\n ) {\n super(message, options);\n this.name = \"NativeExtensionEmbeddedArtifactError\";\n this.reason = reason;\n this.code = NATIVE_EXTENSION_EMBEDDED_ERROR_CODES[reason];\n this.target = options.target;\n if (options.facadePackageJsonUrl !== undefined) {\n this.facadePackageJsonUrl = options.facadePackageJsonUrl;\n }\n }\n}\n\n/** Resolve one exact native library from the dependency closure that owns the facade. */\nexport const resolveNativeExtensionArtifact = async (\n artifact: NativeExtensionArtifact,\n platform: NodeJS.Platform = process.platform,\n arch: string = process.arch\n): Promise<ResolvedNativeExtensionArtifact> => {\n const target = nativeExtensionTarget(platform, arch);\n if (artifact.kind === \"file\") {\n return {\n path: await resolveAccessibleLibrary(artifact.path, target),\n expectedIdentity:\n artifact.expectedIdentity ??\n (await resolveExpectedIdentity(artifact.identitySource, target)),\n target,\n };\n }\n\n if (artifact.kind === \"embedded\") {\n return resolveEmbeddedExtensionArtifact(artifact, target);\n }\n\n const packageTarget = artifact.targets[target];\n if (packageTarget === undefined) {\n throw new NativeExtensionArtifactResolutionError(\n `native extension does not support target ${target}`,\n target\n );\n }\n\n const expectedIdentity = await resolveExpectedIdentity(artifact, target);\n\n const resolveFromFacade = createRequire(artifact.packageJsonUrl);\n let platformPackageJsonPath: string;\n try {\n platformPackageJsonPath = resolveFromFacade.resolve(\n `${packageTarget.packageName}/package.json`\n );\n } catch (cause) {\n throw new NativeExtensionArtifactResolutionError(\n `unable to resolve native extension package \"${packageTarget.packageName}\" for ${target} from ${artifact.packageJsonUrl}`,\n target,\n {\n cause,\n packageName: packageTarget.packageName,\n facadePackageJsonUrl: artifact.packageJsonUrl,\n }\n );\n }\n\n const manifest = await readPlatformPackageManifest(\n platformPackageJsonPath,\n target,\n packageTarget.packageName\n );\n const libraryPath = join(dirname(platformPackageJsonPath), packageTarget.libraryPath);\n return {\n path: await resolveAccessibleLibrary(libraryPath, target, packageTarget.packageName),\n packageName: packageTarget.packageName,\n packageVersion: manifest.version,\n expectedIdentity,\n target,\n };\n};\n\nconst resolveExpectedIdentity = async (\n source: NativeExtensionIdentitySource,\n target: NativeExtensionTarget\n): Promise<NativeExtensionExpectedIdentity> => {\n const [facadeManifest, contractManifest] = await Promise.all([\n readFacadePackageManifest(source.packageJsonUrl, target),\n readExtensionContractManifest(source.contractManifestUrl, target),\n ]);\n const [os, arch] = splitTarget(target);\n return {\n extensionName: contractManifest.extensionName,\n artifactSetVersion: facadeManifest.version,\n contractFingerprint: contractManifest.contractFingerprint,\n target: { os, arch },\n };\n};\n\n// ---------------------------------------------------------------------------\n// Embedded artifacts (add-ext-dialog section 6.1/section 6.4): the facade ships its own\n// platform libraries plus a root-contained staging manifest carrying the\n// identity chain (per-target path, SHA-256, buildIdentity, facade version,\n// contract fingerprint). Resolution validates containment on every path,\n// cross-checks the manifest against the facade/contract manifests, hashes the\n// selected library's real bytes, and feeds sha256/buildIdentity into the\n// LoadExt expected identity (the broker re-hashes before dlopen).\n// ---------------------------------------------------------------------------\n\n/** Fixed location of the embedded staging manifest inside the facade package. */\nexport const EMBEDDED_STAGING_MANIFEST_PATH = \"platforms/manifest.json\";\n\ninterface EmbeddedStagingManifestTargetEntry {\n path: string;\n sha256: string;\n buildIdentity: string;\n}\n\ninterface EmbeddedStagingManifest {\n facadeVersion: string;\n contractFingerprint: string;\n targets: Record<string, EmbeddedStagingManifestTargetEntry>;\n}\n\nconst sha256HexPattern = /^[a-f0-9]{64}$/u;\n\nconst isEmbeddedMatrixTarget = (\n target: NativeExtensionTarget\n): target is NativeExtensionEmbeddedMatrixTarget =>\n (NATIVE_EXTENSION_EMBEDDED_TARGET_MATRIX as readonly string[]).includes(target);\n\nconst lexicalContained = (root: string, candidate: string): boolean => {\n const rel = relative(root, candidate);\n if (rel.length === 0) {\n return false;\n }\n return !(rel === \"..\" || rel.startsWith(`..${sep}`) || isAbsolute(rel));\n};\n\nconst resolveEmbeddedExtensionArtifact = async (\n artifact: NativeExtensionEmbeddedArtifact,\n target: NativeExtensionTarget\n): Promise<ResolvedNativeExtensionArtifact> => {\n const facadePackageJsonUrl = artifact.packageJsonUrl;\n const embeddedError = (\n reason: NativeExtensionEmbeddedErrorReason,\n message: string,\n options: { cause?: unknown } = {}\n ): NativeExtensionEmbeddedArtifactError =>\n new NativeExtensionEmbeddedArtifactError(reason, message, {\n target,\n facadePackageJsonUrl,\n ...(options.cause === undefined ? {} : { cause: options.cause }),\n });\n\n // Targets outside the frozen matrix are unsupported platforms for the\n // embedded artifact kind (linux resolves here, for example).\n if (!isEmbeddedMatrixTarget(target)) {\n throw embeddedError(\n \"target-unsupported\",\n `embedded native extension supports only the frozen staging matrix (${NATIVE_EXTENSION_EMBEDDED_TARGET_MATRIX.join(\", \")}); ${target} is outside it`\n );\n }\n const embeddedTarget = artifact.targets[target];\n if (embeddedTarget === undefined) {\n // Unreachable for typed callers (the descriptor is complete over the\n // matrix); untyped consumers still get the structured rejection.\n throw embeddedError(\n \"target-unsupported\",\n `embedded native extension does not declare target ${target}`\n );\n }\n\n const facadeRoot = dirname(fileURLToPath(new URL(facadePackageJsonUrl)));\n\n // Lexical containment first: absolute and traversal (`../../outside`)\n // libraryPath values are rejected before touching the filesystem.\n if (isAbsolute(embeddedTarget.libraryPath)) {\n throw embeddedError(\n \"path-outside-facade\",\n `embedded library path must be relative to the facade package root: ${embeddedTarget.libraryPath}`\n );\n }\n const candidatePath = resolve(facadeRoot, embeddedTarget.libraryPath);\n if (!lexicalContained(facadeRoot, candidatePath)) {\n throw embeddedError(\n \"path-outside-facade\",\n `embedded library path escapes the facade package root: ${embeddedTarget.libraryPath}`\n );\n }\n\n // Identity-chain inputs: facade package.json and contract.json. Any read or\n // shape failure here means the staging identity chain cannot be established.\n const [facadeManifest, contractManifest] = await Promise.all([\n readEmbeddedJson(facadePackageJsonUrl, embeddedError).then((parsed) => {\n if (!isFacadePackageManifest(parsed)) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded facade package manifest is invalid at ${facadePackageJsonUrl}`\n );\n }\n return parsed;\n }),\n readEmbeddedJson(artifact.contractManifestUrl, embeddedError).then((parsed) => {\n if (!isExtensionContractManifest(parsed)) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded extension contract manifest is invalid at ${artifact.contractManifestUrl}`\n );\n }\n return parsed;\n }),\n ]);\n\n const manifestPath = join(facadeRoot, EMBEDDED_STAGING_MANIFEST_PATH);\n const manifest = await readEmbeddedJson(\n pathToFileURL(manifestPath).href,\n embeddedError\n ).then((parsed) => {\n if (!isEmbeddedStagingManifest(parsed)) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest is invalid at ${manifestPath}`\n );\n }\n return parsed;\n });\n\n if (manifest.facadeVersion !== facadeManifest.version) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest facade version ${manifest.facadeVersion} does not match facade package version ${facadeManifest.version}`\n );\n }\n if (manifest.contractFingerprint !== contractManifest.contractFingerprint) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest contract fingerprint does not match the contract manifest at ${artifact.contractManifestUrl}`\n );\n }\n // Manifest completeness over the frozen matrix (section 6.4): every cell\n // must be present, and no key outside the matrix may appear. An incomplete\n // or widened manifest is a staging-chain break, not a thinner catalog.\n for (const matrixTarget of NATIVE_EXTENSION_EMBEDDED_TARGET_MATRIX) {\n if (manifest.targets[matrixTarget] === undefined) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest is missing required matrix target ${matrixTarget}`\n );\n }\n }\n for (const manifestTarget of Object.keys(manifest.targets)) {\n if (!isEmbeddedMatrixTarget(manifestTarget as NativeExtensionTarget)) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest declares target ${manifestTarget} outside the frozen staging matrix`\n );\n }\n if (\n artifact.targets[manifestTarget as NativeExtensionEmbeddedMatrixTarget] ===\n undefined\n ) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest declares undeclared target ${manifestTarget}`\n );\n }\n }\n const manifestEntry = manifest.targets[target];\n if (manifestEntry === undefined) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest has no entry for target ${target}`\n );\n }\n\n if (isAbsolute(manifestEntry.path)) {\n throw embeddedError(\n \"path-outside-facade\",\n `embedded staging manifest library path must be relative to the facade package root: ${manifestEntry.path}`\n );\n }\n const manifestLibraryPath = resolve(facadeRoot, manifestEntry.path);\n if (!lexicalContained(facadeRoot, manifestLibraryPath)) {\n throw embeddedError(\n \"path-outside-facade\",\n `embedded staging manifest library path escapes the facade package root: ${manifestEntry.path}`\n );\n }\n if (manifestLibraryPath !== candidatePath) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded staging manifest path ${manifestEntry.path} does not match the declared library path ${embeddedTarget.libraryPath} for target ${target}`\n );\n }\n\n // Realpath containment catches symlink escapes: a link inside the facade\n // that resolves outside is rejected even though it is lexically contained.\n const realRoot = await realpath(facadeRoot).catch(() => facadeRoot);\n let realCandidate: string;\n try {\n realCandidate = await realpath(candidatePath);\n } catch (cause) {\n throw embeddedError(\n \"library-unreadable\",\n `embedded native extension library is not accessible at ${candidatePath}`,\n { cause }\n );\n }\n if (!lexicalContained(realRoot, realCandidate)) {\n throw embeddedError(\n \"path-outside-facade\",\n `embedded library resolves outside the facade package root: ${embeddedTarget.libraryPath}`\n );\n }\n\n // Hash the real bytes: a replaced library must never pass a manifest claim\n // (the broker re-checks the same value before dlopen).\n let libraryBytes: Buffer;\n try {\n libraryBytes = await readFile(realCandidate);\n } catch (cause) {\n throw embeddedError(\n \"library-unreadable\",\n `embedded native extension library is not readable at ${realCandidate}`,\n { cause }\n );\n }\n const sha256 = createHash(\"sha256\").update(libraryBytes).digest(\"hex\");\n if (sha256 !== manifestEntry.sha256) {\n throw embeddedError(\n \"manifest-invalid\",\n `embedded library bytes do not match the staging manifest SHA-256 for target ${target}`\n );\n }\n\n const [os, arch] = splitTarget(target);\n const expectedIdentity: NativeExtensionExpectedIdentity = {\n extensionName: contractManifest.extensionName,\n artifactSetVersion: facadeManifest.version,\n contractFingerprint: contractManifest.contractFingerprint,\n target: { os, arch },\n sha256,\n buildIdentity: manifestEntry.buildIdentity,\n };\n return { path: realCandidate, expectedIdentity, target };\n};\n\nconst readEmbeddedJson = async (\n url: string,\n embeddedError: (\n reason: NativeExtensionEmbeddedErrorReason,\n message: string,\n options?: { cause?: unknown }\n ) => NativeExtensionEmbeddedArtifactError\n): Promise<unknown> => {\n try {\n return JSON.parse(await readFile(new URL(url), \"utf8\"));\n } catch (cause) {\n throw embeddedError(\n \"manifest-invalid\",\n `unable to read embedded identity-chain manifest at ${url}`,\n { cause }\n );\n }\n};\n\nconst isEmbeddedStagingManifest = (\n value: unknown\n): value is EmbeddedStagingManifest => {\n if (!isRecordLike(value) || !isRecordLike(value.targets)) {\n return false;\n }\n if (\n typeof value.facadeVersion !== \"string\" ||\n typeof value.contractFingerprint !== \"string\"\n ) {\n return false;\n }\n for (const entry of Object.values(value.targets)) {\n if (\n !isRecordLike(entry) ||\n typeof entry.path !== \"string\" ||\n typeof entry.sha256 !== \"string\" ||\n !sha256HexPattern.test(entry.sha256) ||\n typeof entry.buildIdentity !== \"string\" ||\n entry.buildIdentity.length === 0\n ) {\n return false;\n }\n }\n return true;\n};\n\nconst isRecordLike = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst nativeExtensionTarget = (\n platform: NodeJS.Platform,\n arch: string\n): NativeExtensionTarget => {\n if (arch !== \"arm64\" && arch !== \"x64\") {\n throw new Error(`unsupported native extension architecture: ${arch}`);\n }\n return `${platform}-${arch}`;\n};\n\ninterface PlatformPackageManifest {\n name: string;\n version: string;\n os?: string[];\n cpu?: string[];\n}\n\ninterface FacadePackageManifest {\n name: string;\n version: string;\n}\n\ninterface ExtensionContractManifest {\n extensionName: string;\n contractFingerprint: string;\n}\n\nconst readFacadePackageManifest = async (\n packageJsonUrl: string,\n target: NativeExtensionTarget\n): Promise<FacadePackageManifest> => {\n const parsed = await readJsonUrl(packageJsonUrl, target, \"facade package manifest\");\n if (!isFacadePackageManifest(parsed)) {\n throw new NativeExtensionArtifactResolutionError(\n `native extension facade manifest is invalid at ${packageJsonUrl}`,\n target,\n { facadePackageJsonUrl: packageJsonUrl }\n );\n }\n return parsed;\n};\n\nconst readExtensionContractManifest = async (\n contractManifestUrl: string,\n target: NativeExtensionTarget\n): Promise<ExtensionContractManifest> => {\n const parsed = await readJsonUrl(\n contractManifestUrl,\n target,\n \"extension contract manifest\"\n );\n if (!isExtensionContractManifest(parsed)) {\n throw new NativeExtensionArtifactResolutionError(\n `native extension contract manifest is invalid at ${contractManifestUrl}`,\n target\n );\n }\n return parsed;\n};\n\nconst readJsonUrl = async (\n url: string,\n target: NativeExtensionTarget,\n label: string\n): Promise<unknown> => {\n try {\n return JSON.parse(await readFile(new URL(url), \"utf8\"));\n } catch (cause) {\n throw new NativeExtensionArtifactResolutionError(\n `unable to read ${label} at ${url}`,\n target,\n { cause }\n );\n }\n};\n\nconst readPlatformPackageManifest = async (\n packageJsonPath: string,\n target: NativeExtensionTarget,\n packageName: string\n): Promise<PlatformPackageManifest> => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(await readFile(packageJsonPath, \"utf8\"));\n } catch (cause) {\n throw new NativeExtensionArtifactResolutionError(\n `unable to read native extension package manifest at ${packageJsonPath}`,\n target,\n { cause, packageName }\n );\n }\n if (!isPlatformPackageManifest(parsed) || parsed.name !== packageName) {\n throw new NativeExtensionArtifactResolutionError(\n `native extension package manifest at ${packageJsonPath} does not identify ${packageName}`,\n target,\n { packageName }\n );\n }\n const [platform, arch] = splitTarget(target);\n if (parsed.os !== undefined && !parsed.os.includes(platform)) {\n throw new NativeExtensionArtifactResolutionError(\n `native extension package ${packageName} does not support os ${platform}`,\n target,\n { packageName }\n );\n }\n if (parsed.cpu !== undefined && !parsed.cpu.includes(arch)) {\n throw new NativeExtensionArtifactResolutionError(\n `native extension package ${packageName} does not support cpu ${arch}`,\n target,\n { packageName }\n );\n }\n return parsed;\n};\n\nconst isPlatformPackageManifest = (\n value: unknown\n): value is PlatformPackageManifest =>\n typeof value === \"object\" &&\n value !== null &&\n \"name\" in value &&\n typeof value.name === \"string\" &&\n \"version\" in value &&\n typeof value.version === \"string\" &&\n (!(\"os\" in value) ||\n (Array.isArray(value.os) && value.os.every((item) => typeof item === \"string\"))) &&\n (!(\"cpu\" in value) ||\n (Array.isArray(value.cpu) && value.cpu.every((item) => typeof item === \"string\")));\n\nconst isFacadePackageManifest = (value: unknown): value is FacadePackageManifest =>\n typeof value === \"object\" &&\n value !== null &&\n \"name\" in value &&\n typeof value.name === \"string\" &&\n \"version\" in value &&\n typeof value.version === \"string\";\n\nconst isExtensionContractManifest = (\n value: unknown\n): value is ExtensionContractManifest =>\n typeof value === \"object\" &&\n value !== null &&\n \"extensionName\" in value &&\n typeof value.extensionName === \"string\" &&\n \"contractFingerprint\" in value &&\n typeof value.contractFingerprint === \"string\";\n\nconst splitTarget = (\n target: NativeExtensionTarget\n): [NodeJS.Platform, NativeExtensionArch] => {\n const separator = target.lastIndexOf(\"-\");\n return [\n target.slice(0, separator) as NodeJS.Platform,\n target.slice(separator + 1) as NativeExtensionArch,\n ];\n};\n\nconst resolveAccessibleLibrary = async (\n path: string,\n target: NativeExtensionTarget,\n packageName?: string\n): Promise<string> => {\n try {\n return await realpath(path);\n } catch (cause) {\n throw new NativeExtensionArtifactResolutionError(\n `native extension library is not accessible at ${path}`,\n target,\n {\n cause,\n ...(packageName === undefined ? {} : { packageName }),\n }\n );\n }\n};\n","import {\n PROTOCOL_VERSION,\n type AppEvent,\n type ClientFrame,\n type ClientRequestFrame,\n type AppIdentity,\n type AppIcon,\n type ExtensionEnvelope,\n type ExtOperationPayload,\n type Icon,\n type Menu,\n type RequestId,\n type ServerFrame,\n type Tooltip,\n type TrayBoundsResult,\n type TrayEvent,\n type TrayId,\n type TrayOptions,\n} from \"@opentray/spec\";\nimport {\n normalizeAppIcon,\n selectAppIconVariant,\n validateAppIcon,\n} from \"./app-icon\";\n\nimport {\n resolveNativeExtensionArtifact,\n type NativeExtensionArtifact,\n} from \"./native-extension-artifact\";\n\n/**\n * Optional per-call transport budget (W1, harden-transport-robustness): a\n * transport that enforces deadlines settles the call with a typed\n * `TransportTimeoutError` when no correlated reply arrives within\n * `deadlineMs`. The parameter is also the teardown-class marking channel\n * later phases read to keep caller-initiated teardown out of recovery — the\n * budget class, not a new protocol flag, distinguishes the call.\n */\nexport interface TransportRequestOptions {\n /** Per-call deadline budget in milliseconds; transports default to the interactive class. */\n deadlineMs?: number;\n}\n\nexport interface OpenTrayTransport {\n request(frame: ClientRequestFrame, options?: TransportRequestOptions): Promise<ServerFrame>;\n}\n\n/**\n * Default per-call deadline classes (W1, harden-transport-robustness;\n * field-validated against the pnpm-pub silent-wedge incident): interactive\n * calls settle or reject within 5 s, teardown-class frames within 2 s, and\n * bootstrap-class round-trips (connection init and first bring-up) within\n * 10 s. They live beside `OpenTrayTransport` because they are part of the\n * generic transport call contract, not of one broker implementation.\n */\nexport const INTERACTIVE_CALL_DEADLINE_MS = 5_000;\nexport const TEARDOWN_CALL_DEADLINE_MS = 2_000;\nexport const BOOTSTRAP_CALL_DEADLINE_MS = 10_000;\n\n/**\n * Typed per-call deadline rejection: the transport's budget for one\n * round-trip expired without a correlated reply. This is the third\n * rejection class, distinct from transport-lost (the plain\n * `BROKER_CONNECTION_CLOSED_MESSAGE` sentinel family, or the typed\n * `extension_transport_closed` for accepted deferred operations) and from\n * broker-rejected (`BrokerServerError` / `ExtensionOperationError`). An\n * expiry settles exactly one call; it never declares the transport dead —\n * death stays a socket-close/error (and, later, heartbeat) verdict.\n */\nexport class TransportTimeoutError extends Error {\n readonly requestId: RequestId;\n readonly deadlineMs: number;\n\n constructor(requestId: RequestId, deadlineMs: number) {\n super(`transport call deadline expired after ${deadlineMs}ms: ${requestId}`);\n this.name = \"TransportTimeoutError\";\n this.requestId = requestId;\n this.deadlineMs = deadlineMs;\n }\n}\n\nexport type OpenTrayEventFrame = Extract<\n ServerFrame,\n { type: \"event\" | \"app-event\" | \"ext-event\" }\n>;\n\n/**\n * Supervision state vocabulary (W6 Tier 1, harden-transport-robustness):\n * `healthy` (a live generation is serving), `recovering` (uninvited death was\n * declared and in-process recovery is running), `abandoned` (terminal — the\n * recovery budget is exhausted and every later call fails fast with the\n * typed `TransportAbandonedError`). Edge-triggered through\n * `onTransportStateChange`; the initial `healthy` state never fires.\n */\nexport type TransportState = \"healthy\" | \"recovering\" | \"abandoned\";\n\n/**\n * Context handed to a facade rebuild callback after a supervised recovery\n * (W4): the fresh generation number and the new generation's broker session\n * id, so extension facades can re-create session-attributed native state\n * against the live session instead of the dead one.\n */\nexport interface TransportRebuildContext {\n readonly generation: number;\n readonly sessionId: string | undefined;\n}\n\nexport interface OpenTrayEventSource {\n onEvent(listener: (frame: OpenTrayEventFrame) => void): () => void;\n}\n\nexport interface OpenTrayConnection\n extends OpenTrayTransport,\n OpenTrayEventSource {}\n\nexport interface OpenTrayClient {\n createTray(options: TrayOptions): Promise<TrayHandle>;\n}\n\n/**\n * Public result contract of one extension request (add-ext-dialog section\n * 5.1 / section 5.7 ruling #8): immediate commands settle with the response\n * envelopes; deferred commands settle with exactly one terminal frame, whose\n * `result` payload value is surfaced as `value` (an `error` terminal rejects\n * with `ExtensionOperationError` before this type is produced).\n */\nexport type ExtensionRequestResult<TValue = unknown> =\n | { kind: \"immediate\"; events: ExtensionEnvelope[] }\n | { kind: \"terminal\"; operationId: string; value: TValue };\n\n/**\n * Typed rejection for synchronous broker error frames: carries the wire\n * `code`, the structured `details` payload when the error family freezes one,\n * and the transport cause when relevant. Consumers match on `code`; the human\n * `message` is not a contract. The deferred-operation rejection counterpart\n * is `ExtensionOperationError` (same `{ code, message, details }` family).\n */\nexport class BrokerServerError extends Error {\n readonly code: string;\n readonly details?: unknown;\n\n constructor(\n code: string,\n message: string,\n options: { details?: unknown; cause?: unknown } = {}\n ) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = \"BrokerServerError\";\n this.code = code;\n if (options.details !== undefined) {\n this.details = options.details;\n }\n }\n}\n\nexport interface OpenTrayEventfulClient extends OpenTrayClient {\n createTray(options: TrayOptions): Promise<EventfulTrayHandle>;\n}\n\nexport interface TrayHandle {\n trayId: TrayId;\n app: AppHandle;\n getBounds(): Promise<TrayBoundsResult>;\n setMenu(menu: Menu): Promise<void>;\n setTooltip(tooltip: Tooltip): Promise<void>;\n setIcon(icon: Icon): Promise<void>;\n loadExtension(options: ExtensionLoadOptions): Promise<void>;\n commandExtension(ext: string, data: unknown, callOptions?: TransportRequestOptions): Promise<void>;\n requestExtension<TValue = unknown>(\n ext: string,\n data: unknown,\n callOptions?: TransportRequestOptions\n ): Promise<ExtensionRequestResult<TValue>>;\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions\n ): TrayHandle & TCapability;\n destroy(): Promise<void>;\n}\n\nexport interface AppHandle {\n readonly appId: string;\n getName(): Promise<string>;\n setName(name: string): Promise<string>;\n getAppIcon(): Promise<AppIcon | null>;\n getAppIconVariant(): Promise<string | null>;\n setAppIcon(iconOrVariant: AppIcon | string | null): Promise<void>;\n}\n\nexport type TrayScopedEvent = Exclude<TrayEvent, { type: \"ready\" }>;\nexport type TrayEventType = TrayScopedEvent[\"type\"];\nexport type TrayEventByType<TEvent extends TrayEventType> = Extract<\n TrayScopedEvent,\n { type: TEvent }\n>;\n\nexport interface EventfulTrayHandle extends TrayHandle {\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions\n ): EventfulTrayHandle & TCapability;\n listenExtension<TData = unknown>(\n ext: string,\n handler: (event: ExtensionEnvelope<TData>) => void\n ): () => void;\n listen<TEvent extends TrayEventType>(\n event: TEvent,\n handler: (event: TrayEventByType<TEvent>) => void\n ): () => void;\n onMenuClick(\n handler: (event: TrayEventByType<\"menuClick\">) => void\n ): () => void;\n onTrayClick(\n handler: (event: TrayEventByType<\"trayClick\">) => void\n ): () => void;\n onTrayDoubleClick(\n handler: (event: TrayEventByType<\"trayDoubleClick\">) => void\n ): () => void;\n onAppReopenRequested(\n handler: (event: Extract<AppEvent, { type: \"reopenRequested\" }>) => void\n ): () => void;\n /**\n * Terminal broker-connection-death notification (D3,\n * harden-lifecycle-ownership). Present when the transport publishes its own\n * death signal (the local broker connection always does); fires exactly\n * once, after which pending requests have rejected, event delivery has\n * stopped, and every later request rejects instead of hanging.\n */\n onConnectionDead?(handler: (error: Error) => void): () => void;\n /**\n * Tier 1 transport-supervision state projection (W6,\n * harden-transport-robustness). Present when the underlying transport is\n * supervised (the `createTray` runtime path always supervises): fires\n * edge-triggered `healthy | recovering | abandoned` transitions across\n * connection generations; the current value is not replayed.\n */\n onTransportStateChange?(handler: (state: TransportState) => void): () => void;\n /**\n * Facade rebuild registration (W4, harden-transport-robustness). Present\n * on supervised transports: extension facades register one callback that\n * re-creates their declarative native state (windows, styles,\n * subscriptions) after the supervisor recovered a fresh generation.\n * Callbacks run in registration order after the core journal replay.\n */\n registerTransportRebuild?(\n rebuild: (context: TransportRebuildContext) => Promise<void>\n ): void;\n}\n\nexport interface ExtensionLoadOptions {\n name: string;\n artifact: NativeExtensionArtifact;\n mountId?: string;\n}\n\nexport interface TrayExtensionMountSpec {\n name?: string;\n artifact?: NativeExtensionArtifact;\n mountId?: string;\n}\n\nexport interface TrayExtensionContext {\n readonly appId: string;\n readonly trayId: TrayId;\n /**\n * Broker session identity extracted from the connection's Ready frame,\n * when the transport publishes one (the local broker connection sets it\n * after the handshake). Extensions attribute session-owned native state\n * with it — e.g. `@opentray/ext-webview` window owner tuples. Transports\n * without the field stay unattributed and keep legacy semantics.\n */\n readonly sessionId?: string;\n readonly name: string;\n readonly artifact: NativeExtensionArtifact;\n readonly mountId: string;\n ensureLoaded(): Promise<void>;\n command(data: unknown, callOptions?: TransportRequestOptions): Promise<void>;\n request<TValue = unknown>(data: unknown, callOptions?: TransportRequestOptions): Promise<ExtensionRequestResult<TValue>>;\n}\n\nexport interface TrayExtension<\n TCapability extends object,\n TOptions = undefined\n> {\n readonly name: string;\n readonly artifact: NativeExtensionArtifact;\n resolveMount?(options: TOptions | undefined): TrayExtensionMountSpec;\n extend(\n tray: TrayHandle,\n context: TrayExtensionContext,\n options: TOptions | undefined\n ): TCapability;\n}\n\nexport const createInitFrame = (clientVersion: string): ClientFrame => ({\n type: \"init\",\n protocolVersion: PROTOCOL_VERSION,\n clientVersion,\n});\n\nexport interface CreateClientOptions {\n requestIdPrefix?: string;\n appOptions?: {\n name?: string;\n appIcon?: AppIcon;\n };\n}\n\nexport function createClient(\n transport: OpenTrayConnection,\n options?: CreateClientOptions\n): OpenTrayEventfulClient;\nexport function createClient(\n transport: OpenTrayTransport,\n options?: CreateClientOptions\n): OpenTrayClient;\nexport function createClient(\n transport: OpenTrayTransport,\n options: CreateClientOptions = {}\n): OpenTrayClient | OpenTrayEventfulClient {\n const nextRequestId = createRequestIdFactory(\n options.requestIdPrefix ?? \"opentray\"\n );\n let appPromise: Promise<{ app: { appId: string }; handle: AppHandle }> | undefined;\n\n const ensureApp = async (\n trayOptions: TrayOptions\n ): Promise<{ app: { appId: string }; handle: AppHandle }> => {\n appPromise ??= (async () => {\n const app = await resolveDefaultAppRef(transport, nextRequestId);\n const handle = createAppHandle(transport, app.appId, nextRequestId);\n const configured = options.appOptions;\n if (configured?.name !== undefined) {\n await handle.setName(configured.name);\n }\n if (configured?.appIcon !== undefined) {\n await handle.setAppIcon(configured.appIcon);\n }\n return { app, handle };\n })().catch((error: unknown) => {\n appPromise = undefined;\n throw error;\n });\n return appPromise;\n };\n\n return {\n async createTray(options: TrayOptions): Promise<TrayHandle> {\n const { app } = await ensureApp(options);\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"create-tray\",\n requestId,\n app,\n tray: options,\n });\n const frame = expectResponse(response, requestId, \"tray-created\");\n return createTrayHandle(\n transport,\n app.appId,\n frame.trayId ?? options.id,\n nextRequestId\n );\n },\n };\n}\n\nexport function createTrayHandle(\n transport: OpenTrayConnection,\n appId: string,\n trayId: TrayId,\n nextRequestId?: () => RequestId\n): EventfulTrayHandle;\nexport function createTrayHandle(\n transport: OpenTrayTransport,\n appId: string,\n trayId: TrayId,\n nextRequestId?: () => RequestId\n): TrayHandle;\nexport function createTrayHandle(\n transport: OpenTrayTransport,\n appId: string,\n trayId: TrayId,\n nextRequestId: () => RequestId = createRequestIdFactory(\"opentray\")\n): TrayHandle | EventfulTrayHandle {\n // The local broker connection publishes the Ready frame's session id on\n // the transport itself (after init); read it once here so extension\n // contexts can attribute session-owned state (ext-webview owner tuples).\n const sessionId = readTransportSessionId(transport);\n let nextMountOrdinal = 1;\n const nextMountId = (extensionName: string): string => {\n const mountId = `${formatMountIdComponent(\n extensionName\n )}.${formatMountIdComponent(trayId)}.${nextMountOrdinal}`;\n nextMountOrdinal += 1;\n return mountId;\n };\n const handle: TrayHandle = {\n trayId,\n app: createAppHandle(transport, appId, nextRequestId),\n async getBounds(): Promise<TrayBoundsResult> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"get-tray-bounds\",\n requestId,\n appId,\n trayId,\n });\n return expectResponse(response, requestId, \"tray-bounds\").bounds;\n },\n async setMenu(menu: Menu): Promise<void> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-tray-menu\",\n requestId,\n appId,\n trayId,\n menu,\n });\n expectResponse(response, requestId, \"ack\");\n },\n async setTooltip(tooltip: Tooltip): Promise<void> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-tray-tooltip\",\n requestId,\n appId,\n trayId,\n tooltip,\n });\n expectResponse(response, requestId, \"ack\");\n },\n async setIcon(icon: Icon): Promise<void> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-tray-icon\",\n requestId,\n appId,\n trayId,\n icon,\n });\n expectResponse(response, requestId, \"ack\");\n },\n async loadExtension(options): Promise<void> {\n const requestId = nextRequestId();\n const resolved = await resolveNativeExtensionArtifact(options.artifact);\n const response = await transport.request({\n type: \"load-ext\",\n requestId,\n appId,\n name: options.name,\n path: resolved.path,\n expectedIdentity: resolved.expectedIdentity,\n ...(options.mountId === undefined ? {} : { mountId: options.mountId }),\n });\n expectResponse(response, requestId, \"ack\");\n },\n async commandExtension(ext: string, data: unknown, callOptions?: TransportRequestOptions): Promise<void> {\n await this.requestExtension(ext, data, callOptions);\n },\n async requestExtension<TValue = unknown>(\n ext: string,\n data: unknown,\n callOptions?: TransportRequestOptions\n ): Promise<ExtensionRequestResult<TValue>> {\n const requestId = nextRequestId();\n const response = await transport.request(\n {\n type: \"ext-command\",\n requestId,\n appId,\n trayId,\n ext,\n data,\n },\n callOptions,\n );\n if (response.type === \"ack\") {\n expectResponse(response, requestId, \"ack\");\n return { kind: \"immediate\", events: [] };\n }\n // A successful deferred terminal settles here: the transport correlates\n // the terminal through the operation map (no requestId on the wire) and\n // an `error` terminal has already rejected with ExtensionOperationError.\n if (response.type === \"ext-operation-terminal\") {\n const payload: ExtOperationPayload = response.payload;\n if (payload.kind !== \"result\") {\n // Defensive only: transports reject error terminals themselves, so a\n // typed error payload reaching this branch is a transport contract\n // violation, not a user-visible deferred failure.\n throw new Error(\n `transport settled a deferred request with an error terminal for ${requestId}`\n );\n }\n return { kind: \"terminal\", operationId: response.operationId, value: payload.value as TValue };\n }\n const result = expectResponse(response, requestId, \"ext-command-result\");\n return { kind: \"immediate\", events: result.events };\n },\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions\n ): TrayHandle & TCapability {\n const context = createTrayExtensionContext(\n handle,\n appId,\n extension,\n options,\n nextMountId,\n sessionId\n );\n const capability = extension.extend(handle, context, options);\n return Object.assign({}, handle, capability);\n },\n async destroy(): Promise<void> {\n const requestId = nextRequestId();\n // Teardown-class budget (W3, harden-transport-robustness): the\n // transport-level deadline bounds this round-trip so a wedged broker can\n // never wedge consumer shutdown; no application-layer race wraps it.\n // `deadlineMs` doubles as the teardown-class marker later phases read to\n // keep caller-initiated teardown from ever triggering recovery.\n const response = await transport.request(\n {\n type: \"destroy-tray\",\n requestId,\n appId,\n trayId,\n },\n { deadlineMs: TEARDOWN_CALL_DEADLINE_MS },\n );\n expectResponse(response, requestId, \"ack\");\n },\n };\n if (!isOpenTrayEventSource(transport)) {\n return handle;\n }\n return attachEventfulTrayHandle(handle, transport, appId, nextMountId, sessionId);\n};\n\nconst attachEventfulTrayHandle = (\n handle: TrayHandle,\n source: OpenTrayEventSource,\n appId: string,\n nextMountId: (extensionName: string) => string,\n sessionId: string | undefined\n): EventfulTrayHandle => {\n const listen: EventfulTrayHandle[\"listen\"] = (event, handler) =>\n source.onEvent((frame) => {\n if (frame.type !== \"event\" || frame.event.type !== event) {\n return;\n }\n if (!isOwnedTrayEvent(frame.event, appId, handle.trayId)) {\n return;\n }\n handler(frame.event as TrayEventByType<typeof event>);\n });\n\n // D3: surface the transport's terminal death signal when it publishes one,\n // so eventful consumers and extensions observe broker death instead of\n // silently losing delivery.\n const onConnectionDead = isConnectionDeadSource(source)\n ? (handler: (error: Error) => void) => source.onConnectionDead(handler)\n : undefined;\n\n // W6/W4: surface the supervision state projection and the facade rebuild\n // registration when the transport is supervised (the createTray runtime\n // path always is). Same structural-capability pattern as onConnectionDead.\n const transportSupervision = isTransportSupervisionSource(source)\n ? {\n onTransportStateChange: (handler: (state: TransportState) => void) =>\n source.onTransportStateChange(handler),\n registerTransportRebuild: (rebuild: (context: TransportRebuildContext) => Promise<void>) =>\n source.registerTransportRebuild(rebuild),\n }\n : undefined;\n\n const eventful: EventfulTrayHandle = {\n ...handle,\n ...(onConnectionDead === undefined ? {} : { onConnectionDead }),\n ...(transportSupervision === undefined ? {} : transportSupervision),\n listenExtension<TData = unknown>(\n ext: string,\n handler: (event: ExtensionEnvelope<TData>) => void\n ) {\n return source.onEvent((frame) => {\n if (frame.type !== \"ext-event\" || frame.ext !== ext) {\n return;\n }\n if (frame.appId !== appId || frame.trayId !== handle.trayId) {\n return;\n }\n handler({\n scope: { appId: frame.appId, trayId: frame.trayId, ext: frame.ext },\n data: frame.data as TData,\n });\n });\n },\n listen,\n onMenuClick(handler) {\n return listen(\"menuClick\", handler);\n },\n onTrayClick(handler) {\n return listen(\"trayClick\", handler);\n },\n onTrayDoubleClick(handler) {\n return listen(\"trayDoubleClick\", handler);\n },\n onAppReopenRequested(handler) {\n return source.onEvent((frame) => {\n if (\n frame.type === \"app-event\" &&\n frame.event.type === \"reopenRequested\" &&\n frame.event.appId === appId\n ) {\n handler(frame.event);\n }\n });\n },\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions\n ): EventfulTrayHandle & TCapability {\n const context = createTrayExtensionContext(\n eventful,\n appId,\n extension,\n options,\n nextMountId,\n sessionId\n );\n const capability = extension.extend(eventful, context, options);\n return Object.assign({}, eventful, capability);\n },\n };\n return eventful;\n};\n\nconst isOwnedTrayEvent = (\n event: TrayEvent,\n appId: string,\n trayId: string\n): event is TrayScopedEvent =>\n event.type !== \"ready\" && event.appId === appId && event.trayId === trayId;\n\nconst isOpenTrayEventSource = (\n transport: OpenTrayTransport\n): transport is OpenTrayConnection =>\n \"onEvent\" in transport && typeof transport.onEvent === \"function\";\n\n/** Structural view of transports that publish a terminal death signal (D3). */\ninterface ConnectionDeadSourceTransport {\n onConnectionDead(handler: (error: Error) => void): () => void;\n}\n\nconst isConnectionDeadSource = (\n transport: OpenTrayEventSource\n): transport is OpenTrayEventSource & ConnectionDeadSourceTransport =>\n \"onConnectionDead\" in transport &&\n typeof transport.onConnectionDead === \"function\";\n\n/** Structural view of supervised transports (W4/W6 supervision seams). */\ninterface TransportSupervisionSourceTransport {\n onTransportStateChange(handler: (state: TransportState) => void): () => void;\n registerTransportRebuild(\n rebuild: (context: TransportRebuildContext) => Promise<void>\n ): void;\n}\n\nconst isTransportSupervisionSource = (\n transport: OpenTrayEventSource\n): transport is OpenTrayEventSource & TransportSupervisionSourceTransport =>\n \"onTransportStateChange\" in transport &&\n typeof transport.onTransportStateChange === \"function\" &&\n \"registerTransportRebuild\" in transport &&\n typeof transport.registerTransportRebuild === \"function\";\n\nconst resolveDefaultAppRef = async (\n transport: OpenTrayTransport,\n nextRequestId: () => RequestId\n): Promise<{ appId: string }> => {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"resolve-default-app\",\n requestId,\n });\n return expectResponse(response, requestId, \"default-app\").app;\n};\n\nconst createAppHandle = (\n transport: OpenTrayTransport,\n appId: string,\n nextRequestId: () => RequestId\n): AppHandle => {\n const requestIdentity = async (): Promise<AppIdentity> => {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"get-app-identity\",\n requestId,\n appId,\n });\n return expectResponse(response, requestId, \"app-identity\").identity;\n };\n return {\n appId,\n async getName(): Promise<string> {\n return (await requestIdentity()).appName;\n },\n async setName(name: string): Promise<string> {\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-app-name\",\n requestId,\n appId,\n name,\n });\n expectResponse(response, requestId, \"ack\");\n return (await requestIdentity()).appName;\n },\n async getAppIcon(): Promise<AppIcon | null> {\n return (await requestIdentity()).appIcon ?? null;\n },\n async getAppIconVariant(): Promise<string | null> {\n return (await requestIdentity()).appIconVariant ?? null;\n },\n async setAppIcon(iconOrVariant: AppIcon | string | null): Promise<void> {\n if (typeof iconOrVariant === \"string\") {\n const identity = await requestIdentity();\n if (identity.appIcon === undefined) {\n selectAppIconVariant([], iconOrVariant);\n } else {\n selectAppIconVariant(identity.appIcon, iconOrVariant);\n }\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-app-icon-variant\",\n requestId,\n appId,\n variant: iconOrVariant,\n });\n expectResponse(response, requestId, \"ack\");\n return;\n }\n if (iconOrVariant !== null) await validateAppIcon(iconOrVariant);\n const appIcon =\n iconOrVariant === null ? null : normalizeAppIcon(iconOrVariant);\n const requestId = nextRequestId();\n const response = await transport.request({\n type: \"set-app-icon\",\n requestId,\n appId,\n appIcon,\n });\n expectResponse(response, requestId, \"ack\");\n },\n };\n};\n\nconst createTrayExtensionContext = <TCapability extends object, TOptions>(\n tray: TrayHandle,\n appId: string,\n extension: TrayExtension<TCapability, TOptions>,\n options: TOptions | undefined,\n nextMountId: (extensionName: string) => string,\n sessionId?: string\n): TrayExtensionContext => {\n const mount = extension.resolveMount?.(options) ?? {};\n const name = mount.name ?? extension.name;\n const artifact = mount.artifact ?? extension.artifact;\n const mountId = mount.mountId ?? nextMountId(name);\n let loadPromise: Promise<void> | undefined;\n\n const ensureLoaded = async (): Promise<void> => {\n if (loadPromise === undefined) {\n // Package-manager resolution stays in Node; the broker receives one exact file.\n loadPromise = tray\n .loadExtension({ name, artifact, mountId })\n .catch((error: unknown) => {\n loadPromise = undefined;\n throw error;\n });\n }\n await loadPromise;\n };\n\n return {\n appId,\n trayId: tray.trayId,\n ...(sessionId === undefined ? {} : { sessionId }),\n name,\n artifact,\n mountId,\n ensureLoaded,\n async command(data: unknown, callOptions?: TransportRequestOptions): Promise<void> {\n await ensureLoaded();\n await tray.commandExtension(mountId, data, callOptions);\n },\n async request<TValue = unknown>(\n data: unknown,\n callOptions?: TransportRequestOptions\n ): Promise<ExtensionRequestResult<TValue>> {\n await ensureLoaded();\n return tray.requestExtension<TValue>(mountId, data, callOptions);\n },\n };\n};\n\n/** Structural view of transports that publish the Ready frame's session id. */\ninterface SessionIdBearingTransport {\n readonly sessionId?: unknown;\n}\n\nconst readTransportSessionId = (\n transport: OpenTrayTransport\n): string | undefined => {\n const { sessionId } = transport as SessionIdBearingTransport;\n return typeof sessionId === \"string\" && sessionId.length > 0 ? sessionId : undefined;\n};\n\nconst formatMountIdComponent = (value: string): string => {\n const formatted = value.replaceAll(/[^a-zA-Z0-9._+-]/g, \"_\");\n return formatted.length > 0 ? formatted : \"ext\";\n};\n\nconst createRequestIdFactory = (prefix: string): (() => RequestId) => {\n let next = 1;\n return () => {\n const requestId = `${prefix}-${next}`;\n next += 1;\n return requestId;\n };\n};\n\nconst expectResponse = <TType extends ServerFrame[\"type\"]>(\n frame: ServerFrame,\n requestId: RequestId,\n type: TType\n): Extract<ServerFrame, { type: TType }> => {\n if (frame.type === \"error\") {\n // Synchronous broker errors share the typed `{ code, message, details }`\n // family with deferred terminal errors (add-ext-dialog section 7.5).\n throw new BrokerServerError(frame.code, frame.message, {\n details: frame.details,\n });\n }\n if (frame.type !== type) {\n throw new Error(\n `expected ${type} for ${requestId}, received ${frame.type}`\n );\n }\n if (requestIdOf(frame) !== requestId) {\n throw new Error(\n `expected response for ${requestId}, received ${\n requestIdOf(frame) ?? \"none\"\n }`\n );\n }\n return frame as Extract<ServerFrame, { type: TType }>;\n};\n\nconst requestIdOf = (frame: ServerFrame): RequestId | undefined => {\n switch (frame.type) {\n case \"app-created\":\n case \"default-app\":\n case \"app-identity\":\n case \"tray-created\":\n case \"tray-bounds\":\n case \"ack\":\n case \"ext-command-result\":\n case \"runtime-host-health\":\n return frame.requestId;\n case \"error\":\n return frame.requestId;\n // Deferred-transaction frames never correlate through requestId here:\n // acceptance settles nothing and the terminal frame has no requestId\n // (the local broker connection correlates it through the operation map).\n case \"ext-command-accepted\":\n case \"ext-operation-terminal\":\n case \"ready\":\n case \"event\":\n case \"app-event\":\n case \"ext-event\":\n return undefined;\n }\n};\n","import { basename } from \"node:path\";\n\nimport { sanitizeCallerLabel } from \"@opentray/spec\";\n\nexport interface CallerLabelSources {\n /** Explicit developer-provided label, highest precedence. */\n readonly explicit?: string;\n /**\n * Caller-supplied app identity (`createTray` runtime `appId`). Endpoint\n * identity for app-style consumers: same app, same broker, every launch\n * method. Normalized to the same filesystem-safe slug space as the other\n * sources. Display names (`appName`) never participate (D4,\n * harden-lifecycle-ownership).\n */\n readonly appId?: string;\n /** `npm_package_name` environment value. */\n readonly npmPackageName?: string;\n /** Script path resolved from `process.argv[1]` or equivalent. */\n readonly scriptPath?: string;\n}\n\nexport interface ResolveCallerLabelOptions extends Partial<CallerLabelSources> {\n env?: NodeJS.ProcessEnv;\n argv?: readonly string[];\n}\n\n/**\n * Derives a caller label using the precedence: explicit > appId slug >\n * npm_package_name > script basename > neutral default. The result is always\n * sanitized to a filesystem- and process-safe component, so callers can use it\n * directly in endpoint identity, runtime directories, and process titles.\n */\nexport const resolveCallerLabel = (options: ResolveCallerLabelOptions = {}): string => {\n const env = options.env ?? process.env;\n const argv = options.argv ?? process.argv;\n\n const candidates: string[] = [];\n if (options.explicit !== undefined && options.explicit.length > 0) {\n candidates.push(options.explicit);\n }\n if (options.appId !== undefined && options.appId.length > 0) {\n candidates.push(options.appId);\n }\n const npmName = options.npmPackageName ?? env.npm_package_name;\n if (typeof npmName === \"string\" && npmName.length > 0) {\n candidates.push(npmName);\n }\n const scriptPath = options.scriptPath ?? argv[1];\n if (typeof scriptPath === \"string\" && scriptPath.length > 0) {\n candidates.push(basename(scriptPath));\n }\n\n for (const candidate of candidates) {\n const sanitized = sanitizeCallerLabel(candidate);\n if (sanitized.length > 0) {\n return sanitized;\n }\n }\n\n return sanitizeCallerLabel(undefined);\n};\n","import type { BrokerArtifactTarget } from \"@opentray/spec\";\n\nexport type BrokerPackageOs = \"darwin\" | \"linux\" | \"windows\";\nexport type BrokerArch = \"arm64\" | \"x64\";\n\nexport interface BrokerNativeTarget {\n packageName: string;\n binaryRelativePath: string;\n carrierTemplateRelativePath?: string;\n}\n\nexport const resolveBrokerNativeTarget = (\n platform: string = process.platform,\n arch: string = process.arch,\n): BrokerNativeTarget => {\n const packageOs = platformToPackageOs(platform);\n const nativeArch = normalizeArch(arch);\n return {\n packageName: `@opentray/${packageOs}-${nativeArch}`,\n binaryRelativePath: `bin/${packageOs === \"windows\" ? \"opentray.exe\" : \"opentray\"}`,\n ...(packageOs === \"darwin\"\n ? { carrierTemplateRelativePath: \"app/Info.plist\" }\n : {}),\n };\n};\n\nexport const resolveBrokerArtifactTarget = (\n platform: string = process.platform,\n arch: string = process.arch,\n): BrokerArtifactTarget => {\n const packageOs = platformToPackageOs(platform);\n return {\n os: packageOs === \"windows\" ? \"win32\" : packageOs,\n arch: normalizeArch(arch),\n };\n};\n\nconst platformToPackageOs = (platform: string): BrokerPackageOs => {\n switch (platform) {\n case \"darwin\":\n case \"linux\":\n return platform;\n case \"win32\":\n return \"windows\";\n default:\n throw new MissingPlatformBrokerBinaryError(\n `unsupported OpenTray broker platform: ${platform}`,\n platform,\n process.arch,\n );\n }\n};\n\nconst normalizeArch = (arch: string): BrokerArch => {\n switch (arch) {\n case \"arm64\":\n case \"x64\":\n return arch;\n default:\n throw new MissingPlatformBrokerBinaryError(\n `unsupported OpenTray broker architecture: ${arch}`,\n process.platform,\n arch,\n );\n }\n};\n\nexport class MissingPlatformBrokerBinaryError extends Error {\n readonly code = \"OPENTRAY_MISSING_PLATFORM_BROKER_BINARY\";\n readonly platform: string;\n readonly arch: string;\n readonly packageName: string | undefined;\n readonly binaryPath: string | undefined;\n\n constructor(\n message: string,\n platform: string,\n arch: string,\n options: {\n packageName?: string;\n binaryPath?: string;\n cause?: unknown;\n } = {},\n ) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = \"MissingPlatformBrokerBinaryError\";\n this.platform = platform;\n this.arch = arch;\n this.packageName = options.packageName;\n this.binaryPath = options.binaryPath;\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { access, appendFile, mkdir, readFile, realpath } from \"node:fs/promises\";\nimport { constants } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { spawn } from \"node:child_process\";\n\nimport type { BrokerArtifactIdentity } from \"@opentray/spec\";\nimport type { AppIcon } from \"@opentray/spec\";\nimport { generateDefaultAppIcon } from \"@opentray/icon\";\nimport {\n ensureDarwinAppBundle,\n type OpenTrayAppBundleOptions,\n type OpenTrayPackageIdentity,\n} from \"@opentray/packaging\";\n\nimport type { DaemonPaths } from \"./paths\";\nimport {\n type BrokerNativeTarget,\n MissingPlatformBrokerBinaryError,\n resolveBrokerArtifactTarget,\n resolveBrokerNativeTarget,\n} from \"./native-target\";\n\nexport interface BrokerCommand {\n command: string;\n args: string[];\n cwd?: string;\n}\n\nexport interface ResolvedBrokerArtifact extends BrokerCommand {\n executablePath: string;\n artifactIdentity: BrokerArtifactIdentity;\n}\n\nconst sourceUrl = import.meta.url;\nconst requireFromSource = createRequire(sourceUrl);\n\nexport interface InstalledBrokerBinaryResolution {\n binary?: string;\n binaryPath?: string;\n carrierTemplate?: string;\n carrierTemplatePath?: string;\n}\n\nexport interface ResolveInstalledBrokerBinaryOptions {\n platform?: NodeJS.Platform;\n resolvePackageJson?: (specifier: string) => string;\n assertBinaryAccessible?: (binaryPath: string, platform: NodeJS.Platform) => Promise<void>;\n assertCarrierAccessible?: (carrierPath: string) => Promise<void>;\n}\n\nexport interface ResolveBrokerCommandOptions {\n env?: NodeJS.ProcessEnv;\n platform?: NodeJS.Platform;\n arch?: string;\n sourceDir?: string;\n resolveInstalledBrokerBinary?: (\n target: BrokerNativeTarget,\n options: ResolveInstalledBrokerBinaryOptions,\n ) => Promise<InstalledBrokerBinaryResolution>;\n findWorkspaceRoot?: (start: string) => Promise<string | undefined>;\n ensureDevBrokerBinary?: (\n workspaceRoot: string,\n paths: DaemonPaths,\n platform: NodeJS.Platform,\n ) => Promise<string>;\n ensureDevDarwinCarrierTemplate?: (\n workspaceRoot: string,\n paths: DaemonPaths,\n ) => Promise<string>;\n appBundle?: OpenTrayAppBundleOptions & { readonly path: string };\n appIcon?: AppIcon;\n packageIdentity?: OpenTrayPackageIdentity;\n}\n\nexport interface ResolveBrokerArtifactOptions extends ResolveBrokerCommandOptions {\n resolveExecutablePath?: (path: string) => Promise<string>;\n readExecutable?: (path: string) => Promise<Uint8Array>;\n}\n\nexport const resolveBrokerArtifact = async (\n paths: DaemonPaths,\n options: ResolveBrokerArtifactOptions = {},\n): Promise<ResolvedBrokerArtifact> => {\n const command = await resolveBrokerCommand(paths, options);\n const executablePath = await (options.resolveExecutablePath ?? realpath)(command.command);\n const bytes = await (options.readExecutable ?? readFile)(executablePath);\n const executableHash = createHash(\"sha256\").update(bytes).digest(\"hex\");\n const artifactIdentity: BrokerArtifactIdentity = {\n packageVersion: paths.packageVersion,\n target: resolveBrokerArtifactTarget(\n options.platform ?? process.platform,\n options.arch ?? process.arch,\n ),\n executableHash,\n buildIdentity: `sha256:${executableHash.slice(0, 16)}`,\n };\n return {\n ...command,\n command: executablePath,\n args: [\n ...command.args,\n \"--broker-executable-path\",\n executablePath,\n \"--broker-artifact-identity\",\n JSON.stringify(artifactIdentity),\n ],\n executablePath,\n artifactIdentity,\n };\n};\n\nexport const resolveBrokerCommand = async (\n paths: DaemonPaths,\n options: ResolveBrokerCommandOptions = {},\n): Promise<BrokerCommand> => {\n const env = options.env ?? process.env;\n const platform = options.platform ?? process.platform;\n const arch = options.arch ?? process.arch;\n const explicit = env.OPENTRAY_BROKER_BIN;\n if (explicit !== undefined && explicit.length > 0) {\n if (platform !== \"darwin\" || options.appBundle === undefined) {\n return commandForBinary(explicit, paths);\n }\n const templatePath = await resolveExplicitDarwinCarrierTemplate(paths, options, platform, arch);\n const binary = await ensureDarwinBundle(options, paths, explicit, templatePath);\n return commandForBinary(binary, paths);\n }\n\n const target = resolveBrokerNativeTarget(platform, arch);\n const installed = await (options.resolveInstalledBrokerBinary ?? resolveInstalledBrokerBinary)(\n target,\n { platform },\n );\n if (installed.binary !== undefined) {\n if (platform !== \"darwin\") return commandForBinary(installed.binary, paths);\n if (options.appBundle === undefined) return commandForBinary(installed.binary, paths);\n if (installed.carrierTemplate === undefined) {\n throw missingDarwinCarrierError(target, installed, arch);\n }\n const binary = await ensureDarwinBundle(options, paths, installed.binary, installed.carrierTemplate);\n return commandForBinary(binary, paths);\n }\n\n const sourceDir = options.sourceDir ?? dirname(fileURLToPath(sourceUrl));\n const workspaceRoot = await (options.findWorkspaceRoot ?? findWorkspaceRoot)(sourceDir);\n if (workspaceRoot !== undefined) {\n const binary = await (options.ensureDevBrokerBinary ?? ensureDevBrokerBinary)(\n workspaceRoot,\n paths,\n platform,\n );\n if (platform !== \"darwin\") return commandForBinary(binary, paths);\n const carrierBinary =\n options.appBundle === undefined\n ? binary\n : await ensureDarwinBundle(\n options,\n paths,\n binary,\n await (\n options.ensureDevDarwinCarrierTemplate ?? ensureDevDarwinCarrierTemplate\n )(workspaceRoot, paths),\n );\n return commandForBinary(carrierBinary, paths);\n }\n\n throw new MissingPlatformBrokerBinaryError(\n installed.binaryPath === undefined\n ? `unable to resolve OpenTray broker binary for ${platform}/${arch}; install \"${target.packageName}\" for this platform or set OPENTRAY_BROKER_BIN`\n : `unable to resolve OpenTray broker binary for ${platform}/${arch}; package \"${target.packageName}\" was found but binary \"${installed.binaryPath}\" is not accessible; restage the runtime package or set OPENTRAY_BROKER_BIN`,\n platform,\n arch,\n {\n packageName: target.packageName,\n ...(installed.binaryPath === undefined ? {} : { binaryPath: installed.binaryPath }),\n },\n );\n};\n\nconst resolveExplicitDarwinCarrierTemplate = async (\n paths: DaemonPaths,\n options: ResolveBrokerCommandOptions,\n platform: NodeJS.Platform,\n arch: string,\n): Promise<string> => {\n const sourceDir = options.sourceDir ?? dirname(fileURLToPath(sourceUrl));\n const workspaceRoot = await (options.findWorkspaceRoot ?? findWorkspaceRoot)(sourceDir);\n if (workspaceRoot !== undefined) {\n return (\n options.ensureDevDarwinCarrierTemplate ?? ensureDevDarwinCarrierTemplate\n )(workspaceRoot, paths);\n }\n\n const target = resolveBrokerNativeTarget(platform, arch);\n const installed = await (options.resolveInstalledBrokerBinary ?? resolveInstalledBrokerBinary)(\n target,\n { platform },\n );\n if (installed.carrierTemplate !== undefined) {\n return installed.carrierTemplate;\n }\n throw missingDarwinCarrierError(target, installed, arch);\n};\n\nexport const resolveInstalledBrokerBinary = async (\n target: BrokerNativeTarget,\n options: ResolveInstalledBrokerBinaryOptions = {},\n): Promise<InstalledBrokerBinaryResolution> => {\n const platform = options.platform ?? process.platform;\n let packageJsonPath: string;\n try {\n packageJsonPath = (\n options.resolvePackageJson ?? requireFromSource.resolve.bind(requireFromSource)\n )(`${target.packageName}/package.json`);\n } catch (error) {\n if (isNodeError(error) && error.code === \"MODULE_NOT_FOUND\") {\n return {};\n }\n throw error;\n }\n\n const binaryPath = join(dirname(packageJsonPath), target.binaryRelativePath);\n const carrierTemplatePath =\n target.carrierTemplateRelativePath === undefined\n ? undefined\n : join(dirname(packageJsonPath), target.carrierTemplateRelativePath);\n let carrierTemplate: string | undefined;\n if (carrierTemplatePath !== undefined) {\n try {\n await (options.assertCarrierAccessible ?? assertInstalledCarrierAccessible)(\n carrierTemplatePath,\n );\n carrierTemplate = carrierTemplatePath;\n } catch (error) {\n if (\n !isNodeError(error) ||\n (error.code !== \"ENOENT\" && error.code !== \"EACCES\" && error.code !== \"EPERM\")\n ) {\n throw error;\n }\n }\n }\n try {\n await (options.assertBinaryAccessible ?? assertInstalledBrokerBinaryAccessible)(\n binaryPath,\n platform,\n );\n return {\n binary: binaryPath,\n binaryPath,\n ...(carrierTemplatePath === undefined ? {} : { carrierTemplatePath }),\n ...(carrierTemplate === undefined ? {} : { carrierTemplate }),\n };\n } catch (error) {\n if (\n isNodeError(error) &&\n (error.code === \"ENOENT\" || error.code === \"EACCES\" || error.code === \"EPERM\")\n ) {\n return {\n binaryPath,\n ...(carrierTemplatePath === undefined ? {} : { carrierTemplatePath }),\n ...(carrierTemplate === undefined ? {} : { carrierTemplate }),\n };\n }\n throw error;\n }\n};\n\nconst commandForBinary = (binary: string, paths: DaemonPaths, cwd?: string): BrokerCommand => {\n const command: BrokerCommand = {\n command: binary,\n args: [\n \"broker\",\n \"--endpoint\",\n paths.endpoint,\n \"--ready-file\",\n paths.readyFile,\n \"--package-version\",\n paths.packageVersion,\n \"--protocol-version\",\n `${paths.protocolVersion}`,\n \"--app-id\",\n paths.appId,\n \"--app-name\",\n paths.appName,\n \"--caller-label\",\n paths.callerLabel,\n ],\n };\n if (cwd !== undefined) {\n command.cwd = cwd;\n }\n return command;\n};\n\nconst findWorkspaceRoot = async (start: string): Promise<string | undefined> => {\n let current = start;\n while (true) {\n if (await exists(join(current, \"Cargo.toml\"))) {\n if (await exists(join(current, \"crates\", \"opentray-bin\", \"Cargo.toml\"))) {\n return current;\n }\n }\n\n const parent = dirname(current);\n if (parent === current) {\n return undefined;\n }\n current = parent;\n }\n};\n\nexport const resolveDevBrokerBinaryPath = (\n workspaceRoot: string,\n platform: NodeJS.Platform = process.platform,\n callerLabel = \"opentray\",\n): string =>\n join(\n resolveDevBrokerTargetDir(workspaceRoot, platform, callerLabel),\n \"debug\",\n platform === \"win32\" ? \"opentray.exe\" : \"opentray\",\n );\n\nconst resolveDevBrokerTargetDir = (\n workspaceRoot: string,\n platform: NodeJS.Platform,\n callerLabel: string,\n): string =>\n platform === \"win32\"\n ? join(workspaceRoot, \"target\", \"opentray-source\", callerLabel)\n : join(workspaceRoot, \"target\");\n\nconst ensureDevBrokerBinary = async (\n workspaceRoot: string,\n paths: DaemonPaths,\n platform: NodeJS.Platform,\n): Promise<string> => {\n const targetDir = resolveDevBrokerTargetDir(workspaceRoot, platform, paths.callerLabel);\n const binary = resolveDevBrokerBinaryPath(workspaceRoot, platform, paths.callerLabel);\n await runCargoBuild(workspaceRoot, platform === \"win32\" ? targetDir : undefined);\n return binary;\n};\n\nconst ensureDevDarwinCarrierTemplate = async (\n workspaceRoot: string,\n _paths: DaemonPaths,\n): Promise<string> => {\n return join(workspaceRoot, \"packages/darwin-app-carrier/Info.plist\");\n};\n\nconst ensureDarwinBundle = async (\n options: ResolveBrokerCommandOptions,\n paths: DaemonPaths,\n brokerPath: string,\n templatePath: string,\n): Promise<string> => {\n const appBundle = options.appBundle;\n if (appBundle === undefined) return brokerPath;\n const arch = options.arch ?? process.arch;\n if (arch !== \"arm64\" && arch !== \"x64\") {\n throw new Error(`unsupported Darwin app bundle architecture: ${arch}`);\n }\n const defaultAppIcon = await synthesizeDefaultAppIcon(options, appBundle, paths);\n return ensureDarwinAppBundle({\n bundlePath: appBundle.path,\n packageName: options.packageIdentity?.name ?? paths.callerLabel,\n appId: paths.appId,\n appName: paths.appName,\n target: { os: \"darwin\", arch },\n brokerPath,\n templatePath,\n ...(defaultAppIcon === undefined && options.appIcon === undefined\n ? {}\n : { appIcon: (options.appIcon ?? defaultAppIcon)! }),\n ...(appBundle.reinitialize === undefined ? {} : { reinitialize: appBundle.reinitialize }),\n });\n};\n\n/**\n * The synthesized glyph default (shared-icon-kernel plan D6/D7/D8): a carrier\n * materialization concern, never Core App identity. Only synthesized when the\n * caller declared no `appIcon`, did not opt out, and the runtime owns bundle\n * generation (`reinitialize: false` keeps a prebuilt bundle read-only).\n * Failure falls back to the pre-change behavior (no icon) with a diagnostic\n * line in the runtime's stable broker log — it must never block a start.\n */\nconst synthesizeDefaultAppIcon = async (\n options: ResolveBrokerCommandOptions,\n appBundle: OpenTrayAppBundleOptions & { readonly path: string },\n paths: DaemonPaths,\n): Promise<AppIcon | undefined> => {\n if (options.appIcon !== undefined) return undefined;\n if (appBundle.defaultAppIcon === false) return undefined;\n if (appBundle.reinitialize === false) return undefined;\n try {\n const generated = await generateDefaultAppIcon({\n appName: paths.appName,\n outputDir: join(paths.runtimeDir, \"app-icon\"),\n });\n if (generated.degraded) {\n // The name's script is not covered by this host's fonts; the neutral\n // terminal mark is used. Diagnosed, never blocking.\n await appendFile(\n paths.brokerLog,\n `[opentray:icon] default app icon degraded to the neutral mark: no font in the ladder covers the first character of ${JSON.stringify(paths.appName)}\\n`,\n ).catch(() => {});\n }\n return generated.appIcon;\n } catch (error) {\n try {\n // Embedded callers may reach bundle resolution before the runtime\n // directory exists; diagnostics must never block materialization.\n await mkdir(dirname(paths.brokerLog), { recursive: true });\n await appendFile(\n paths.brokerLog,\n `[opentray:icon] default app icon synthesis failed; materializing without an icon: ${String(error)}\\n`,\n );\n } catch {\n // Diagnostics must never turn an icon fallback into a start failure.\n }\n return undefined;\n }\n};\n\nconst runCargoBuild = (workspaceRoot: string, targetDir?: string): Promise<void> =>\n runProcess(\n \"cargo\",\n [\n \"build\",\n \"-p\",\n \"opentray-bin\",\n ...(targetDir === undefined ? [] : [\"--target-dir\", targetDir]),\n ],\n workspaceRoot,\n process.env.OPENTRAY_BROKER_BUILD_LOGS === \"1\" ? \"inherit\" : \"ignore\",\n );\n\nconst runProcess = (\n command: string,\n args: readonly string[],\n cwd: string,\n stdio: \"ignore\" | \"inherit\" = \"ignore\",\n): Promise<void> =>\n new Promise((resolve, reject) => {\n const child = spawn(command, [...args], { cwd, stdio });\n child.once(\"error\", reject);\n child.once(\"exit\", (code) => {\n if (code === 0) {\n resolve();\n return;\n }\n reject(new Error(`${command} ${args.join(\" \")} failed with code ${code ?? \"unknown\"}`));\n });\n });\n\nconst exists = async (path: string): Promise<boolean> => {\n try {\n await access(path, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n};\n\nconst binaryAccessMode = (platform: NodeJS.Platform): number =>\n platform === \"win32\" ? constants.F_OK : constants.X_OK;\n\nconst assertInstalledBrokerBinaryAccessible = async (\n binaryPath: string,\n platform: NodeJS.Platform,\n): Promise<void> => {\n await access(binaryPath, binaryAccessMode(platform));\n};\n\nconst assertInstalledCarrierAccessible = async (carrierPath: string): Promise<void> => {\n await access(carrierPath, constants.F_OK);\n};\n\nconst missingDarwinCarrierError = (\n target: BrokerNativeTarget,\n resolution: InstalledBrokerBinaryResolution,\n arch: string,\n): MissingPlatformBrokerBinaryError =>\n new MissingPlatformBrokerBinaryError(\n `unable to resolve OpenTray Darwin app bundle template for ${target.packageName}; expected ${resolution.carrierTemplatePath ?? target.carrierTemplateRelativePath ?? \"app/Info.plist\"}`,\n \"darwin\",\n arch,\n {\n packageName: target.packageName,\n ...(resolution.carrierTemplatePath === undefined\n ? {}\n : { binaryPath: resolution.carrierTemplatePath }),\n },\n );\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error;\n}\n","// Orthogonal intents (updated 2026-07-21; original user requests: detached\n// brokers must be caller-scoped, artifact-coherent, and diagnosable by default):\n// 1. Start, inspect, restart, and stop one caller-scoped broker under a lock.\n// 2. Reject liveness-only reuse through exact ready artifact identity.\n// 3. Preserve Darwin stable-bundle live-owner protection.\n// 4. Persist detached broker output and early exit identity unless explicitly overridden.\n// 5. Bound native cold-start readiness and recover caller locks left by dead processes.\n\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { constants } from \"node:fs\";\nimport {\n access,\n appendFile,\n link,\n mkdir,\n open,\n readFile,\n rm,\n stat,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { spawn } from \"node:child_process\";\nimport { isAbsolute } from \"node:path\";\n\nimport {\n brokerArtifactIdentityEquals,\n isBrokerArtifactIdentity,\n type BrokerReadyMetadata,\n} from \"@opentray/spec\";\n\nimport { resolveBrokerArtifact, type ResolvedBrokerArtifact } from \"./broker-command\";\nimport type { DaemonPaths } from \"./paths\";\nimport type { AppIcon } from \"@opentray/spec\";\nimport type { OpenTrayAppBundleOptions, OpenTrayPackageIdentity } from \"@opentray/packaging\";\nimport { clearDarwinAppBundleOwner, writeDarwinAppBundleOwner } from \"@opentray/packaging\";\n\nconst DAEMON_STDIO_ENV = \"OPENTRAY_DAEMON_STDIO\";\nconst DAEMON_POLL_INTERVAL_MS = 50;\nconst DEFAULT_DAEMON_READY_TIMEOUT_MS = 10_000;\nconst DEFAULT_DAEMON_LOCK_TIMEOUT_MS = DEFAULT_DAEMON_READY_TIMEOUT_MS + 5_000;\nconst ABANDONED_RECLAIM_CLAIM_MS = 1_000;\n\nexport type DaemonStartResult =\n | {\n status: \"started\";\n pid: number;\n paths: DaemonPaths;\n broker: ResolvedBrokerArtifact;\n }\n | {\n status: \"already-running\";\n pid: number;\n paths: DaemonPaths;\n broker: ResolvedBrokerArtifact;\n };\n\nexport type DaemonStopResult =\n | { status: \"stopped\"; pid: number; paths: DaemonPaths }\n | { status: \"not-running\"; paths: DaemonPaths };\n\nexport type DaemonInspectResult =\n | { status: \"running\"; pid: number; paths: DaemonPaths }\n | { status: \"not-running\"; paths: DaemonPaths; stalePid?: number };\n\nexport interface DaemonDriver {\n resolveBroker(paths: DaemonPaths): Promise<ResolvedBrokerArtifact>;\n isAlive(pid: number): Promise<boolean>;\n spawnBroker(paths: DaemonPaths, broker: ResolvedBrokerArtifact): Promise<number>;\n stop(pid: number): Promise<void>;\n}\n\nexport interface StartDaemonOptions {\n paths: DaemonPaths;\n driver: DaemonDriver;\n lockTimeoutMs?: number;\n readinessTimeoutMs?: number;\n}\n\nexport interface StopDaemonOptions {\n paths: DaemonPaths;\n driver: DaemonDriver;\n}\n\nexport interface InspectDaemonOptions {\n paths: DaemonPaths;\n driver: DaemonDriver;\n}\n\nexport interface NodeDaemonDriverOptions {\n readonly appBundle?: OpenTrayAppBundleOptions & { readonly path: string };\n readonly appIcon?: AppIcon;\n readonly packageIdentity?: OpenTrayPackageIdentity;\n readonly env?: NodeJS.ProcessEnv;\n}\n\nexport const createNodeDaemonDriver = (\n cliEntrypoint: string,\n options: NodeDaemonDriverOptions = {},\n): DaemonDriver => ({\n async resolveBroker(paths) {\n return resolveBrokerArtifact(paths, {\n ...(options.appBundle === undefined ? {} : { appBundle: options.appBundle }),\n ...(options.appIcon === undefined ? {} : { appIcon: options.appIcon }),\n ...(options.packageIdentity === undefined\n ? {}\n : { packageIdentity: options.packageIdentity }),\n });\n },\n async isAlive(pid) {\n return isProcessAlive(pid);\n },\n async spawnBroker(paths, broker) {\n // The caller label flows to the broker via both a CLI flag and an env var.\n // The broker uses it to bind the per-caller endpoint and to set its own\n // process title so task managers show the owning application.\n const env = options.env ?? process.env;\n const stdio = resolveBrokerStdio(env[DAEMON_STDIO_ENV]);\n if (stdio === \"log\") await mkdir(paths.runtimeDir, { recursive: true });\n const logHandle = stdio === \"log\" ? await open(paths.brokerLog, \"a\") : undefined;\n if (logHandle !== undefined) {\n await logHandle.appendFile(\n `${JSON.stringify({\n timestamp: new Date().toISOString(),\n event: \"broker-spawn\",\n command: broker.command,\n cwd: broker.cwd ?? process.cwd(),\n appId: paths.appId,\n appName: paths.appName,\n })}\\n`,\n \"utf8\",\n );\n }\n if (isAbsolute(broker.command)) {\n try {\n await access(\n broker.command,\n process.platform === \"win32\" ? constants.F_OK : constants.X_OK,\n );\n } catch (error) {\n if (stdio === \"log\") {\n await appendFile(\n paths.brokerLog,\n `${JSON.stringify({\n timestamp: new Date().toISOString(),\n event: \"broker-spawn-error\",\n command: broker.command,\n error: error instanceof Error ? error.message : String(error),\n })}\\n`,\n \"utf8\",\n ).catch(() => undefined);\n }\n await logHandle?.close();\n return 0;\n }\n }\n let child: ReturnType<typeof spawn>;\n try {\n child = spawn(broker.command, broker.args, {\n cwd: broker.cwd,\n detached: true,\n env: {\n ...env,\n OPENTRAY_DAEMON_HOME: paths.homeDir,\n OPENTRAY_DAEMON_PACKAGE_VERSION: paths.packageVersion,\n OPENTRAY_DAEMON_CLI_ENTRYPOINT: cliEntrypoint,\n OPENTRAY_DAEMON_APP_ID: paths.appId,\n OPENTRAY_DAEMON_APP_NAME: paths.appName,\n OPENTRAY_DAEMON_CALLER_LABEL: paths.callerLabel,\n },\n stdio:\n logHandle === undefined\n ? stdio === \"log\"\n ? \"ignore\"\n : stdio\n : [\"ignore\", logHandle.fd, logHandle.fd],\n });\n } finally {\n await logHandle?.close();\n }\n\n child.on(\"error\", (error) => {\n if (stdio !== \"log\") return;\n void appendFile(\n paths.brokerLog,\n `${JSON.stringify({\n timestamp: new Date().toISOString(),\n event: \"broker-spawn-error\",\n command: broker.command,\n error: error.message,\n })}\\n`,\n \"utf8\",\n ).catch(() => undefined);\n });\n child.once(\"exit\", (code, signal) => {\n if (stdio !== \"log\") return;\n void appendFile(\n paths.brokerLog,\n `${JSON.stringify({\n timestamp: new Date().toISOString(),\n event: \"broker-exit\",\n command: broker.command,\n code,\n signal,\n })}\\n`,\n \"utf8\",\n ).catch(() => undefined);\n });\n\n child.unref();\n const pid = child.pid ?? 0;\n if (process.platform === \"darwin\" && options.appBundle !== undefined && pid > 0) {\n await writeDarwinAppBundleOwner(\n options.appBundle.path,\n pid,\n broker.artifactIdentity.executableHash,\n );\n }\n return pid;\n },\n async stop(pid) {\n process.kill(pid, \"SIGTERM\");\n if (process.platform === \"darwin\" && options.appBundle !== undefined) {\n await clearDarwinAppBundleOwner(options.appBundle.path, pid);\n }\n },\n});\n\nexport const resolveBrokerStdio = (value: string | undefined): \"log\" | \"ignore\" | \"inherit\" => {\n if (value === \"inherit\") return \"inherit\";\n if (value === \"ignore\") return \"ignore\";\n return \"log\";\n};\n\nexport const startDaemon = async ({\n paths,\n driver,\n lockTimeoutMs = DEFAULT_DAEMON_LOCK_TIMEOUT_MS,\n readinessTimeoutMs = DEFAULT_DAEMON_READY_TIMEOUT_MS,\n}: StartDaemonOptions): Promise<DaemonStartResult> => {\n await mkdir(paths.runtimeDir, { recursive: true });\n\n const lock = await acquireDaemonLock(paths.lockFile, lockTimeoutMs);\n try {\n const existingPid = await readPid(paths.pidFile);\n let existingAlive = existingPid !== undefined && (await driver.isAlive(existingPid));\n let broker: ResolvedBrokerArtifact;\n try {\n // Darwin bundle materialization is part of broker resolution. The bundle owner marker\n // rejects an incompatible live owner before any managed file is replaced.\n broker = await driver.resolveBroker(paths);\n } catch (error) {\n if (existingAlive && isBundleInUseError(error) && existingPid !== undefined) {\n await driver.stop(existingPid);\n if (!(await waitUntilStopped(driver, existingPid))) {\n throw new Error(\n `incompatible daemon broker did not stop within the bounded shutdown window: pid=${existingPid}`,\n );\n }\n existingAlive = false;\n broker = await driver.resolveBroker(paths);\n } else {\n throw error;\n }\n }\n if (existingPid !== undefined && existingAlive) {\n const ready = await readReadyMetadata(paths.readyFile);\n // Liveness is not compatibility: only the exact resolved executable may win reuse.\n if (readyMatchesBroker(ready, paths, existingPid, broker)) {\n return {\n status: \"already-running\",\n pid: existingPid,\n paths,\n broker,\n };\n }\n await driver.stop(existingPid);\n if (!(await waitUntilStopped(driver, existingPid))) {\n throw new Error(\n `incompatible daemon broker did not stop within the bounded shutdown window: pid=${existingPid}`,\n );\n }\n }\n\n await cleanupRuntimeFiles(paths);\n const pid = await driver.spawnBroker(paths, broker);\n if (!Number.isInteger(pid) || pid <= 0) {\n throw new Error(\"daemon broker process did not expose a valid pid\");\n }\n await writeFile(paths.pidFile, `${pid}\\n`, \"utf8\");\n try {\n await waitForReadyFile(paths, driver, pid, broker, readinessTimeoutMs);\n } catch (error) {\n if (await driver.isAlive(pid)) {\n await driver.stop(pid);\n await waitUntilStopped(driver, pid);\n }\n await cleanupRuntimeFiles(paths);\n throw error;\n }\n return { status: \"started\", pid, paths, broker };\n } finally {\n await lock.release();\n }\n};\n\nexport const stopDaemon = async ({\n paths,\n driver,\n}: StopDaemonOptions): Promise<DaemonStopResult> => {\n const pid = await readPid(paths.pidFile);\n if (pid === undefined || !(await driver.isAlive(pid))) {\n await cleanupRuntimeFiles(paths);\n return { status: \"not-running\", paths };\n }\n\n await driver.stop(pid);\n if (!(await waitUntilStopped(driver, pid))) {\n throw new Error(`daemon broker did not stop within the bounded shutdown window: pid=${pid}`);\n }\n await cleanupRuntimeFiles(paths);\n return { status: \"stopped\", pid, paths };\n};\n\nexport const restartDaemon = async (options: StartDaemonOptions): Promise<DaemonStartResult> => {\n await stopDaemon({ paths: options.paths, driver: options.driver });\n return startDaemon(options);\n};\n\nexport const inspectDaemon = async ({\n paths,\n driver,\n}: InspectDaemonOptions): Promise<DaemonInspectResult> => {\n const pid = await readPid(paths.pidFile);\n if (pid !== undefined && (await driver.isAlive(pid))) {\n return { status: \"running\", pid, paths };\n }\n\n await cleanupRuntimeFiles(paths);\n return pid === undefined\n ? { status: \"not-running\", paths }\n : { status: \"not-running\", paths, stalePid: pid };\n};\n\nconst readPid = async (pidFile: string): Promise<number | undefined> => {\n try {\n const content = await readFile(pidFile, \"utf8\");\n const pid = Number.parseInt(content.trim(), 10);\n return Number.isInteger(pid) && pid > 0 ? pid : undefined;\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n};\n\nconst cleanupRuntimeFiles = async (paths: DaemonPaths): Promise<void> => {\n await rm(paths.readyFile, { force: true });\n await rm(paths.pidFile, { force: true });\n if (process.platform !== \"win32\") {\n await rm(paths.endpoint, { force: true });\n }\n};\n\nconst waitUntilStopped = async (driver: DaemonDriver, pid: number): Promise<boolean> => {\n for (let attempt = 0; attempt < 20; attempt += 1) {\n if (!(await driver.isAlive(pid))) {\n return true;\n }\n await sleep(DAEMON_POLL_INTERVAL_MS);\n }\n return false;\n};\n\nconst waitForReadyFile = async (\n paths: DaemonPaths,\n driver: DaemonDriver,\n pid: number,\n broker: ResolvedBrokerArtifact,\n timeoutMs: number,\n): Promise<void> => {\n const deadline = Date.now() + timeoutMs;\n while (true) {\n const ready = await readReadyMetadata(paths.readyFile);\n if (readyMatchesBroker(ready, paths, pid, broker)) {\n return;\n }\n if (ready !== undefined) {\n throw new Error(\n `daemon readiness artifact identity mismatch: expected=${JSON.stringify(broker.artifactIdentity)} actual=${JSON.stringify(ready.brokerArtifactIdentity)}`,\n );\n }\n if (!(await driver.isAlive(pid))) {\n throw new Error(\n `daemon broker exited before readiness: pid=${pid}; readyFile=${paths.readyFile}; brokerLog=${paths.brokerLog}; set ${DAEMON_STDIO_ENV}=inherit to mirror broker stderr`,\n );\n }\n const remainingMs = deadline - Date.now();\n if (remainingMs <= 0) break;\n await sleep(Math.min(DAEMON_POLL_INTERVAL_MS, remainingMs));\n }\n\n throw new Error(\n `timed out waiting for daemon readiness after ${timeoutMs}ms: pid=${pid}; readyFile=${paths.readyFile}; brokerLog=${paths.brokerLog}; set ${DAEMON_STDIO_ENV}=inherit to mirror broker stderr`,\n );\n};\n\nconst readReadyMetadata = async (readyFile: string): Promise<BrokerReadyMetadata | undefined> => {\n let value: unknown;\n try {\n value = JSON.parse(await readFile(readyFile, \"utf8\"));\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return undefined;\n }\n if (error instanceof SyntaxError) {\n return undefined;\n }\n throw error;\n }\n if (\n !isRecord(value) ||\n !Number.isInteger(value.pid) ||\n typeof value.pid !== \"number\" ||\n typeof value.endpoint !== \"string\" ||\n typeof value.packageVersion !== \"string\" ||\n typeof value.protocolVersion !== \"number\" ||\n typeof value.appId !== \"string\" ||\n typeof value.appName !== \"string\" ||\n typeof value.callerLabel !== \"string\" ||\n typeof value.executablePath !== \"string\" ||\n !isBrokerArtifactIdentity(value.brokerArtifactIdentity)\n ) {\n return undefined;\n }\n return {\n pid: value.pid,\n endpoint: value.endpoint,\n packageVersion: value.packageVersion,\n protocolVersion: value.protocolVersion,\n appId: value.appId,\n appName: value.appName,\n callerLabel: value.callerLabel,\n executablePath: value.executablePath,\n brokerArtifactIdentity: value.brokerArtifactIdentity,\n };\n};\n\nconst readyMatchesBroker = (\n ready: BrokerReadyMetadata | undefined,\n paths: DaemonPaths,\n pid: number,\n broker: ResolvedBrokerArtifact,\n): boolean =>\n ready !== undefined &&\n ready.pid === pid &&\n ready.endpoint === paths.endpoint &&\n ready.packageVersion === paths.packageVersion &&\n ready.protocolVersion === paths.protocolVersion &&\n ready.appId === paths.appId &&\n ready.appName === paths.appName &&\n ready.callerLabel === paths.callerLabel &&\n executablePathsEqual(ready.executablePath, broker.executablePath) &&\n brokerArtifactIdentityEquals(ready.brokerArtifactIdentity, broker.artifactIdentity);\n\nconst isBundleInUseError = (error: unknown): boolean =>\n error instanceof Error && \"code\" in error && error.code === \"bundle_in_use\";\n\nexport const executablePathsEqual = (\n left: string,\n right: string,\n platform: NodeJS.Platform = process.platform,\n): boolean => {\n if (platform !== \"win32\") {\n return left === right;\n }\n\n const normalize = (value: string): string =>\n value\n .replaceAll(\"\\\\\", \"/\")\n .replace(/^\\/\\/?\\?\\//u, \"\")\n .toLowerCase();\n return normalize(left) === normalize(right);\n};\n\nexport const acquireDaemonLock = async (\n lockFile: string,\n timeoutMs: number,\n): Promise<{\n release(): Promise<void>;\n}> => {\n const deadline = Date.now() + timeoutMs;\n const owner = `${JSON.stringify({ pid: process.pid, token: randomUUID() })}\\n`;\n while (Date.now() <= deadline) {\n try {\n const handle = await open(\n lockFile,\n constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY,\n );\n await handle.writeFile(owner, \"utf8\");\n return {\n async release() {\n await handle.close();\n if ((await readLockSource(lockFile)) !== owner) return;\n await unlink(lockFile).catch((error: unknown) => {\n if (!isNodeError(error) || error.code !== \"ENOENT\") {\n throw error;\n }\n });\n },\n };\n } catch (error) {\n if (isNodeError(error) && error.code === \"EEXIST\") {\n if (await reclaimDeadLockOwner(lockFile)) continue;\n await sleep(25);\n continue;\n }\n throw error;\n }\n }\n\n throw new Error(`timed out acquiring daemon lock: ${lockFile}`);\n};\n\nconst reclaimDeadLockOwner = async (lockFile: string): Promise<boolean> => {\n const observed = await readLockSource(lockFile);\n if (observed === undefined) return true;\n const owner = parseLockOwner(observed);\n if (owner === undefined || isProcessAlive(owner.pid)) return false;\n\n const claimFile = `${lockFile}.reclaim-${createHash(\"sha256\").update(observed).digest(\"hex\").slice(0, 16)}`;\n try {\n await link(lockFile, claimFile);\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") return true;\n if (isNodeError(error) && error.code === \"EEXIST\") {\n await clearAbandonedReclaimClaim(claimFile);\n return false;\n }\n throw error;\n }\n\n try {\n // Only the hard-link claim winner may remove this exact dead owner inode.\n if ((await readLockSource(lockFile)) !== observed || isProcessAlive(owner.pid)) return false;\n try {\n await unlink(lockFile);\n return true;\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") return true;\n throw error;\n }\n } finally {\n await unlink(claimFile).catch((error: unknown) => {\n if (!isNodeError(error) || error.code !== \"ENOENT\") throw error;\n });\n }\n};\n\nconst clearAbandonedReclaimClaim = async (claimFile: string): Promise<void> => {\n try {\n const claim = await stat(claimFile);\n if (Date.now() - claim.ctimeMs < ABANDONED_RECLAIM_CLAIM_MS) return;\n await unlink(claimFile);\n } catch (error) {\n if (!isNodeError(error) || error.code !== \"ENOENT\") throw error;\n }\n};\n\nconst readLockSource = async (lockFile: string): Promise<string | undefined> => {\n try {\n return await readFile(lockFile, \"utf8\");\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") return undefined;\n throw error;\n }\n};\n\nconst parseLockOwner = (source: string): { readonly pid: number } | undefined => {\n const legacyPid = Number(source.trim());\n if (Number.isInteger(legacyPid) && legacyPid > 0) return { pid: legacyPid };\n\n let value: unknown;\n try {\n value = JSON.parse(source);\n } catch {\n return undefined;\n }\n if (\n !isRecord(value) ||\n typeof value.pid !== \"number\" ||\n !Number.isInteger(value.pid) ||\n value.pid <= 0 ||\n typeof value.token !== \"string\" ||\n value.token.length === 0\n ) {\n return undefined;\n }\n return { pid: value.pid };\n};\n\nconst isProcessAlive = (pid: number): boolean => {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return !(isNodeError(error) && error.code === \"ESRCH\");\n }\n};\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst isNodeError = (error: unknown): error is NodeJS.ErrnoException =>\n error instanceof Error && \"code\" in error;\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n","import { readFile } from \"node:fs/promises\";\n\nexport const readPackageVersion = async (packageJsonUrl: URL): Promise<string> => {\n const value: unknown = JSON.parse(await readFile(packageJsonUrl, \"utf8\"));\n if (!isPackageJsonWithVersion(value)) {\n throw new Error(`package.json is missing a string version: ${packageJsonUrl.href}`);\n }\n\n return value.version;\n};\n\nconst isPackageJsonWithVersion = (value: unknown): value is { version: string } =>\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n \"version\" in value &&\n typeof value.version === \"string\";\n","import {\n createBrokerEndpointIdentity,\n formatUnixSocketPath,\n formatWindowsPipeName,\n} from \"@opentray/spec\";\n\nexport interface DaemonPathOptions {\n homeDir: string;\n packageVersion: string;\n callerLabel?: string;\n appId?: string;\n appName?: string;\n platform?: NodeJS.Platform;\n}\n\nexport interface DaemonPaths {\n homeDir: string;\n packageVersion: string;\n callerLabel: string;\n appId: string;\n appName: string;\n protocolVersion: number;\n stateRoot: string;\n runtimeDir: string;\n endpoint: string;\n pidFile: string;\n lockFile: string;\n readyFile: string;\n brokerLog: string;\n}\n\nexport const resolveDaemonPaths = ({\n homeDir,\n packageVersion,\n callerLabel,\n appId,\n appName,\n platform = process.platform,\n}: DaemonPathOptions): DaemonPaths => {\n const identity = createBrokerEndpointIdentity(\n callerLabel === undefined ? { packageVersion } : { packageVersion, callerLabel },\n );\n const resolvedAppId = normalizeAppIdentityField(appId, identity.callerLabel);\n const resolvedAppName = normalizeAppIdentityField(appName, identity.callerLabel);\n const normalizedHome = homeDir.replace(/[\\\\/]+$/u, \"\");\n const stateRoot = `${normalizedHome}/.opentray/${identity.packageVersion}/${identity.callerLabel}`;\n const runtimeDir = `${stateRoot}/runtime`;\n const endpoint =\n platform === \"win32\"\n ? formatWindowsPipeName(identity)\n : formatUnixSocketPath(normalizedHome, identity);\n\n return {\n homeDir: normalizedHome,\n packageVersion: identity.packageVersion,\n callerLabel: identity.callerLabel,\n appId: resolvedAppId,\n appName: resolvedAppName,\n protocolVersion: identity.protocolVersion,\n stateRoot,\n runtimeDir,\n endpoint,\n pidFile: `${runtimeDir}/broker.pid`,\n lockFile: `${runtimeDir}/broker.lock`,\n readyFile: `${runtimeDir}/ready.json`,\n brokerLog: `${runtimeDir}/broker.log`,\n };\n};\n\nconst normalizeAppIdentityField = (value: string | undefined, fallback: string): string => {\n const trimmed = value?.trim();\n return trimmed === undefined || trimmed.length === 0 ? fallback : trimmed;\n};\n","// Orthogonal intents (2026-07-21; original user requests: a normal install\n// yields one coherent local runtime; the last app launch command is committed\n// only after a successful broker handshake):\n// 1. Resolve caller identity, endpoint, package graph, and stable Darwin bundle.\n// 2. Start/reuse one compatible caller-scoped broker and validate its identity.\n// 3. Own request/event transport and deterministic connection teardown.\n// 4. Commit mutable Darwin launch state after runtime initialization succeeds.\n\nimport { createConnection, type Socket } from \"node:net\";\nimport { homedir } from \"node:os\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { appendFile, mkdir } from \"node:fs/promises\";\n\nimport {\n PROTOCOL_VERSION,\n brokerArtifactIdentityEquals,\n parseServerFrame,\n type BrokerArtifactIdentity,\n type BrokerEndpointIdentityOptions,\n type ClientRequestFrame,\n type ExtOperationPayload,\n type RequestId,\n type ServerFrame,\n} from \"@opentray/spec\";\nimport type { OpenTrayAppBundleOptions, OpenTrayAppLaunchDescriptor } from \"@opentray/packaging\";\nimport {\n resolveDefaultDarwinAppBundlePath,\n convergeDarwinAppBundleIdentity,\n resolveOpenTrayPackageIdentity,\n updateDarwinAppLaunchDescriptor,\n type OpenTrayPackageIdentity,\n} from \"@opentray/packaging\";\n\nimport type { OpenTrayTransport, TransportRequestOptions } from \"./client\";\nimport {\n BOOTSTRAP_CALL_DEADLINE_MS,\n INTERACTIVE_CALL_DEADLINE_MS,\n TEARDOWN_CALL_DEADLINE_MS,\n TransportTimeoutError,\n BrokerServerError,\n} from \"./client\";\nimport { resolveCallerLabel } from \"./daemon/caller-label\";\nimport { createNodeDaemonDriver, startDaemon, type DaemonDriver } from \"./daemon/lifecycle\";\nimport { readPackageVersion } from \"./daemon/package-version\";\nimport { resolveDaemonPaths } from \"./daemon/paths\";\nimport type { DaemonPaths } from \"./daemon/paths\";\n\nconst packageJsonUrl = new URL(\"../package.json\", import.meta.url);\n\nexport type LocalRuntimeEventFrame = Extract<\n ServerFrame,\n { type: \"event\" | \"app-event\" | \"ext-event\" }\n>;\n\n/**\n * Transport-close sentinel every pending request rejects with when the\n * broker socket closes (the broker exits once its last session closes, so a\n * caller racing its own teardown against that exit sees this message).\n * Exported so the tray-handle destroy path can treat it as the desired end\n * state instead of a failure (P3.6 quit-path finding, 2026-09-12).\n */\nexport const BROKER_CONNECTION_CLOSED_MESSAGE = \"broker connection closed\";\n\n/**\n * Generic transport-close rejection code for every pending deferred operation\n * (add-ext-dialog section 5.1 frozen): the core client carries no extension-specific\n * branch. Extension facades map this shared code onto their public surface\n * (e.g. ext-dialog's `dialog_transport_closed`) - that mapping is facade work,\n * never core work.\n */\nexport const EXTENSION_TRANSPORT_CLOSED_CODE = \"extension_transport_closed\";\n\n/**\n * Typed rejection every deferred operation settles with: the `error` payload\n * branch of an `ext-operation-terminal` frame, or the generic\n * `extension_transport_closed` rejection when the transport dies while an\n * operation is pending. Consumers match on `code`; the human `message` is not\n * a contract. `details` carries the wire error's structured payload when the\n * extension supplied one.\n */\nexport class ExtensionOperationError extends Error {\n readonly code: string;\n readonly details?: unknown;\n\n constructor(\n code: string,\n message: string,\n options: { details?: unknown; cause?: unknown } = {}\n ) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.name = \"ExtensionOperationError\";\n this.code = code;\n if (options.details !== undefined) {\n this.details = options.details;\n }\n }\n}\n\nconst extensionTransportClosedError = (cause: Error): ExtensionOperationError =>\n new ExtensionOperationError(\n EXTENSION_TRANSPORT_CLOSED_CODE,\n \"the broker transport closed while a deferred extension operation was pending\",\n { cause }\n );\n\n/**\n * Correlation label the bootstrap deadline reports under: the init frame\n * carries no requestId on the wire, so the typed timeout names the call class\n * itself.\n */\nconst INIT_REQUEST_ID = \"init\";\n\n/**\n * Typed handshake rejection for a Ready frame whose protocol version does not\n * equal the version this client sent in its Init frame: a structurally valid\n * Ready frame alone must never accept the session (add-ext-dialog batch A\n * review P1-9). The message names both sides; consumers may match\n * `instanceof` or the two numeric fields.\n */\nexport class BrokerProtocolVersionError extends Error {\n readonly clientProtocolVersion: number;\n readonly brokerProtocolVersion: number;\n\n constructor(clientProtocolVersion: number, brokerProtocolVersion: number) {\n super(\n `broker protocol version mismatch: client=${clientProtocolVersion} broker=${brokerProtocolVersion}`\n );\n this.name = \"BrokerProtocolVersionError\";\n this.clientProtocolVersion = clientProtocolVersion;\n this.brokerProtocolVersion = brokerProtocolVersion;\n }\n}\n\nexport interface LocalBrokerClient extends OpenTrayTransport {\n readonly endpoint: string;\n readonly callerLabel: string;\n readonly sessionId: string;\n /**\n * Terminal connection-death state (D3, harden-lifecycle-ownership): true\n * once the broker socket errored or closed. Pending and future requests\n * reject; event delivery has stopped.\n */\n readonly connectionDead: boolean;\n /**\n * Terminal connection-death notification; fires exactly once, either for a\n * transport error or the transport-close sentinel, and also after a\n * caller-initiated graceful `close()` completes.\n */\n onConnectionDead(listener: (error: Error) => void): () => void;\n /**\n * Internal deadline-expiry observation seam (W1, harden-transport-robustness):\n * not consumer API. A supervision layer (Phase C heartbeat) subscribes to\n * attribute probe failures — an expiry settles one call and never declares\n * the transport dead, but it counts as one liveness-failure signal.\n */\n onDeadlineExpiry(listener: (expiry: TransportDeadlineExpiry) => void): () => void;\n onEvent(listener: (frame: LocalRuntimeEventFrame) => void): () => void;\n close(): Promise<void>;\n}\n\n/** Payload of the internal deadline-expiry seam: which call class budget expired. */\nexport interface TransportDeadlineExpiry {\n readonly requestId: RequestId;\n readonly deadlineMs: number;\n}\n\nexport interface ConnectLocalBrokerOptions extends Partial<BrokerEndpointIdentityOptions> {\n endpoint?: string;\n homeDir?: string;\n appId?: string;\n appName?: string;\n clientVersion?: string;\n autoStart?: boolean;\n daemonDriver?: DaemonDriver;\n cliEntrypoint?: string;\n callerLabel?: string;\n expectedBrokerArtifactIdentity?: BrokerArtifactIdentity;\n appIcon?: import(\"@opentray/spec\").AppIcon;\n appBundle?: OpenTrayAppBundleOptions;\n appLaunch?: OpenTrayAppLaunchDescriptor;\n packageName?: string;\n packageRoot?: string;\n}\n\ninterface PendingRequest {\n resolve(frame: ServerFrame): void;\n reject(error: Error): void;\n /**\n * Per-call deadline timer (W1): unref'd so library callers' process exit is\n * never held open by an outstanding call; cleared on every settle path.\n */\n deadlineTimer?: ReturnType<typeof setTimeout> | undefined;\n /**\n * Set when the matching `ext-command-accepted` frame arrives (add-ext-dialog\n * section 5.1 pending-until-final): the promise stays pending until exactly one\n * `ext-operation-terminal` settles it, and a transport death rejects it with\n * the generic typed `extension_transport_closed` instead of the plain\n * transport sentinel. Acceptance clears the deadline (two-phase law): the\n * deadline bounds dispatch→acceptance — the transport round-trip the client\n * owns — while the accepted operation awaits native completion that can be\n * legitimately user-paced (a held modal dialog) and is bounded only by\n * transport liveness, never by a transport deadline.\n */\n deferredOperation?: string;\n}\n\n/**\n * Minimal structural socket the connection needs; exported so in-repo tests\n * can drive the transport against deterministic fake sockets (never-answering\n * brokers, wedged graceful ends) instead of timing-dependent real ones.\n */\nexport interface BrokerSocket {\n setEncoding(encoding: BufferEncoding): void;\n on(event: \"data\", listener: (chunk: Buffer | string) => void): void;\n on(event: \"error\", listener: (error: Error) => void): void;\n on(event: \"close\", listener: () => void): void;\n once(event: \"connect\", listener: () => void): void;\n once(event: \"error\", listener: (error: Error) => void): void;\n off(event: \"error\", listener: (error: Error) => void): void;\n write(data: string): void;\n end(callback: () => void): void;\n destroy(): void;\n}\n\nexport const connectLocalBroker = async (\n options: ConnectLocalBrokerOptions = {},\n): Promise<LocalBrokerClient> => {\n const packageVersion = options.packageVersion ?? (await readPackageVersion(packageJsonUrl));\n const clientVersion = options.clientVersion ?? packageVersion;\n const appId = normalizeAppIdentityField(options.appId);\n const appName = normalizeAppIdentityField(options.appName);\n // Endpoint identity precedence (D4, harden-lifecycle-ownership): internal\n // diagnostic override > appId slug > tool fallbacks. `appName` never\n // participates: display names are not filesystem-safe endpoint segments.\n const callerLabel =\n options.callerLabel ?? resolveCallerLabel(appId === undefined ? {} : { appId });\n const paths = resolveDaemonPaths({\n homeDir: options.homeDir ?? process.env.OPENTRAY_HOME ?? homedir(),\n packageVersion,\n callerLabel,\n ...(appId === undefined ? {} : { appId }),\n ...(appName === undefined ? {} : { appName }),\n });\n const endpoint = options.endpoint ?? paths.endpoint;\n const autoStart = options.autoStart ?? endpoint === paths.endpoint;\n if (autoStart && endpoint !== paths.endpoint) {\n throw new Error(\"local broker autoStart requires the derived same-version endpoint\");\n }\n const cliEntrypoint = options.cliEntrypoint ?? resolveCliEntrypoint();\n const packageIdentity =\n process.platform === \"darwin\" && autoStart\n ? await resolveOpenTrayPackageIdentity({\n ...(options.packageName === undefined ? {} : { packageName: options.packageName }),\n ...(options.packageRoot === undefined ? {} : { packageRoot: options.packageRoot }),\n })\n : undefined;\n const appBundle =\n process.platform === \"darwin\" && autoStart\n ? resolveDarwinAppBundleOptions(options.appBundle, paths, packageIdentity)\n : undefined;\n const driver =\n options.daemonDriver ??\n createNodeDaemonDriver(cliEntrypoint, {\n ...(appBundle === undefined ? {} : { appBundle }),\n ...(options.appIcon === undefined ? {} : { appIcon: options.appIcon }),\n ...(packageIdentity === undefined ? {} : { packageIdentity }),\n });\n const expectedBrokerArtifactIdentity = autoStart\n ? (await startDaemon({ paths, driver })).broker.artifactIdentity\n : (options.expectedBrokerArtifactIdentity ??\n (await driver.resolveBroker(paths)).artifactIdentity);\n const socket = await connectSocket(endpoint);\n const connection = new LocalBrokerConnection(socket, endpoint, callerLabel);\n\n try {\n await connection.init(\n clientVersion,\n options.protocolVersion ?? PROTOCOL_VERSION,\n expectedBrokerArtifactIdentity,\n );\n if (appBundle !== undefined && options.appLaunch !== undefined) {\n await updateDarwinAppLaunchDescriptor(appBundle.path, options.appLaunch);\n const convergence = await convergeDarwinAppBundleIdentity({\n currentBundlePath: appBundle.path,\n appId: paths.appId,\n managedAppsRoot: resolve(paths.homeDir, \".opentray/apps\"),\n legacyRuntimeRoot: resolve(paths.homeDir, \".opentray\"),\n legacyBundlePaths: [resolve(paths.runtimeDir, \"darwin-carrier/OpenTray.app\")],\n });\n await appendBrokerDiagnostic(paths.brokerLog, {\n event: \"bundle-identity-convergence\",\n removed: convergence.removed,\n skippedLiveOwner: convergence.skippedLiveOwner,\n failedUnregister: convergence.failedUnregister,\n });\n }\n } catch (error) {\n await connection.close();\n throw error;\n }\n return connection;\n};\n\nconst appendBrokerDiagnostic = async (\n path: string,\n value: Readonly<Record<string, unknown>>,\n): Promise<void> => {\n try {\n await mkdir(dirname(path), { recursive: true });\n await appendFile(\n path,\n `${JSON.stringify({ timestamp: new Date().toISOString(), ...value })}\\n`,\n \"utf8\",\n );\n } catch {\n // Diagnostics must never turn a successful tray connection into a failure.\n }\n};\n\nconst resolveDarwinAppBundleOptions = (\n configured: OpenTrayAppBundleOptions | undefined,\n paths: DaemonPaths,\n packageIdentity: OpenTrayPackageIdentity | undefined,\n): OpenTrayAppBundleOptions & { readonly path: string } => {\n if (packageIdentity === undefined) {\n throw new Error(\"Darwin app bundle resolution requires the caller package identity\");\n }\n const configuredPath = configured?.path;\n const path =\n configuredPath === undefined\n ? resolveDefaultDarwinAppBundlePath({\n homeDir: paths.homeDir,\n packageName: packageIdentity.name,\n appName: paths.appName,\n })\n : typeof configuredPath === \"string\"\n ? isAbsolute(configuredPath)\n ? configuredPath\n : resolve(packageIdentity.root, configuredPath)\n : configuredPath.protocol === \"file:\"\n ? fileURLToPath(configuredPath)\n : (() => {\n throw new Error(`Darwin appBundle.path must be a file URL: ${configuredPath.href}`);\n })();\n return {\n path,\n ...(configured?.reinitialize === undefined ? {} : { reinitialize: configured.reinitialize }),\n };\n};\n\nconst normalizeAppIdentityField = (value: string | undefined): string | undefined => {\n const trimmed = value?.trim();\n return trimmed === undefined || trimmed.length === 0 ? undefined : trimmed;\n};\n\nexport class LocalBrokerConnection implements LocalBrokerClient {\n readonly endpoint: string;\n readonly callerLabel: string;\n sessionId = \"\";\n\n private buffer = \"\";\n private readonly listeners = new Set<(frame: LocalRuntimeEventFrame) => void>();\n private readonly pending = new Map<RequestId, PendingRequest>();\n /** operationId -> requestId of accepted-but-unsettled deferred operations. */\n private readonly deferredOperations = new Map<string, RequestId>();\n private readonly deadListeners = new Set<(error: Error) => void>();\n private readonly deadlineExpiryListeners = new Set<(expiry: TransportDeadlineExpiry) => void>();\n private deadError: Error | undefined;\n private ready:\n | {\n resolve(frame: Extract<ServerFrame, { type: \"ready\" }>): void;\n reject(error: Error): void;\n }\n | undefined;\n\n constructor(\n private readonly socket: BrokerSocket,\n endpoint: string,\n callerLabel: string,\n ) {\n this.endpoint = endpoint;\n this.callerLabel = callerLabel;\n socket.setEncoding(\"utf8\");\n socket.on(\"data\", (chunk: Buffer | string) => {\n this.consume(String(chunk));\n });\n socket.on(\"error\", (error) => {\n // Transport errors race the close event per platform (Linux delivers\n // ECONNRESET before close; macOS close-first). The terminal surface is\n // the stable classification message — the underlying transport error\n // stays observable as `cause` for diagnostics, so both orderings\n // expose identical public behavior.\n this.markDead(\n new Error(BROKER_CONNECTION_CLOSED_MESSAGE, { cause: error }),\n );\n });\n socket.on(\"close\", () => {\n this.markDead(new Error(BROKER_CONNECTION_CLOSED_MESSAGE));\n });\n }\n\n get connectionDead(): boolean {\n return this.deadError !== undefined;\n }\n\n onConnectionDead(listener: (error: Error) => void): () => void {\n this.deadListeners.add(listener);\n return () => {\n this.deadListeners.delete(listener);\n };\n }\n\n onDeadlineExpiry(listener: (expiry: TransportDeadlineExpiry) => void): () => void {\n this.deadlineExpiryListeners.add(listener);\n return () => {\n this.deadlineExpiryListeners.delete(listener);\n };\n }\n\n async init(\n clientVersion: string,\n protocolVersion: number,\n expectedBrokerArtifactIdentity: BrokerArtifactIdentity,\n ): Promise<void> {\n const ready = new Promise<Extract<ServerFrame, { type: \"ready\" }>>((resolve, reject) => {\n this.ready = { resolve, reject };\n });\n this.write({\n type: \"init\",\n protocolVersion,\n clientVersion,\n });\n const frame = await this.raceBootstrapDeadline(ready);\n // A structurally valid Ready frame is not session authority: the broker\n // must speak exactly the protocol version this client announced (direct\n // connections have no daemon-readiness metadata protecting them).\n if (frame.protocolVersion !== protocolVersion) {\n throw new BrokerProtocolVersionError(protocolVersion, frame.protocolVersion);\n }\n if (\n !brokerArtifactIdentityEquals(frame.brokerArtifactIdentity, expectedBrokerArtifactIdentity)\n ) {\n throw new Error(\n `broker artifact identity mismatch: expected=${JSON.stringify(expectedBrokerArtifactIdentity)} actual=${JSON.stringify(frame.brokerArtifactIdentity)}`,\n );\n }\n this.sessionId = frame.sessionId;\n }\n\n async request(\n frame: ClientRequestFrame,\n options: TransportRequestOptions = {},\n ): Promise<ServerFrame> {\n if (this.pending.has(frame.requestId)) {\n throw new Error(`duplicate requestId: ${frame.requestId}`);\n }\n // Requests issued after transport death reject immediately: a destroyed\n // socket swallows writes without a terminal event, so the request map\n // would otherwise hold them forever (F2 zombie-entry finding, 2026-09-14:\n // post-death getUrl/destroy stayed pending indefinitely in both Node and\n // Bun because write-after-close only returns false).\n if (this.deadError !== undefined) {\n throw new Error(this.deadError.message);\n }\n\n // Per-call budget (W1, harden-transport-robustness): a half-open transport\n // where both processes stay alive but neither direction is delivered would\n // otherwise hold this entry forever. Expiry settles exactly this call with\n // the typed timeout rejection and removes the entry, so a late reply finds\n // no owner; it never marks the transport dead.\n const deadlineMs = options.deadlineMs ?? INTERACTIVE_CALL_DEADLINE_MS;\n const response = new Promise<ServerFrame>((resolve, reject) => {\n const deadlineTimer = setTimeout(() => {\n this.expireRequest(frame.requestId, deadlineMs);\n }, deadlineMs);\n // Library semantics: an outstanding call must never keep the host\n // process alive on its own.\n deadlineTimer.unref();\n this.pending.set(frame.requestId, { resolve, reject, deadlineTimer });\n });\n this.write(frame);\n return response;\n }\n\n onEvent(listener: (frame: LocalRuntimeEventFrame) => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n async close(): Promise<void> {\n if (this.deadError !== undefined) {\n // The transport already reached its terminal state; there is nothing\n // left to end. Resolving keeps explicit teardown paths (e.g. generated\n // app Quit after broker death) finite.\n return;\n }\n this.write({ type: \"exit\" });\n // Wall-clock-bounded graceful teardown (W3): a peer that never completes\n // the half-close must not wedge consumer shutdown. `end` completing late\n // degrades to `destroy`; either way close itself resolves — it never\n // rejects with a timeout, keeping the graceful-close sentinel semantics\n // (the subsequent socket close reports through the existing death path).\n await new Promise<void>((resolve) => {\n const degrade = setTimeout(() => {\n this.socket.destroy();\n resolve();\n }, TEARDOWN_CALL_DEADLINE_MS);\n degrade.unref();\n this.socket.end(() => {\n clearTimeout(degrade);\n resolve();\n });\n });\n }\n\n private consume(chunk: string): void {\n this.buffer += chunk;\n while (true) {\n const newline = this.buffer.indexOf(\"\\n\");\n if (newline < 0) {\n return;\n }\n\n const line = this.buffer.slice(0, newline).trim();\n this.buffer = this.buffer.slice(newline + 1);\n if (line.length > 0) {\n this.dispatchLine(line);\n }\n }\n }\n\n private dispatchLine(line: string): void {\n const parsed = parseServerFrame(line);\n if (!parsed.ok || parsed.frame === undefined) {\n this.rejectAll(new Error(`${parsed.error ?? \"invalid server frame\"}: ${line}`));\n return;\n }\n\n this.dispatchFrame(parsed.frame);\n }\n\n private dispatchFrame(frame: ServerFrame): void {\n if (frame.type === \"ready\") {\n this.ready?.resolve(frame);\n this.ready = undefined;\n return;\n }\n\n if (frame.type === \"error\") {\n // Synchronous server errors keep the typed `{ code, message, details }`\n // family (add-ext-dialog section 7.5): the same shape a deferred\n // terminal error rejects with, so consumers match one contract.\n const error = new BrokerServerError(frame.code, frame.message, {\n details: frame.details,\n });\n if (frame.requestId !== undefined) {\n this.takePending(frame.requestId)?.reject(error);\n return;\n }\n // An error with no requestId could not be correlated to a specific request.\n // If the handshake is still pending, reject it; otherwise reject every\n // pending request so callers fail loudly instead of hanging indefinitely.\n // (See issue #3: createTray never resolves on a malformed frame.)\n if (this.ready) {\n this.ready.reject(error);\n this.ready = undefined;\n return;\n }\n this.rejectAll(error);\n return;\n }\n\n if (frame.type === \"ext-command-accepted\") {\n this.acceptDeferredOperation(frame.requestId, frame.operationId);\n return;\n }\n\n if (frame.type === \"ext-operation-terminal\") {\n this.settleDeferredOperation(frame.operationId, frame.payload);\n return;\n }\n\n const requestId = responseRequestId(frame);\n if (requestId !== undefined) {\n // Request responses and broker events are separate streams even on one\n // socket. A reply arriving after its deadline finds no entry — the\n // stateless late-settlement discard (W1) — and settles nothing.\n this.takePending(requestId)?.resolve(frame);\n return;\n }\n\n if (\n frame.type === \"event\" ||\n frame.type === \"app-event\" ||\n frame.type === \"ext-event\"\n ) {\n for (const listener of this.listeners) {\n listener(frame);\n }\n }\n }\n\n private write(frame: unknown): void {\n this.socket.write(`${JSON.stringify(frame)}\\n`);\n }\n\n /**\n * Pending-until-final acceptance (add-ext-dialog section 5.1): acceptance never\n * settles the request. The broker's owner loop guarantees exactly one\n * terminal per operation; a second acceptance for the same request or an\n * already-bound operationId is defensively ignored, never a second\n * registration. Acceptance also stops the call's deadline: dispatch was the\n * bounded transport phase the client owns, and the accepted operation now\n * awaits a native terminal that can be legitimately user-paced (a held modal\n * dialog), bounded only by transport liveness.\n */\n private acceptDeferredOperation(requestId: RequestId, operationId: string): void {\n const entry = this.pending.get(requestId);\n if (entry === undefined || entry.deferredOperation !== undefined) {\n return;\n }\n if (this.deferredOperations.has(operationId)) {\n return;\n }\n entry.deferredOperation = operationId;\n this.deferredOperations.set(operationId, requestId);\n this.clearDeadline(entry);\n }\n\n /**\n * The single terminal settlement: resolves the still-pending request with\n * the terminal frame (`payload.kind === \"result\"`), or rejects it with the\n * typed wire error (`\"error\"`). Terminals for unknown or already-settled\n * operationIds are silently dropped - the broker side already settles\n * through a one-shot CAS; the client mirrors that stateless drop instead of\n * guessing an owner. A terminal arriving after the call's deadline expired\n * is the same stateless drop (W1).\n */\n private settleDeferredOperation(operationId: string, payload: ExtOperationPayload): void {\n const requestId = this.deferredOperations.get(operationId);\n if (requestId === undefined) {\n return;\n }\n const entry = this.takePending(requestId);\n if (entry === undefined) {\n this.deferredOperations.delete(operationId);\n return;\n }\n if (payload.kind === \"result\") {\n // The terminal frame is the correlated server-frame settlement of the\n // original request; its payload carries the deferred value.\n const terminal: Extract<ServerFrame, { type: \"ext-operation-terminal\" }> = {\n type: \"ext-operation-terminal\",\n operationId,\n payload,\n };\n entry.resolve(terminal);\n return;\n }\n const wireError = payload.error;\n entry.reject(\n new ExtensionOperationError(wireError.code, wireError.message, {\n details: wireError.details,\n }),\n );\n }\n\n /**\n * Removes and fully cleans one pending entry: clears its deadline timer and\n * the deferred-operation reverse mapping, so every settle path (response,\n * correlated error, deferred terminal, expiry) leaves no timer or mapping\n * behind.\n */\n private takePending(requestId: RequestId): PendingRequest | undefined {\n const entry = this.pending.get(requestId);\n if (entry === undefined) {\n return undefined;\n }\n this.pending.delete(requestId);\n this.clearDeadline(entry);\n if (entry.deferredOperation !== undefined) {\n this.deferredOperations.delete(entry.deferredOperation);\n }\n return entry;\n }\n\n private clearDeadline(entry: PendingRequest): void {\n if (entry.deadlineTimer !== undefined) {\n clearTimeout(entry.deadlineTimer);\n entry.deadlineTimer = undefined;\n }\n }\n\n /**\n * Deadline expiry (W1): settles exactly this call with the typed timeout\n * rejection and removes its entries, so a late reply or terminal finds no\n * owner. Deliberately NOT `markDead` — an unanswered call is one liveness\n * signal, not a death verdict; the connection stays usable and the death\n * listeners stay silent. The expiry is reported through the internal seam\n * for the Phase C heartbeat's failure classification.\n */\n private expireRequest(requestId: RequestId, deadlineMs: number): void {\n const entry = this.pending.get(requestId);\n if (entry === undefined) {\n return;\n }\n this.takePending(requestId);\n this.notifyDeadlineExpiry({ requestId, deadlineMs });\n entry.reject(new TransportTimeoutError(requestId, deadlineMs));\n }\n\n /**\n * Bootstrap-class budget (W1): the Ready frame must arrive within\n * `BOOTSTRAP_CALL_DEADLINE_MS` or init settles with the typed timeout\n * rejection. Like per-call expiry this never marks the transport dead —\n * `connectLocalBroker`'s error path performs the bounded close.\n */\n private raceBootstrapDeadline(\n ready: Promise<Extract<ServerFrame, { type: \"ready\" }>>,\n ): Promise<Extract<ServerFrame, { type: \"ready\" }>> {\n return new Promise((resolve, reject) => {\n let bootstrapTimer: ReturnType<typeof setTimeout> | undefined = setTimeout(() => {\n bootstrapTimer = undefined;\n this.notifyDeadlineExpiry({\n requestId: INIT_REQUEST_ID,\n deadlineMs: BOOTSTRAP_CALL_DEADLINE_MS,\n });\n reject(new TransportTimeoutError(INIT_REQUEST_ID, BOOTSTRAP_CALL_DEADLINE_MS));\n }, BOOTSTRAP_CALL_DEADLINE_MS);\n bootstrapTimer.unref();\n const settle = (settleFn: () => void): void => {\n if (bootstrapTimer !== undefined) {\n clearTimeout(bootstrapTimer);\n bootstrapTimer = undefined;\n }\n settleFn();\n };\n ready.then(\n (frame) => settle(() => resolve(frame)),\n (error) => settle(() => reject(error)),\n );\n });\n }\n\n private notifyDeadlineExpiry(expiry: TransportDeadlineExpiry): void {\n for (const listener of [...this.deadlineExpiryListeners]) {\n try {\n listener(expiry);\n } catch {\n // A throwing seam listener must not block expiry propagation to the\n // remaining listeners.\n }\n }\n }\n\n private rejectAll(error: Error): void {\n this.ready?.reject(error);\n this.ready = undefined;\n for (const pending of this.pending.values()) {\n this.clearDeadline(pending);\n pending.reject(error);\n }\n this.pending.clear();\n this.deferredOperations.clear();\n }\n\n /**\n * Terminal connection-death transition (D3): first socket error/close wins,\n * rejects everything pending, and notifies every terminal listener exactly\n * once. Later terminal events are no-ops.\n *\n * Pending-until-final (add-ext-dialog section 5.1): accepted deferred operations\n * reject with the generic typed `extension_transport_closed` (the core\n * client has no extension-name branch); every ordinary pending request\n * keeps the plain transport sentinel.\n */\n private markDead(error: Error): void {\n if (this.deadError !== undefined) {\n return;\n }\n this.deadError = error;\n this.ready?.reject(error);\n this.ready = undefined;\n for (const pending of this.pending.values()) {\n this.clearDeadline(pending);\n pending.reject(\n pending.deferredOperation === undefined ? error : extensionTransportClosedError(error),\n );\n }\n this.pending.clear();\n this.deferredOperations.clear();\n for (const listener of [...this.deadListeners]) {\n try {\n listener(error);\n } catch {\n // A throwing terminal listener must not block death propagation to\n // the remaining listeners.\n }\n }\n }\n}\n\nconst connectSocket = (endpoint: string): Promise<BrokerSocket> =>\n new Promise((resolve, reject) => {\n const socket = createConnection(endpoint);\n socket.once(\"connect\", () => {\n socket.off(\"error\", reject);\n resolve(socket);\n });\n socket.once(\"error\", reject);\n });\n\nconst responseRequestId = (frame: ServerFrame): RequestId | undefined => {\n switch (frame.type) {\n case \"app-created\":\n case \"default-app\":\n case \"app-identity\":\n case \"tray-created\":\n case \"tray-bounds\":\n case \"ack\":\n case \"ext-command-result\":\n case \"runtime-host-health\":\n return frame.requestId;\n // Acceptance never settles a request (handled before correlation), and a\n // terminal frame carries no requestId at all: both are routed through the\n // deferred-operation map in `dispatchFrame`.\n case \"ext-command-accepted\":\n case \"ext-operation-terminal\":\n case \"ready\":\n case \"event\":\n case \"app-event\":\n case \"ext-event\":\n case \"error\":\n return undefined;\n }\n};\n\nconst resolveCliEntrypoint = (): string => {\n const suffix = fileURLToPath(import.meta.url).endsWith(\".ts\") ? \"cli.ts\" : \"cli.mjs\";\n return fileURLToPath(new URL(`./${suffix}`, import.meta.url));\n};\n","// Orthogonal intents (2026-09-20; harden-transport-robustness Phase C/D,\n// original user request: broker death must surface as a bounded event and\n// recover with zero consumer code):\n// 1. Supervise exactly one live broker connection per generation; never\n// resurrect a dead connection (its D3 single-flight death contract stays\n// per-connection truth).\n// 2. Detect uninvited death through socket close/error plus an idle-gated\n// health-probe heartbeat (Phase A deadline machinery bounds each probe).\n// 3. Recover by reconnecting through the caller's original connect options\n// (identity gates and lock reclaim live in connectLocalBroker), replaying\n// a declarative journal, and re-running registered facade rebuild\n// callbacks in registration order.\n// 4. Bound recovery with an in-process sliding-window budget; exhaustion is\n// the terminal `abandoned` state with typed fail-fast calls.\n// 5. Keep caller-initiated teardown recovery-free and wall-clock bounded\n// (the Phase A teardown budget class is the caller-intent marker).\n\nimport type {\n AppIcon,\n AppRef,\n ClientRequestFrame,\n ExpectedExtensionIdentity,\n Icon,\n Menu,\n RequestId,\n ServerFrame,\n Tooltip,\n TrayId,\n TrayOptions,\n} from \"@opentray/spec\";\n\nimport {\n BROKER_CONNECTION_CLOSED_MESSAGE,\n type LocalBrokerClient,\n} from \"./local-broker\";\nimport {\n BOOTSTRAP_CALL_DEADLINE_MS,\n TEARDOWN_CALL_DEADLINE_MS,\n BrokerServerError,\n type OpenTrayEventFrame,\n type TransportRebuildContext,\n type TransportRequestOptions,\n type TransportState,\n} from \"./client\";\n\n/**\n * Default heartbeat cadence (W2; field-validated numbers from the pnpm-pub\n * silent-wedge reference implementation): probe only after 30 s of silence,\n * settle each probe within 3 s, declare death after 3 consecutive failures.\n */\nexport const DEFAULT_HEARTBEAT_INTERVAL_MS = 30_000;\nexport const DEFAULT_PROBE_DEADLINE_MS = 3_000;\nexport const DEFAULT_HEARTBEAT_FAILURE_THRESHOLD = 3;\n\n/**\n * Default recovery budget (W5): 3 respawn attempts per 10-minute window,\n * 1 s initial cooldown with exponential backoff (factor 2, capped at 30 s),\n * and a 10 s budget per reconnect attempt so a hanging connect can never\n * park the recovery loop. In-memory per supervisor — a fresh `createTray` is\n * a fresh budget, matching \"a manual process restart resets the budget\".\n */\nexport const DEFAULT_RECOVERY_MAX_RESTARTS = 3;\nexport const DEFAULT_RECOVERY_WINDOW_MS = 600_000;\nexport const DEFAULT_RECOVERY_COOLDOWN_MS = 1_000;\nexport const DEFAULT_RECOVERY_BACKOFF_FACTOR = 2;\nexport const DEFAULT_RECOVERY_BACKOFF_CAP_MS = 30_000;\nexport const DEFAULT_RECOVERY_CONNECT_TIMEOUT_MS = 10_000;\n\n/**\n * Typed fail-fast rejection for every call issued after supervision reached\n * its terminal `abandoned` state: the recovery budget is exhausted and the\n * runtime stays headless by design (the consumer process keeps running).\n * Consumers match on `code` (`transport_abandoned`); `details` carries the\n * budget facts `{ recoveries, windowMs }`.\n */\nexport class TransportAbandonedError extends Error {\n readonly code = \"transport_abandoned\";\n readonly details: { readonly recoveries: number; readonly windowMs: number };\n\n constructor(recoveries: number, windowMs: number) {\n super(\n `transport abandoned: ${recoveries} recovery attempts within ${windowMs}ms exhausted the budget; every later call fails fast`,\n );\n this.name = \"TransportAbandonedError\";\n this.details = { recoveries, windowMs };\n }\n}\n\n/**\n * Tier 0/2 recovery policy (W6). Every key has a working default; the whole\n * object is optional — not configuring it means full default protection.\n * Policy stays in the app; mechanism stays in the SDK.\n */\nexport interface TransportRecoveryOptions {\n /**\n * Master switch (default `true`). `false` degrades supervision to today's\n * behavior plus heartbeat death detection: declared death stays terminal\n * per connection, no respawn, no `recovering`/`abandoned` transitions.\n */\n enabled?: boolean;\n /** Recovery attempts allowed per sliding `windowMs` (default 3). */\n maxRestarts?: number;\n /** Sliding budget window in milliseconds (default 600_000 = 10 min). */\n windowMs?: number;\n /** Cooldown before the first respawn attempt (default 1_000). */\n cooldownMs?: number;\n /** Multiplier applied to the cooldown after each failed attempt (default 2). */\n backoffFactor?: number;\n /** Backoff ceiling in milliseconds (default 30_000). */\n backoffCapMs?: number;\n /**\n * Budget for one reconnect attempt (default 10 s). A connect factory that\n * never settles counts as a failed attempt instead of parking the\n * recovery loop; its late-resolving connection is closed on arrival.\n */\n connectTimeoutMs?: number;\n /**\n * Tier 2 hand-over (default: absent). When provided, an uninvited death\n * performs a bounded teardown, invokes this callback exactly once, and goes\n * terminal — the supervisor never performs in-process rebuild and never\n * loops. The SDK never embeds app-process restart vectors itself.\n */\n restartApp?: () => void | Promise<void>;\n}\n\n/** Constructor tuning for {@link createTransportSupervisor}. */\nexport interface CreateTransportSupervisorOptions {\n /**\n * Establishes one broker connection generation. Production callers close\n * over `connectLocalBroker` with the caller's original options so a\n * respawn is exactly a reconnect: daemon lifecycle, identity gates, and\n * lock reclaim all reapply unchanged.\n */\n connect(): Promise<LocalBrokerClient>;\n /** Idle gap before a health probe is sent (default 30 s). */\n heartbeatIntervalMs?: number;\n /** Per-probe deadline budget (default 3 s). */\n probeDeadlineMs?: number;\n /** Consecutive probe failures that declare death (default 3). */\n heartbeatFailureThreshold?: number;\n /** Recovery policy; every key defaulted (Tier 0). */\n recovery?: TransportRecoveryOptions;\n}\n\n/**\n * Declarative state snapshot recorded from successfully settled mutating\n * frames (Tier 0's zero-API journal). One ordered list; keyed entries\n * (tray/app mutations, extension mounts) replace in place at first-occurrence\n * position, `create-tray` entries append in creation order. Only frames that\n * settled successfully are recorded — a rejected mutation never became\n * broker state.\n */\ntype JournalEntry =\n | { kind: \"resolve-default-app\"; appId: string }\n | { kind: \"create-tray\"; app: AppRef; tray: TrayOptions; trayId: TrayId }\n | {\n kind: \"set-tray-menu\";\n appId: string;\n trayId: TrayId;\n menu: Menu;\n }\n | { kind: \"set-tray-icon\"; appId: string; trayId: TrayId; icon: Icon }\n | {\n kind: \"set-tray-tooltip\";\n appId: string;\n trayId: TrayId;\n tooltip: Tooltip;\n }\n | { kind: \"set-app-name\"; appId: string; name: string }\n | { kind: \"set-app-icon\"; appId: string; appIcon: AppIcon | null }\n | { kind: \"set-app-icon-variant\"; appId: string; variant: string }\n | {\n kind: \"load-ext\";\n appId: string;\n name: string;\n path: string;\n expectedIdentity: ExpectedExtensionIdentity;\n mountId?: string;\n };\n\nconst journalKeyOf = (entry: JournalEntry): string | undefined => {\n switch (entry.kind) {\n case \"resolve-default-app\":\n return \"resolve-default-app\";\n case \"create-tray\":\n return undefined;\n case \"set-tray-menu\":\n case \"set-tray-icon\":\n case \"set-tray-tooltip\":\n return `${entry.kind}:${entry.appId}:${entry.trayId}`;\n case \"set-app-name\":\n case \"set-app-icon\":\n case \"set-app-icon-variant\":\n return `${entry.kind}:${entry.appId}`;\n case \"load-ext\":\n return `load-ext:${entry.appId}:${entry.mountId ?? entry.name}`;\n }\n};\n\n/** Structural view of connections publishing Phase A's expiry seam. */\ninterface DeadlineExpirySource {\n onDeadlineExpiry(listener: (expiry: { requestId: RequestId; deadlineMs: number }) => void): () => void;\n}\n\nconst isDeadlineExpirySource = (\n connection: LocalBrokerClient,\n): connection is LocalBrokerClient & DeadlineExpirySource =>\n \"onDeadlineExpiry\" in connection && typeof connection.onDeadlineExpiry === \"function\";\n\n/** Structural view of connections publishing their terminal death signal. */\ninterface ConnectionDeadSource {\n onConnectionDead(handler: (error: Error) => void): () => void;\n}\n\nconst isConnectionDeadSource = (\n connection: LocalBrokerClient,\n): connection is LocalBrokerClient & ConnectionDeadSource =>\n \"onConnectionDead\" in connection && typeof connection.onConnectionDead === \"function\";\n\nconst sleepUnref = (ms: number): Promise<void> =>\n new Promise((resolve) => {\n const timer = setTimeout(resolve, ms);\n timer.unref();\n });\n\n/**\n * Supervised transport (W2/W4/W5/W6): a stable `OpenTrayConnection`-shaped\n * proxy for the layers above (createClient, tray handles) that owns one\n * broker connection per generation underneath. Consumer event subscriptions\n * and the supervision state machine survive generation changes;\n * per-connection surfaces (`onConnectionDead`) stay per-generation truth.\n */\nexport class SupervisedLocalBrokerConnection {\n private readonly heartbeatIntervalMs: number;\n private readonly probeDeadlineMs: number;\n private readonly heartbeatFailureThreshold: number;\n private readonly recoveryEnabled: boolean;\n private readonly maxRestarts: number;\n private readonly recoveryWindowMs: number;\n private readonly cooldownMs: number;\n private readonly backoffFactor: number;\n private readonly backoffCapMs: number;\n private readonly connectTimeoutMs: number;\n private readonly restartApp: (() => void | Promise<void>) | undefined;\n\n private connection: LocalBrokerClient | undefined;\n private generation = 0;\n private state: TransportState = \"healthy\";\n private journal: JournalEntry[] = [];\n private readonly eventListeners = new Set<(frame: OpenTrayEventFrame) => void>();\n private readonly deadListeners = new Set<(error: Error) => void>();\n private readonly stateListeners = new Set<(state: TransportState) => void>();\n private readonly rebuildCallbacks: Array<\n (context: TransportRebuildContext) => Promise<void>\n > = [];\n private unwireGeneration: () => void = noop;\n private heartbeatTimer: ReturnType<typeof setInterval> | undefined;\n private heartbeatOrdinal = 0;\n private heartbeatInFlight = false;\n private consecutiveHeartbeatFailures = 0;\n private lastSettledAt = 0;\n private restartTimestamps: number[] = [];\n private callerInitiated = false;\n /**\n * Monotonic teardown epoch: `shutdown()` bumps it so an in-flight recovery\n * attempt can detect that it raced caller-initiated teardown and abort\n * instead of resurrecting a destroyed runtime (no candidate adoption, no\n * `healthy` transition, no restarted heartbeat).\n */\n private teardownEpoch = 0;\n private shutdownPromise: Promise<void> | undefined;\n\n constructor(\n private readonly connectFactory: () => Promise<LocalBrokerClient>,\n options: CreateTransportSupervisorOptions,\n ) {\n this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;\n this.probeDeadlineMs = options.probeDeadlineMs ?? DEFAULT_PROBE_DEADLINE_MS;\n this.heartbeatFailureThreshold =\n options.heartbeatFailureThreshold ?? DEFAULT_HEARTBEAT_FAILURE_THRESHOLD;\n const recovery = options.recovery ?? {};\n this.recoveryEnabled = recovery.enabled ?? true;\n this.maxRestarts = recovery.maxRestarts ?? DEFAULT_RECOVERY_MAX_RESTARTS;\n this.recoveryWindowMs = recovery.windowMs ?? DEFAULT_RECOVERY_WINDOW_MS;\n this.cooldownMs = recovery.cooldownMs ?? DEFAULT_RECOVERY_COOLDOWN_MS;\n this.backoffFactor = recovery.backoffFactor ?? DEFAULT_RECOVERY_BACKOFF_FACTOR;\n this.backoffCapMs = recovery.backoffCapMs ?? DEFAULT_RECOVERY_BACKOFF_CAP_MS;\n this.connectTimeoutMs = recovery.connectTimeoutMs ?? DEFAULT_RECOVERY_CONNECT_TIMEOUT_MS;\n this.restartApp = recovery.restartApp;\n }\n\n /** Current supervision state; edge events go to {@link onTransportStateChange}. */\n get transportState(): TransportState {\n return this.state;\n }\n\n /** Monotonic generation counter; each respawn/replay increments it once. */\n get transportGeneration(): number {\n return this.generation;\n }\n\n /** Current generation's endpoint (proxy; absent before the first connect). */\n get endpoint(): string {\n return this.connection?.endpoint ?? \"\";\n }\n\n /** Current generation's caller label (proxy; absent before the first connect). */\n get callerLabel(): string {\n return this.connection?.callerLabel ?? \"\";\n }\n\n /**\n * Current generation's broker session id. Read dynamically so extension\n * contexts and rebuild callbacks can attribute session-owned state to the\n * live generation (the id changes on every respawn).\n */\n get sessionId(): string {\n return this.connection?.sessionId ?? \"\";\n }\n\n /** True once the current generation's connection died (or none exists). */\n get connectionDead(): boolean {\n return this.connection === undefined || this.connection.connectionDead;\n }\n\n /**\n * Establishes generation 0. A failure here propagates to the caller\n * unchanged — supervision (heartbeat, recovery) only guards a connection\n * that once existed; an app that never started is a plain startup failure.\n */\n async connect(): Promise<void> {\n const connection = await this.connectFactory();\n this.connection = connection;\n this.unwireGeneration = this.wireGeneration(connection);\n this.lastSettledAt = Date.now();\n this.consecutiveHeartbeatFailures = 0;\n this.startHeartbeat();\n }\n\n /**\n * Forwards one request to the current generation. After the terminal\n * `abandoned` state every call fails fast with {@link TransportAbandonedError}.\n * A teardown-budget call (`deadlineMs === TEARDOWN_CALL_DEADLINE_MS`) marks\n * the supervision caller-initiated: Phase A froze the budget class as the\n * caller-intent channel, so a socket close racing caller-initiated destroy\n * can never be misread as uninvited death.\n */\n async request(\n frame: ClientRequestFrame,\n options: TransportRequestOptions = {},\n ): Promise<ServerFrame> {\n if (this.state === \"abandoned\") {\n throw new TransportAbandonedError(this.restartTimestamps.length, this.recoveryWindowMs);\n }\n if (options.deadlineMs === TEARDOWN_CALL_DEADLINE_MS) {\n this.callerInitiated = true;\n }\n const connection = this.connection;\n if (connection === undefined) {\n throw new Error(BROKER_CONNECTION_CLOSED_MESSAGE);\n }\n const candidate = journalCandidateFrom(frame);\n const response = await connection.request(frame, options);\n this.noteSuccessfulSettlement();\n if (candidate !== undefined) {\n this.commitJournalEntry(candidate, response);\n }\n if (frame.type === \"destroy-tray\") {\n // A successfully destroyed tray must not resurrect on recovery: the\n // journal mirrors declarative broker state, so teardown evicts it.\n this.evictJournalTray(frame.appId, frame.trayId);\n }\n return response;\n }\n\n /**\n * Consumer event subscription that survives generation changes: each new\n * generation's event stream fans out to the same listeners.\n */\n onEvent(listener: (frame: OpenTrayEventFrame) => void): () => void {\n this.eventListeners.add(listener);\n return () => {\n this.eventListeners.delete(listener);\n };\n }\n\n /**\n * Per-connection death notification, forwarded for every generation (D3\n * semantics preserved: consumers using it for per-connection cleanup keep\n * working; the supervision state machine is the new higher-level truth).\n */\n onConnectionDead(listener: (error: Error) => void): () => void {\n this.deadListeners.add(listener);\n return () => {\n this.deadListeners.delete(listener);\n };\n }\n\n /**\n * Tier 1 health projection (W6): edge-triggered `healthy | recovering |\n * abandoned` transitions. The initial `healthy` state never fires —\n * consumers reading the current state use `transportState`.\n */\n onTransportStateChange(listener: (state: TransportState) => void): () => void {\n this.stateListeners.add(listener);\n return () => {\n this.stateListeners.delete(listener);\n };\n }\n\n /**\n * Registers one facade rebuild callback (W4). Callbacks run in\n * registration order after the core journal replay on every successful\n * recovery, receiving the fresh generation number and session id so\n * session-attributed native state can be re-created against the live\n * broker session.\n */\n registerTransportRebuild(\n rebuild: (context: TransportRebuildContext) => Promise<void>,\n ): void {\n this.rebuildCallbacks.push(rebuild);\n }\n\n /**\n * Graceful teardown channel (W4/W3): idempotent, marks the supervision\n * caller-initiated synchronously (so the close-driven death event can\n * never trigger recovery), bumps the teardown epoch (so an in-flight\n * recovery attempt aborts instead of resurrecting the runtime), stops the\n * heartbeat, then closes the current generation — including an\n * adoption-in-progress candidate routed through `this.connection` —\n * within its bounded graceful-close budget.\n */\n async shutdown(): Promise<void> {\n this.callerInitiated = true;\n this.teardownEpoch += 1;\n this.shutdownPromise ??= (async () => {\n this.stopHeartbeat();\n this.unwireGeneration();\n this.unwireGeneration = noop;\n const connection = this.connection;\n this.connection = undefined;\n if (connection !== undefined) {\n await connection.close().catch(noopAsync);\n }\n })();\n await this.shutdownPromise;\n }\n\n /** LocalBrokerClient structural compatibility: graceful close == shutdown. */\n close(): Promise<void> {\n return this.shutdown();\n }\n\n private startHeartbeat(): void {\n if (this.heartbeatTimer !== undefined) {\n return;\n }\n this.heartbeatTimer = setInterval(() => {\n void this.heartbeatTick();\n }, this.heartbeatIntervalMs);\n // Library semantics: supervision must never keep the host process alive.\n this.heartbeatTimer.unref();\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer !== undefined) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = undefined;\n }\n }\n\n /**\n * Idle-gated heartbeat (W2): a transport that keeps settling requests\n * proves its own liveness, so the probe budget is spent only on silence.\n * A probe failure of any rejection class (typed timeout, transport-lost,\n * broker error frame) counts; a successful settlement resets the streak.\n * Single-flight with a generation token: at most one probe per generation\n * is outstanding (a configured interval shorter than the probe deadline\n * must not run concurrent probes whose completions double-count), and a\n * probe that outlives its generation settles nothing.\n */\n private async heartbeatTick(): Promise<void> {\n if (this.heartbeatInFlight) {\n return;\n }\n const connection = this.connection;\n const probeGeneration = this.generation;\n if (\n connection === undefined ||\n this.state !== \"healthy\" ||\n this.callerInitiated\n ) {\n return;\n }\n if (Date.now() - this.lastSettledAt < this.heartbeatIntervalMs) {\n return;\n }\n this.heartbeatInFlight = true;\n const requestId = `supervisor-heartbeat-${this.generation}-${(this.heartbeatOrdinal += 1)}`;\n try {\n await connection.request(\n { type: \"health\", requestId },\n { deadlineMs: this.probeDeadlineMs },\n );\n if (this.generation === probeGeneration && this.state === \"healthy\") {\n this.consecutiveHeartbeatFailures = 0;\n this.noteSuccessfulSettlement();\n }\n } catch (error) {\n if (this.generation !== probeGeneration || this.state !== \"healthy\") {\n return;\n }\n this.consecutiveHeartbeatFailures += 1;\n if (this.consecutiveHeartbeatFailures < this.heartbeatFailureThreshold) {\n return;\n }\n // Declared death: settle the verdict through the sentinel family so\n // consumers matching the message keep working; the cause carries the\n // probe accounting for diagnostics.\n const death = new Error(BROKER_CONNECTION_CLOSED_MESSAGE, {\n cause: `heartbeat declared death after ${this.consecutiveHeartbeatFailures} consecutive probe failures (${String(error)})`,\n });\n // The death funnel runs first and unwires this generation; the bounded\n // close then rejects the half-open socket's pending entries through\n // the real destroy path without a second death notification.\n this.handleGenerationDeath(death);\n void connection.close().catch(noopAsync);\n } finally {\n this.heartbeatInFlight = false;\n }\n }\n\n private noteSuccessfulSettlement(): void {\n this.lastSettledAt = Date.now();\n this.consecutiveHeartbeatFailures = 0;\n }\n\n /**\n * Subscribes this supervisor's stable listener sets to one generation.\n * Event fanout and the death/expiry seams are wired before the generation\n * becomes `this.connection` (recovery candidates are wired before replay)\n * so no observable event window opens between adoption steps.\n */\n private wireGeneration(connection: LocalBrokerClient): () => void {\n const unwires: Array<() => void> = [];\n const unlistenEvents = connection.onEvent((frame) => {\n for (const listener of [...this.eventListeners]) {\n try {\n listener(frame);\n } catch {\n // A throwing consumer listener must not block fan-out.\n }\n }\n });\n unwires.push(unlistenEvents);\n // Structural capability tap (repo pattern): transports without a\n // death signal keep every other supervision feature and simply never\n // declare socket-close deaths — the real local broker connection always\n // publishes one, test fakes may not.\n if (isConnectionDeadSource(connection)) {\n const unlistenDead = connection.onConnectionDead((error) => {\n this.handleGenerationDeath(error);\n });\n unwires.push(unlistenDead);\n }\n if (isDeadlineExpirySource(connection)) {\n const unlistenExpiry = connection.onDeadlineExpiry((expiry) => {\n // Probe expiries are attributed by the probe's own rejection; every\n // other expiry is one liveness-failure signal (W1: an expiry never\n // declares death by itself).\n if (expiry.requestId.startsWith(\"supervisor-heartbeat-\")) {\n return;\n }\n this.consecutiveHeartbeatFailures += 1;\n if (\n this.consecutiveHeartbeatFailures >= this.heartbeatFailureThreshold &&\n this.state === \"healthy\" &&\n !this.callerInitiated\n ) {\n const connectionAtDeath = this.connection;\n // Death funnel first (unwires), bounded close second: same ordering\n // guarantee as the probe-failure path above.\n this.handleGenerationDeath(\n new Error(BROKER_CONNECTION_CLOSED_MESSAGE, {\n cause: `heartbeat declared death after ${this.consecutiveHeartbeatFailures} consecutive deadline expiries`,\n }),\n );\n if (connectionAtDeath !== undefined) {\n void connectionAtDeath.close().catch(noopAsync);\n }\n }\n });\n unwires.push(unlistenExpiry);\n }\n return () => {\n for (const unwire of unwires.splice(0)) {\n unwire();\n }\n };\n }\n\n /**\n * Death funnel: forwards the per-connection event first (D3 truth), stops\n * this generation's wiring, then decides the supervision reaction. The\n * state guard makes the reaction single-flight — deaths of candidates\n * during an ongoing recovery only forward, they never nest recoveries.\n */\n private handleGenerationDeath(error: Error): void {\n for (const listener of [...this.deadListeners]) {\n try {\n listener(error);\n } catch {\n // A throwing terminal listener must not block death propagation.\n }\n }\n if (this.callerInitiated || this.state !== \"healthy\") {\n return;\n }\n this.unwireGeneration();\n this.unwireGeneration = noop;\n if (this.restartApp !== undefined) {\n void this.handOverToRestartApp();\n return;\n }\n if (!this.recoveryEnabled) {\n // Tier-off: declared death stays terminal per connection (today's\n // behavior + heartbeat); no state transitions, no respawn.\n return;\n }\n void this.runRecovery();\n }\n\n /**\n * Tier 2 hand-over: bounded teardown of the current generation, the app's\n * restart vector invoked exactly once, then terminal. No in-process\n * rebuild, no loop — restart ownership belongs to the callback.\n */\n private async handOverToRestartApp(): Promise<void> {\n this.setState(\"recovering\");\n // Suppress every further supervision reaction first: our own teardown\n // fires the generation's death event, and the restart vector is the\n // app's policy from here on.\n this.callerInitiated = true;\n this.stopHeartbeat();\n const connection = this.connection;\n if (connection !== undefined && !connection.connectionDead) {\n await connection.close().catch(noopAsync);\n }\n try {\n await this.restartApp?.();\n } catch (error) {\n // The callback is app policy: surface the failure, never re-enter\n // supervision with it, and still settle the terminal state.\n console.error(\"OpenTray recovery.restartApp callback failed:\", error);\n }\n this.setState(\"abandoned\");\n }\n\n /**\n * In-process recovery (W4/W5): cooldown backoff → reconnect through the\n * original connect options → journal replay → facade rebuilds → healthy.\n * Every attempt consumes budget up front; a failed attempt (connect,\n * replay, or rebuild — including artifact identity mismatches) retries\n * inside the remaining budget until exhaustion abandons the runtime. Each\n * reconnect attempt is bounded by the connect budget, and every step\n * re-checks the teardown epoch so a shutdown racing the loop aborts it\n * instead of resurrecting the runtime.\n */\n private async runRecovery(): Promise<void> {\n this.setState(\"recovering\");\n let backoffOrdinal = 0;\n while (true) {\n if (this.callerInitiated) {\n // Consumer teardown raced the recovery; the graceful path wins.\n return;\n }\n if (!this.consumeRestartBudget()) {\n this.setState(\"abandoned\");\n return;\n }\n await sleepUnref(this.cooldownForBackoff(backoffOrdinal));\n if (this.callerInitiated) {\n return;\n }\n const attemptEpoch = this.teardownEpoch;\n try {\n const candidate = await this.connectWithBudget();\n if (this.teardownEpoch !== attemptEpoch || this.callerInitiated) {\n // Shutdown landed while the connect was in flight: the candidate\n // belongs to nobody — close it and stay torn down.\n await candidate.close().catch(noopAsync);\n return;\n }\n await this.adoptGeneration(candidate, attemptEpoch);\n if (this.teardownEpoch !== attemptEpoch || this.callerInitiated) {\n return;\n }\n this.setState(\"healthy\");\n return;\n } catch {\n backoffOrdinal += 1;\n }\n }\n }\n\n /**\n * One reconnect attempt under the connect budget. A factory that never\n * settles counts as a failed attempt; a connection arriving after the\n * budget expired is closed on arrival so no orphan generation leaks.\n */\n private async connectWithBudget(): Promise<LocalBrokerClient> {\n let settled = false;\n return new Promise<LocalBrokerClient>((resolve, reject) => {\n const late = (candidate: LocalBrokerClient): void => {\n void candidate.close().catch(noopAsync);\n };\n const timer = setTimeout(() => {\n if (settled) {\n return;\n }\n settled = true;\n reject(new Error(`recovery connect exceeded ${this.connectTimeoutMs}ms`));\n }, this.connectTimeoutMs);\n timer.unref();\n this.connectFactory().then(\n (candidate) => {\n if (settled) {\n late(candidate);\n return;\n }\n settled = true;\n clearTimeout(timer);\n resolve(candidate);\n },\n (error: unknown) => {\n if (settled) {\n return;\n }\n settled = true;\n clearTimeout(timer);\n reject(error instanceof Error ? error : new Error(String(error)));\n },\n );\n });\n }\n\n private cooldownForBackoff(backoffOrdinal: number): number {\n return Math.min(\n this.cooldownMs * this.backoffFactor ** backoffOrdinal,\n this.backoffCapMs,\n );\n }\n\n /**\n * Sliding-window budget: one timestamp per respawn attempt (successful or\n * not — both are respawns the consumer experienced). In-memory per\n * supervisor by ruling; a fresh `createTray` starts a fresh budget.\n */\n private consumeRestartBudget(): boolean {\n const windowStart = Date.now() - this.recoveryWindowMs;\n this.restartTimestamps = this.restartTimestamps.filter(\n (timestamp) => timestamp > windowStart,\n );\n if (this.restartTimestamps.length >= this.maxRestarts) {\n return false;\n }\n this.restartTimestamps.push(Date.now());\n return true;\n }\n\n /**\n * Wires the candidate generation, replays the journal, and runs the\n * facade rebuild callbacks. The candidate becomes `this.connection` for\n * the adoption's duration — facade rebuild callbacks route their\n * re-creation commands through this supervisor, so they must reach the\n * candidate, not the dead generation (the rebuild-routing law). A failure\n * rolls the candidate back out (unwired, closed) and restores the dead\n * previous connection so consumer calls keep failing fast; a teardown\n * racing the adoption aborts without resurrecting anything.\n */\n private async adoptGeneration(\n candidate: LocalBrokerClient,\n attemptEpoch: number,\n ): Promise<void> {\n const previousConnection = this.connection;\n this.generation += 1;\n this.unwireGeneration = this.wireGeneration(candidate);\n this.connection = candidate;\n try {\n await this.replayJournal(candidate);\n for (const rebuild of [...this.rebuildCallbacks]) {\n await rebuild({\n generation: this.generation,\n sessionId: candidate.sessionId.length > 0 ? candidate.sessionId : undefined,\n });\n }\n if (this.teardownEpoch !== attemptEpoch || this.callerInitiated) {\n // Shutdown raced a fully replayed candidate: unwind it instead of\n // resurrecting a torn-down runtime.\n this.rollbackAdoption(candidate, previousConnection);\n throw new Error(\"recovery aborted by caller-initiated teardown\");\n }\n } catch (error) {\n this.rollbackAdoption(candidate, previousConnection);\n throw error;\n }\n this.consecutiveHeartbeatFailures = 0;\n this.noteSuccessfulSettlement();\n }\n\n /**\n * Removes a failed (or torn-down) adoption candidate: stop its wiring,\n * close it bounded, and restore the previous dead connection unless a\n * caller-initiated shutdown already dissolved the runtime (shutdown's own\n * close handled the candidate in that window; the restore must not undo\n * the torn-down state).\n */\n private rollbackAdoption(\n candidate: LocalBrokerClient,\n previousConnection: LocalBrokerClient | undefined,\n ): void {\n this.unwireGeneration();\n this.unwireGeneration = noop;\n if (this.connection === candidate) {\n this.connection = this.callerInitiated ? undefined : previousConnection;\n }\n void candidate.close().catch(noopAsync);\n }\n\n /**\n * Replays the declarative journal in record order with fresh request ids\n * under the bootstrap deadline class. The resolved default app of the new\n * generation becomes the appId authority: replayed frames are rewritten\n * onto it, so app-scoped state follows broker truth instead of a stale\n * generation's identity.\n */\n private async replayJournal(connection: LocalBrokerClient): Promise<void> {\n let ordinal = 0;\n const appIdRewrites = new Map<string, string>();\n const rewriteAppId = (appId: string): string => appIdRewrites.get(appId) ?? appId;\n for (const entry of this.journal) {\n ordinal += 1;\n const requestId: RequestId = `supervisor-replay-${this.generation}-${ordinal}`;\n let frame: ClientRequestFrame;\n switch (entry.kind) {\n case \"resolve-default-app\":\n frame = { type: \"resolve-default-app\", requestId };\n break;\n case \"create-tray\":\n frame = {\n type: \"create-tray\",\n requestId,\n app: { appId: rewriteAppId(entry.app.appId) },\n // Inject the originally resolved trayId: handle identity must\n // stay stable across generations even when the caller omitted a\n // tray id and the first broker assigned one.\n tray: { ...entry.tray, id: entry.trayId },\n };\n break;\n case \"set-tray-menu\":\n frame = {\n type: \"set-tray-menu\",\n requestId,\n appId: rewriteAppId(entry.appId),\n trayId: entry.trayId,\n menu: entry.menu,\n };\n break;\n case \"set-tray-icon\":\n frame = {\n type: \"set-tray-icon\",\n requestId,\n appId: rewriteAppId(entry.appId),\n trayId: entry.trayId,\n icon: entry.icon,\n };\n break;\n case \"set-tray-tooltip\":\n frame = {\n type: \"set-tray-tooltip\",\n requestId,\n appId: rewriteAppId(entry.appId),\n trayId: entry.trayId,\n tooltip: entry.tooltip,\n };\n break;\n case \"set-app-name\":\n frame = {\n type: \"set-app-name\",\n requestId,\n appId: rewriteAppId(entry.appId),\n name: entry.name,\n };\n break;\n case \"set-app-icon\":\n frame = {\n type: \"set-app-icon\",\n requestId,\n appId: rewriteAppId(entry.appId),\n appIcon: entry.appIcon,\n };\n break;\n case \"set-app-icon-variant\":\n frame = {\n type: \"set-app-icon-variant\",\n requestId,\n appId: rewriteAppId(entry.appId),\n variant: entry.variant,\n };\n break;\n case \"load-ext\":\n frame = {\n type: \"load-ext\",\n requestId,\n appId: rewriteAppId(entry.appId),\n name: entry.name,\n path: entry.path,\n expectedIdentity: entry.expectedIdentity,\n ...(entry.mountId === undefined ? {} : { mountId: entry.mountId }),\n };\n break;\n }\n const response = await connection.request(frame, {\n deadlineMs: BOOTSTRAP_CALL_DEADLINE_MS,\n });\n if (response.type === \"error\") {\n throw new BrokerServerError(response.code, response.message, {\n details: response.details,\n });\n }\n if (entry.kind === \"resolve-default-app\" && response.type === \"default-app\") {\n appIdRewrites.set(entry.appId, response.app.appId);\n }\n }\n }\n\n private setState(state: TransportState): void {\n if (this.state === state) {\n return;\n }\n this.state = state;\n if (state === \"abandoned\") {\n // Terminal: no heartbeat is ever useful again.\n this.stopHeartbeat();\n }\n for (const listener of [...this.stateListeners]) {\n try {\n listener(state);\n } catch {\n // A throwing state listener must not block the transition.\n }\n }\n }\n\n private commitJournalEntry(frame: ClientRequestFrame, response: ServerFrame): void {\n switch (frame.type) {\n case \"resolve-default-app\":\n if (response.type === \"default-app\") {\n this.upsertJournal({\n kind: \"resolve-default-app\",\n appId: response.app.appId,\n });\n }\n return;\n case \"create-tray\": {\n const trayId: TrayId =\n response.type === \"tray-created\" && typeof response.trayId === \"string\"\n ? response.trayId\n : frame.tray.id;\n this.journal.push({\n kind: \"create-tray\",\n app: frame.app,\n tray: frame.tray,\n trayId,\n });\n return;\n }\n case \"set-tray-menu\":\n this.upsertJournal({\n kind: \"set-tray-menu\",\n appId: frame.appId,\n trayId: frame.trayId,\n menu: frame.menu,\n });\n return;\n case \"set-tray-icon\":\n this.upsertJournal({\n kind: \"set-tray-icon\",\n appId: frame.appId,\n trayId: frame.trayId,\n icon: frame.icon,\n });\n return;\n case \"set-tray-tooltip\":\n this.upsertJournal({\n kind: \"set-tray-tooltip\",\n appId: frame.appId,\n trayId: frame.trayId,\n tooltip: frame.tooltip,\n });\n return;\n case \"set-app-name\":\n this.upsertJournal({ kind: \"set-app-name\", appId: frame.appId, name: frame.name });\n return;\n case \"set-app-icon\":\n this.upsertJournal({\n kind: \"set-app-icon\",\n appId: frame.appId,\n appIcon: frame.appIcon,\n });\n return;\n case \"set-app-icon-variant\":\n this.upsertJournal({\n kind: \"set-app-icon-variant\",\n appId: frame.appId,\n variant: frame.variant,\n });\n return;\n case \"load-ext\":\n this.upsertJournal({\n kind: \"load-ext\",\n appId: frame.appId,\n name: frame.name,\n path: frame.path,\n expectedIdentity: frame.expectedIdentity,\n ...(frame.mountId === undefined ? {} : { mountId: frame.mountId }),\n });\n return;\n default:\n return;\n }\n }\n\n /**\n * Keyed entries replace in place at first-occurrence position (last-write-\n * wins value, stable ordering); first occurrences append. Tray creations\n * and mount declarations keep their creation order by construction.\n */\n private upsertJournal(entry: JournalEntry): void {\n const key = journalKeyOf(entry);\n if (key === undefined) {\n this.journal.push(entry);\n return;\n }\n const existing = this.journal.findIndex(\n (candidate) => journalKeyOf(candidate) === key,\n );\n if (existing < 0) {\n this.journal.push(entry);\n return;\n }\n this.journal[existing] = entry;\n }\n\n private evictJournalTray(appId: string, trayId: TrayId): void {\n this.journal = this.journal.filter((entry) => {\n switch (entry.kind) {\n case \"create-tray\":\n return !(entry.app.appId === appId && entry.trayId === trayId);\n case \"set-tray-menu\":\n case \"set-tray-icon\":\n case \"set-tray-tooltip\":\n return !(entry.appId === appId && entry.trayId === trayId);\n default:\n return true;\n }\n });\n }\n}\n\n/**\n * Snapshot candidate for the declarative journal: a defensive clone of every\n * journalable mutating frame, taken before the await so later caller\n * mutation of the frame object cannot corrupt the recorded state. The entry\n * is committed only after the frame settles successfully.\n */\nconst journalCandidateFrom = (frame: ClientRequestFrame): ClientRequestFrame | undefined => {\n switch (frame.type) {\n case \"resolve-default-app\":\n case \"create-tray\":\n case \"set-tray-menu\":\n case \"set-tray-icon\":\n case \"set-tray-tooltip\":\n case \"set-app-name\":\n case \"set-app-icon\":\n case \"set-app-icon-variant\":\n case \"load-ext\":\n return structuredClone(frame);\n default:\n return undefined;\n }\n};\n\n/** Constructs a supervised transport around one connect factory. */\nexport const createTransportSupervisor = (\n options: CreateTransportSupervisorOptions,\n): SupervisedLocalBrokerConnection =>\n new SupervisedLocalBrokerConnection(options.connect, options);\n\nconst noop = (): void => {};\nconst noopAsync = (): void => {};\n","import type { Menu, MenuItem, MenuItemId } from \"@opentray/spec\";\n\nimport type { TrayEventByType } from \"./client\";\n\nexport type CreateTrayMenuClickHandler = (\n event: TrayEventByType<\"menuClick\">\n) => void;\n\n/** App-facing menu input accepted by top-level createTray and setMenu. */\nexport type CreateTrayMenu = {\n items: CreateTrayMenuItem[];\n};\n\n/** Menu item shorthand normalized to protocol MenuItem before runtime transport. */\nexport type CreateTrayMenuItem =\n | string\n | readonly [title: string, items: readonly CreateTrayMenuItem[]]\n | CreateTrayItem\n | CreateTrayCheckItem\n | CreateTrayRadioItem\n | CreateTraySeparatorItem\n | CreateTraySubmenuItem;\n\nexport type CreateTrayItem = {\n type?: \"item\";\n id?: MenuItemId;\n title: string;\n primaryEvent?: boolean;\n enabled?: boolean;\n shortcut?: string;\n onMenuClick?: CreateTrayMenuClickHandler;\n};\n\nexport type CreateTrayCheckItem = {\n type: \"check\";\n id?: MenuItemId;\n title: string;\n enabled?: boolean;\n checked?: boolean;\n onMenuClick?: CreateTrayMenuClickHandler;\n};\n\nexport type CreateTrayRadioItem = {\n type: \"radio\";\n id?: MenuItemId;\n title: string;\n enabled?: boolean;\n checked?: boolean;\n group: number;\n onMenuClick?: CreateTrayMenuClickHandler;\n};\n\nexport type CreateTraySeparatorItem = {\n type: \"separator\";\n};\n\nexport type CreateTraySubmenuItem = {\n type: \"submenu\";\n title: string;\n enabled?: boolean;\n items: readonly CreateTrayMenuItem[];\n};\n\nexport interface NormalizedCreateTrayMenu {\n menu: Menu;\n handlers: Map<MenuItemId, CreateTrayMenuClickHandler[]>;\n}\n\nexport const normalizeCreateTrayMenu = (\n menu: CreateTrayMenu\n): NormalizedCreateTrayMenu => {\n const state: NormalizeState = {\n usedIds: collectExplicitMenuIds(menu.items),\n nextId: 1,\n handlers: new Map(),\n };\n return {\n menu: {\n items: menu.items.map((item) => normalizeCreateTrayMenuItem(item, state)),\n },\n handlers: state.handlers,\n };\n};\n\nconst normalizeCreateTrayMenuItem = (\n item: CreateTrayMenuItem,\n state: NormalizeState\n): MenuItem => {\n if (typeof item === \"string\") {\n if (isSeparatorShortcut(item)) {\n return { type: \"separator\" };\n }\n return normalizePlainItem({ title: item }, state);\n }\n if (isSubmenuTuple(item)) {\n const [title, items] = item;\n return {\n type: \"submenu\",\n title,\n items: items.map((child) => normalizeCreateTrayMenuItem(child, state)),\n };\n }\n switch (item.type) {\n case undefined:\n case \"item\":\n return normalizePlainItem(item, state);\n case \"check\":\n return normalizeCheckItem(item, state);\n case \"radio\":\n return normalizeRadioItem(item, state);\n case \"separator\":\n return item;\n case \"submenu\":\n return {\n type: \"submenu\",\n title: item.title,\n ...(item.enabled === undefined ? {} : { enabled: item.enabled }),\n items: item.items.map((child) =>\n normalizeCreateTrayMenuItem(child, state)\n ),\n };\n }\n throw new Error(\"unsupported menu item\");\n};\n\nconst normalizeClickableItem = (\n item: {\n id?: MenuItemId;\n onMenuClick?: CreateTrayMenuClickHandler;\n },\n state: NormalizeState\n): MenuItemId => {\n const id = item.id ?? allocateMenuItemId(state);\n registerClickId(state, id);\n if (item.onMenuClick !== undefined) {\n const handlers = state.handlers.get(id) ?? [];\n handlers.push(item.onMenuClick);\n state.handlers.set(id, handlers);\n }\n return id;\n};\n\nconst normalizePlainItem = (\n item: CreateTrayItem,\n state: NormalizeState\n): Extract<MenuItem, { type: \"item\" }> => {\n const id = normalizeClickableItem(item, state);\n return {\n type: \"item\",\n id,\n title: item.title,\n ...(item.primaryEvent === undefined\n ? {}\n : { primaryEvent: item.primaryEvent }),\n ...(item.enabled === undefined ? {} : { enabled: item.enabled }),\n ...(item.shortcut === undefined ? {} : { shortcut: item.shortcut }),\n };\n};\n\nconst normalizeCheckItem = (\n item: CreateTrayCheckItem,\n state: NormalizeState\n): Extract<MenuItem, { type: \"check\" }> => {\n const id = normalizeClickableItem(item, state);\n return {\n type: \"check\",\n id,\n title: item.title,\n ...(item.enabled === undefined ? {} : { enabled: item.enabled }),\n ...(item.checked === undefined ? {} : { checked: item.checked }),\n };\n};\n\nconst normalizeRadioItem = (\n item: CreateTrayRadioItem,\n state: NormalizeState\n): Extract<MenuItem, { type: \"radio\" }> => {\n const id = normalizeClickableItem(item, state);\n return {\n type: \"radio\",\n id,\n title: item.title,\n ...(item.enabled === undefined ? {} : { enabled: item.enabled }),\n ...(item.checked === undefined ? {} : { checked: item.checked }),\n group: item.group,\n };\n};\n\nconst allocateMenuItemId = (state: NormalizeState): MenuItemId => {\n while (state.usedIds.has(state.nextId)) {\n state.nextId += 1;\n }\n const id = state.nextId;\n state.usedIds.add(id);\n state.nextId += 1;\n return id;\n};\n\nconst collectExplicitMenuIds = (\n items: readonly CreateTrayMenuItem[]\n): Set<MenuItemId> => {\n const ids = new Set<MenuItemId>();\n for (const item of items) {\n if (typeof item === \"string\") {\n continue;\n }\n if (isSubmenuTuple(item)) {\n for (const id of collectExplicitMenuIds(item[1])) {\n ids.add(id);\n }\n continue;\n }\n switch (item.type) {\n case undefined:\n case \"item\":\n case \"check\":\n case \"radio\":\n if (item.id !== undefined) {\n ids.add(item.id);\n }\n break;\n case \"submenu\":\n for (const id of collectExplicitMenuIds(item.items)) {\n ids.add(id);\n }\n break;\n case \"separator\":\n break;\n }\n }\n return ids;\n};\n\nconst isSeparatorShortcut = (value: string): boolean => /^-+$/.test(value);\n\nconst isSubmenuTuple = (\n item: CreateTrayMenuItem\n): item is readonly [title: string, items: readonly CreateTrayMenuItem[]] =>\n Array.isArray(item);\n\nconst registerClickId = (state: NormalizeState, id: MenuItemId): void => {\n const seen = state.seenClickIds ?? new Set<MenuItemId>();\n if (seen.has(id)) {\n throw new Error(`duplicate menu item id: ${id}`);\n }\n seen.add(id);\n state.seenClickIds = seen;\n};\n\ninterface NormalizeState {\n usedIds: Set<MenuItemId>;\n nextId: MenuItemId;\n handlers: Map<MenuItemId, CreateTrayMenuClickHandler[]>;\n seenClickIds?: Set<MenuItemId>;\n}\n","// Orthogonal intents (2026-07-20; original user request: an empty launch\n// setting reuses the current process invocation and explicit scripts are allowed):\n// 1. Normalize caller-facing launch options into a durable executable vector.\n// 2. Resolve cwd and path-like commands without invoking a shell.\n// 3. Keep environment variables out of the persisted descriptor.\n\nimport { isAbsolute, resolve } from \"node:path\";\n\nimport type { OpenTrayAppLaunchDescriptor, OpenTrayAppLaunchOptions } from \"@opentray/packaging\";\n\nexport const normalizeAppLaunch = (\n configured: OpenTrayAppLaunchOptions | null | undefined,\n context: {\n readonly execPath?: string;\n readonly argv?: readonly string[];\n readonly cwd?: string;\n } = {},\n): OpenTrayAppLaunchDescriptor => {\n const currentCwd = context.cwd ?? process.cwd();\n if (configured === undefined || configured === null) {\n return {\n schemaVersion: 1,\n command: validateRequiredText(context.execPath ?? process.execPath, \"process.execPath\"),\n args: [...(context.argv ?? process.argv).slice(1)].map((arg, index) =>\n validateArg(arg, `process.argv[${index + 1}]`),\n ),\n cwd: validateRequiredText(currentCwd, \"process.cwd()\"),\n };\n }\n const command = validateRequiredText(configured.command, \"appLaunch.command\");\n const configuredCwd =\n configured.cwd === undefined\n ? currentCwd\n : validateRequiredText(configured.cwd, \"appLaunch.cwd\");\n const cwd = resolve(currentCwd, configuredCwd);\n const args = [...(configured.args ?? [])].map((arg, index) =>\n validateArg(arg, `appLaunch.args[${index}]`),\n );\n return {\n schemaVersion: 1,\n command: resolvePathLikeCommand(command, currentCwd),\n args,\n cwd,\n };\n};\n\nconst resolvePathLikeCommand = (command: string, cwd: string): string => {\n if (isAbsolute(command) || command.includes(\"/\") || command.includes(\"\\\\\")) {\n return resolve(cwd, command);\n }\n return command;\n};\n\nconst validateRequiredText = (value: string, field: string): string => {\n if (value.trim().length === 0 || value.includes(\"\\u0000\")) {\n throw new Error(`${field} must be a non-empty string without NUL`);\n }\n return value;\n};\n\nconst validateArg = (value: string, field: string): string => {\n if (value.includes(\"\\u0000\")) {\n throw new Error(`${field} must be a string without NUL`);\n }\n return value;\n};\n","// Orthogonal intents (maintained 2026-07-21; original user requests: pnpm\n// install must be sufficient; an empty App launch command must remember the\n// current process.argv invocation for the next stable-bundle launch):\n// 1. Expose one direct, ergonomic createTray entrypoint.\n// 2. Normalize app-facing menu shorthand into the protocol model.\n// 3. Make the returned handle own and deterministically close its broker session.\n// 4. Snapshot caller launch intent before initializing the local runtime.\n\nimport type { AppIcon, Icon, Tooltip, TrayOptions } from \"@opentray/spec\";\nimport type {\n OpenTrayAppBundleOptions,\n OpenTrayAppLaunchOptions,\n} from \"@opentray/packaging\";\n\nimport {\n createClient,\n type EventfulTrayHandle,\n type TrayExtension,\n} from \"./client\";\nimport { connectLocalBroker, BROKER_CONNECTION_CLOSED_MESSAGE } from \"./local-broker\";\nimport {\n createTransportSupervisor,\n type TransportRecoveryOptions,\n} from \"./transport-supervision\";\nimport {\n normalizeCreateTrayMenu,\n type CreateTrayMenu,\n type CreateTrayMenuClickHandler,\n} from \"./menu-input\";\nimport { normalizeAppIcon, validateAppIcon } from \"./app-icon\";\nimport { normalizeAppLaunch } from \"./app-launch\";\n\nexport interface OpenTrayRuntimeOptions {\n endpoint?: string;\n homeDir?: string;\n packageVersion?: string;\n protocolVersion?: number;\n clientVersion?: string;\n appId?: string;\n appName?: string;\n appIcon?: AppIcon;\n appBundle?: OpenTrayAppBundleOptions;\n /** Stable app-entry launch vector. Omitted/null snapshots the current invocation. */\n appLaunch?: OpenTrayAppLaunchOptions | null;\n autoStart?: boolean;\n /**\n * Optional transport supervision policy (Tier 0/2,\n * harden-transport-robustness). Every key has a working default; omitting\n * the object entirely means full default protection: heartbeat death\n * detection, automatic in-process recovery with journal replay, and a\n * bounded restart budget. `enabled: false` keeps death detection but\n * degrades to today's fail-fast behavior.\n */\n recovery?: TransportRecoveryOptions;\n}\n\n/** App-facing tray options accepted by top-level createTray. */\nexport interface CreateTrayOptions {\n id: string;\n tooltip?: Tooltip;\n icon?: Icon;\n menu?: CreateTrayMenu;\n}\n\n/** Tray handle returned by top-level createTray with ergonomic menu and session ownership. */\nexport interface CreateTrayHandle\n extends Omit<EventfulTrayHandle, \"setMenu\" | \"extend\" | \"destroy\"> {\n setMenu(menu: CreateTrayMenu): Promise<void>;\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions\n ): CreateTrayHandle & TCapability;\n destroy(): Promise<void>;\n}\n\nexport const createTray = async (\n options: CreateTrayOptions,\n runtimeOptions: OpenTrayRuntimeOptions = {}\n): Promise<CreateTrayHandle> => {\n if (runtimeOptions.appIcon !== undefined) {\n await validateAppIcon(runtimeOptions.appIcon);\n }\n const appIcon =\n runtimeOptions.appIcon === undefined\n ? undefined\n : normalizeAppIcon(runtimeOptions.appIcon);\n const normalized = normalizeCreateTrayOptions(options);\n const appLaunch = normalizeAppLaunch(runtimeOptions.appLaunch);\n const { recovery, ...brokerOptions } = runtimeOptions;\n // The supervisor owns the broker connection from here on: it presents the\n // stable transport surface to createClient/handles while holding one\n // LocalBrokerConnection per generation underneath. A respawn is exactly a\n // reconnect through the original options — daemon lifecycle, identity\n // gates, and lock reclaim all reapply unchanged.\n const supervisor = createTransportSupervisor({\n connect: () =>\n connectLocalBroker({\n ...brokerOptions,\n ...(appIcon === undefined ? {} : { appIcon }),\n appLaunch,\n }),\n ...(recovery === undefined ? {} : { recovery }),\n });\n try {\n await supervisor.connect();\n const tray = await createClient(supervisor, {\n appOptions: {\n ...(runtimeOptions.appName === undefined\n ? {}\n : { name: runtimeOptions.appName }),\n ...(appIcon === undefined ? {} : { appIcon }),\n },\n }).createTray(normalized.options);\n return wrapCreateTrayHandle(tray, {\n shutdown: () => supervisor.shutdown(),\n destroyPromise: undefined,\n menuUnsubscribe: bindMenuClickHandlers(tray, normalized.menuHandlers),\n });\n } catch (error) {\n await supervisor.shutdown().catch(noop);\n throw error;\n }\n};\n\nconst normalizeCreateTrayOptions = (\n options: CreateTrayOptions\n): NormalizedCreateTrayOptions => {\n const protocolOptions: Omit<TrayOptions, \"menu\"> = {\n id: options.id,\n ...(options.tooltip === undefined ? {} : { tooltip: options.tooltip }),\n ...(options.icon === undefined ? {} : { icon: options.icon }),\n };\n if (options.menu === undefined) {\n return { options: protocolOptions, menuHandlers: new Map() };\n }\n const normalized = normalizeCreateTrayMenu(options.menu);\n return {\n options: {\n ...protocolOptions,\n menu: normalized.menu,\n },\n menuHandlers: normalized.handlers,\n };\n};\n\nconst wrapCreateTrayHandle = (\n tray: EventfulTrayHandle,\n state: CreateTrayHandleState\n): CreateTrayHandle => {\n const handle: CreateTrayHandle = {\n ...tray,\n async setMenu(menu: CreateTrayMenu): Promise<void> {\n const normalized = normalizeCreateTrayMenu(menu);\n await tray.setMenu(normalized.menu);\n state.menuUnsubscribe();\n state.menuUnsubscribe = bindMenuClickHandlers(tray, normalized.handlers);\n },\n extend<TCapability extends object, TOptions = undefined>(\n extension: TrayExtension<TCapability, TOptions>,\n options?: TOptions\n ): CreateTrayHandle & TCapability {\n const extended = tray.extend(extension, options);\n return wrapCreateTrayHandle(extended, state) as CreateTrayHandle &\n TCapability;\n },\n async destroy(): Promise<void> {\n state.destroyPromise ??= (async () => {\n state.menuUnsubscribe();\n state.menuUnsubscribe = noop;\n // The broker tears its transport down as soon as its last session\n // closes, so the destroy request can race the broker-side socket\n // close. Both the destroy frame and the connection close rejecting\n // with the transport-close sentinel is the requested end state, not\n // a failure — a generated app's Quit must exit cleanly when the\n // broker exits first (P3.6 quit-path finding, 2026-09-12).\n // The destroy frame carries the teardown budget class (W3), which\n // the supervisor reads as the caller-initiated marker — so this\n // close race can never be misread as uninvited death and never\n // triggers recovery.\n const isTransportClosed = (error: unknown): boolean =>\n error instanceof Error &&\n error.message === BROKER_CONNECTION_CLOSED_MESSAGE;\n try {\n await tray.destroy();\n } catch (error) {\n if (!isTransportClosed(error)) {\n throw error;\n }\n } finally {\n try {\n await state.shutdown();\n } catch (error) {\n if (!isTransportClosed(error)) {\n throw error;\n }\n }\n }\n })();\n await state.destroyPromise;\n },\n };\n return handle;\n};\n\nconst bindMenuClickHandlers = (\n tray: EventfulTrayHandle,\n handlers: Map<number, CreateTrayMenuClickHandler[]>\n): (() => void) => {\n if (handlers.size === 0) {\n return noop;\n }\n return tray.onMenuClick((event) => {\n for (const handler of handlers.get(event.itemId) ?? []) {\n handler(event);\n }\n });\n};\n\nconst noop = (): void => {};\n\ninterface NormalizedCreateTrayOptions {\n options: TrayOptions;\n menuHandlers: Map<number, CreateTrayMenuClickHandler[]>;\n}\n\ninterface CreateTrayHandleState {\n /** Graceful supervised teardown: marks caller-initiated and closes the generation. */\n shutdown: () => Promise<void>;\n destroyPromise: Promise<void> | undefined;\n menuUnsubscribe: () => void;\n}\n"],"mappings":"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"}
|