@abitat_reece/host-daemon 0.1.9 → 0.1.10

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.
@@ -1,5 +1,6 @@
1
1
  import WebSocket from "ws";
2
2
  import { createRelayReplayCache, decryptRelayEnvelope, encryptRelayEnvelope, relaySessionKey, validateRelayEnvelopeFreshness } from "@abitat_reece/shared";
3
+ import { errorDiagnostics, logDiagnostics } from "./diagnostics-log.js";
3
4
  const RELAY_HEARTBEAT_INTERVAL_MS = 15_000;
4
5
  const RELAY_HEARTBEAT_STALE_MS = 45_000;
5
6
  export { createRelayReplayCache };
@@ -39,18 +40,28 @@ export function startRelayClient(input) {
39
40
  return;
40
41
  }
41
42
  const url = relayWebSocketUrl(input.relayEndpoint, input.relayId);
43
+ logDiagnostics(input.diagnostics, "info", "relay.connect.attempt", {
44
+ relayEndpoint: input.relayEndpoint,
45
+ relayId: input.relayId
46
+ });
42
47
  const activeSocket = new WebSocket(url);
43
48
  socket = activeSocket;
44
49
  activeSocket.on("open", () => {
45
50
  if (socket !== activeSocket || stopped) {
46
51
  return;
47
52
  }
53
+ logDiagnostics(input.diagnostics, "info", "relay.connect.open", {
54
+ relayEndpoint: input.relayEndpoint,
55
+ relayId: input.relayId
56
+ });
48
57
  heartbeat?.stop();
49
58
  heartbeat = createRelayHeartbeatController({
59
+ diagnostics: input.diagnostics,
60
+ diagnosticsMetadata: { relayId: input.relayId },
50
61
  heartbeatIntervalMs: input.heartbeatIntervalMs,
51
62
  onStale: () => {
52
63
  if (socket === activeSocket) {
53
- scheduleReconnect();
64
+ scheduleReconnect("stale_heartbeat");
54
65
  }
55
66
  },
56
67
  socket: activeSocket,
@@ -79,19 +90,31 @@ export function startRelayClient(input) {
79
90
  if (socket !== activeSocket) {
80
91
  return;
81
92
  }
93
+ logDiagnostics(input.diagnostics, "warn", "relay.connect.closed", {
94
+ relayId: input.relayId
95
+ });
82
96
  heartbeat?.stop();
83
97
  heartbeat = null;
84
98
  socket = null;
85
- scheduleReconnect();
99
+ scheduleReconnect("socket_closed");
86
100
  });
87
- activeSocket.on("error", () => {
101
+ activeSocket.on("error", (error) => {
102
+ logDiagnostics(input.diagnostics, "warn", "relay.connect.error", {
103
+ error: errorDiagnostics(error),
104
+ relayId: input.relayId
105
+ });
88
106
  activeSocket.close();
89
107
  });
90
108
  };
91
- const scheduleReconnect = () => {
109
+ const scheduleReconnect = (reason) => {
92
110
  if (stopped || reconnectTimer) {
93
111
  return;
94
112
  }
113
+ logDiagnostics(input.diagnostics, "info", "relay.reconnect.scheduled", {
114
+ delayMs: input.reconnectIntervalMs ?? 2_000,
115
+ reason,
116
+ relayId: input.relayId
117
+ });
95
118
  reconnectTimer = setTimeout(() => {
96
119
  reconnectTimer = null;
97
120
  connect();
@@ -125,6 +148,11 @@ export function createRelayHeartbeatController(input) {
125
148
  return;
126
149
  }
127
150
  if (now() - lastHeartbeatAckAt > staleAfterMs) {
151
+ logDiagnostics(input.diagnostics, "warn", "relay.heartbeat.stale", {
152
+ ...input.diagnosticsMetadata,
153
+ msSinceLastAck: now() - lastHeartbeatAckAt,
154
+ staleAfterMs
155
+ });
128
156
  stop();
129
157
  if (typeof input.socket.terminate === "function") {
130
158
  input.socket.terminate();
@@ -1 +1 @@
1
- {"version":3,"file":"relay-client.js","sourceRoot":"","sources":["../../src/local-control/relay-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"relay-client.js","sourceRoot":"","sources":["../../src/local-control/relay-client.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { type IncomingMessage, type Server, type ServerResponse } from "node:http";
2
2
  import type { CodexMobileModelSettings, CodexModelOption, ConversationStatus } from "@abitat_reece/shared";
3
3
  import { type LocalControlStore, type LocalControlTransport } from "./state.js";
4
+ import { type MobileControlDiagnosticsLogger } from "./diagnostics-log.js";
4
5
  export interface LocalCodexProjectSummary {
5
6
  id: string;
6
7
  workspaceId: string;
@@ -40,6 +41,7 @@ export interface LocalCodexMessage {
40
41
  metadata?: Record<string, unknown>;
41
42
  createdAt: string;
42
43
  }
44
+ export type LocalCodexDeliveryMode = "queue" | "steer";
43
45
  export interface LocalCodexCompletionState {
44
46
  conversationId: string;
45
47
  failed: boolean;
@@ -61,6 +63,7 @@ export interface LocalCodexBridge {
61
63
  }>;
62
64
  continueConversation(conversationId: string, input: {
63
65
  attachments?: LocalAttachmentReference[];
66
+ delivery?: LocalCodexDeliveryMode;
64
67
  modelSettings?: CodexMobileModelSettings;
65
68
  prompt: string;
66
69
  }): Promise<{
@@ -93,6 +96,7 @@ interface StartLocalControlServerInput {
93
96
  attachmentDirectory?: string;
94
97
  bindHost: string;
95
98
  codex: LocalCodexBridge;
99
+ diagnostics?: MobileControlDiagnosticsLogger;
96
100
  endpoint: string;
97
101
  port: number;
98
102
  store: LocalControlStore;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/local-control/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/local-control/server.ts"],"names":[],"mappings":"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"}
@@ -3,21 +3,25 @@ import { mkdir, writeFile } from "node:fs/promises";
3
3
  import { randomBytes } from "node:crypto";
4
4
  import { dirname, join } from "node:path";
5
5
  import { defaultLocalAttachmentDirectory } from "./state.js";
6
+ import { attachmentDiagnostics, errorDiagnostics, logDiagnostics, promptDiagnostics } from "./diagnostics-log.js";
6
7
  const LOCAL_WORKSPACE_ID = "local";
7
8
  export async function startLocalControlServer(input) {
8
9
  const identity = await input.store.getMacIdentity();
10
+ const diagnostics = input.diagnostics;
9
11
  const sessions = new Map();
10
12
  const signals = [];
11
13
  let endpoint = input.endpoint;
12
14
  const server = createServer(async (request, response) => {
15
+ const method = request.method ?? "GET";
16
+ let path = "/";
13
17
  try {
14
- if (request.method === "OPTIONS") {
18
+ if (method === "OPTIONS") {
15
19
  writeJson(response, 204, null);
16
20
  return;
17
21
  }
18
22
  const url = new URL(request.url ?? "/", endpoint);
19
- const path = normalizePath(url.pathname);
20
- if (request.method === "GET" && path === "/health") {
23
+ path = normalizePath(url.pathname);
24
+ if (method === "GET" && path === "/health") {
21
25
  const codex = await input.codex.bootstrap().catch((error) => ({
22
26
  available: false,
23
27
  error: errorMessage(error)
@@ -33,21 +37,59 @@ export async function startLocalControlServer(input) {
33
37
  });
34
38
  return;
35
39
  }
36
- if (request.method === "POST" &&
40
+ if (method === "POST" &&
37
41
  (path === "/pairing/consume" || path === "/api/mobile/pairing/complete")) {
38
42
  const body = await readJson(request);
39
- const pairing = await input.store.consumePairing({
40
- code: stringValue(body.code),
41
- deviceName: stringValue(body.deviceName) || "iPhone",
42
- manualCode: stringValue(body.manualCode),
43
- pairingSecret: stringValue(body.pairingSecret),
44
- platform: stringValue(body.platform) || "ios"
43
+ let pairing;
44
+ try {
45
+ pairing = await input.store.consumePairing({
46
+ code: stringValue(body.code),
47
+ deviceName: stringValue(body.deviceName) || "iPhone",
48
+ manualCode: stringValue(body.manualCode),
49
+ pairingSecret: stringValue(body.pairingSecret),
50
+ platform: stringValue(body.platform) || "ios"
51
+ });
52
+ }
53
+ catch (error) {
54
+ const message = errorMessage(error);
55
+ logDiagnostics(diagnostics, "warn", message.includes("expired") ? "pairing.expired" : "pairing.rejected", {
56
+ error: message,
57
+ hasManualCode: Boolean(stringValue(body.manualCode) || stringValue(body.code)),
58
+ hasPairingSecret: Boolean(stringValue(body.pairingSecret)),
59
+ method,
60
+ path,
61
+ platform: stringValue(body.platform) || "ios"
62
+ });
63
+ throw error;
64
+ }
65
+ logDiagnostics(diagnostics, "info", "pairing.consumed", {
66
+ deviceId: pairing.machineId,
67
+ hostMachineId: pairing.hostMachineId,
68
+ method,
69
+ path,
70
+ platform: stringValue(body.platform) || "ios",
71
+ workspaceId: pairing.workspaceId
45
72
  });
46
73
  writeJson(response, 201, pairing);
47
74
  return;
48
75
  }
49
- const actor = await requireMobileDevice(request, input.store);
50
- if (request.method === "GET" && (path === "/me" || path === "/api/mobile/bootstrap")) {
76
+ const actor = await requireMobileDevice(request, input.store).catch((error) => {
77
+ logDiagnostics(diagnostics, "warn", "mobile_request.rejected", {
78
+ error: errorDiagnostics(error),
79
+ hasAuthorization: hasAuthorizationHeader(request),
80
+ method,
81
+ path,
82
+ status: statusCode(error)
83
+ });
84
+ throw error;
85
+ });
86
+ logDiagnostics(diagnostics, "info", "mobile_request.authenticated", {
87
+ deviceId: actor.id,
88
+ method,
89
+ path,
90
+ platform: actor.platform
91
+ });
92
+ if (method === "GET" && (path === "/me" || path === "/api/mobile/bootstrap")) {
51
93
  writeJson(response, 200, {
52
94
  workspace: { id: LOCAL_WORKSPACE_ID, name: `${identity.macName} Local` },
53
95
  phone: {
@@ -63,19 +105,29 @@ export async function startLocalControlServer(input) {
63
105
  });
64
106
  return;
65
107
  }
66
- if (request.method === "GET" && path === "/api/mobile/projects") {
67
- writeJson(response, 200, { projects: await input.codex.listProjects() });
108
+ if (method === "GET" && path === "/api/mobile/projects") {
109
+ const projects = await input.codex.listProjects();
110
+ logDiagnostics(diagnostics, "info", "projects.list.result", {
111
+ count: projects.length,
112
+ deviceId: actor.id
113
+ });
114
+ writeJson(response, 200, { projects });
68
115
  return;
69
116
  }
70
- if (request.method === "GET" && path === "/api/mobile/codex/models") {
117
+ if (method === "GET" && path === "/api/mobile/codex/models") {
71
118
  writeJson(response, 200, { models: await input.codex.listModelOptions() });
72
119
  return;
73
120
  }
74
- if (request.method === "GET" && path === "/api/mobile/codex/completions") {
75
- writeJson(response, 200, { completions: await input.codex.listCompletionStates() });
121
+ if (method === "GET" && path === "/api/mobile/codex/completions") {
122
+ const completions = await input.codex.listCompletionStates();
123
+ logDiagnostics(diagnostics, "info", "completion.states.list.result", {
124
+ count: completions.length,
125
+ deviceId: actor.id
126
+ });
127
+ writeJson(response, 200, { completions });
76
128
  return;
77
129
  }
78
- if (request.method === "POST" && path === "/api/mobile/notifications/register") {
130
+ if (method === "POST" && path === "/api/mobile/notifications/register") {
79
131
  const body = await readJson(request);
80
132
  const subscription = await input.store.registerPushSubscription(actor.id, {
81
133
  platform: stringValue(body.platform) || "ios",
@@ -89,81 +141,188 @@ export async function startLocalControlServer(input) {
89
141
  provider: subscription.provider
90
142
  }
91
143
  });
144
+ logDiagnostics(diagnostics, "info", "push.register.result", {
145
+ deviceId: actor.id,
146
+ platform: subscription.platform,
147
+ provider: subscription.provider
148
+ });
92
149
  return;
93
150
  }
94
- if (request.method === "POST" && path === "/api/mobile/notifications/diagnostics") {
95
- await readJson(request);
151
+ if (method === "POST" && path === "/api/mobile/notifications/diagnostics") {
152
+ const body = await readJson(request);
153
+ logDiagnostics(diagnostics, "warn", "push.registration.diagnostic", {
154
+ deviceId: actor.id,
155
+ message: stringValue(body.message),
156
+ stage: stringValue(body.stage)
157
+ });
96
158
  writeJson(response, 200, { ok: true });
97
159
  return;
98
160
  }
99
161
  const projectConversationsMatch = matchPath(path, "/api/mobile/projects/:projectId/conversations");
100
- if (projectConversationsMatch && request.method === "GET") {
101
- writeJson(response, 200, {
102
- conversations: await input.codex.listProjectConversations(projectConversationsMatch.projectId)
162
+ if (projectConversationsMatch && method === "GET") {
163
+ const conversations = await input.codex.listProjectConversations(projectConversationsMatch.projectId);
164
+ logDiagnostics(diagnostics, "info", "conversations.list.result", {
165
+ count: conversations.length,
166
+ deviceId: actor.id,
167
+ projectId: projectConversationsMatch.projectId
103
168
  });
169
+ writeJson(response, 200, { conversations });
104
170
  return;
105
171
  }
106
- if (projectConversationsMatch && request.method === "POST") {
172
+ if (projectConversationsMatch && method === "POST") {
107
173
  const body = await readJson(request);
108
- const started = await input.codex.startConversation(projectConversationsMatch.projectId, {
109
- attachments: attachmentReferences(body.attachments),
110
- modelSettings: modelSettings(body),
111
- prompt: requiredPrompt(body)
174
+ const attachments = attachmentReferences(body.attachments);
175
+ const prompt = requiredPrompt(body);
176
+ logDiagnostics(diagnostics, "info", "conversation.start.request", {
177
+ ...promptDiagnostics(prompt),
178
+ ...attachmentDiagnostics(attachments),
179
+ deviceId: actor.id,
180
+ model: stringValue(body.model) || undefined,
181
+ projectId: projectConversationsMatch.projectId
182
+ });
183
+ let started;
184
+ try {
185
+ started = await input.codex.startConversation(projectConversationsMatch.projectId, {
186
+ attachments,
187
+ modelSettings: modelSettings(body),
188
+ prompt
189
+ });
190
+ }
191
+ catch (error) {
192
+ const status = statusCode(error);
193
+ logDiagnostics(diagnostics, "error", "conversation.start.failure", {
194
+ error: errorDiagnostics(error),
195
+ projectId: projectConversationsMatch.projectId,
196
+ status
197
+ });
198
+ throw error;
199
+ }
200
+ logDiagnostics(diagnostics, "info", "conversation.start.result", {
201
+ conversationId: started.conversationId,
202
+ projectId: projectConversationsMatch.projectId,
203
+ status: started.status
112
204
  });
113
205
  writeJson(response, 201, started);
114
206
  return;
115
207
  }
116
208
  const messageMatch = matchPath(path, "/api/mobile/conversations/:conversationId/messages");
117
- if (messageMatch && request.method === "GET") {
209
+ if (messageMatch && method === "GET") {
118
210
  const afterSequence = numberQuery(url.searchParams.get("afterSequence"));
119
211
  const includeRuntime = url.searchParams.get("includeRuntime") === "true";
212
+ const messages = await input.codex.listMessages(messageMatch.conversationId, {
213
+ afterSequence,
214
+ includeRuntime
215
+ });
216
+ logDiagnostics(diagnostics, "info", "messages.list.result", {
217
+ ...messageCounts(messages),
218
+ afterSequence,
219
+ conversationId: messageMatch.conversationId,
220
+ includeRuntime,
221
+ returned: messages.length
222
+ });
120
223
  writeJson(response, 200, {
121
- messages: await input.codex.listMessages(messageMatch.conversationId, {
122
- afterSequence,
123
- includeRuntime
124
- })
224
+ messages
125
225
  });
126
226
  return;
127
227
  }
128
- if (messageMatch && request.method === "POST") {
228
+ if (messageMatch && method === "POST") {
129
229
  const body = await readJson(request);
130
- const continued = await input.codex.continueConversation(messageMatch.conversationId, {
131
- prompt: stringValue(body.content) || requiredPrompt(body)
230
+ const prompt = stringValue(body.content) || requiredPrompt(body);
231
+ const delivery = deliveryMode(body.delivery);
232
+ logDiagnostics(diagnostics, "info", "conversation.continue.request", {
233
+ ...promptDiagnostics(prompt),
234
+ conversationId: messageMatch.conversationId,
235
+ delivery,
236
+ deviceId: actor.id
237
+ });
238
+ let continued;
239
+ try {
240
+ continued = await input.codex.continueConversation(messageMatch.conversationId, {
241
+ delivery,
242
+ prompt
243
+ });
244
+ }
245
+ catch (error) {
246
+ const status = statusCode(error);
247
+ logDiagnostics(diagnostics, "error", "conversation.continue.failure", {
248
+ conversationId: messageMatch.conversationId,
249
+ error: errorDiagnostics(error),
250
+ status
251
+ });
252
+ throw error;
253
+ }
254
+ logDiagnostics(diagnostics, "info", "conversation.continue.result", {
255
+ conversationId: continued.conversationId,
256
+ status: continued.status
132
257
  });
133
258
  const messages = await input.codex.listMessages(continued.conversationId);
134
259
  writeJson(response, 201, { message: messages.at(-1) ?? null });
135
260
  return;
136
261
  }
137
262
  const continueMatch = matchPath(path, "/api/mobile/conversations/:conversationId/continue");
138
- if (continueMatch && request.method === "POST") {
263
+ if (continueMatch && method === "POST") {
139
264
  const body = await readJson(request);
140
- const continued = await input.codex.continueConversation(continueMatch.conversationId, {
141
- attachments: attachmentReferences(body.attachments),
142
- modelSettings: modelSettings(body),
143
- prompt: requiredPrompt(body)
265
+ const attachments = attachmentReferences(body.attachments);
266
+ const delivery = deliveryMode(body.delivery);
267
+ const prompt = requiredPrompt(body);
268
+ logDiagnostics(diagnostics, "info", "conversation.continue.request", {
269
+ ...promptDiagnostics(prompt),
270
+ ...attachmentDiagnostics(attachments),
271
+ conversationId: continueMatch.conversationId,
272
+ delivery,
273
+ deviceId: actor.id,
274
+ model: stringValue(body.model) || undefined
275
+ });
276
+ let continued;
277
+ try {
278
+ continued = await input.codex.continueConversation(continueMatch.conversationId, {
279
+ attachments,
280
+ delivery,
281
+ modelSettings: modelSettings(body),
282
+ prompt
283
+ });
284
+ }
285
+ catch (error) {
286
+ const status = statusCode(error);
287
+ logDiagnostics(diagnostics, "error", "conversation.continue.failure", {
288
+ conversationId: continueMatch.conversationId,
289
+ error: errorDiagnostics(error),
290
+ status
291
+ });
292
+ throw error;
293
+ }
294
+ logDiagnostics(diagnostics, "info", "conversation.continue.result", {
295
+ conversationId: continued.conversationId,
296
+ status: continued.status
144
297
  });
145
298
  writeJson(response, 200, continued);
146
299
  return;
147
300
  }
148
- if (request.method === "POST" && path === "/api/mobile/attachments") {
301
+ if (method === "POST" && path === "/api/mobile/attachments") {
149
302
  const attachment = await saveAttachment(input.attachmentDirectory ?? defaultLocalAttachmentDirectory(), await readJson(request));
303
+ logDiagnostics(diagnostics, "info", "attachment.saved", {
304
+ deviceId: actor.id,
305
+ kind: attachment.kind,
306
+ mimeType: attachment.mimeType,
307
+ size: attachment.size
308
+ });
150
309
  writeJson(response, 201, { attachment });
151
310
  return;
152
311
  }
153
- if (request.method === "GET" && path === "/remote-control/status") {
312
+ if (method === "GET" && path === "/remote-control/status") {
154
313
  writeJson(response, 200, {
155
314
  sessions: Array.from(sessions.values()).filter((session) => session.clientMachineId === actor.id)
156
315
  });
157
316
  return;
158
317
  }
159
- if (request.method === "GET" &&
318
+ if (method === "GET" &&
160
319
  (path === "/api/remote-control/sessions" || path === "/remote-control/sessions")) {
161
320
  writeJson(response, 200, {
162
321
  sessions: Array.from(sessions.values()).filter((session) => session.clientMachineId === actor.id)
163
322
  });
164
323
  return;
165
324
  }
166
- if (request.method === "POST" &&
325
+ if (method === "POST" &&
167
326
  (path === "/api/remote-control/sessions" || path === "/remote-control/start")) {
168
327
  const body = await readJson(request);
169
328
  const hostMachineId = stringValue(body.hostMachineId) || identity.macId;
@@ -189,7 +348,7 @@ export async function startLocalControlServer(input) {
189
348
  return;
190
349
  }
191
350
  const remoteSessionMatch = matchPath(path, "/api/remote-control/sessions/:sessionId");
192
- if (remoteSessionMatch && request.method === "DELETE") {
351
+ if (remoteSessionMatch && method === "DELETE") {
193
352
  const session = requireRemoteSession(sessions, remoteSessionMatch.sessionId, actor.id);
194
353
  const ended = { ...session, status: "ended", updatedAt: new Date().toISOString() };
195
354
  sessions.set(session.id, ended);
@@ -197,7 +356,7 @@ export async function startLocalControlServer(input) {
197
356
  return;
198
357
  }
199
358
  const signalMatch = matchPath(path, "/api/remote-control/sessions/:sessionId/signals");
200
- if (signalMatch && request.method === "GET") {
359
+ if (signalMatch && method === "GET") {
201
360
  requireRemoteSession(sessions, signalMatch.sessionId, actor.id);
202
361
  writeJson(response, 200, {
203
362
  signals: signals.filter((signal) => signal.sessionId === signalMatch.sessionId &&
@@ -205,8 +364,8 @@ export async function startLocalControlServer(input) {
205
364
  });
206
365
  return;
207
366
  }
208
- if ((signalMatch && request.method === "POST") ||
209
- (path === "/remote-control/input" && request.method === "POST")) {
367
+ if ((signalMatch && method === "POST") ||
368
+ (path === "/remote-control/input" && method === "POST")) {
210
369
  const body = await readJson(request);
211
370
  const sessionId = signalMatch?.sessionId ?? stringValue(body.sessionId);
212
371
  const session = requireRemoteSession(sessions, sessionId, actor.id);
@@ -227,6 +386,14 @@ export async function startLocalControlServer(input) {
227
386
  }
228
387
  catch (error) {
229
388
  const status = statusCode(error);
389
+ if (status >= 500) {
390
+ logDiagnostics(diagnostics, "error", "mobile_request.failure", {
391
+ error: errorDiagnostics(error),
392
+ method,
393
+ path,
394
+ status
395
+ });
396
+ }
230
397
  writeJson(response, status, { error: errorMessage(error) });
231
398
  }
232
399
  });
@@ -238,6 +405,12 @@ export async function startLocalControlServer(input) {
238
405
  if (address && typeof address === "object" && input.endpoint.endsWith(":0")) {
239
406
  endpoint = input.endpoint.replace(/:0$/u, `:${address.port}`);
240
407
  }
408
+ logDiagnostics(diagnostics, "info", "local_control.server_start", {
409
+ bindHost: input.bindHost,
410
+ endpoint,
411
+ port: address && typeof address === "object" ? address.port : input.port,
412
+ transport: input.transport
413
+ });
241
414
  resolve();
242
415
  });
243
416
  });
@@ -264,6 +437,9 @@ async function requireMobileDevice(request, store) {
264
437
  });
265
438
  }
266
439
  }
440
+ function hasAuthorizationHeader(request) {
441
+ return typeof request.headers.authorization === "string" && request.headers.authorization !== "";
442
+ }
267
443
  function requireRemoteSession(sessions, sessionId, clientMachineId) {
268
444
  const session = sessions.get(sessionId);
269
445
  if (!session || session.clientMachineId !== clientMachineId) {
@@ -361,6 +537,9 @@ async function saveAttachment(directory, body) {
361
537
  size: bytes.byteLength
362
538
  };
363
539
  }
540
+ function deliveryMode(input) {
541
+ return input === "queue" || input === "steer" ? input : undefined;
542
+ }
364
543
  function safeFileName(value) {
365
544
  return value.replace(/[/\\]/gu, "_").slice(0, 240) || "attachment.bin";
366
545
  }
@@ -386,6 +565,28 @@ function numberQuery(value) {
386
565
  const parsed = Number(value);
387
566
  return Number.isFinite(parsed) ? parsed : undefined;
388
567
  }
568
+ function messageCounts(messages) {
569
+ const counts = {
570
+ assistant: 0,
571
+ runtime: 0,
572
+ user: 0,
573
+ visible: 0
574
+ };
575
+ for (const message of messages) {
576
+ if (message.role === "assistant") {
577
+ counts.assistant += 1;
578
+ counts.visible += 1;
579
+ }
580
+ else if (message.role === "user") {
581
+ counts.user += 1;
582
+ counts.visible += 1;
583
+ }
584
+ else if (message.role === "runtime") {
585
+ counts.runtime += 1;
586
+ }
587
+ }
588
+ return counts;
589
+ }
389
590
  function statusCode(error) {
390
591
  if (error &&
391
592
  typeof error === "object" &&