@schoolai/shipyard 3.14.0 → 3.15.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.
Files changed (37) hide show
  1. package/dist/capability-detector-worker.js +5 -5
  2. package/dist/{chunk-OX3UY44R.js → chunk-5PBWS7BB.js} +31 -42
  3. package/dist/chunk-5PBWS7BB.js.map +1 -0
  4. package/dist/{chunk-RCEAMZVG.js → chunk-6SK6FBYC.js} +2 -2
  5. package/dist/{chunk-M3WBYTB3.js → chunk-AXHG3QQA.js} +16 -1
  6. package/dist/chunk-AXHG3QQA.js.map +1 -0
  7. package/dist/{chunk-T3OTZ66B.js → chunk-B7WZUKYX.js} +219 -86
  8. package/dist/chunk-B7WZUKYX.js.map +1 -0
  9. package/dist/{chunk-BUAEJNUG.js → chunk-HPDRJ4VZ.js} +3 -3
  10. package/dist/{chunk-BUAEJNUG.js.map → chunk-HPDRJ4VZ.js.map} +1 -1
  11. package/dist/{chunk-WGS7ZW6N.js → chunk-L5FQEZ6Y.js} +3 -3
  12. package/dist/{chunk-KUPHN3ZN.js → chunk-RHHRJR3L.js} +2 -2
  13. package/dist/{chunk-3KE2VDKA.js → chunk-VKY7UXTP.js} +25 -3
  14. package/dist/chunk-VKY7UXTP.js.map +1 -0
  15. package/dist/{chunk-IWBDVGD2.js → chunk-VTALUCDB.js} +2 -2
  16. package/dist/cursor-runner.js +3 -3
  17. package/dist/electron-utility.js +2 -2
  18. package/dist/index.js +4 -4
  19. package/dist/{login-HRR3T4SZ.js → login-EYGYOEXL.js} +3 -3
  20. package/dist/{mcp-servers-GUA5WOHO.js → mcp-servers-DSOX243C.js} +8 -2
  21. package/dist/{plan-backfill-QNJUWOYP.js → plan-backfill-SMJEKTMM.js} +4 -4
  22. package/dist/{serve-25I4ML7R.js → serve-DAP6V7SY.js} +339 -147
  23. package/dist/{serve-25I4ML7R.js.map → serve-DAP6V7SY.js.map} +1 -1
  24. package/dist/{start-O2DXLW23.js → start-AX2ZK3AY.js} +6 -6
  25. package/package.json +1 -1
  26. package/dist/chunk-3KE2VDKA.js.map +0 -1
  27. package/dist/chunk-M3WBYTB3.js.map +0 -1
  28. package/dist/chunk-OX3UY44R.js.map +0 -1
  29. package/dist/chunk-T3OTZ66B.js.map +0 -1
  30. /package/dist/{chunk-RCEAMZVG.js.map → chunk-6SK6FBYC.js.map} +0 -0
  31. /package/dist/{chunk-WGS7ZW6N.js.map → chunk-L5FQEZ6Y.js.map} +0 -0
  32. /package/dist/{chunk-KUPHN3ZN.js.map → chunk-RHHRJR3L.js.map} +0 -0
  33. /package/dist/{chunk-IWBDVGD2.js.map → chunk-VTALUCDB.js.map} +0 -0
  34. /package/dist/{login-HRR3T4SZ.js.map → login-EYGYOEXL.js.map} +0 -0
  35. /package/dist/{mcp-servers-GUA5WOHO.js.map → mcp-servers-DSOX243C.js.map} +0 -0
  36. /package/dist/{plan-backfill-QNJUWOYP.js.map → plan-backfill-SMJEKTMM.js.map} +0 -0
  37. /package/dist/{start-O2DXLW23.js.map → start-AX2ZK3AY.js.map} +0 -0
@@ -14,10 +14,10 @@ import {
14
14
  } from "./chunk-JCEWPG3R.js";
15
15
 
16
16
  // src/shared/capabilities/mcp-servers.ts
17
- import { readFile as readFile3, stat as stat2 } from "fs/promises";
17
+ import { readFile as readFile4 } from "fs/promises";
18
18
  import { homedir as homedir2 } from "os";
19
- import { basename, join as join3, resolve } from "path";
20
- import { parse as parseToml } from "toml";
19
+ import { join as join3, resolve } from "path";
20
+ import { parse as parseToml2 } from "toml";
21
21
 
22
22
  // src/shared/mcp/claude-code-credentials.ts
23
23
  import { execFile as execFileCb } from "child_process";
@@ -523,6 +523,84 @@ var MCPTokenStore = class {
523
523
  }
524
524
  };
525
525
 
526
+ // src/services/metrics/telemeter.ts
527
+ var TELEMETERED_EVENT_NAMES = [
528
+ "anthropic_login_failed",
529
+ "claudeai_integrations_fetch_failed",
530
+ "codex_spawn_failed",
531
+ "run_stall_timeout",
532
+ "request_task_state_replay_failed",
533
+ "loro_recovery_failed",
534
+ "mcp_server_connect_failed",
535
+ "mcp_server_needs_auth",
536
+ "mcp_reconnect_failed",
537
+ "mcp_reconnect_terminal",
538
+ "mcp_reconnect_terminal_unsupported",
539
+ "mcp_reauth_failed",
540
+ "mcp_adopted_set_failed",
541
+ "mcp_push_failed",
542
+ "harness_mcp_registration_failed",
543
+ "codex_auth_divergence_detected",
544
+ "cursor_auth_divergence_detected",
545
+ /**
546
+ * A Codex remote-compact cycle failed with a 401 "Missing bearer" error —
547
+ * the app-server lost its in-memory token during refresh-token rotation.
548
+ * Emitted once per compact attempt (not per retry) so fleet dashboards can
549
+ * surface the storm rate without log amplification.
550
+ */
551
+ "codex_compact_auth_failure",
552
+ "event_loop_stall",
553
+ "machine_sleep_artifact",
554
+ /**
555
+ * Per-process memory from the Electron main process (`app.getAppMetrics()`).
556
+ * The only source of true per-process RSS for the renderer/GPU/utility — JS
557
+ * heap (browser_metrics_sample) is capped ~4GB and cannot reveal a 50GB
558
+ * process. Forwarded to D1 by the daemon so runaway RAM is localizable
559
+ * fleet-wide to the offending Electron process.
560
+ */
561
+ "electron_app_metrics",
562
+ /** Electron main cleared a wedged Squirrel.Mac staged install on launch. */
563
+ "squirrel_install_stuck_recovered",
564
+ /**
565
+ * An ALO control-channel entry exhausted its maxDeliver retry budget
566
+ * without receiving an ack. Payload: { streamId, attempts, channel: 'control' }.
567
+ * Emitted via the `onDeadLetter` callback in control-channel-wiring.ts.
568
+ * Complements the `alo_resend_exhausted` ERROR log event emitted by the
569
+ * shell itself; this telemetry path routes it to D1 for fleet-wide
570
+ * observability so silent resend exhaustion is detectable in aggregate.
571
+ */
572
+ "alo_resend_exhausted",
573
+ /**
574
+ * An ALO control-channel shell reaped itself as an orphan — no truncating
575
+ * ack landed for `orphanThresholdMs` (5 min) while its retry buffer was
576
+ * non-empty, so the WHOLE buffer of unacked control messages was discarded.
577
+ * This is the bulk-loss sibling of `alo_resend_exhausted` (one entry): a
578
+ * reap can drop dozens of messages at once. Payload:
579
+ * { streamId, discardedCount, msSinceLastAck, attempts, channel: 'control' }.
580
+ * Emitted via the `onOrphanReaped` callback in control-channel-wiring.ts;
581
+ * the shell also emits a matching ERROR log. Routed to D1 so silent
582
+ * reconnect-time loss is detectable fleet-wide.
583
+ */
584
+ "alo_shell_orphan_reaped",
585
+ /**
586
+ * A `task_index_snapshot` envelope serialized past the control-channel
587
+ * high-water even after byte-bounded pagination — i.e. a single slim entry
588
+ * alone exceeds the cap (a page is guaranteed >=1 entry for forward
589
+ * progress). The control channel may drop it whole (`channel_send_dropped`).
590
+ * Payload: { bytes, taskCount, limitBytes }. Surfaces the pathological
591
+ * oversized-record case the byte budget cannot otherwise bound.
592
+ */
593
+ "task_index_snapshot_oversized"
594
+ ];
595
+ var TELEMETERED_EVENTS = new Set(TELEMETERED_EVENT_NAMES);
596
+ var sink = null;
597
+ function setTelemetrySink(fn) {
598
+ sink = fn;
599
+ }
600
+ function telemeter(event, payload) {
601
+ sink?.(event, payload);
602
+ }
603
+
526
604
  // src/shared/auth/anthropic-credentials.ts
527
605
  import { execFile as execFileCb2 } from "child_process";
528
606
  import { promisify as promisify2 } from "util";
@@ -677,6 +755,17 @@ function classifyHttpStatus(status) {
677
755
  if (status >= 500 && status < 600) return "http_5xx";
678
756
  return "http_other";
679
757
  }
758
+ function classifyClaudeAiIntegrationsFailure(input) {
759
+ const accountIssue = input.status === 403 && input.errorBody?.includes("user:mcp_servers") ? {
760
+ kind: "missing_user_mcp_servers_scope",
761
+ message: "Re-authenticate with Claude to enable claude.ai connectors."
762
+ } : null;
763
+ return {
764
+ errorClass: classifyHttpStatus(input.status),
765
+ shouldBackoffAuth: input.status === 401 || input.status === 403,
766
+ accountIssue
767
+ };
768
+ }
680
769
  function classifyException(err) {
681
770
  if (err instanceof Error) {
682
771
  if (err.name === "AbortError") return "timeout";
@@ -693,16 +782,16 @@ async function readErrorBody(response) {
693
782
  return null;
694
783
  }
695
784
  }
696
- async function fetchClaudeAiIntegrations(log) {
785
+ async function fetchClaudeAiIntegrationsWithStatus(log) {
697
786
  const url = CLAUDEAI_INTEGRATIONS_URL;
698
787
  if (Date.now() < authBackoffUntil) {
699
- return [];
788
+ return { servers: [] };
700
789
  }
701
790
  try {
702
791
  const token = await readKeychainOAuthToken(log);
703
792
  if (!token) {
704
793
  log({ event: "claudeai_integrations_skipped", reason: "no_oauth_token" });
705
- return [];
794
+ return { servers: [] };
706
795
  }
707
796
  const controller = new AbortController();
708
797
  const timeout = setTimeout(() => controller.abort(), 5e3);
@@ -717,14 +806,22 @@ async function fetchClaudeAiIntegrations(log) {
717
806
  });
718
807
  if (!response.ok) {
719
808
  const errorBody = await readErrorBody(response);
809
+ const decision = classifyClaudeAiIntegrationsFailure({
810
+ status: response.status,
811
+ errorBody
812
+ });
720
813
  log({
721
814
  event: "claudeai_integrations_fetch_failed",
722
815
  url,
723
816
  status: response.status,
724
- errorClass: classifyHttpStatus(response.status),
817
+ errorClass: decision.errorClass,
725
818
  errorBody
726
819
  });
727
- if (response.status === 401 || response.status === 403) {
820
+ telemeter("claudeai_integrations_fetch_failed", {
821
+ status: response.status,
822
+ errorClass: decision.errorClass
823
+ });
824
+ if (decision.shouldBackoffAuth) {
728
825
  authBackoffUntil = Date.now() + AUTH_BACKOFF_MS;
729
826
  log({
730
827
  event: "claudeai_integrations_auth_backoff",
@@ -732,39 +829,49 @@ async function fetchClaudeAiIntegrations(log) {
732
829
  backoffMs: AUTH_BACKOFF_MS
733
830
  });
734
831
  }
735
- return [];
832
+ return decision.accountIssue ? { servers: [], accountIssue: decision.accountIssue } : { servers: [] };
736
833
  }
737
834
  authBackoffUntil = 0;
738
835
  const body = await response.json();
739
836
  const servers = parseClaudeAiServers(body, log);
740
- return servers.map((s) => ({
741
- name: s.name,
742
- type: "http",
743
- runtimeId: CLAUDE_CODE_RUNTIME_ID,
744
- url: s.url,
745
- enabled: true,
746
- source: "claudeai",
747
- authStatus: "unknown",
748
- /** Gateway id — drives the `mcp-proxy.anthropic.com/v1/mcp/{id}` route. */
749
- ...s.id ? { id: s.id } : {}
750
- }));
837
+ return {
838
+ servers: servers.map((s) => ({
839
+ name: s.name,
840
+ type: "http",
841
+ runtimeId: CLAUDE_CODE_RUNTIME_ID,
842
+ url: s.url,
843
+ enabled: true,
844
+ source: "claudeai",
845
+ authStatus: "unknown",
846
+ /** Gateway id drives the `mcp-proxy.anthropic.com/v1/mcp/{id}` route. */
847
+ ...s.id ? { id: s.id } : {}
848
+ }))
849
+ };
751
850
  } finally {
752
851
  clearTimeout(timeout);
753
852
  }
754
853
  } catch (err) {
854
+ const errorClass = classifyException(err);
755
855
  log({
756
856
  event: "claudeai_integrations_fetch_failed",
757
857
  url,
758
858
  status: null,
759
- errorClass: classifyException(err),
859
+ errorClass,
760
860
  errorBody: null,
761
861
  error: err instanceof Error ? err.message : String(err)
762
862
  });
763
- return [];
863
+ telemeter("claudeai_integrations_fetch_failed", {
864
+ status: null,
865
+ errorClass
866
+ });
867
+ return { servers: [] };
764
868
  }
765
869
  }
766
870
 
767
- // src/shared/capabilities/mcp-servers.ts
871
+ // src/shared/capabilities/mcp-config-readers.ts
872
+ import { readFile as readFile3, stat as stat2 } from "fs/promises";
873
+ import { basename } from "path";
874
+ import { parse as parseToml } from "toml";
768
875
  var MCPStdioEntrySchema = external_exports.object({
769
876
  type: external_exports.literal("stdio").optional(),
770
877
  command: external_exports.string(),
@@ -811,54 +918,6 @@ var CodexMCPHttpEntrySchema = external_exports.object({
811
918
  bearer_token_env_var: external_exports.string().optional(),
812
919
  enabled: external_exports.boolean().optional()
813
920
  }).passthrough();
814
- function shouldFetchClaudeAiIntegrations(preferredAuth) {
815
- if (preferredAuth == null) return true;
816
- return preferredAuth === "claude-ai";
817
- }
818
- function canonicalMcpServerKey(server) {
819
- if (!server.url) return server.name.toLowerCase();
820
- try {
821
- const parsed = new URL(server.url);
822
- parsed.hostname = parsed.hostname.toLowerCase();
823
- parsed.protocol = parsed.protocol.toLowerCase();
824
- const normalized = parsed.toString();
825
- return normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
826
- } catch {
827
- return server.name.toLowerCase();
828
- }
829
- }
830
- function dedupeServerCandidates(candidates) {
831
- const deduped = /* @__PURE__ */ new Map();
832
- const allSources = /* @__PURE__ */ new Map();
833
- const firstId = /* @__PURE__ */ new Map();
834
- for (const candidate of candidates) {
835
- const key = canonicalMcpServerKey(candidate.server);
836
- const existing = deduped.get(key);
837
- if (!existing || candidate.priority >= existing.priority) {
838
- deduped.set(key, candidate);
839
- }
840
- const src = candidate.server.source;
841
- const srcs = allSources.get(key);
842
- if (srcs === void 0) {
843
- allSources.set(key, [src]);
844
- } else if (!srcs.includes(src)) {
845
- srcs.push(src);
846
- }
847
- if (!firstId.has(key) && candidate.server.id) {
848
- firstId.set(key, candidate.server.id);
849
- }
850
- }
851
- return [...deduped.values()].map((candidate) => {
852
- const key = canonicalMcpServerKey(candidate.server);
853
- const sources = allSources.get(key) ?? [candidate.server.source];
854
- const id = firstId.get(key) ?? candidate.server.id;
855
- return {
856
- ...candidate.server,
857
- sources,
858
- ...id !== void 0 ? { id } : {}
859
- };
860
- });
861
- }
862
921
  var SECRET_PATTERNS = /^(sk-|ghp_|gho_|glpat-|xoxb-|xoxp-|Bearer\s|token\s)/i;
863
922
  var SECRET_FLAGS = /* @__PURE__ */ new Set(["--api-key", "--token", "--secret", "--password", "--key", "-k"]);
864
923
  function redactArgs(args) {
@@ -1166,15 +1225,80 @@ async function readCursorMCPConfig(filePath, source, log, metadata, now = Date.n
1166
1225
  now
1167
1226
  );
1168
1227
  }
1228
+
1229
+ // src/shared/capabilities/mcp-servers.ts
1230
+ function shouldFetchClaudeAiIntegrations(preferredAuth) {
1231
+ if (preferredAuth == null) return true;
1232
+ return preferredAuth === "claude-ai";
1233
+ }
1234
+ function claudeAiAccountIssueServer() {
1235
+ return {
1236
+ name: "claude.ai connectors",
1237
+ type: "http",
1238
+ runtimeId: CLAUDE_CODE_RUNTIME_ID,
1239
+ enabled: false,
1240
+ source: "claudeai",
1241
+ sourceLabel: "Claude.ai",
1242
+ authStatus: "unauthenticated"
1243
+ };
1244
+ }
1245
+ function parseTomlRecord2(raw) {
1246
+ const parsed = parseToml2(raw);
1247
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
1248
+ }
1249
+ function canonicalMcpServerKey(server) {
1250
+ if (!server.url) return server.name.toLowerCase();
1251
+ try {
1252
+ const parsed = new URL(server.url);
1253
+ parsed.hostname = parsed.hostname.toLowerCase();
1254
+ parsed.protocol = parsed.protocol.toLowerCase();
1255
+ const normalized = parsed.toString();
1256
+ return normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
1257
+ } catch {
1258
+ return server.name.toLowerCase();
1259
+ }
1260
+ }
1261
+ function dedupeServerCandidates(candidates) {
1262
+ const deduped = /* @__PURE__ */ new Map();
1263
+ const allSources = /* @__PURE__ */ new Map();
1264
+ const firstId = /* @__PURE__ */ new Map();
1265
+ for (const candidate of candidates) {
1266
+ const key = canonicalMcpServerKey(candidate.server);
1267
+ const existing = deduped.get(key);
1268
+ if (!existing || candidate.priority >= existing.priority) {
1269
+ deduped.set(key, candidate);
1270
+ }
1271
+ const src = candidate.server.source;
1272
+ const srcs = allSources.get(key);
1273
+ if (srcs === void 0) {
1274
+ allSources.set(key, [src]);
1275
+ } else if (!srcs.includes(src)) {
1276
+ srcs.push(src);
1277
+ }
1278
+ if (!firstId.has(key) && candidate.server.id) {
1279
+ firstId.set(key, candidate.server.id);
1280
+ }
1281
+ }
1282
+ return [...deduped.values()].map((candidate) => {
1283
+ const key = canonicalMcpServerKey(candidate.server);
1284
+ const sources = allSources.get(key) ?? [candidate.server.source];
1285
+ const id = firstId.get(key) ?? candidate.server.id;
1286
+ return {
1287
+ ...candidate.server,
1288
+ sources,
1289
+ ...id !== void 0 ? { id } : {}
1290
+ };
1291
+ });
1292
+ }
1169
1293
  async function readPluginMCPServers(log) {
1170
1294
  const servers = [];
1171
1295
  try {
1172
1296
  const settingsPath = join3(homedir2(), ".claude", "settings.json");
1173
- const settingsRaw = await readFile3(settingsPath, "utf-8");
1297
+ const settingsRaw = await readFile4(settingsPath, "utf-8");
1174
1298
  const settings = JSON.parse(settingsRaw);
1175
1299
  if (!settings.enabledPlugins) return [];
1176
1300
  const installedPath = join3(homedir2(), ".claude", "plugins", "installed_plugins.json");
1177
- const installedRaw = await readFile3(installedPath, "utf-8");
1301
+ const installedRaw = await readFile4(installedPath, "utf-8");
1178
1302
  const installed = JSON.parse(installedRaw);
1179
1303
  if (!installed.plugins) return [];
1180
1304
  for (const [pluginId, enabled] of Object.entries(settings.enabledPlugins)) {
@@ -1229,8 +1353,8 @@ var CodexPluginMcpServersFileSchema = external_exports.object({
1229
1353
  });
1230
1354
  async function readCodexTomlConfig(configPath) {
1231
1355
  try {
1232
- const raw = await readFile3(configPath, "utf-8");
1233
- const parsed = parseTomlRecord(raw);
1356
+ const raw = await readFile4(configPath, "utf-8");
1357
+ const parsed = parseTomlRecord2(raw);
1234
1358
  const result = CodexConfigTomlSchema.safeParse(parsed);
1235
1359
  return result.success ? result.data : null;
1236
1360
  } catch {
@@ -1244,7 +1368,7 @@ async function readMarketplaceJson(marketplaceSourceDir) {
1244
1368
  ];
1245
1369
  for (const candidate of candidates) {
1246
1370
  try {
1247
- const raw = await readFile3(candidate, "utf-8");
1371
+ const raw = await readFile4(candidate, "utf-8");
1248
1372
  const parsed = JSON.parse(raw);
1249
1373
  const result = MarketplaceJsonSchema.safeParse(parsed);
1250
1374
  if (result.success) return result.data;
@@ -1256,7 +1380,7 @@ async function readMarketplaceJson(marketplaceSourceDir) {
1256
1380
  async function readCodexPluginManifestMcps(pluginRoot, pluginId, marketplaceName, log) {
1257
1381
  const manifestPath = join3(pluginRoot, ".codex-plugin", "plugin.json");
1258
1382
  try {
1259
- const raw = await readFile3(manifestPath, "utf-8");
1383
+ const raw = await readFile4(manifestPath, "utf-8");
1260
1384
  const parsed = JSON.parse(raw);
1261
1385
  const manifestResult = CodexPluginManifestSchema.safeParse(parsed);
1262
1386
  if (!manifestResult.success) {
@@ -1272,7 +1396,7 @@ async function readCodexPluginManifestMcps(pluginRoot, pluginId, marketplaceName
1272
1396
  if (!manifest.mcpServers) return [];
1273
1397
  const mcpFilePath = resolve(pluginRoot, manifest.mcpServers);
1274
1398
  try {
1275
- const mcpRaw = await readFile3(mcpFilePath, "utf-8");
1399
+ const mcpRaw = await readFile4(mcpFilePath, "utf-8");
1276
1400
  const mcpParsed = JSON.parse(mcpRaw);
1277
1401
  const mcpResult = CodexPluginMcpServersFileSchema.safeParse(mcpParsed);
1278
1402
  if (!mcpResult.success || !mcpResult.data.mcpServers) return [];
@@ -1317,7 +1441,7 @@ async function detectCodexPluginMcps(codexHome, configToml, log) {
1317
1441
  }
1318
1442
  await Promise.all(
1319
1443
  marketplaceJson.plugins.map(async (plugin) => {
1320
- if (!plugin.source || plugin.source.source !== "local") return;
1444
+ if (plugin.source?.source !== "local") return;
1321
1445
  const pluginId = `${plugin.name}@${marketplaceName}`;
1322
1446
  const pluginEnabledEntry = pluginEnabledMap[pluginId];
1323
1447
  if (pluginEnabledEntry?.enabled === false) return;
@@ -1343,12 +1467,15 @@ function pushCandidates(target, servers, priority) {
1343
1467
  target.push({ server, priority });
1344
1468
  }
1345
1469
  }
1470
+ function isCcExpiryActive(expiresAt) {
1471
+ return expiresAt == null || expiresAt > Date.now();
1472
+ }
1346
1473
  async function resolveClaudeCodeAuthStatuses(servers) {
1347
1474
  for (const server of servers.values()) {
1348
1475
  if (server.authStatus !== "unknown") continue;
1349
1476
  if (server.type === "stdio") continue;
1350
1477
  const ccCreds = await readClaudeCodeCredentials(server.name, server.url ?? "");
1351
- if (ccCreds?.accessToken && ccCreds.expiresAt && ccCreds.expiresAt > Date.now()) {
1478
+ if (ccCreds?.accessToken && isCcExpiryActive(ccCreds.expiresAt)) {
1352
1479
  server.authStatus = "authenticated";
1353
1480
  }
1354
1481
  }
@@ -1470,7 +1597,7 @@ async function detectMCPServersInner(environments, tokenStore, log, preferredAut
1470
1597
  const userClaudeJsonPath = join3(homedir2(), ".claude.json");
1471
1598
  const codexHome = join3(homedir2(), ".codex");
1472
1599
  const fetchClaudeAi = shouldFetchClaudeAiIntegrations(preferredAuth);
1473
- const claudeAiPromise = fetchClaudeAi ? fetchClaudeAiIntegrations(log) : Promise.resolve([]);
1600
+ const claudeAiPromise = fetchClaudeAi ? fetchClaudeAiIntegrationsWithStatus(log) : Promise.resolve({ servers: [] });
1474
1601
  if (!fetchClaudeAi) {
1475
1602
  log({ event: "claudeai_integrations_skipped_by_method", method: preferredAuth ?? null });
1476
1603
  }
@@ -1484,7 +1611,7 @@ async function detectMCPServersInner(environments, tokenStore, log, preferredAut
1484
1611
  userCursorServers,
1485
1612
  pluginServers,
1486
1613
  codexPluginServers,
1487
- claudeAiServers,
1614
+ claudeAiResult,
1488
1615
  claudeJsonLocalServers
1489
1616
  ] = await Promise.all([
1490
1617
  readMCPConfig(userSettingsPath, "user", log, {
@@ -1528,6 +1655,7 @@ async function detectMCPServersInner(environments, tokenStore, log, preferredAut
1528
1655
  }
1529
1656
  )
1530
1657
  ]);
1658
+ const claudeAiServers = claudeAiResult.accountIssue ? [...claudeAiResult.servers, claudeAiAccountIssueServer()] : claudeAiResult.servers;
1531
1659
  pushCandidates(allCandidates, claudeAiServers, 10);
1532
1660
  pushCandidates(allCandidates, pluginServers, 20);
1533
1661
  pushCandidates(allCandidates, codexPluginServers, 25);
@@ -1570,15 +1698,14 @@ export {
1570
1698
  resolveStdioEnv,
1571
1699
  resolveEnabledMcpServers,
1572
1700
  MCPTokenStore,
1701
+ setTelemetrySink,
1702
+ telemeter,
1573
1703
  readKeychainOAuthToken,
1574
1704
  CLAUDE_CODE_RUNTIME_ID,
1575
1705
  CODEX_RUNTIME_ID,
1576
1706
  CURSOR_RUNTIME_ID,
1577
1707
  getRuntimeDescriptor,
1578
1708
  getRuntimeDisplayName,
1579
- shouldFetchClaudeAiIntegrations,
1580
- canonicalMcpServerKey,
1581
- dedupeServerCandidates,
1582
1709
  redactArgs,
1583
1710
  redactEnv,
1584
1711
  resetMCPConfigCaches,
@@ -1586,7 +1713,13 @@ export {
1586
1713
  readClaudeJsonLocalMcpServers,
1587
1714
  readCodexMCPConfig,
1588
1715
  readCursorMCPConfig,
1716
+ shouldFetchClaudeAiIntegrations,
1717
+ canonicalMcpServerKey,
1718
+ dedupeServerCandidates,
1589
1719
  detectCodexPluginMcps,
1720
+ isCcExpiryActive,
1721
+ resolveClaudeCodeAuthStatuses,
1722
+ resolveAuthStatuses,
1590
1723
  detectMCPServers
1591
1724
  };
1592
- //# sourceMappingURL=chunk-T3OTZ66B.js.map
1725
+ //# sourceMappingURL=chunk-B7WZUKYX.js.map