@opentray/spec 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,27 +4,33 @@ Shared TypeScript protocol and contract package for OpenTray.
4
4
 
5
5
  ## Role
6
6
 
7
- - Define JSON-RPC payload shapes.
8
- - Define broker protocol version and endpoint identity helpers.
9
- - Define public `Space`, `Tray`, `Session`, and extension contract types.
10
- - Keep protocol types reusable by the `opentray` package and official extensions.
7
+ - Define newline-delimited JSON protocol payload shapes.
8
+ - Define protocol version and endpoint identity helpers.
9
+ - Define public `App`, `Tray`, `Session`, icon projection, menu, tooltip, and extension contract types.
10
+ - Keep protocol types reusable by `opentray` and official extensions.
11
11
 
12
- This package must stay platform-neutral and must not import native implementation packages.
12
+ This package is platform-neutral and must not import native implementation packages.
13
13
 
14
- ## Example
14
+ ## Tray Contract
15
15
 
16
- Run a protocol parser example that shows successful server-frame parsing and malformed-frame rejection:
17
-
18
- ```bash
19
- pnpm --filter @opentray/spec example:parse
20
- ```
21
-
22
- Endpoint identity is version-scoped during the current unstable broker stage:
16
+ `TrayOptions` uses `id` as the tray atom identity. Visible tray text belongs to the unified `icon` field:
23
17
 
24
18
  ```ts
25
- import { createBrokerEndpointIdentity, formatUnixSocketPath } from "@opentray/spec";
26
-
27
- const identity = createBrokerEndpointIdentity({ packageVersion: "0.1.0" });
28
- console.log(formatUnixSocketPath("~", identity));
29
- // ~/.opentray/0.1.0/opentray-p1.sock
19
+ import type { Icon, TrayOptions } from "@opentray/spec";
20
+
21
+ const icon: Icon = {
22
+ type: "file",
23
+ path: "./status.png",
24
+ text: "Status",
25
+ "icon-only": { type: "file", path: "./status-small.png" },
26
+ "text-only": "Status",
27
+ "icon-text": { type: "file", path: "./status.png", text: "Status" },
28
+ };
29
+
30
+ const tray: TrayOptions = {
31
+ id: "com.example.status",
32
+ icon,
33
+ };
30
34
  ```
35
+
36
+ `Space`, `Surface`, `spaceId`, `create-space`, and top-level tray `title` are removed public vocabulary for v0.9.
package/dist/index.d.mts CHANGED
@@ -1,13 +1,9 @@
1
1
  //#region src/index.d.ts
2
2
  type SessionId = string;
3
3
  type RequestId = string;
4
- type SpaceId = string;
4
+ type AppId = string;
5
5
  type TrayId = string;
6
6
  type MenuItemId = number;
7
- /** @deprecated Use `SessionId`. */
8
- type LeaseId = SessionId;
9
- /** @deprecated Use `SpaceId`. */
10
- type SurfaceId = SpaceId;
11
7
  declare const PROTOCOL_VERSION = 1;
12
8
  declare const OPENTRAY_PROTOCOL_FAMILY = "opentray-protocol";
13
9
  declare const OPENTRAY_PROTOCOL_LINE_MAJOR = 1;
@@ -44,42 +40,59 @@ declare const formatProtocolDistTag: ({
44
40
  minor
45
41
  }: ProtocolDistTagOptions) => string;
46
42
  declare const parseProtocolDistTag: (tag: string) => ProtocolDistTag;
43
+ /**
44
+ * Neutral caller label used when no usable caller identity can be derived.
45
+ * Keeps the broker honest instead of impersonating an unrelated application.
46
+ */
47
+ declare const DEFAULT_CALLER_LABEL = "opentray";
48
+ /**
49
+ * Maximum length of a sanitized caller label. Keeps socket paths, runtime
50
+ * directory names, and process titles within platform limits.
51
+ */
52
+ declare const CALLER_LABEL_MAX_LENGTH = 48;
47
53
  interface BrokerEndpointIdentity {
48
54
  packageVersion: string;
49
55
  protocolVersion: number;
56
+ callerLabel: string;
50
57
  }
51
58
  interface BrokerEndpointIdentityOptions {
52
59
  packageVersion: string;
53
60
  protocolVersion?: number;
61
+ callerLabel?: string;
54
62
  }
63
+ declare const sanitizeCallerLabel: (value: string | undefined) => string;
55
64
  declare const createBrokerEndpointIdentity: ({
56
65
  packageVersion,
57
- protocolVersion
66
+ protocolVersion,
67
+ callerLabel
58
68
  }: BrokerEndpointIdentityOptions) => BrokerEndpointIdentity;
59
69
  declare const isSupportedProtocolVersion: (protocolVersion: number) => boolean;
60
70
  declare const formatBrokerEndpointName: (identity: BrokerEndpointIdentity) => string;
61
71
  declare const formatBrokerStateRoot: (homeDir: string, identity: BrokerEndpointIdentity) => string;
62
72
  declare const formatUnixSocketPath: (homeDir: string, identity: BrokerEndpointIdentity) => string;
63
73
  declare const formatWindowsPipeName: (identity: BrokerEndpointIdentity) => string;
64
- interface SpaceOptions {
65
- id?: SpaceId;
66
- title?: string;
74
+ /**
75
+ * Human-readable process title for a broker pinned to a caller. Used by the SDK
76
+ * spawn path so task managers show the owning application, not a generic name.
77
+ */
78
+ declare const formatBrokerProcessTitle: (identity: BrokerEndpointIdentity) => string;
79
+ interface AppOptions {
80
+ id?: AppId;
81
+ name?: string;
67
82
  icon?: Icon;
68
83
  default?: boolean;
69
84
  }
70
- /** @deprecated Use `SpaceOptions`. */
71
- type SurfaceOptions = SpaceOptions;
72
- interface SpaceRef {
73
- spaceId: SpaceId;
85
+ interface AppRef {
86
+ appId: AppId;
87
+ }
88
+ interface AppIdentity {
89
+ appId: AppId;
90
+ appName: string;
74
91
  }
75
- /** @deprecated Use `SpaceRef`. */
76
- type SurfaceRef = SpaceRef;
77
92
  interface TrayOptions {
78
- trayId?: TrayId;
79
- appId?: string;
80
- title?: string;
93
+ id: string;
81
94
  tooltip?: Tooltip;
82
- icon: Icon;
95
+ icon?: Icon;
83
96
  menu?: Menu;
84
97
  }
85
98
  interface Tooltip {
@@ -117,7 +130,7 @@ type MenuItem = {
117
130
  enabled?: boolean;
118
131
  items: MenuItem[];
119
132
  };
120
- type Icon = {
133
+ type IconImage = {
121
134
  type: "rgba";
122
135
  data: Uint8Array | number[];
123
136
  width: number;
@@ -129,6 +142,18 @@ type Icon = {
129
142
  type: "file";
130
143
  path: string;
131
144
  };
145
+ type SimpleIcon = IconImage & {
146
+ text?: string;
147
+ };
148
+ type IconText = IconImage & {
149
+ text: string;
150
+ };
151
+ interface IconCandidates {
152
+ "icon-only"?: IconImage;
153
+ "text-only"?: string;
154
+ "icon-text"?: IconText;
155
+ }
156
+ type Icon = IconCandidates & Partial<SimpleIcon>;
132
157
  interface Rect {
133
158
  x: number;
134
159
  y: number;
@@ -144,29 +169,29 @@ interface TrayBoundsResult {
144
169
  type MouseButton = "left" | "right" | "middle";
145
170
  type TrayEvent = {
146
171
  type: "ready";
147
- spaceId: SpaceId;
172
+ appId: AppId;
148
173
  } | {
149
174
  type: "menuClick";
150
- spaceId: SpaceId;
175
+ appId: AppId;
151
176
  trayId: TrayId;
152
177
  itemId: MenuItemId;
153
178
  } | {
154
179
  type: "trayClick";
155
- spaceId: SpaceId;
180
+ appId: AppId;
156
181
  trayId: TrayId;
157
182
  button: MouseButton;
158
183
  x: number;
159
184
  y: number;
160
185
  } | {
161
186
  type: "trayDoubleClick";
162
- spaceId: SpaceId;
187
+ appId: AppId;
163
188
  trayId: TrayId;
164
189
  button: MouseButton;
165
190
  x: number;
166
191
  y: number;
167
192
  };
168
193
  interface ExtensionScope {
169
- spaceId: SpaceId;
194
+ appId: AppId;
170
195
  trayId?: TrayId;
171
196
  ext: string;
172
197
  }
@@ -174,18 +199,21 @@ interface ExtensionEnvelope<TData = unknown> {
174
199
  scope: ExtensionScope;
175
200
  data: TData;
176
201
  }
177
- interface DaemonSessionHealth {
202
+ interface RuntimeHostSessionHealth {
178
203
  sessionId: number;
179
- internalLeaseId?: SessionId;
204
+ internalSessionId?: SessionId;
180
205
  initialized: boolean;
181
206
  }
182
- interface DaemonHealth {
207
+ interface RuntimeHostHealth {
183
208
  pid: number;
184
209
  packageVersion: string;
185
210
  protocolVersion: number;
186
211
  endpoint: string;
212
+ appId: AppId;
213
+ appName: string;
214
+ callerLabel: string;
187
215
  sessionCount: number;
188
- sessions: DaemonSessionHealth[];
216
+ sessions: RuntimeHostSessionHealth[];
189
217
  }
190
218
  type ClientFrame = {
191
219
  type: "init";
@@ -195,68 +223,62 @@ type ClientFrame = {
195
223
  type: "exit";
196
224
  };
197
225
  type ClientRequestFrame = ({
198
- type: "create-space";
226
+ type: "create-app";
199
227
  requestId: RequestId;
200
- } & SpaceOptions) | {
201
- type: "resolve-default-space";
228
+ } & AppOptions) | {
229
+ type: "resolve-default-app";
202
230
  requestId: RequestId;
203
231
  } | {
204
232
  type: "create-tray";
205
233
  requestId: RequestId;
206
- space: SpaceRef;
234
+ app: AppRef;
207
235
  tray: TrayOptions;
208
236
  } | {
209
237
  type: "destroy-tray";
210
238
  requestId: RequestId;
211
- spaceId: SpaceId;
239
+ appId: AppId;
212
240
  trayId: TrayId;
213
241
  } | {
214
242
  type: "get-tray-bounds";
215
243
  requestId: RequestId;
216
- spaceId: SpaceId;
244
+ appId: AppId;
217
245
  trayId: TrayId;
218
246
  } | {
219
247
  type: "set-tray-menu";
220
248
  requestId: RequestId;
221
- spaceId: SpaceId;
249
+ appId: AppId;
222
250
  trayId: TrayId;
223
251
  menu: Menu;
224
252
  } | {
225
253
  type: "set-tray-icon";
226
254
  requestId: RequestId;
227
- spaceId: SpaceId;
255
+ appId: AppId;
228
256
  trayId: TrayId;
229
257
  icon: Icon;
230
258
  } | {
231
259
  type: "set-tray-tooltip";
232
260
  requestId: RequestId;
233
- spaceId: SpaceId;
261
+ appId: AppId;
234
262
  trayId: TrayId;
235
263
  tooltip: Tooltip;
236
- } | {
237
- type: "set-tray-title";
238
- requestId: RequestId;
239
- spaceId: SpaceId;
240
- trayId: TrayId;
241
- title: string;
242
264
  } | {
243
265
  type: "load-ext";
244
266
  requestId: RequestId;
245
- spaceId: SpaceId;
267
+ appId: AppId;
246
268
  name: string;
247
269
  path: string;
248
270
  mountId?: string;
249
271
  } | {
250
272
  type: "ext-command";
251
273
  requestId: RequestId;
252
- spaceId: SpaceId;
274
+ appId: AppId;
253
275
  trayId: TrayId;
254
276
  ext: string;
255
277
  data: unknown;
256
278
  } | {
257
279
  type: "unload-ext";
258
280
  requestId: RequestId;
259
- spaceId: SpaceId;
281
+ appId: AppId;
260
282
  name: string;
261
283
  } | {
262
284
  type: "health";
@@ -268,22 +290,22 @@ type ServerFrame = {
268
290
  brokerVersion: string;
269
291
  sessionId: SessionId;
270
292
  } | {
271
- type: "space-created";
293
+ type: "app-created";
272
294
  requestId: RequestId;
273
- space: SpaceRef;
295
+ app: AppRef;
274
296
  } | {
275
- type: "default-space";
297
+ type: "default-app";
276
298
  requestId: RequestId;
277
- space: SpaceRef;
299
+ app: AppRef;
278
300
  } | {
279
301
  type: "tray-created";
280
302
  requestId: RequestId;
281
- spaceId: SpaceId;
303
+ appId: AppId;
282
304
  trayId: TrayId;
283
305
  } | {
284
306
  type: "tray-bounds";
285
307
  requestId: RequestId;
286
- spaceId: SpaceId;
308
+ appId: AppId;
287
309
  trayId: TrayId;
288
310
  bounds: TrayBoundsResult;
289
311
  } | {
@@ -294,15 +316,15 @@ type ServerFrame = {
294
316
  requestId: RequestId;
295
317
  events: ExtensionEnvelope[];
296
318
  } | {
297
- type: "daemon-health";
319
+ type: "runtime-host-health";
298
320
  requestId: RequestId;
299
- health: DaemonHealth;
321
+ health: RuntimeHostHealth;
300
322
  } | {
301
323
  type: "event";
302
324
  event: TrayEvent;
303
325
  } | {
304
326
  type: "ext-event";
305
- spaceId: SpaceId;
327
+ appId: AppId;
306
328
  trayId: TrayId;
307
329
  ext: string;
308
330
  data: unknown;
@@ -320,5 +342,5 @@ interface ParseResult<T> {
320
342
  declare const parseServerFrame: (line: string) => ParseResult<ServerFrame>;
321
343
  declare const isServerFrame: (value: unknown) => value is ServerFrame;
322
344
  //#endregion
323
- export { BrokerEndpointIdentity, BrokerEndpointIdentityOptions, ClientFrame, ClientRequestFrame, DaemonHealth, DaemonSessionHealth, ExtensionEnvelope, ExtensionScope, Icon, LeaseId, Menu, MenuItem, MenuItemId, MouseButton, OPENTRAY_PROTOCOL_FAMILY, OPENTRAY_PROTOCOL_LINE, OPENTRAY_PROTOCOL_LINE_MAJOR, OPENTRAY_PROTOCOL_LINE_MINOR, OpenTrayProtocolLine, PROTOCOL_VERSION, ParseResult, ProtocolDistTag, ProtocolDistTagOptions, ProtocolLineReleaseChannel, Rect, RequestId, ServerFrame, SessionId, SpaceId, SpaceOptions, SpaceRef, SurfaceId, SurfaceOptions, SurfaceRef, Tooltip, TrayBoundsKind, TrayBoundsResult, TrayEvent, TrayId, TrayOptions, compareOpenTrayProtocolLine, createBrokerEndpointIdentity, formatBrokerEndpointName, formatBrokerStateRoot, formatOpenTrayProtocolLine, formatProtocolDistTag, formatUnixSocketPath, formatWindowsPipeName, isOpenTrayProtocolLineCompatible, isProtocolLineReleaseChannel, isServerFrame, isSupportedProtocolVersion, parseProtocolDistTag, parseServerFrame, protocolLineReleaseChannels };
345
+ export { AppId, AppIdentity, AppOptions, AppRef, BrokerEndpointIdentity, BrokerEndpointIdentityOptions, CALLER_LABEL_MAX_LENGTH, ClientFrame, ClientRequestFrame, DEFAULT_CALLER_LABEL, ExtensionEnvelope, ExtensionScope, Icon, IconCandidates, IconImage, IconText, Menu, MenuItem, MenuItemId, MouseButton, OPENTRAY_PROTOCOL_FAMILY, OPENTRAY_PROTOCOL_LINE, OPENTRAY_PROTOCOL_LINE_MAJOR, OPENTRAY_PROTOCOL_LINE_MINOR, OpenTrayProtocolLine, PROTOCOL_VERSION, ParseResult, ProtocolDistTag, ProtocolDistTagOptions, ProtocolLineReleaseChannel, Rect, RequestId, RuntimeHostHealth, RuntimeHostSessionHealth, ServerFrame, SessionId, SimpleIcon, Tooltip, TrayBoundsKind, TrayBoundsResult, TrayEvent, TrayId, TrayOptions, compareOpenTrayProtocolLine, createBrokerEndpointIdentity, formatBrokerEndpointName, formatBrokerProcessTitle, formatBrokerStateRoot, formatOpenTrayProtocolLine, formatProtocolDistTag, formatUnixSocketPath, formatWindowsPipeName, isOpenTrayProtocolLineCompatible, isProtocolLineReleaseChannel, isServerFrame, isSupportedProtocolVersion, parseProtocolDistTag, parseServerFrame, protocolLineReleaseChannels, sanitizeCallerLabel };
324
346
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -47,26 +47,54 @@ const parseProtocolDistTag = (tag) => {
47
47
  minor
48
48
  };
49
49
  };
50
- const createBrokerEndpointIdentity = ({ packageVersion, protocolVersion = 1 }) => {
50
+ /**
51
+ * Neutral caller label used when no usable caller identity can be derived.
52
+ * Keeps the broker honest instead of impersonating an unrelated application.
53
+ */
54
+ const DEFAULT_CALLER_LABEL = "opentray";
55
+ /**
56
+ * Maximum length of a sanitized caller label. Keeps socket paths, runtime
57
+ * directory names, and process titles within platform limits.
58
+ */
59
+ const CALLER_LABEL_MAX_LENGTH = 48;
60
+ const callerLabelAllowedPattern = /[a-z0-9-]+/g;
61
+ const sanitizeCallerLabel = (value) => {
62
+ if (value !== void 0 && typeof value !== "string") throw new Error(`callerLabel must be a string: ${String(value)}`);
63
+ const segments = (value ?? "").toLowerCase().match(callerLabelAllowedPattern);
64
+ if (segments === null || segments.length === 0) return DEFAULT_CALLER_LABEL;
65
+ const trimmed = segments.join("-").replace(/^-+|-+$/gu, "");
66
+ if (trimmed.length === 0) return DEFAULT_CALLER_LABEL;
67
+ return trimmed.slice(0, 48);
68
+ };
69
+ const createBrokerEndpointIdentity = ({ packageVersion, protocolVersion = 1, callerLabel }) => {
51
70
  assertEndpointComponent(packageVersion, "packageVersion");
52
71
  if (!Number.isInteger(protocolVersion) || protocolVersion <= 0) throw new Error(`protocolVersion must be a positive integer: ${protocolVersion}`);
53
72
  return {
54
73
  packageVersion,
55
- protocolVersion
74
+ protocolVersion,
75
+ callerLabel: sanitizeCallerLabel(callerLabel)
56
76
  };
57
77
  };
58
78
  const isSupportedProtocolVersion = (protocolVersion) => protocolVersion === 1;
59
79
  const formatBrokerEndpointName = (identity) => {
60
80
  assertEndpointIdentity(identity);
61
- return `opentray-${identity.packageVersion}-p${identity.protocolVersion}`;
81
+ return `opentray-${identity.packageVersion}-p${identity.protocolVersion}-${identity.callerLabel}`;
62
82
  };
63
83
  const formatBrokerStateRoot = (homeDir, identity) => {
64
84
  assertEndpointIdentity(identity);
65
85
  if (homeDir.length === 0) throw new Error("homeDir must not be empty");
66
- return `${homeDir.replace(/[\\/]+$/u, "")}/.opentray/${identity.packageVersion}`;
86
+ return `${homeDir.replace(/[\\/]+$/u, "")}/.opentray/${identity.packageVersion}/${identity.callerLabel}`;
67
87
  };
68
88
  const formatUnixSocketPath = (homeDir, identity) => `${formatBrokerStateRoot(homeDir, identity)}/opentray-p${identity.protocolVersion}.sock`;
69
89
  const formatWindowsPipeName = (identity) => `\\\\.\\pipe\\${formatBrokerEndpointName(identity)}`;
90
+ /**
91
+ * Human-readable process title for a broker pinned to a caller. Used by the SDK
92
+ * spawn path so task managers show the owning application, not a generic name.
93
+ */
94
+ const formatBrokerProcessTitle = (identity) => {
95
+ assertEndpointIdentity(identity);
96
+ return `opentray · ${identity.callerLabel}`;
97
+ };
70
98
  const endpointComponentPattern = /^[0-9A-Za-z._+-]+$/u;
71
99
  const assertOpenTrayProtocolLine = (line, name) => {
72
100
  assertProtocolLineVersion(line.major, `${name}.major`);
@@ -109,15 +137,15 @@ const isServerFrame = (value) => {
109
137
  if (!isRecord(value) || typeof value.type !== "string") return false;
110
138
  switch (value.type) {
111
139
  case "ready": return typeof value.protocolVersion === "number" && typeof value.brokerVersion === "string" && typeof value.sessionId === "string";
112
- case "space-created": return typeof value.requestId === "string" && isRecord(value.space);
113
- case "default-space": return typeof value.requestId === "string" && isRecord(value.space);
114
- case "tray-created": return typeof value.requestId === "string" && typeof value.spaceId === "string" && typeof value.trayId === "string";
115
- case "tray-bounds": return typeof value.requestId === "string" && typeof value.spaceId === "string" && typeof value.trayId === "string" && isTrayBoundsResult(value.bounds);
140
+ case "app-created": return typeof value.requestId === "string" && isRecord(value.app);
141
+ case "default-app": return typeof value.requestId === "string" && isRecord(value.app);
142
+ case "tray-created": return typeof value.requestId === "string" && typeof value.appId === "string" && typeof value.trayId === "string";
143
+ case "tray-bounds": return typeof value.requestId === "string" && typeof value.appId === "string" && typeof value.trayId === "string" && isTrayBoundsResult(value.bounds);
116
144
  case "ack": return typeof value.requestId === "string";
117
145
  case "ext-command-result": return typeof value.requestId === "string" && Array.isArray(value.events) && value.events.every(isExtensionEnvelope);
118
- case "daemon-health": return typeof value.requestId === "string" && isDaemonHealth(value.health);
146
+ case "runtime-host-health": return typeof value.requestId === "string" && isRuntimeHostHealth(value.health);
119
147
  case "event": return isTrayEvent(value.event);
120
- case "ext-event": return typeof value.spaceId === "string" && typeof value.trayId === "string" && typeof value.ext === "string";
148
+ case "ext-event": return typeof value.appId === "string" && typeof value.trayId === "string" && typeof value.ext === "string";
121
149
  case "error": return (value.requestId === void 0 || typeof value.requestId === "string") && typeof value.code === "string" && typeof value.message === "string";
122
150
  default: return false;
123
151
  }
@@ -125,27 +153,27 @@ const isServerFrame = (value) => {
125
153
  const isExtensionEnvelope = (value) => {
126
154
  if (!isRecord(value) || !isRecord(value.scope)) return false;
127
155
  const scope = value.scope;
128
- return (typeof scope.spaceId === "string" || typeof scope.surfaceId === "string") && (scope.trayId === void 0 || typeof scope.trayId === "string") && typeof scope.ext === "string" && "data" in value;
156
+ return typeof scope.appId === "string" && (scope.trayId === void 0 || typeof scope.trayId === "string") && typeof scope.ext === "string" && "data" in value;
129
157
  };
130
- const isDaemonHealth = (value) => {
158
+ const isRuntimeHostHealth = (value) => {
131
159
  if (!isRecord(value)) return false;
132
- return typeof value.pid === "number" && typeof value.packageVersion === "string" && typeof value.protocolVersion === "number" && typeof value.endpoint === "string" && typeof value.sessionCount === "number" && Array.isArray(value.sessions) && value.sessions.every(isDaemonSessionHealth);
160
+ return typeof value.pid === "number" && typeof value.packageVersion === "string" && typeof value.protocolVersion === "number" && typeof value.endpoint === "string" && typeof value.appId === "string" && typeof value.appName === "string" && typeof value.callerLabel === "string" && typeof value.sessionCount === "number" && Array.isArray(value.sessions) && value.sessions.every(isRuntimeHostSessionHealth);
133
161
  };
134
- const isDaemonSessionHealth = (value) => isRecord(value) && typeof value.sessionId === "number" && (value.internalLeaseId === void 0 || typeof value.internalLeaseId === "string") && typeof value.initialized === "boolean";
162
+ const isRuntimeHostSessionHealth = (value) => isRecord(value) && typeof value.sessionId === "number" && (value.internalSessionId === void 0 || typeof value.internalSessionId === "string") && typeof value.initialized === "boolean";
135
163
  const isRect = (value) => isRecord(value) && typeof value.x === "number" && typeof value.y === "number" && typeof value.width === "number" && typeof value.height === "number";
136
164
  const isTrayBoundsResult = (value) => isRecord(value) && (value.kind === "native" || value.kind === "inferred" || value.kind === "unavailable") && typeof value.source === "string" && (value.rect === null || isRect(value.rect));
137
165
  const isTrayEvent = (value) => {
138
166
  if (!isRecord(value) || typeof value.type !== "string") return false;
139
167
  switch (value.type) {
140
- case "ready": return typeof value.spaceId === "string";
141
- case "menuClick": return typeof value.spaceId === "string" && typeof value.trayId === "string" && typeof value.itemId === "number";
168
+ case "ready": return typeof value.appId === "string";
169
+ case "menuClick": return typeof value.appId === "string" && typeof value.trayId === "string" && typeof value.itemId === "number";
142
170
  case "trayClick":
143
- case "trayDoubleClick": return typeof value.spaceId === "string" && typeof value.trayId === "string" && isMouseButton(value.button) && typeof value.x === "number" && typeof value.y === "number";
171
+ case "trayDoubleClick": return typeof value.appId === "string" && typeof value.trayId === "string" && isMouseButton(value.button) && typeof value.x === "number" && typeof value.y === "number";
144
172
  default: return false;
145
173
  }
146
174
  };
147
175
  const isMouseButton = (value) => value === "left" || value === "right" || value === "middle";
148
176
  //#endregion
149
- export { OPENTRAY_PROTOCOL_FAMILY, OPENTRAY_PROTOCOL_LINE, OPENTRAY_PROTOCOL_LINE_MAJOR, OPENTRAY_PROTOCOL_LINE_MINOR, PROTOCOL_VERSION, compareOpenTrayProtocolLine, createBrokerEndpointIdentity, formatBrokerEndpointName, formatBrokerStateRoot, formatOpenTrayProtocolLine, formatProtocolDistTag, formatUnixSocketPath, formatWindowsPipeName, isOpenTrayProtocolLineCompatible, isProtocolLineReleaseChannel, isServerFrame, isSupportedProtocolVersion, parseProtocolDistTag, parseServerFrame, protocolLineReleaseChannels };
177
+ export { CALLER_LABEL_MAX_LENGTH, DEFAULT_CALLER_LABEL, OPENTRAY_PROTOCOL_FAMILY, OPENTRAY_PROTOCOL_LINE, OPENTRAY_PROTOCOL_LINE_MAJOR, OPENTRAY_PROTOCOL_LINE_MINOR, PROTOCOL_VERSION, compareOpenTrayProtocolLine, createBrokerEndpointIdentity, formatBrokerEndpointName, formatBrokerProcessTitle, formatBrokerStateRoot, formatOpenTrayProtocolLine, formatProtocolDistTag, formatUnixSocketPath, formatWindowsPipeName, isOpenTrayProtocolLineCompatible, isProtocolLineReleaseChannel, isServerFrame, isSupportedProtocolVersion, parseProtocolDistTag, parseServerFrame, protocolLineReleaseChannels, sanitizeCallerLabel };
150
178
 
151
179
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["export type SessionId = string;\nexport type RequestId = string;\nexport type SpaceId = string;\nexport type TrayId = string;\nexport type MenuItemId = number;\n\n/** @deprecated Use `SessionId`. */\nexport type LeaseId = SessionId;\n/** @deprecated Use `SpaceId`. */\nexport type SurfaceId = SpaceId;\n\nexport const PROTOCOL_VERSION = 1;\nexport const OPENTRAY_PROTOCOL_FAMILY = \"opentray-protocol\";\nexport const OPENTRAY_PROTOCOL_LINE_MAJOR = 1;\nexport const OPENTRAY_PROTOCOL_LINE_MINOR = 1;\n\nexport const protocolLineReleaseChannels = [\"stable\", \"alpha\"] as const;\nexport type ProtocolLineReleaseChannel = (typeof protocolLineReleaseChannels)[number];\n\nexport interface OpenTrayProtocolLine {\n family: typeof OPENTRAY_PROTOCOL_FAMILY;\n major: number;\n minor: number;\n}\n\nexport interface ProtocolDistTagOptions {\n channel: ProtocolLineReleaseChannel;\n major?: number;\n minor?: number;\n}\n\nexport interface ProtocolDistTag {\n channel: ProtocolLineReleaseChannel;\n major: number;\n minor: number;\n}\n\nexport const OPENTRAY_PROTOCOL_LINE: OpenTrayProtocolLine = {\n family: OPENTRAY_PROTOCOL_FAMILY,\n major: OPENTRAY_PROTOCOL_LINE_MAJOR,\n minor: OPENTRAY_PROTOCOL_LINE_MINOR,\n};\n\n// Install-time protocol lines can advance by minor version while runtime authority stays numeric.\nexport const compareOpenTrayProtocolLine = (\n left: OpenTrayProtocolLine,\n right: OpenTrayProtocolLine,\n): number => {\n assertOpenTrayProtocolLine(left, \"left\");\n assertOpenTrayProtocolLine(right, \"right\");\n if (left.major !== right.major) {\n return left.major - right.major;\n }\n return left.minor - right.minor;\n};\n\nexport const isOpenTrayProtocolLineCompatible = (\n supported: OpenTrayProtocolLine,\n required: OpenTrayProtocolLine,\n): boolean => {\n assertOpenTrayProtocolLine(supported, \"supported\");\n assertOpenTrayProtocolLine(required, \"required\");\n return supported.major === required.major && supported.minor >= required.minor;\n};\n\nexport const formatOpenTrayProtocolLine = ({\n family,\n major,\n minor,\n}: OpenTrayProtocolLine = OPENTRAY_PROTOCOL_LINE): string => {\n assertProtocolLineVersion(major, \"major\");\n assertProtocolLineVersion(minor, \"minor\");\n return `${family}/${major}.${minor}`;\n};\n\nexport const isProtocolLineReleaseChannel = (value: string): value is ProtocolLineReleaseChannel =>\n protocolLineReleaseChannels.includes(value as ProtocolLineReleaseChannel);\n\nexport const formatProtocolDistTag = ({\n channel,\n major = OPENTRAY_PROTOCOL_LINE_MAJOR,\n minor = OPENTRAY_PROTOCOL_LINE_MINOR,\n}: ProtocolDistTagOptions): string => {\n assertProtocolLineReleaseChannel(channel);\n assertProtocolLineVersion(major, \"major\");\n assertProtocolLineVersion(minor, \"minor\");\n return `${channel}-${major}-${minor}`;\n};\n\nexport const parseProtocolDistTag = (tag: string): ProtocolDistTag => {\n const match = /^(?<channel>[a-z]+)-(?<major>\\d+)-(?<minor>\\d+)$/u.exec(tag);\n const groups = match?.groups;\n if (groups === undefined) {\n throw new Error(`invalid OpenTray protocol dist-tag: ${tag}`);\n }\n const channel = groups.channel;\n if (channel === undefined || !isProtocolLineReleaseChannel(channel)) {\n throw new Error(`unsupported OpenTray protocol dist-tag channel: ${channel ?? \"\"}`);\n }\n const major = Number(groups.major);\n const minor = Number(groups.minor);\n assertProtocolLineVersion(major, \"major\");\n assertProtocolLineVersion(minor, \"minor\");\n return { channel, major, minor };\n};\n\nexport interface BrokerEndpointIdentity {\n packageVersion: string;\n protocolVersion: number;\n}\n\nexport interface BrokerEndpointIdentityOptions {\n packageVersion: string;\n protocolVersion?: number;\n}\n\nexport const createBrokerEndpointIdentity = ({\n packageVersion,\n protocolVersion = PROTOCOL_VERSION,\n}: BrokerEndpointIdentityOptions): BrokerEndpointIdentity => {\n assertEndpointComponent(packageVersion, \"packageVersion\");\n if (!Number.isInteger(protocolVersion) || protocolVersion <= 0) {\n throw new Error(`protocolVersion must be a positive integer: ${protocolVersion}`);\n }\n\n return {\n packageVersion,\n protocolVersion,\n };\n};\n\nexport const isSupportedProtocolVersion = (protocolVersion: number): boolean =>\n protocolVersion === PROTOCOL_VERSION;\n\nexport const formatBrokerEndpointName = (identity: BrokerEndpointIdentity): string => {\n assertEndpointIdentity(identity);\n return `opentray-${identity.packageVersion}-p${identity.protocolVersion}`;\n};\n\nexport const formatBrokerStateRoot = (homeDir: string, identity: BrokerEndpointIdentity): string => {\n assertEndpointIdentity(identity);\n if (homeDir.length === 0) {\n throw new Error(\"homeDir must not be empty\");\n }\n\n const normalizedHome = homeDir.replace(/[\\\\/]+$/u, \"\");\n return `${normalizedHome}/.opentray/${identity.packageVersion}`;\n};\n\nexport const formatUnixSocketPath = (homeDir: string, identity: BrokerEndpointIdentity): string =>\n `${formatBrokerStateRoot(homeDir, identity)}/opentray-p${identity.protocolVersion}.sock`;\n\nexport const formatWindowsPipeName = (identity: BrokerEndpointIdentity): string =>\n `\\\\\\\\.\\\\pipe\\\\${formatBrokerEndpointName(identity)}`;\n\nconst endpointComponentPattern = /^[0-9A-Za-z._+-]+$/u;\n\nconst assertOpenTrayProtocolLine = (line: OpenTrayProtocolLine, name: string): void => {\n assertProtocolLineVersion(line.major, `${name}.major`);\n assertProtocolLineVersion(line.minor, `${name}.minor`);\n};\n\nconst assertProtocolLineReleaseChannel = (channel: string): void => {\n if (!isProtocolLineReleaseChannel(channel)) {\n throw new Error(`unsupported OpenTray protocol release channel: ${channel}`);\n }\n};\n\nconst assertProtocolLineVersion = (value: number, name: string): void => {\n if (!Number.isInteger(value) || value < 0) {\n throw new Error(`protocol line ${name} must be a non-negative integer: ${value}`);\n }\n};\n\nconst assertEndpointIdentity = (identity: BrokerEndpointIdentity): void => {\n assertEndpointComponent(identity.packageVersion, \"packageVersion\");\n if (!Number.isInteger(identity.protocolVersion) || identity.protocolVersion <= 0) {\n throw new Error(`protocolVersion must be a positive integer: ${identity.protocolVersion}`);\n }\n};\n\nconst assertEndpointComponent = (value: string, name: string): void => {\n if (value.length === 0) {\n throw new Error(`${name} must not be empty`);\n }\n if (!endpointComponentPattern.test(value)) {\n throw new Error(`${name} contains invalid endpoint characters: ${value}`);\n }\n};\n\nexport interface SpaceOptions {\n id?: SpaceId;\n title?: string;\n icon?: Icon;\n default?: boolean;\n}\n\n/** @deprecated Use `SpaceOptions`. */\nexport type SurfaceOptions = SpaceOptions;\n\nexport interface SpaceRef {\n spaceId: SpaceId;\n}\n\n/** @deprecated Use `SpaceRef`. */\nexport type SurfaceRef = SpaceRef;\n\nexport interface TrayOptions {\n trayId?: TrayId;\n appId?: string;\n title?: string;\n tooltip?: Tooltip;\n icon: Icon;\n menu?: Menu;\n}\n\nexport interface Tooltip {\n title: string;\n description: string;\n}\n\nexport interface Menu {\n items: MenuItem[];\n}\n\nexport type MenuItem =\n | {\n type: \"item\";\n id: MenuItemId;\n title: string;\n primaryEvent?: boolean;\n enabled?: boolean;\n shortcut?: string;\n }\n | {\n type: \"check\";\n id: MenuItemId;\n title: string;\n enabled?: boolean;\n checked?: boolean;\n }\n | {\n type: \"radio\";\n id: MenuItemId;\n title: string;\n enabled?: boolean;\n checked?: boolean;\n group: number;\n }\n | {\n type: \"separator\";\n }\n | {\n type: \"submenu\";\n title: string;\n enabled?: boolean;\n items: MenuItem[];\n };\n\nexport type Icon =\n | { type: \"rgba\"; data: Uint8Array | number[]; width: number; height: number }\n | { type: \"encoded\"; data: Uint8Array | number[] }\n | { type: \"file\"; path: string };\n\nexport interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport type TrayBoundsKind = \"native\" | \"inferred\" | \"unavailable\";\n\nexport interface TrayBoundsResult {\n kind: TrayBoundsKind;\n source: string;\n rect: Rect | null;\n}\n\nexport type MouseButton = \"left\" | \"right\" | \"middle\";\n\nexport type TrayEvent =\n | { type: \"ready\"; spaceId: SpaceId }\n | { type: \"menuClick\"; spaceId: SpaceId; trayId: TrayId; itemId: MenuItemId }\n | { type: \"trayClick\"; spaceId: SpaceId; trayId: TrayId; button: MouseButton; x: number; y: number }\n | { type: \"trayDoubleClick\"; spaceId: SpaceId; trayId: TrayId; button: MouseButton; x: number; y: number };\n\nexport interface ExtensionScope {\n spaceId: SpaceId;\n trayId?: TrayId;\n ext: string;\n}\n\nexport interface ExtensionEnvelope<TData = unknown> {\n scope: ExtensionScope;\n data: TData;\n}\n\nexport interface DaemonSessionHealth {\n sessionId: number;\n internalLeaseId?: SessionId;\n initialized: boolean;\n}\n\nexport interface DaemonHealth {\n pid: number;\n packageVersion: string;\n protocolVersion: number;\n endpoint: string;\n sessionCount: number;\n sessions: DaemonSessionHealth[];\n}\n\nexport type ClientFrame =\n | { type: \"init\"; protocolVersion: number; clientVersion: string }\n | ClientRequestFrame\n | { type: \"exit\" };\n\nexport type ClientRequestFrame =\n | ({ type: \"create-space\"; requestId: RequestId } & SpaceOptions)\n | { type: \"resolve-default-space\"; requestId: RequestId }\n | { type: \"create-tray\"; requestId: RequestId; space: SpaceRef; tray: TrayOptions }\n | { type: \"destroy-tray\"; requestId: RequestId; spaceId: SpaceId; trayId: TrayId }\n | { type: \"get-tray-bounds\"; requestId: RequestId; spaceId: SpaceId; trayId: TrayId }\n | { type: \"set-tray-menu\"; requestId: RequestId; spaceId: SpaceId; trayId: TrayId; menu: Menu }\n | { type: \"set-tray-icon\"; requestId: RequestId; spaceId: SpaceId; trayId: TrayId; icon: Icon }\n | { type: \"set-tray-tooltip\"; requestId: RequestId; spaceId: SpaceId; trayId: TrayId; tooltip: Tooltip }\n | { type: \"set-tray-title\"; requestId: RequestId; spaceId: SpaceId; trayId: TrayId; title: string }\n | { type: \"load-ext\"; requestId: RequestId; spaceId: SpaceId; name: string; path: string; mountId?: string }\n | { type: \"ext-command\"; requestId: RequestId; spaceId: SpaceId; trayId: TrayId; ext: string; data: unknown }\n | { type: \"unload-ext\"; requestId: RequestId; spaceId: SpaceId; name: string }\n | { type: \"health\"; requestId: RequestId };\n\nexport type ServerFrame =\n | { type: \"ready\"; protocolVersion: number; brokerVersion: string; sessionId: SessionId }\n | { type: \"space-created\"; requestId: RequestId; space: SpaceRef }\n | { type: \"default-space\"; requestId: RequestId; space: SpaceRef }\n | { type: \"tray-created\"; requestId: RequestId; spaceId: SpaceId; trayId: TrayId }\n | { type: \"tray-bounds\"; requestId: RequestId; spaceId: SpaceId; trayId: TrayId; bounds: TrayBoundsResult }\n | { type: \"ack\"; requestId: RequestId }\n | { type: \"ext-command-result\"; requestId: RequestId; events: ExtensionEnvelope[] }\n | { type: \"daemon-health\"; requestId: RequestId; health: DaemonHealth }\n | { type: \"event\"; event: TrayEvent }\n | { type: \"ext-event\"; spaceId: SpaceId; trayId: TrayId; ext: string; data: unknown }\n | { type: \"error\"; requestId?: RequestId; code: string; message: string };\n\nexport interface ParseResult<T> {\n ok: boolean;\n frame?: T;\n error?: string;\n}\n\nexport const parseServerFrame = (line: string): ParseResult<ServerFrame> => {\n try {\n const value: unknown = JSON.parse(line);\n if (!isServerFrame(value)) {\n return { ok: false, error: \"invalid server frame\" };\n }\n return { ok: true, frame: value };\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : \"unknown parse error\",\n };\n }\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nexport const isServerFrame = (value: unknown): value is ServerFrame => {\n if (!isRecord(value) || typeof value.type !== \"string\") {\n return false;\n }\n\n switch (value.type) {\n case \"ready\":\n return (\n typeof value.protocolVersion === \"number\" &&\n typeof value.brokerVersion === \"string\" &&\n typeof value.sessionId === \"string\"\n );\n case \"space-created\":\n return typeof value.requestId === \"string\" && isRecord(value.space);\n case \"default-space\":\n return typeof value.requestId === \"string\" && isRecord(value.space);\n case \"tray-created\":\n return (\n typeof value.requestId === \"string\" &&\n typeof value.spaceId === \"string\" &&\n typeof value.trayId === \"string\"\n );\n case \"tray-bounds\":\n return (\n typeof value.requestId === \"string\" &&\n typeof value.spaceId === \"string\" &&\n typeof value.trayId === \"string\" &&\n isTrayBoundsResult(value.bounds)\n );\n case \"ack\":\n return typeof value.requestId === \"string\";\n case \"ext-command-result\":\n return typeof value.requestId === \"string\" && Array.isArray(value.events) && value.events.every(isExtensionEnvelope);\n case \"daemon-health\":\n return typeof value.requestId === \"string\" && isDaemonHealth(value.health);\n case \"event\":\n return isTrayEvent(value.event);\n case \"ext-event\":\n return (\n typeof value.spaceId === \"string\" &&\n typeof value.trayId === \"string\" &&\n typeof value.ext === \"string\"\n );\n case \"error\":\n return (\n (value.requestId === undefined || typeof value.requestId === \"string\") &&\n typeof value.code === \"string\" &&\n typeof value.message === \"string\"\n );\n default:\n return false;\n }\n};\n\nconst isExtensionEnvelope = (value: unknown): value is ExtensionEnvelope => {\n if (!isRecord(value) || !isRecord(value.scope)) {\n return false;\n }\n const scope = value.scope as Record<string, unknown>;\n return (\n (typeof scope.spaceId === \"string\" || typeof scope.surfaceId === \"string\") &&\n (scope.trayId === undefined || typeof scope.trayId === \"string\") &&\n typeof scope.ext === \"string\" &&\n \"data\" in value\n );\n};\n\nconst isDaemonHealth = (value: unknown): value is DaemonHealth => {\n if (!isRecord(value)) {\n return false;\n }\n\n return (\n typeof value.pid === \"number\" &&\n typeof value.packageVersion === \"string\" &&\n typeof value.protocolVersion === \"number\" &&\n typeof value.endpoint === \"string\" &&\n typeof value.sessionCount === \"number\" &&\n Array.isArray(value.sessions) &&\n value.sessions.every(isDaemonSessionHealth)\n );\n};\n\nconst isDaemonSessionHealth = (value: unknown): value is DaemonSessionHealth =>\n isRecord(value) &&\n typeof value.sessionId === \"number\" &&\n (value.internalLeaseId === undefined || typeof value.internalLeaseId === \"string\") &&\n typeof value.initialized === \"boolean\";\n\nconst isRect = (value: unknown): value is Rect =>\n isRecord(value) &&\n typeof value.x === \"number\" &&\n typeof value.y === \"number\" &&\n typeof value.width === \"number\" &&\n typeof value.height === \"number\";\n\nconst isTrayBoundsResult = (value: unknown): value is TrayBoundsResult =>\n isRecord(value) &&\n (value.kind === \"native\" || value.kind === \"inferred\" || value.kind === \"unavailable\") &&\n typeof value.source === \"string\" &&\n (value.rect === null || isRect(value.rect));\n\nconst isTrayEvent = (value: unknown): value is TrayEvent => {\n if (!isRecord(value) || typeof value.type !== \"string\") {\n return false;\n }\n\n switch (value.type) {\n case \"ready\":\n return typeof value.spaceId === \"string\";\n case \"menuClick\":\n return (\n typeof value.spaceId === \"string\" &&\n typeof value.trayId === \"string\" &&\n typeof value.itemId === \"number\"\n );\n case \"trayClick\":\n case \"trayDoubleClick\":\n return (\n typeof value.spaceId === \"string\" &&\n typeof value.trayId === \"string\" &&\n isMouseButton(value.button) &&\n typeof value.x === \"number\" &&\n typeof value.y === \"number\"\n );\n default:\n return false;\n }\n};\n\nconst isMouseButton = (value: unknown): value is MouseButton =>\n value === \"left\" || value === \"right\" || value === \"middle\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["export type SessionId = string;\nexport type RequestId = string;\nexport type AppId = string;\nexport type TrayId = string;\nexport type MenuItemId = number;\n\nexport const PROTOCOL_VERSION = 1;\nexport const OPENTRAY_PROTOCOL_FAMILY = \"opentray-protocol\";\nexport const OPENTRAY_PROTOCOL_LINE_MAJOR = 1;\nexport const OPENTRAY_PROTOCOL_LINE_MINOR = 1;\n\nexport const protocolLineReleaseChannels = [\"stable\", \"alpha\"] as const;\nexport type ProtocolLineReleaseChannel =\n (typeof protocolLineReleaseChannels)[number];\n\nexport interface OpenTrayProtocolLine {\n family: typeof OPENTRAY_PROTOCOL_FAMILY;\n major: number;\n minor: number;\n}\n\nexport interface ProtocolDistTagOptions {\n channel: ProtocolLineReleaseChannel;\n major?: number;\n minor?: number;\n}\n\nexport interface ProtocolDistTag {\n channel: ProtocolLineReleaseChannel;\n major: number;\n minor: number;\n}\n\nexport const OPENTRAY_PROTOCOL_LINE: OpenTrayProtocolLine = {\n family: OPENTRAY_PROTOCOL_FAMILY,\n major: OPENTRAY_PROTOCOL_LINE_MAJOR,\n minor: OPENTRAY_PROTOCOL_LINE_MINOR,\n};\n\n// Install-time protocol lines can advance by minor version while runtime authority stays numeric.\nexport const compareOpenTrayProtocolLine = (\n left: OpenTrayProtocolLine,\n right: OpenTrayProtocolLine\n): number => {\n assertOpenTrayProtocolLine(left, \"left\");\n assertOpenTrayProtocolLine(right, \"right\");\n if (left.major !== right.major) {\n return left.major - right.major;\n }\n return left.minor - right.minor;\n};\n\nexport const isOpenTrayProtocolLineCompatible = (\n supported: OpenTrayProtocolLine,\n required: OpenTrayProtocolLine\n): boolean => {\n assertOpenTrayProtocolLine(supported, \"supported\");\n assertOpenTrayProtocolLine(required, \"required\");\n return (\n supported.major === required.major && supported.minor >= required.minor\n );\n};\n\nexport const formatOpenTrayProtocolLine = ({\n family,\n major,\n minor,\n}: OpenTrayProtocolLine = OPENTRAY_PROTOCOL_LINE): string => {\n assertProtocolLineVersion(major, \"major\");\n assertProtocolLineVersion(minor, \"minor\");\n return `${family}/${major}.${minor}`;\n};\n\nexport const isProtocolLineReleaseChannel = (\n value: string\n): value is ProtocolLineReleaseChannel =>\n protocolLineReleaseChannels.includes(value as ProtocolLineReleaseChannel);\n\nexport const formatProtocolDistTag = ({\n channel,\n major = OPENTRAY_PROTOCOL_LINE_MAJOR,\n minor = OPENTRAY_PROTOCOL_LINE_MINOR,\n}: ProtocolDistTagOptions): string => {\n assertProtocolLineReleaseChannel(channel);\n assertProtocolLineVersion(major, \"major\");\n assertProtocolLineVersion(minor, \"minor\");\n return `${channel}-${major}-${minor}`;\n};\n\nexport const parseProtocolDistTag = (tag: string): ProtocolDistTag => {\n const match = /^(?<channel>[a-z]+)-(?<major>\\d+)-(?<minor>\\d+)$/u.exec(tag);\n const groups = match?.groups;\n if (groups === undefined) {\n throw new Error(`invalid OpenTray protocol dist-tag: ${tag}`);\n }\n const channel = groups.channel;\n if (channel === undefined || !isProtocolLineReleaseChannel(channel)) {\n throw new Error(\n `unsupported OpenTray protocol dist-tag channel: ${channel ?? \"\"}`\n );\n }\n const major = Number(groups.major);\n const minor = Number(groups.minor);\n assertProtocolLineVersion(major, \"major\");\n assertProtocolLineVersion(minor, \"minor\");\n return { channel, major, minor };\n};\n\n/**\n * Neutral caller label used when no usable caller identity can be derived.\n * Keeps the broker honest instead of impersonating an unrelated application.\n */\nexport const DEFAULT_CALLER_LABEL = \"opentray\";\n\n/**\n * Maximum length of a sanitized caller label. Keeps socket paths, runtime\n * directory names, and process titles within platform limits.\n */\nexport const CALLER_LABEL_MAX_LENGTH = 48;\n\nconst callerLabelAllowedPattern = /[a-z0-9-]+/g;\n\nexport interface BrokerEndpointIdentity {\n packageVersion: string;\n protocolVersion: number;\n callerLabel: string;\n}\n\nexport interface BrokerEndpointIdentityOptions {\n packageVersion: string;\n protocolVersion?: number;\n callerLabel?: string;\n}\n\nexport const sanitizeCallerLabel = (value: string | undefined): string => {\n if (value !== undefined && typeof value !== \"string\") {\n throw new Error(`callerLabel must be a string: ${String(value)}`);\n }\n const raw = value ?? \"\";\n const lowered = raw.toLowerCase();\n const segments = lowered.match(callerLabelAllowedPattern);\n if (segments === null || segments.length === 0) {\n return DEFAULT_CALLER_LABEL;\n }\n const joined = segments.join(\"-\");\n const trimmed = joined.replace(/^-+|-+$/gu, \"\");\n if (trimmed.length === 0) {\n return DEFAULT_CALLER_LABEL;\n }\n return trimmed.slice(0, CALLER_LABEL_MAX_LENGTH);\n};\n\nexport const createBrokerEndpointIdentity = ({\n packageVersion,\n protocolVersion = PROTOCOL_VERSION,\n callerLabel,\n}: BrokerEndpointIdentityOptions): BrokerEndpointIdentity => {\n assertEndpointComponent(packageVersion, \"packageVersion\");\n if (!Number.isInteger(protocolVersion) || protocolVersion <= 0) {\n throw new Error(\n `protocolVersion must be a positive integer: ${protocolVersion}`\n );\n }\n\n return {\n packageVersion,\n protocolVersion,\n callerLabel: sanitizeCallerLabel(callerLabel),\n };\n};\n\nexport const isSupportedProtocolVersion = (protocolVersion: number): boolean =>\n protocolVersion === PROTOCOL_VERSION;\n\nexport const formatBrokerEndpointName = (\n identity: BrokerEndpointIdentity\n): string => {\n assertEndpointIdentity(identity);\n return `opentray-${identity.packageVersion}-p${identity.protocolVersion}-${identity.callerLabel}`;\n};\n\nexport const formatBrokerStateRoot = (\n homeDir: string,\n identity: BrokerEndpointIdentity\n): string => {\n assertEndpointIdentity(identity);\n if (homeDir.length === 0) {\n throw new Error(\"homeDir must not be empty\");\n }\n\n const normalizedHome = homeDir.replace(/[\\\\/]+$/u, \"\");\n return `${normalizedHome}/.opentray/${identity.packageVersion}/${identity.callerLabel}`;\n};\n\nexport const formatUnixSocketPath = (\n homeDir: string,\n identity: BrokerEndpointIdentity\n): string =>\n `${formatBrokerStateRoot(homeDir, identity)}/opentray-p${\n identity.protocolVersion\n }.sock`;\n\nexport const formatWindowsPipeName = (\n identity: BrokerEndpointIdentity\n): string => `\\\\\\\\.\\\\pipe\\\\${formatBrokerEndpointName(identity)}`;\n\n/**\n * Human-readable process title for a broker pinned to a caller. Used by the SDK\n * spawn path so task managers show the owning application, not a generic name.\n */\nexport const formatBrokerProcessTitle = (\n identity: BrokerEndpointIdentity\n): string => {\n assertEndpointIdentity(identity);\n return `opentray · ${identity.callerLabel}`;\n};\n\nconst endpointComponentPattern = /^[0-9A-Za-z._+-]+$/u;\n\nconst assertOpenTrayProtocolLine = (\n line: OpenTrayProtocolLine,\n name: string\n): void => {\n assertProtocolLineVersion(line.major, `${name}.major`);\n assertProtocolLineVersion(line.minor, `${name}.minor`);\n};\n\nconst assertProtocolLineReleaseChannel = (channel: string): void => {\n if (!isProtocolLineReleaseChannel(channel)) {\n throw new Error(\n `unsupported OpenTray protocol release channel: ${channel}`\n );\n }\n};\n\nconst assertProtocolLineVersion = (value: number, name: string): void => {\n if (!Number.isInteger(value) || value < 0) {\n throw new Error(\n `protocol line ${name} must be a non-negative integer: ${value}`\n );\n }\n};\n\nconst assertEndpointIdentity = (identity: BrokerEndpointIdentity): void => {\n assertEndpointComponent(identity.packageVersion, \"packageVersion\");\n if (\n !Number.isInteger(identity.protocolVersion) ||\n identity.protocolVersion <= 0\n ) {\n throw new Error(\n `protocolVersion must be a positive integer: ${identity.protocolVersion}`\n );\n }\n};\n\nconst assertEndpointComponent = (value: string, name: string): void => {\n if (value.length === 0) {\n throw new Error(`${name} must not be empty`);\n }\n if (!endpointComponentPattern.test(value)) {\n throw new Error(`${name} contains invalid endpoint characters: ${value}`);\n }\n};\n\nexport interface AppOptions {\n id?: AppId;\n name?: string;\n icon?: Icon;\n default?: boolean;\n}\n\nexport interface AppRef {\n appId: AppId;\n}\n\nexport interface AppIdentity {\n appId: AppId;\n appName: string;\n}\n\nexport interface TrayOptions {\n id: string;\n tooltip?: Tooltip;\n icon?: Icon;\n menu?: Menu;\n}\n\nexport interface Tooltip {\n title: string;\n description: string;\n}\n\nexport interface Menu {\n items: MenuItem[];\n}\n\nexport type MenuItem =\n | {\n type: \"item\";\n id: MenuItemId;\n title: string;\n primaryEvent?: boolean;\n enabled?: boolean;\n shortcut?: string;\n }\n | {\n type: \"check\";\n id: MenuItemId;\n title: string;\n enabled?: boolean;\n checked?: boolean;\n }\n | {\n type: \"radio\";\n id: MenuItemId;\n title: string;\n enabled?: boolean;\n checked?: boolean;\n group: number;\n }\n | {\n type: \"separator\";\n }\n | {\n type: \"submenu\";\n title: string;\n enabled?: boolean;\n items: MenuItem[];\n };\n\nexport type IconImage =\n | { type: \"rgba\"; data: Uint8Array | number[]; width: number; height: number }\n | { type: \"encoded\"; data: Uint8Array | number[] }\n | { type: \"file\"; path: string };\n\nexport type SimpleIcon = IconImage & { text?: string };\n\nexport type IconText = IconImage & { text: string };\n\nexport interface IconCandidates {\n \"icon-only\"?: IconImage;\n \"text-only\"?: string;\n \"icon-text\"?: IconText;\n}\n\nexport type Icon = IconCandidates & Partial<SimpleIcon>;\n\nexport interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport type TrayBoundsKind = \"native\" | \"inferred\" | \"unavailable\";\n\nexport interface TrayBoundsResult {\n kind: TrayBoundsKind;\n source: string;\n rect: Rect | null;\n}\n\nexport type MouseButton = \"left\" | \"right\" | \"middle\";\n\nexport type TrayEvent =\n | { type: \"ready\"; appId: AppId }\n | { type: \"menuClick\"; appId: AppId; trayId: TrayId; itemId: MenuItemId }\n | {\n type: \"trayClick\";\n appId: AppId;\n trayId: TrayId;\n button: MouseButton;\n x: number;\n y: number;\n }\n | {\n type: \"trayDoubleClick\";\n appId: AppId;\n trayId: TrayId;\n button: MouseButton;\n x: number;\n y: number;\n };\n\nexport interface ExtensionScope {\n appId: AppId;\n trayId?: TrayId;\n ext: string;\n}\n\nexport interface ExtensionEnvelope<TData = unknown> {\n scope: ExtensionScope;\n data: TData;\n}\n\nexport interface RuntimeHostSessionHealth {\n sessionId: number;\n internalSessionId?: SessionId;\n initialized: boolean;\n}\n\nexport interface RuntimeHostHealth {\n pid: number;\n packageVersion: string;\n protocolVersion: number;\n endpoint: string;\n appId: AppId;\n appName: string;\n callerLabel: string;\n sessionCount: number;\n sessions: RuntimeHostSessionHealth[];\n}\n\nexport type ClientFrame =\n | { type: \"init\"; protocolVersion: number; clientVersion: string }\n | ClientRequestFrame\n | { type: \"exit\" };\n\nexport type ClientRequestFrame =\n | ({ type: \"create-app\"; requestId: RequestId } & AppOptions)\n | { type: \"resolve-default-app\"; requestId: RequestId }\n | {\n type: \"create-tray\";\n requestId: RequestId;\n app: AppRef;\n tray: TrayOptions;\n }\n | { type: \"destroy-tray\"; requestId: RequestId; appId: AppId; trayId: TrayId }\n | {\n type: \"get-tray-bounds\";\n requestId: RequestId;\n appId: AppId;\n trayId: TrayId;\n }\n | {\n type: \"set-tray-menu\";\n requestId: RequestId;\n appId: AppId;\n trayId: TrayId;\n menu: Menu;\n }\n | {\n type: \"set-tray-icon\";\n requestId: RequestId;\n appId: AppId;\n trayId: TrayId;\n icon: Icon;\n }\n | {\n type: \"set-tray-tooltip\";\n requestId: RequestId;\n appId: AppId;\n trayId: TrayId;\n tooltip: Tooltip;\n }\n | {\n type: \"load-ext\";\n requestId: RequestId;\n appId: AppId;\n name: string;\n path: string;\n mountId?: string;\n }\n | {\n type: \"ext-command\";\n requestId: RequestId;\n appId: AppId;\n trayId: TrayId;\n ext: string;\n data: unknown;\n }\n | { type: \"unload-ext\"; requestId: RequestId; appId: AppId; name: string }\n | { type: \"health\"; requestId: RequestId };\n\nexport type ServerFrame =\n | {\n type: \"ready\";\n protocolVersion: number;\n brokerVersion: string;\n sessionId: SessionId;\n }\n | { type: \"app-created\"; requestId: RequestId; app: AppRef }\n | { type: \"default-app\"; requestId: RequestId; app: AppRef }\n | { type: \"tray-created\"; requestId: RequestId; appId: AppId; trayId: TrayId }\n | {\n type: \"tray-bounds\";\n requestId: RequestId;\n appId: AppId;\n trayId: TrayId;\n bounds: TrayBoundsResult;\n }\n | { type: \"ack\"; requestId: RequestId }\n | {\n type: \"ext-command-result\";\n requestId: RequestId;\n events: ExtensionEnvelope[];\n }\n | {\n type: \"runtime-host-health\";\n requestId: RequestId;\n health: RuntimeHostHealth;\n }\n | { type: \"event\"; event: TrayEvent }\n | {\n type: \"ext-event\";\n appId: AppId;\n trayId: TrayId;\n ext: string;\n data: unknown;\n }\n | { type: \"error\"; requestId?: RequestId; code: string; message: string };\n\nexport interface ParseResult<T> {\n ok: boolean;\n frame?: T;\n error?: string;\n}\n\nexport const parseServerFrame = (line: string): ParseResult<ServerFrame> => {\n try {\n const value: unknown = JSON.parse(line);\n if (!isServerFrame(value)) {\n return { ok: false, error: \"invalid server frame\" };\n }\n return { ok: true, frame: value };\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : \"unknown parse error\",\n };\n }\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nexport const isServerFrame = (value: unknown): value is ServerFrame => {\n if (!isRecord(value) || typeof value.type !== \"string\") {\n return false;\n }\n\n switch (value.type) {\n case \"ready\":\n return (\n typeof value.protocolVersion === \"number\" &&\n typeof value.brokerVersion === \"string\" &&\n typeof value.sessionId === \"string\"\n );\n case \"app-created\":\n return typeof value.requestId === \"string\" && isRecord(value.app);\n case \"default-app\":\n return typeof value.requestId === \"string\" && isRecord(value.app);\n case \"tray-created\":\n return (\n typeof value.requestId === \"string\" &&\n typeof value.appId === \"string\" &&\n typeof value.trayId === \"string\"\n );\n case \"tray-bounds\":\n return (\n typeof value.requestId === \"string\" &&\n typeof value.appId === \"string\" &&\n typeof value.trayId === \"string\" &&\n isTrayBoundsResult(value.bounds)\n );\n case \"ack\":\n return typeof value.requestId === \"string\";\n case \"ext-command-result\":\n return (\n typeof value.requestId === \"string\" &&\n Array.isArray(value.events) &&\n value.events.every(isExtensionEnvelope)\n );\n case \"runtime-host-health\":\n return (\n typeof value.requestId === \"string\" && isRuntimeHostHealth(value.health)\n );\n case \"event\":\n return isTrayEvent(value.event);\n case \"ext-event\":\n return (\n typeof value.appId === \"string\" &&\n typeof value.trayId === \"string\" &&\n typeof value.ext === \"string\"\n );\n case \"error\":\n return (\n (value.requestId === undefined ||\n typeof value.requestId === \"string\") &&\n typeof value.code === \"string\" &&\n typeof value.message === \"string\"\n );\n default:\n return false;\n }\n};\n\nconst isExtensionEnvelope = (value: unknown): value is ExtensionEnvelope => {\n if (!isRecord(value) || !isRecord(value.scope)) {\n return false;\n }\n const scope = value.scope as Record<string, unknown>;\n return (\n typeof scope.appId === \"string\" &&\n (scope.trayId === undefined || typeof scope.trayId === \"string\") &&\n typeof scope.ext === \"string\" &&\n \"data\" in value\n );\n};\n\nconst isRuntimeHostHealth = (value: unknown): value is RuntimeHostHealth => {\n if (!isRecord(value)) {\n return false;\n }\n\n return (\n typeof value.pid === \"number\" &&\n typeof value.packageVersion === \"string\" &&\n typeof value.protocolVersion === \"number\" &&\n typeof value.endpoint === \"string\" &&\n typeof value.appId === \"string\" &&\n typeof value.appName === \"string\" &&\n typeof value.callerLabel === \"string\" &&\n typeof value.sessionCount === \"number\" &&\n Array.isArray(value.sessions) &&\n value.sessions.every(isRuntimeHostSessionHealth)\n );\n};\n\nconst isRuntimeHostSessionHealth = (\n value: unknown\n): value is RuntimeHostSessionHealth =>\n isRecord(value) &&\n typeof value.sessionId === \"number\" &&\n (value.internalSessionId === undefined ||\n typeof value.internalSessionId === \"string\") &&\n typeof value.initialized === \"boolean\";\n\nconst isRect = (value: unknown): value is Rect =>\n isRecord(value) &&\n typeof value.x === \"number\" &&\n typeof value.y === \"number\" &&\n typeof value.width === \"number\" &&\n typeof value.height === \"number\";\n\nconst isTrayBoundsResult = (value: unknown): value is TrayBoundsResult =>\n isRecord(value) &&\n (value.kind === \"native\" ||\n value.kind === \"inferred\" ||\n value.kind === \"unavailable\") &&\n typeof value.source === \"string\" &&\n (value.rect === null || isRect(value.rect));\n\nconst isTrayEvent = (value: unknown): value is TrayEvent => {\n if (!isRecord(value) || typeof value.type !== \"string\") {\n return false;\n }\n\n switch (value.type) {\n case \"ready\":\n return typeof value.appId === \"string\";\n case \"menuClick\":\n return (\n typeof value.appId === \"string\" &&\n typeof value.trayId === \"string\" &&\n typeof value.itemId === \"number\"\n );\n case \"trayClick\":\n case \"trayDoubleClick\":\n return (\n typeof value.appId === \"string\" &&\n typeof value.trayId === \"string\" &&\n isMouseButton(value.button) &&\n typeof value.x === \"number\" &&\n typeof value.y === \"number\"\n );\n default:\n return false;\n }\n};\n\nconst isMouseButton = (value: unknown): value is MouseButton =>\n value === \"left\" || value === \"right\" || value === \"middle\";\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opentray/spec",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Shared TypeScript protocol and contract types for OpenTray.",
5
5
  "type": "module",
6
6
  "license": "MIT",