opentray 0.27.4 → 0.27.7
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/README.md +21 -1
- package/dist/index.d.mts +19 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +38 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -108,7 +108,27 @@ that need exact wire shapes.
|
|
|
108
108
|
|
|
109
109
|
`primaryEvent` is a role on a normal menu item and emits the usual `menuClick`.
|
|
110
110
|
Use `tray.onTrayClick(...)` when you want to listen to raw tray-icon clicks
|
|
111
|
-
without making
|
|
111
|
+
without making the menu item the primary route.
|
|
112
|
+
|
|
113
|
+
### Broker connection death
|
|
114
|
+
|
|
115
|
+
When the local broker connection dies (socket error, broker exit, or a
|
|
116
|
+
completed graceful close), the SDK reaches a terminal connection-dead state:
|
|
117
|
+
|
|
118
|
+
- Pending requests reject with the transport-close sentinel message exported
|
|
119
|
+
as `BROKER_CONNECTION_CLOSED_MESSAGE`; requests issued after death reject
|
|
120
|
+
immediately with the same message instead of hanging on a dead socket.
|
|
121
|
+
- Event delivery stops. Eventful tray handles expose
|
|
122
|
+
`tray.onConnectionDead(handler)` — present on local broker transports — which
|
|
123
|
+
fires exactly once with the terminal error; treat it as the fail-loud signal
|
|
124
|
+
to exit or supervised-restart an entry whose backend is gone.
|
|
125
|
+
- `destroy()` treats the sentinel as the requested end state, so a Quit issued
|
|
126
|
+
after broker death still settles.
|
|
127
|
+
|
|
128
|
+
Endpoint identity is app identity: when `createTray` receives an `appId`, the
|
|
129
|
+
caller label (and therefore the per-caller broker endpoint) is that appId
|
|
130
|
+
normalized to a filesystem-safe slug, stable across every launch method of the
|
|
131
|
+
same app. Display names (`appName`) never participate in endpoint derivation.
|
|
112
132
|
|
|
113
133
|
## Darwin App Bundle
|
|
114
134
|
|
package/dist/index.d.mts
CHANGED
|
@@ -104,6 +104,14 @@ interface EventfulTrayHandle extends TrayHandle {
|
|
|
104
104
|
onAppReopenRequested(handler: (event: Extract<AppEvent$1, {
|
|
105
105
|
type: "reopenRequested";
|
|
106
106
|
}>) => void): () => void;
|
|
107
|
+
/**
|
|
108
|
+
* Terminal broker-connection-death notification (D3,
|
|
109
|
+
* harden-lifecycle-ownership). Present when the transport publishes its own
|
|
110
|
+
* death signal (the local broker connection always does); fires exactly
|
|
111
|
+
* once, after which pending requests have rejected, event delivery has
|
|
112
|
+
* stopped, and every later request rejects instead of hanging.
|
|
113
|
+
*/
|
|
114
|
+
onConnectionDead?(handler: (error: Error) => void): () => void;
|
|
107
115
|
}
|
|
108
116
|
interface ExtensionLoadOptions {
|
|
109
117
|
name: string;
|
|
@@ -226,6 +234,16 @@ interface CreateTrayHandle extends Omit<EventfulTrayHandle, "setMenu" | "extend"
|
|
|
226
234
|
}
|
|
227
235
|
declare const createTray: (options: CreateTrayOptions, runtimeOptions?: OpenTrayRuntimeOptions) => Promise<CreateTrayHandle>;
|
|
228
236
|
//#endregion
|
|
237
|
+
//#region src/local-broker.d.ts
|
|
238
|
+
/**
|
|
239
|
+
* Transport-close sentinel every pending request rejects with when the
|
|
240
|
+
* broker socket closes (the broker exits once its last session closes, so a
|
|
241
|
+
* caller racing its own teardown against that exit sees this message).
|
|
242
|
+
* Exported so the tray-handle destroy path can treat it as the desired end
|
|
243
|
+
* state instead of a failure (P3.6 quit-path finding, 2026-09-12).
|
|
244
|
+
*/
|
|
245
|
+
declare const BROKER_CONNECTION_CLOSED_MESSAGE = "broker connection closed";
|
|
246
|
+
//#endregion
|
|
229
247
|
//#region src/app-icon.d.ts
|
|
230
248
|
declare const DEFAULT_APP_ICON_VARIANT: "default";
|
|
231
249
|
declare class InvalidAppIconError extends Error {
|
|
@@ -241,5 +259,5 @@ declare class AppIconVariantNotFoundError extends Error {
|
|
|
241
259
|
/** Validate an explicit AppIcon, including native file signatures, before broker startup. */
|
|
242
260
|
declare const validateAppIcon: (icon: unknown, platform?: NodeJS.Platform) => Promise<void>;
|
|
243
261
|
//#endregion
|
|
244
|
-
export { type AppEvent, type AppHandle, type AppIcon, type AppIconAsset, type AppIconSource, type AppIconVariant, AppIconVariantNotFoundError, type AppIconVariantOf, type AppId, type AppIdentity, type AppOptions, type AppRef, type BrokerEndpointIdentity, type BrokerEndpointIdentityOptions, type ClientFrame, type ClientRequestFrame, type CreateClientOptions, type CreateTrayCheckItem, type CreateTrayHandle, type CreateTrayItem, type CreateTrayMenu, type CreateTrayMenu as TrayMenu, type CreateTrayMenuClickHandler, type CreateTrayMenuItem, type CreateTrayOptions, type CreateTrayRadioItem, type CreateTraySeparatorItem, type CreateTraySubmenuItem, DEFAULT_APP_ICON_VARIANT, type DarwinIcon, type DarwinIconText, type EventfulTrayHandle, type ExtensionEnvelope, type ExtensionLoadOptions, type Icon, type IconCandidates, type IconImage, type IconText, InvalidAppIconError, type LinuxIcon, type Menu, type MenuItem, type MenuItemId, type MouseButton, type NativeExtensionArch, type NativeExtensionArtifact, NativeExtensionArtifactResolutionError, type NativeExtensionExpectedIdentity, type NativeExtensionFileArtifact, type NativeExtensionIdentitySource, type NativeExtensionPackageArtifact, type NativeExtensionPackageTarget, type NativeExtensionTarget, type OpenTrayAppBundleOptions, type OpenTrayAppLaunchOptions, type OpenTrayClient, type OpenTrayConnection, type OpenTrayEventFrame, type OpenTrayEventSource, type OpenTrayRuntimeOptions, type OpenTrayTransport, PROTOCOL_VERSION, type Rect, type ResolvedNativeExtensionArtifact, type ServerFrame, type SimpleIcon, type Tooltip, type TrayBoundsKind, type TrayBoundsResult, type TrayEvent, type TrayEventByType, type TrayEventType, type TrayExtension, type TrayExtensionContext, type TrayExtensionMountSpec, type TrayHandle, type TrayIcon, type TrayId, type TrayOptions, type TrayTooltip, type Win32Icon, createBrokerEndpointIdentity, createClient, createInitFrame, createTray, createTrayHandle, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion, resolveNativeExtensionArtifact, validateAppIcon };
|
|
262
|
+
export { type AppEvent, type AppHandle, type AppIcon, type AppIconAsset, type AppIconSource, type AppIconVariant, AppIconVariantNotFoundError, type AppIconVariantOf, type AppId, type AppIdentity, type AppOptions, type AppRef, BROKER_CONNECTION_CLOSED_MESSAGE, type BrokerEndpointIdentity, type BrokerEndpointIdentityOptions, type ClientFrame, type ClientRequestFrame, type CreateClientOptions, type CreateTrayCheckItem, type CreateTrayHandle, type CreateTrayItem, type CreateTrayMenu, type CreateTrayMenu as TrayMenu, type CreateTrayMenuClickHandler, type CreateTrayMenuItem, type CreateTrayOptions, type CreateTrayRadioItem, type CreateTraySeparatorItem, type CreateTraySubmenuItem, DEFAULT_APP_ICON_VARIANT, type DarwinIcon, type DarwinIconText, type EventfulTrayHandle, type ExtensionEnvelope, type ExtensionLoadOptions, type Icon, type IconCandidates, type IconImage, type IconText, InvalidAppIconError, type LinuxIcon, type Menu, type MenuItem, type MenuItemId, type MouseButton, type NativeExtensionArch, type NativeExtensionArtifact, NativeExtensionArtifactResolutionError, type NativeExtensionExpectedIdentity, type NativeExtensionFileArtifact, type NativeExtensionIdentitySource, type NativeExtensionPackageArtifact, type NativeExtensionPackageTarget, type NativeExtensionTarget, type OpenTrayAppBundleOptions, type OpenTrayAppLaunchOptions, type OpenTrayClient, type OpenTrayConnection, type OpenTrayEventFrame, type OpenTrayEventSource, type OpenTrayRuntimeOptions, type OpenTrayTransport, PROTOCOL_VERSION, type Rect, type ResolvedNativeExtensionArtifact, type ServerFrame, type SimpleIcon, type Tooltip, type TrayBoundsKind, type TrayBoundsResult, type TrayEvent, type TrayEventByType, type TrayEventType, type TrayExtension, type TrayExtensionContext, type TrayExtensionMountSpec, type TrayHandle, type TrayIcon, type TrayId, type TrayOptions, type TrayTooltip, type Win32Icon, createBrokerEndpointIdentity, createClient, createInitFrame, createTray, createTrayHandle, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion, resolveNativeExtensionArtifact, validateAppIcon };
|
|
245
263
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/native-extension-artifact.ts","../src/client.ts","../src/menu-input.ts","../src/sdk.ts","../src/app-icon.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/native-extension-artifact.ts","../src/client.ts","../src/menu-input.ts","../src/sdk.ts","../src/local-broker.ts","../src/app-icon.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -501,8 +501,10 @@ const attachEventfulTrayHandle = (handle, source, appId, nextMountId, sessionId)
|
|
|
501
501
|
if (!isOwnedTrayEvent(frame.event, appId, handle.trayId)) return;
|
|
502
502
|
handler(frame.event);
|
|
503
503
|
});
|
|
504
|
+
const onConnectionDead = isConnectionDeadSource(source) ? (handler) => source.onConnectionDead(handler) : void 0;
|
|
504
505
|
const eventful = {
|
|
505
506
|
...handle,
|
|
507
|
+
...onConnectionDead === void 0 ? {} : { onConnectionDead },
|
|
506
508
|
listenExtension(ext, handler) {
|
|
507
509
|
return source.onEvent((frame) => {
|
|
508
510
|
if (frame.type !== "ext-event" || frame.ext !== ext) return;
|
|
@@ -542,6 +544,7 @@ const attachEventfulTrayHandle = (handle, source, appId, nextMountId, sessionId)
|
|
|
542
544
|
};
|
|
543
545
|
const isOwnedTrayEvent = (event, appId, trayId) => event.type !== "ready" && event.appId === appId && event.trayId === trayId;
|
|
544
546
|
const isOpenTrayEventSource = (transport) => "onEvent" in transport && typeof transport.onEvent === "function";
|
|
547
|
+
const isConnectionDeadSource = (transport) => "onConnectionDead" in transport && typeof transport.onConnectionDead === "function";
|
|
545
548
|
const resolveDefaultAppRef = async (transport, nextRequestId) => {
|
|
546
549
|
const requestId = nextRequestId();
|
|
547
550
|
const response = await transport.request({
|
|
@@ -687,16 +690,17 @@ const requestIdOf = (frame) => {
|
|
|
687
690
|
//#endregion
|
|
688
691
|
//#region src/daemon/caller-label.ts
|
|
689
692
|
/**
|
|
690
|
-
* Derives a caller label using the precedence: explicit >
|
|
691
|
-
* script basename > neutral default. The result is always
|
|
692
|
-
* filesystem- and process-safe component, so callers can use it
|
|
693
|
-
* endpoint identity, runtime directories, and process titles.
|
|
693
|
+
* Derives a caller label using the precedence: explicit > appId slug >
|
|
694
|
+
* npm_package_name > script basename > neutral default. The result is always
|
|
695
|
+
* sanitized to a filesystem- and process-safe component, so callers can use it
|
|
696
|
+
* directly in endpoint identity, runtime directories, and process titles.
|
|
694
697
|
*/
|
|
695
698
|
const resolveCallerLabel = (options = {}) => {
|
|
696
699
|
const env = options.env ?? process.env;
|
|
697
700
|
const argv = options.argv ?? process.argv;
|
|
698
701
|
const candidates = [];
|
|
699
702
|
if (options.explicit !== void 0 && options.explicit.length > 0) candidates.push(options.explicit);
|
|
703
|
+
if (options.appId !== void 0 && options.appId.length > 0) candidates.push(options.appId);
|
|
700
704
|
const npmName = options.npmPackageName ?? env.npm_package_name;
|
|
701
705
|
if (typeof npmName === "string" && npmName.length > 0) candidates.push(npmName);
|
|
702
706
|
const scriptPath = options.scriptPath ?? argv[1];
|
|
@@ -1366,7 +1370,7 @@ const connectLocalBroker = async (options = {}) => {
|
|
|
1366
1370
|
const clientVersion = options.clientVersion ?? packageVersion;
|
|
1367
1371
|
const appId = normalizeAppIdentityField(options.appId);
|
|
1368
1372
|
const appName = normalizeAppIdentityField(options.appName);
|
|
1369
|
-
const callerLabel = options.callerLabel ??
|
|
1373
|
+
const callerLabel = options.callerLabel ?? resolveCallerLabel(appId === void 0 ? {} : { appId });
|
|
1370
1374
|
const paths = resolveDaemonPaths({
|
|
1371
1375
|
homeDir: options.homeDir ?? process.env.OPENTRAY_HOME ?? homedir(),
|
|
1372
1376
|
packageVersion,
|
|
@@ -1452,6 +1456,8 @@ var LocalBrokerConnection = class {
|
|
|
1452
1456
|
buffer = "";
|
|
1453
1457
|
listeners = /* @__PURE__ */ new Set();
|
|
1454
1458
|
pending = /* @__PURE__ */ new Map();
|
|
1459
|
+
deadListeners = /* @__PURE__ */ new Set();
|
|
1460
|
+
deadError;
|
|
1455
1461
|
ready;
|
|
1456
1462
|
constructor(socket, endpoint, callerLabel) {
|
|
1457
1463
|
this.socket = socket;
|
|
@@ -1462,12 +1468,21 @@ var LocalBrokerConnection = class {
|
|
|
1462
1468
|
this.consume(String(chunk));
|
|
1463
1469
|
});
|
|
1464
1470
|
socket.on("error", (error) => {
|
|
1465
|
-
this.
|
|
1471
|
+
this.markDead(new Error(BROKER_CONNECTION_CLOSED_MESSAGE, { cause: error }));
|
|
1466
1472
|
});
|
|
1467
1473
|
socket.on("close", () => {
|
|
1468
|
-
this.
|
|
1474
|
+
this.markDead(/* @__PURE__ */ new Error(BROKER_CONNECTION_CLOSED_MESSAGE));
|
|
1469
1475
|
});
|
|
1470
1476
|
}
|
|
1477
|
+
get connectionDead() {
|
|
1478
|
+
return this.deadError !== void 0;
|
|
1479
|
+
}
|
|
1480
|
+
onConnectionDead(listener) {
|
|
1481
|
+
this.deadListeners.add(listener);
|
|
1482
|
+
return () => {
|
|
1483
|
+
this.deadListeners.delete(listener);
|
|
1484
|
+
};
|
|
1485
|
+
}
|
|
1471
1486
|
async init(clientVersion, protocolVersion, expectedBrokerArtifactIdentity) {
|
|
1472
1487
|
const ready = new Promise((resolve, reject) => {
|
|
1473
1488
|
this.ready = {
|
|
@@ -1486,6 +1501,7 @@ var LocalBrokerConnection = class {
|
|
|
1486
1501
|
}
|
|
1487
1502
|
async request(frame) {
|
|
1488
1503
|
if (this.pending.has(frame.requestId)) throw new Error(`duplicate requestId: ${frame.requestId}`);
|
|
1504
|
+
if (this.deadError !== void 0) throw new Error(this.deadError.message);
|
|
1489
1505
|
const response = new Promise((resolve, reject) => {
|
|
1490
1506
|
this.pending.set(frame.requestId, {
|
|
1491
1507
|
resolve,
|
|
@@ -1502,6 +1518,7 @@ var LocalBrokerConnection = class {
|
|
|
1502
1518
|
};
|
|
1503
1519
|
}
|
|
1504
1520
|
async close() {
|
|
1521
|
+
if (this.deadError !== void 0) return;
|
|
1505
1522
|
this.write({ type: "exit" });
|
|
1506
1523
|
await new Promise((resolve) => {
|
|
1507
1524
|
this.socket.end(resolve);
|
|
@@ -1563,6 +1580,19 @@ var LocalBrokerConnection = class {
|
|
|
1563
1580
|
for (const pending of this.pending.values()) pending.reject(error);
|
|
1564
1581
|
this.pending.clear();
|
|
1565
1582
|
}
|
|
1583
|
+
/**
|
|
1584
|
+
* Terminal connection-death transition (D3): first socket error/close wins,
|
|
1585
|
+
* rejects everything pending, and notifies every terminal listener exactly
|
|
1586
|
+
* once. Later terminal events are no-ops.
|
|
1587
|
+
*/
|
|
1588
|
+
markDead(error) {
|
|
1589
|
+
if (this.deadError !== void 0) return;
|
|
1590
|
+
this.deadError = error;
|
|
1591
|
+
this.rejectAll(error);
|
|
1592
|
+
for (const listener of [...this.deadListeners]) try {
|
|
1593
|
+
listener(error);
|
|
1594
|
+
} catch {}
|
|
1595
|
+
}
|
|
1566
1596
|
};
|
|
1567
1597
|
const connectSocket = (endpoint) => new Promise((resolve, reject) => {
|
|
1568
1598
|
const socket = createConnection(endpoint);
|
|
@@ -1831,6 +1861,6 @@ const bindMenuClickHandlers = (tray, handlers) => {
|
|
|
1831
1861
|
};
|
|
1832
1862
|
const noop = () => {};
|
|
1833
1863
|
//#endregion
|
|
1834
|
-
export { AppIconVariantNotFoundError, DEFAULT_APP_ICON_VARIANT, InvalidAppIconError, NativeExtensionArtifactResolutionError, PROTOCOL_VERSION, createBrokerEndpointIdentity, createClient, createInitFrame, createTray, createTrayHandle, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion, resolveNativeExtensionArtifact, validateAppIcon };
|
|
1864
|
+
export { AppIconVariantNotFoundError, BROKER_CONNECTION_CLOSED_MESSAGE, DEFAULT_APP_ICON_VARIANT, InvalidAppIconError, NativeExtensionArtifactResolutionError, PROTOCOL_VERSION, createBrokerEndpointIdentity, createClient, createInitFrame, createTray, createTrayHandle, formatBrokerEndpointName, formatBrokerStateRoot, formatUnixSocketPath, formatWindowsPipeName, isSupportedProtocolVersion, resolveNativeExtensionArtifact, validateAppIcon };
|
|
1835
1865
|
|
|
1836
1866
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["isRecord","PROTOCOL_VERSION","isNodeError","createBrokerEndpointIdentity","normalizeAppIdentityField","formatWindowsPipeName","formatUnixSocketPath","PROTOCOL_VERSION"],"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/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\nimport { readFile, realpath } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\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\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\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/** 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 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\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 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\nexport interface OpenTrayTransport {\n request(frame: ClientRequestFrame): Promise<ServerFrame>;\n}\n\nexport type OpenTrayEventFrame = Extract<\n ServerFrame,\n { type: \"event\" | \"app-event\" | \"ext-event\" }\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\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(ext: string, data: unknown): Promise<ExtensionEnvelope[]>;\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\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(data: unknown): Promise<ExtensionEnvelope[]>;\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(\n ext: string,\n data: unknown\n ): Promise<ExtensionEnvelope[]> {\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 [];\n }\n return expectResponse(response, requestId, \"ext-command-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 const response = await transport.request({\n type: \"destroy-tray\",\n requestId,\n appId,\n trayId,\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 const eventful: EventfulTrayHandle = {\n ...handle,\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\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(data: unknown): Promise<ExtensionEnvelope[]> {\n await ensureLoaded();\n return tray.requestExtension(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 throw new Error(`${frame.code}: ${frame.message}`);\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 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 /** `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 > npm_package_name >\n * script basename > neutral default. The result is always sanitized to a\n * filesystem- and process-safe component, so callers can use it directly in\n * 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 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 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 } 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\nexport interface LocalBrokerClient extends OpenTrayTransport {\n readonly endpoint: string;\n readonly callerLabel: string;\n readonly sessionId: string;\n onEvent(listener: (frame: LocalRuntimeEventFrame) => void): () => void;\n close(): Promise<void>;\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\ninterface 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}\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 const callerLabel = options.callerLabel ?? appName ?? appId ?? resolveCallerLabel();\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\nclass 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 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 this.rejectAll(error);\n });\n socket.on(\"close\", () => {\n this.rejectAll(new Error(BROKER_CONNECTION_CLOSED_MESSAGE));\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 ready;\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(frame: ClientRequestFrame): Promise<ServerFrame> {\n if (this.pending.has(frame.requestId)) {\n throw new Error(`duplicate requestId: ${frame.requestId}`);\n }\n\n const response = new Promise<ServerFrame>((resolve, reject) => {\n this.pending.set(frame.requestId, { resolve, reject });\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 this.write({ type: \"exit\" });\n await new Promise<void>((resolve) => {\n this.socket.end(resolve);\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 const error = new Error(`${frame.code}: ${frame.message}`);\n if (frame.requestId !== undefined) {\n this.pending.get(frame.requestId)?.reject(error);\n this.pending.delete(frame.requestId);\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 const requestId = responseRequestId(frame);\n if (requestId !== undefined) {\n // Request responses and broker events are separate streams even on one socket.\n this.pending.get(requestId)?.resolve(frame);\n this.pending.delete(requestId);\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 private rejectAll(error: Error): void {\n this.ready?.reject(error);\n this.ready = undefined;\n for (const pending of this.pending.values()) {\n pending.reject(error);\n }\n this.pending.clear();\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 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","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 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\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 connection = await connectLocalBroker({\n ...runtimeOptions,\n ...(appIcon === undefined ? {} : { appIcon }),\n appLaunch,\n });\n try {\n const tray = await createClient(connection, {\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 closeConnection: () => connection.close(),\n destroyPromise: undefined,\n menuUnsubscribe: bindMenuClickHandlers(tray, normalized.menuHandlers),\n });\n } catch (error) {\n await connection.close().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 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.closeConnection();\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 closeConnection: () => Promise<void>;\n destroyPromise: Promise<void> | undefined;\n menuUnsubscribe: () => void;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["isRecord","PROTOCOL_VERSION","isNodeError","createBrokerEndpointIdentity","normalizeAppIdentityField","formatWindowsPipeName","formatUnixSocketPath","PROTOCOL_VERSION"],"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/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\nimport { readFile, realpath } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\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\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\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/** 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 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\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 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\nexport interface OpenTrayTransport {\n request(frame: ClientRequestFrame): Promise<ServerFrame>;\n}\n\nexport type OpenTrayEventFrame = Extract<\n ServerFrame,\n { type: \"event\" | \"app-event\" | \"ext-event\" }\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\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(ext: string, data: unknown): Promise<ExtensionEnvelope[]>;\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\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(data: unknown): Promise<ExtensionEnvelope[]>;\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(\n ext: string,\n data: unknown\n ): Promise<ExtensionEnvelope[]> {\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 [];\n }\n return expectResponse(response, requestId, \"ext-command-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 const response = await transport.request({\n type: \"destroy-tray\",\n requestId,\n appId,\n trayId,\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 const eventful: EventfulTrayHandle = {\n ...handle,\n ...(onConnectionDead === undefined ? {} : { onConnectionDead }),\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\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(data: unknown): Promise<ExtensionEnvelope[]> {\n await ensureLoaded();\n return tray.requestExtension(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 throw new Error(`${frame.code}: ${frame.message}`);\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 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 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 } 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\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 onEvent(listener: (frame: LocalRuntimeEventFrame) => void): () => void;\n close(): Promise<void>;\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\ninterface 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}\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\nclass 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 private readonly deadListeners = new Set<(error: Error) => 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 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 ready;\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(frame: ClientRequestFrame): 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 const response = new Promise<ServerFrame>((resolve, reject) => {\n this.pending.set(frame.requestId, { resolve, reject });\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 await new Promise<void>((resolve) => {\n this.socket.end(resolve);\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 const error = new Error(`${frame.code}: ${frame.message}`);\n if (frame.requestId !== undefined) {\n this.pending.get(frame.requestId)?.reject(error);\n this.pending.delete(frame.requestId);\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 const requestId = responseRequestId(frame);\n if (requestId !== undefined) {\n // Request responses and broker events are separate streams even on one socket.\n this.pending.get(requestId)?.resolve(frame);\n this.pending.delete(requestId);\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 private rejectAll(error: Error): void {\n this.ready?.reject(error);\n this.ready = undefined;\n for (const pending of this.pending.values()) {\n pending.reject(error);\n }\n this.pending.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 private markDead(error: Error): void {\n if (this.deadError !== undefined) {\n return;\n }\n this.deadError = error;\n this.rejectAll(error);\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 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","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 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\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 connection = await connectLocalBroker({\n ...runtimeOptions,\n ...(appIcon === undefined ? {} : { appIcon }),\n appLaunch,\n });\n try {\n const tray = await createClient(connection, {\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 closeConnection: () => connection.close(),\n destroyPromise: undefined,\n menuUnsubscribe: bindMenuClickHandlers(tray, normalized.menuHandlers),\n });\n } catch (error) {\n await connection.close().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 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.closeConnection();\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 closeConnection: () => Promise<void>;\n destroyPromise: Promise<void> | undefined;\n menuUnsubscribe: () => void;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opentray",
|
|
3
|
-
"version": "0.27.
|
|
3
|
+
"version": "0.27.7",
|
|
4
4
|
"description": "Developer-facing OpenTray SDK and CLI package.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
],
|
|
25
25
|
"sideEffects": false,
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@opentray/icon": "0.27.
|
|
28
|
-
"@opentray/packaging": "0.27.
|
|
29
|
-
"@opentray/spec": "0.27.
|
|
27
|
+
"@opentray/icon": "0.27.7",
|
|
28
|
+
"@opentray/packaging": "0.27.7",
|
|
29
|
+
"@opentray/spec": "0.27.7"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"tsdown": "^0.22.1",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"vitest": "^4.1.7"
|
|
35
35
|
},
|
|
36
36
|
"optionalDependencies": {
|
|
37
|
-
"@opentray/darwin-arm64": "0.27.
|
|
38
|
-
"@opentray/darwin-x64": "0.27.
|
|
39
|
-
"@opentray/linux-arm64": "0.27.
|
|
40
|
-
"@opentray/linux-x64": "0.27.
|
|
41
|
-
"@opentray/windows-arm64": "0.27.
|
|
42
|
-
"@opentray/windows-x64": "0.27.
|
|
37
|
+
"@opentray/darwin-arm64": "0.27.7",
|
|
38
|
+
"@opentray/darwin-x64": "0.27.7",
|
|
39
|
+
"@opentray/linux-arm64": "0.27.7",
|
|
40
|
+
"@opentray/linux-x64": "0.27.7",
|
|
41
|
+
"@opentray/windows-arm64": "0.27.7",
|
|
42
|
+
"@opentray/windows-x64": "0.27.7"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
45
|
"build": "tsdown src/index.ts src/cli.ts --format esm --dts",
|