@openscout/scout 0.2.65 → 0.2.68

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.
@@ -63,6 +63,9 @@ function shouldFallbackFromUnixSocket(error) {
63
63
  const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
64
64
  return code === "ENOENT" || code === "ECONNREFUSED" || code === "ENOTSOCK" || code === "EACCES" || code === "FailedToOpenSocket";
65
65
  }
66
+ function errorMessage(error) {
67
+ return error instanceof Error ? error.message : String(error);
68
+ }
66
69
  function requestBrokerOverUnixSocket(socketPath, baseUrl, path, options) {
67
70
  return new Promise((resolve, reject) => {
68
71
  const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
@@ -116,17 +119,36 @@ async function requestBrokerWire(baseUrl, path, options) {
116
119
  const socketPath = options.socketPath?.trim();
117
120
  if (socketPath) {
118
121
  try {
119
- return await requestBrokerOverUnixSocket(socketPath, baseUrl, path, options);
122
+ return {
123
+ response: await requestBrokerOverUnixSocket(socketPath, baseUrl, path, options),
124
+ trace: {
125
+ transport: "unix_socket",
126
+ socketPath
127
+ }
128
+ };
120
129
  } catch (error) {
121
130
  if (!shouldFallbackFromUnixSocket(error)) {
122
131
  throw error;
123
132
  }
133
+ return {
134
+ response: await requestBrokerOverHttp(baseUrl, path, options),
135
+ trace: {
136
+ transport: "http",
137
+ socketPath,
138
+ socketFallbackError: `${socketPath}: ${errorMessage(error)}`
139
+ }
140
+ };
124
141
  }
125
142
  }
126
- return requestBrokerOverHttp(baseUrl, path, options);
143
+ return {
144
+ response: await requestBrokerOverHttp(baseUrl, path, options),
145
+ trace: {
146
+ transport: "http"
147
+ }
148
+ };
127
149
  }
128
- async function requestScoutBrokerJson(baseUrl, path, options = {}) {
129
- const response = await requestBrokerWire(baseUrl, path, options);
150
+ async function requestScoutBrokerJsonWithTrace(baseUrl, path, options = {}) {
151
+ const { response, trace } = await requestBrokerWire(baseUrl, path, options);
130
152
  let parsed;
131
153
  let parsedJson = false;
132
154
  if (response.text.length > 0) {
@@ -139,14 +161,14 @@ async function requestScoutBrokerJson(baseUrl, path, options = {}) {
139
161
  }
140
162
  if (!response.ok) {
141
163
  if (parsedJson && options.acceptErrorJson?.(parsed)) {
142
- return parsed;
164
+ return { value: parsed, trace };
143
165
  }
144
166
  throw new Error(`${path} returned ${response.status}: ${response.text}`);
145
167
  }
146
168
  if (parsedJson) {
147
- return parsed;
169
+ return { value: parsed, trace };
148
170
  }
149
- return;
171
+ return { value: undefined, trace };
150
172
  }
151
173
 
152
174
  // packages/runtime/src/support-paths.ts
@@ -476,11 +498,13 @@ function resolveBrokerServiceConfig() {
476
498
  brokerPort,
477
499
  brokerUrl,
478
500
  brokerSocketPath,
479
- advertiseScope
501
+ advertiseScope,
502
+ coreAgents: readCoreAgentsSync()
480
503
  };
481
504
  }
482
505
  function renderLaunchAgentPlist(config) {
483
506
  const launchPath = resolveLaunchAgentPATH();
507
+ const coreAgentsValue = (config.coreAgents ?? []).join(",");
484
508
  const envEntries = {
485
509
  OPENSCOUT_BROKER_HOST: config.brokerHost,
486
510
  OPENSCOUT_BROKER_PORT: String(config.brokerPort),
@@ -505,6 +529,9 @@ function renderLaunchAgentPlist(config) {
505
529
  "OPENSCOUT_SSE_KEEPALIVE_MS"
506
530
  ])
507
531
  };
532
+ if (coreAgentsValue) {
533
+ envEntries["OPENSCOUT_CORE_AGENTS"] = coreAgentsValue;
534
+ }
508
535
  const envBlock = Object.entries(envEntries).map(([key, value]) => `
509
536
  <key>${xmlEscape(key)}</key>
510
537
  <string>${xmlEscape(value)}</string>`).join("");
@@ -540,6 +567,18 @@ function renderLaunchAgentPlist(config) {
540
567
  </plist>
541
568
  `;
542
569
  }
570
+ function readCoreAgentsSync() {
571
+ try {
572
+ const settingsPath = resolveOpenScoutSupportPaths().settingsPath;
573
+ const raw = readFileSync(settingsPath, "utf8");
574
+ const settings = JSON.parse(raw);
575
+ const raw_agents = settings?.agents?.coreAgents;
576
+ if (Array.isArray(raw_agents)) {
577
+ return raw_agents.filter((v) => typeof v === "string" && v.trim().length > 0);
578
+ }
579
+ } catch {}
580
+ return [];
581
+ }
543
582
  function collectOptionalEnvVars(keys) {
544
583
  const entries = {};
545
584
  for (const key of keys) {
@@ -684,22 +723,37 @@ function inspectLaunchctl(config) {
684
723
  async function fetchHealthSnapshot(config) {
685
724
  const controller = new AbortController;
686
725
  const timeout = setTimeout(() => controller.abort(), 1000);
726
+ const checkedAt = Date.now();
687
727
  try {
688
- const payload = await requestScoutBrokerJson(config.brokerUrl, "/health", {
728
+ const { value: payload, trace } = await requestScoutBrokerJsonWithTrace(config.brokerUrl, "/health", {
689
729
  signal: controller.signal,
690
730
  socketPath: config.brokerSocketPath
691
731
  });
692
732
  return {
693
733
  reachable: true,
694
734
  ok: Boolean(payload.ok),
735
+ checkedAt,
736
+ transport: trace.transport,
737
+ socketPath: trace.socketPath,
738
+ socketFallbackError: trace.socketFallbackError,
695
739
  nodeId: payload.nodeId,
696
740
  meshId: payload.meshId,
697
- counts: payload.counts
741
+ counts: payload.counts ? {
742
+ nodes: payload.counts.nodes ?? 0,
743
+ actors: payload.counts.actors ?? 0,
744
+ agents: payload.counts.agents ?? 0,
745
+ conversations: payload.counts.conversations ?? 0,
746
+ messages: payload.counts.messages ?? 0,
747
+ flights: payload.counts.flights ?? 0,
748
+ collaborationRecords: payload.counts.collaborationRecords ?? 0
749
+ } : undefined
698
750
  };
699
751
  } catch (error) {
700
752
  return {
701
753
  reachable: false,
702
754
  ok: false,
755
+ checkedAt,
756
+ socketPath: config.brokerSocketPath,
703
757
  error: error instanceof Error ? error.message : String(error)
704
758
  };
705
759
  } finally {
@@ -834,8 +888,12 @@ function formatBrokerServiceStatus(status) {
834
888
  `broker socket: ${status.brokerSocketPath}`,
835
889
  `reachable: ${status.reachable ? "yes" : "no"}`,
836
890
  `health: ${status.health.ok ? "ok" : status.health.error ?? "unreachable"}`,
891
+ `health transport: ${status.health.transport ?? "unknown"}`,
837
892
  `logs: ${status.stdoutLogPath}`
838
893
  ];
894
+ if (status.health.socketFallbackError) {
895
+ lines.push(`socket fallback: ${status.health.socketFallbackError}`);
896
+ }
839
897
  if (status.lastLogLine) {
840
898
  lines.push(`last log: ${status.lastLogLine}`);
841
899
  }
@@ -960,7 +1018,7 @@ function resolveOpenScoutLocalEdgeConfig(input = {}) {
960
1018
  const portalHost = resolveScoutWebNamedHostname(input.portalHost ?? DEFAULT_SCOUT_WEB_PORTAL_HOST);
961
1019
  const nodeHost = resolveScoutWebNamedHostname(input.nodeHost ?? resolveConfiguredScoutWebHostname());
962
1020
  const wildcardHost = `*.${portalHost}`;
963
- const scheme = input.scheme ?? "both";
1021
+ const scheme = input.scheme ?? "http";
964
1022
  const upstream = `127.0.0.1:${input.webPort ?? resolveWebPort()}`;
965
1023
  const brokerUpstream = `127.0.0.1:${input.brokerPort ?? resolveBrokerPort()}`;
966
1024
  return {
@@ -1222,6 +1280,7 @@ var mdnsProcesses = [];
1222
1280
  var brokerRestartDelayMs = RESTART_MIN_DELAY_MS;
1223
1281
  var edgeRestartDelayMs = RESTART_MIN_DELAY_MS;
1224
1282
  var supervisedWebPid = null;
1283
+ var supervisorKeepAlive = null;
1225
1284
  var config = resolveBrokerServiceConfig();
1226
1285
  function log(message, details) {
1227
1286
  if (details === undefined) {
@@ -1317,7 +1376,7 @@ function resolveEdgeScheme() {
1317
1376
  if (value === "http" || value === "https" || value === "both") {
1318
1377
  return value;
1319
1378
  }
1320
- return "both";
1379
+ return "http";
1321
1380
  }
1322
1381
  function resolveEdgeConfig() {
1323
1382
  const portalHost = process.env.OPENSCOUT_WEB_PORTAL_HOST?.trim() || DEFAULT_SCOUT_WEB_PORTAL_HOST;
@@ -1523,6 +1582,10 @@ async function shutdown(exitCode = 0) {
1523
1582
  return;
1524
1583
  }
1525
1584
  shuttingDown = true;
1585
+ if (supervisorKeepAlive) {
1586
+ clearInterval(supervisorKeepAlive);
1587
+ supervisorKeepAlive = null;
1588
+ }
1526
1589
  stopSupervisedWeb();
1527
1590
  stopMenuBarApp();
1528
1591
  stopEdgeProcesses();
@@ -1535,6 +1598,14 @@ async function shutdown(exitCode = 0) {
1535
1598
  function sleep2(ms) {
1536
1599
  return new Promise((resolveSleep) => setTimeout(resolveSleep, ms));
1537
1600
  }
1601
+ function keepSupervisorAlive() {
1602
+ if (supervisorKeepAlive) {
1603
+ return;
1604
+ }
1605
+ supervisorKeepAlive = setInterval(() => {
1606
+ return;
1607
+ }, 60000);
1608
+ }
1538
1609
  for (const signal of ["SIGINT", "SIGTERM"]) {
1539
1610
  process.on(signal, () => {
1540
1611
  shutdown(0).catch((error) => {
@@ -1548,6 +1619,7 @@ log("starting Scout base service", {
1548
1619
  brokerUrl: config.brokerUrl,
1549
1620
  bootout: `launchctl bootout ${config.serviceTarget}`
1550
1621
  });
1622
+ keepSupervisorAlive();
1551
1623
  spawnBroker();
1552
1624
  startLocalEdge();
1553
1625
  startMenuBarApp();