@abraca/mcp 2.16.0 → 2.17.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.
@@ -21467,6 +21467,7 @@ var AbracadabraMCPServer = class AbracadabraMCPServer {
21467
21467
  this._spaceConnections = /* @__PURE__ */ new Map();
21468
21468
  this.childCache = /* @__PURE__ */ new Map();
21469
21469
  this.evictionTimer = null;
21470
+ this.heartbeatTimer = null;
21470
21471
  this._mcpServerRef = null;
21471
21472
  this._serverRef = null;
21472
21473
  this._handledTaskIds = /* @__PURE__ */ new Set();
@@ -21564,6 +21565,9 @@ var AbracadabraMCPServer = class AbracadabraMCPServer {
21564
21565
  await this._connectToSpace(initialDocId);
21565
21566
  console.error("[abracadabra-mcp] Space doc synced");
21566
21567
  this.evictionTimer = setInterval(() => this.evictIdle(), 6e4);
21568
+ this.heartbeatTimer = setInterval(() => {
21569
+ this.ensureConnected();
21570
+ }, 3e4);
21567
21571
  }
21568
21572
  /** Connect to a space's root doc and cache it. Sets it as the active connection. */
21569
21573
  async _connectToSpace(docId) {
@@ -21672,34 +21676,37 @@ var AbracadabraMCPServer = class AbracadabraMCPServer {
21672
21676
  console.error("[abracadabra-mcp] Re-auth during heal failed:", e);
21673
21677
  }
21674
21678
  const conn = this._activeConnection;
21675
- if (!conn) return;
21676
- if (this._wsConnected(conn.provider)) return;
21677
- try {
21678
- await waitForSync(conn.provider, 6e3);
21679
- } catch {}
21680
- if (this._wsConnected(conn.provider)) return;
21681
- console.error("[abracadabra-mcp] Active connection dead — rebuilding space provider…");
21682
- const docId = conn.docId;
21683
- this._spaceConnections.delete(docId);
21684
- try {
21685
- conn.provider.destroy();
21686
- } catch {}
21687
- for (const [, cached] of this.childCache) try {
21688
- cached.provider.destroy();
21689
- } catch {}
21690
- this.childCache.clear();
21691
- try {
21692
- await this._connectToSpace(docId);
21693
- console.error("[abracadabra-mcp] Space provider rebuilt + synced");
21694
- } catch (e) {
21695
- console.error("[abracadabra-mcp] Connection rebuild failed:", e);
21696
- }
21679
+ if (conn) await this._healProvider(conn.provider, "space");
21680
+ if (this._inboxProvider) await this._healProvider(this._inboxProvider, "inbox");
21697
21681
  } finally {
21698
21682
  this._reconnecting = null;
21699
21683
  }
21700
21684
  })();
21701
21685
  return this._reconnecting;
21702
21686
  }
21687
+ /**
21688
+ * Bring one provider's socket back to a synced state WITHOUT swapping its
21689
+ * Y.Doc. First let the SDK's own auto-reconnect finish if it's mid-flight;
21690
+ * if the socket is still dead, force a reconnect on the same doc. Because the
21691
+ * document is never replaced, every observer attached to it (root awareness,
21692
+ * tree reads, the inbox `entries` array, the stateless chat listener) keeps
21693
+ * firing — no re-attach needed. Best-effort: logs but never throws.
21694
+ */
21695
+ async _healProvider(provider, label) {
21696
+ if (this._wsConnected(provider)) return;
21697
+ try {
21698
+ await waitForSync(provider, 6e3);
21699
+ } catch {}
21700
+ if (this._wsConnected(provider)) return;
21701
+ console.error(`[abracadabra-mcp] ${label} socket dead — forcing reconnect on the same doc…`);
21702
+ provider.reconnect();
21703
+ try {
21704
+ await waitForSync(provider, 1e4);
21705
+ console.error(`[abracadabra-mcp] ${label} reconnected + re-synced`);
21706
+ } catch (e) {
21707
+ console.error(`[abracadabra-mcp] ${label} reconnect did not re-sync in time:`, e);
21708
+ }
21709
+ }
21703
21710
  async ensureSpaceActive(targetId) {
21704
21711
  await this.ensureConnected();
21705
21712
  if (!targetId || targetId === this._rootDocId) return true;
@@ -22306,6 +22313,10 @@ var AbracadabraMCPServer = class AbracadabraMCPServer {
22306
22313
  clearInterval(this.evictionTimer);
22307
22314
  this.evictionTimer = null;
22308
22315
  }
22316
+ if (this.heartbeatTimer) {
22317
+ clearInterval(this.heartbeatTimer);
22318
+ this.heartbeatTimer = null;
22319
+ }
22309
22320
  for (const dispose of this._inboxDisposers) try {
22310
22321
  dispose();
22311
22322
  } catch {}
@@ -22776,6 +22787,8 @@ function registerContentTools(mcp, server) {
22776
22787
  const contentToWrite = body || markdown;
22777
22788
  const existingLabel = server.getDocSummary(docId)?.label;
22778
22789
  (0, _abraca_convert.populateYDocFromMarkdown)(fragment, contentToWrite, title || existingLabel || "Untitled");
22790
+ const coverTree = server.getTreeMap();
22791
+ if (coverTree) (0, _abraca_dabra.reconcileDocCover)(coverTree, docId, fragment);
22779
22792
  server.setFocusedDoc(docId);
22780
22793
  server.setDocCursor(docId, fragment.length);
22781
22794
  return { content: [{