@syncause/debug-daemon 0.1.0 → 0.1.1

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 (2) hide show
  1. package/dist/index.js +35 -6
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -25742,7 +25742,7 @@ var AppService = class {
25742
25742
  async fetchAppList() {
25743
25743
  if (!this.userApiKey) {
25744
25744
  Logger.getInstance().warn("No API key found for fetching app list.");
25745
- return [];
25745
+ return null;
25746
25746
  }
25747
25747
  try {
25748
25748
  const applist_response = await fetch(`${this.proxyUrl}/api/v1/apps?api_key=${this.userApiKey}`, {
@@ -25750,15 +25750,19 @@ var AppService = class {
25750
25750
  "X-API_Key": this.userApiKey
25751
25751
  }
25752
25752
  });
25753
+ if (!applist_response.ok) {
25754
+ Logger.getInstance().warn(`Failed to fetch app list: ${applist_response.status} ${applist_response.statusText}`);
25755
+ return null;
25756
+ }
25753
25757
  const applist_data = await applist_response.json();
25754
25758
  if (applist_data.code !== 200 || !applist_data.data) {
25755
25759
  Logger.getInstance().warn("Failed to fetch app list or no data returned");
25756
- return [];
25760
+ return null;
25757
25761
  }
25758
25762
  return Array.isArray(applist_data.data) ? applist_data.data : [];
25759
25763
  } catch (error) {
25760
25764
  Logger.getInstance().error("Error fetching app list:", error);
25761
- return [];
25765
+ return null;
25762
25766
  }
25763
25767
  }
25764
25768
  /**
@@ -25767,6 +25771,9 @@ var AppService = class {
25767
25771
  */
25768
25772
  async refreshCache() {
25769
25773
  const appResponses = await this.fetchAppList();
25774
+ if (appResponses === null) {
25775
+ return Array.from(this.appCache.values()).filter((app) => app.isConnected).map((app) => app.id);
25776
+ }
25770
25777
  const newCache = /* @__PURE__ */ new Map();
25771
25778
  const connectedAppIds = [];
25772
25779
  for (const appResponse of appResponses) {
@@ -25799,18 +25806,27 @@ var AppService = class {
25799
25806
  }
25800
25807
  async getActiveAppByProjectId(projectId) {
25801
25808
  const appResponses = await this.fetchAppList();
25809
+ if (appResponses === null) {
25810
+ const cachedApp = Array.from(this.appCache.values()).find((app) => app.projectId === projectId && app.isConnected);
25811
+ if (cachedApp) return cachedApp;
25812
+ return Array.from(this.appCache.values()).find((app) => app.projectId === projectId) || null;
25813
+ }
25802
25814
  const currentApps = appResponses.filter((app) => app.project_id === projectId);
25803
25815
  if (currentApps.length === 0) {
25804
25816
  Logger.getInstance().warn(`No apps found with projectId: ${projectId}`);
25805
25817
  return null;
25806
25818
  }
25807
25819
  const connectedApps = currentApps.filter((app) => app.is_connected);
25808
- const appIds = connectedApps.length > 0 ? connectedApps.map((app) => app.id).filter((id) => id !== void 0) : currentApps.map((app) => app.id).filter((id) => id !== void 0);
25809
25820
  let selectedAppResponse = connectedApps.length > 0 ? connectedApps[0] : currentApps[0];
25810
25821
  return this.convertAppResponseToApp(selectedAppResponse);
25811
25822
  }
25812
25823
  async getAppStatus(projectId) {
25813
25824
  const appResponses = await this.fetchAppList();
25825
+ if (appResponses === null) {
25826
+ const projectApps2 = Array.from(this.appCache.values()).filter((app) => app.projectId === projectId);
25827
+ if (projectApps2.length === 0) return "NOT_FOUND" /* NOT_FOUND */;
25828
+ return projectApps2.some((app) => app.isConnected) ? "CONNECTED" /* CONNECTED */ : "DISCONNECTED" /* DISCONNECTED */;
25829
+ }
25814
25830
  const projectApps = appResponses.filter((app) => app.project_id === projectId);
25815
25831
  if (projectApps.length === 0) {
25816
25832
  return "NOT_FOUND" /* NOT_FOUND */;
@@ -26583,6 +26599,8 @@ var DiskStorage = class {
26583
26599
  loadedProjectIds = /* @__PURE__ */ new Set();
26584
26600
  // Project IDs to Store: Tracks which projectIds need to be persisted to disk
26585
26601
  projectIdsToStore = /* @__PURE__ */ new Set();
26602
+ // Last Access Map: Tracks the last time a projectId was accessed
26603
+ lastAccessMap = /* @__PURE__ */ new Map();
26586
26604
  // Persistence Timer
26587
26605
  persistTimer;
26588
26606
  // ========== Concurrency Safety ==========
@@ -26646,13 +26664,20 @@ var DiskStorage = class {
26646
26664
  }
26647
26665
  }
26648
26666
  /**
26649
- * Clean up inactive caches (based on active list)
26667
+ * Clean up inactive caches (based on active list and TTL)
26650
26668
  * @param activeProjectIds List of currently active projectIds
26651
26669
  */
26652
26670
  async cleanupInactiveProjects(activeProjectIds) {
26653
26671
  const activeSet = new Set(activeProjectIds);
26672
+ const now = Date.now();
26673
+ const CACHE_TTL = 2 * 60 * 1e3;
26654
26674
  const cachedProjectIds = Array.from(this.factsCache.keys());
26655
- const inactiveProjectIds = cachedProjectIds.filter((projectId) => !activeSet.has(projectId));
26675
+ const inactiveProjectIds = cachedProjectIds.filter((projectId) => {
26676
+ if (activeSet.has(projectId)) return false;
26677
+ const lastAccess = this.lastAccessMap.get(projectId) || 0;
26678
+ if (now - lastAccess < CACHE_TTL) return false;
26679
+ return true;
26680
+ });
26656
26681
  if (inactiveProjectIds.length > 0) {
26657
26682
  Logger.getInstance().info(`Cleaning up ${inactiveProjectIds.length} inactive project caches...`);
26658
26683
  await Promise.all(
@@ -26726,6 +26751,7 @@ var DiskStorage = class {
26726
26751
  this.runtimeEventsMap.delete(projectId);
26727
26752
  this.projectIdsToStore.delete(projectId);
26728
26753
  this.loadedProjectIds.delete(projectId);
26754
+ this.lastAccessMap.delete(projectId);
26729
26755
  Logger.getInstance().info(`Cleared cache for project ${projectId}`);
26730
26756
  }
26731
26757
  getProjectRuntimeEvents(projectId) {
@@ -26790,6 +26816,7 @@ var DiskStorage = class {
26790
26816
  * Each projectId is loaded from disk only on first access; subsequent access uses cache.
26791
26817
  */
26792
26818
  async getRuntimeFacts(projectId) {
26819
+ this.lastAccessMap.set(projectId, Date.now());
26793
26820
  if (this.factsCache.has(projectId)) {
26794
26821
  return [...this.factsCache.get(projectId)];
26795
26822
  }
@@ -26807,6 +26834,7 @@ var DiskStorage = class {
26807
26834
  * Use lock protection to avoid concurrency conflicts with updateRuntimeFact.
26808
26835
  */
26809
26836
  async saveRuntimeFacts(projectId, facts) {
26837
+ this.lastAccessMap.set(projectId, Date.now());
26810
26838
  return this.withLock(projectId, async () => {
26811
26839
  const limitedFacts = this.limitTraces(facts);
26812
26840
  this.factsCache.set(projectId, limitedFacts);
@@ -26819,6 +26847,7 @@ var DiskStorage = class {
26819
26847
  * Use lock protection to avoid concurrency conflicts with saveRuntimeFacts.
26820
26848
  */
26821
26849
  async updateRuntimeFact(projectId, updatedTrace) {
26850
+ this.lastAccessMap.set(projectId, Date.now());
26822
26851
  return this.withLock(projectId, async () => {
26823
26852
  let traces = this.factsCache.get(projectId);
26824
26853
  if (!traces) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syncause/debug-daemon",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Syncause Debug MCP Daemon",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -35,4 +35,4 @@
35
35
  "winston": "^3.18.3",
36
36
  "winston-daily-rotate-file": "^5.0.0"
37
37
  }
38
- }
38
+ }