@abraca/mcp 2.9.0 → 2.11.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.
@@ -21477,6 +21477,7 @@ var AbracadabraMCPServer = class AbracadabraMCPServer {
21477
21477
  this._activeTurnChannel = null;
21478
21478
  this._signFn = null;
21479
21479
  this._toolHistory = [];
21480
+ this._reconnecting = null;
21480
21481
  this._inboxStarted = false;
21481
21482
  this._inboxDocId = null;
21482
21483
  this._inboxDoc = null;
@@ -21647,7 +21648,60 @@ var AbracadabraMCPServer = class AbracadabraMCPServer {
21647
21648
  * child-content provider cache survives — content docs are keyed by global
21648
21649
  * guid, independent of which space is active.
21649
21650
  */
21651
+ /**
21652
+ * Heal the active connection before a tool op so a dropped/idle WebSocket or
21653
+ * an expired JWT doesn't surface as a 15s sync timeout ("MCP not responding").
21654
+ * Refreshes the token, lets the SDK's own auto-reconnect finish if it's mid-
21655
+ * flight, and rebuilds the space connection from scratch if the socket is
21656
+ * truly dead. De-duped so parallel tool calls heal once. Best-effort: never
21657
+ * throws — a failed heal falls through to the normal (possibly erroring) op.
21658
+ */
21659
+ /** Whether a provider's shared WebSocket is currently connected. Isolated in
21660
+ * its own scope so repeated checks don't trip TS control-flow narrowing on
21661
+ * the live `connectionStatus` getter. */
21662
+ _wsConnected(provider) {
21663
+ return provider.connectionStatus === _abraca_dabra.WebSocketStatus.Connected;
21664
+ }
21665
+ async ensureConnected() {
21666
+ if (this._reconnecting) return this._reconnecting;
21667
+ this._reconnecting = (async () => {
21668
+ try {
21669
+ if (!this.client.isTokenValid() && this._signFn && this._userId) try {
21670
+ await this.client.loginWithKey(this._userId, this._signFn);
21671
+ } catch (e) {
21672
+ console.error("[abracadabra-mcp] Re-auth during heal failed:", e);
21673
+ }
21674
+ 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
+ }
21697
+ } finally {
21698
+ this._reconnecting = null;
21699
+ }
21700
+ })();
21701
+ return this._reconnecting;
21702
+ }
21650
21703
  async ensureSpaceActive(targetId) {
21704
+ await this.ensureConnected();
21651
21705
  if (!targetId || targetId === this._rootDocId) return true;
21652
21706
  if (this._spaces.some((s) => s.id === targetId)) {
21653
21707
  await this._connectToSpace(targetId);
@@ -21704,11 +21758,18 @@ var AbracadabraMCPServer = class AbracadabraMCPServer {
21704
21758
  * Caches providers and waits for sync before returning.
21705
21759
  */
21706
21760
  async getChildProvider(docId) {
21761
+ await this.ensureConnected();
21707
21762
  const cached = this.childCache.get(docId);
21708
- if (cached) {
21763
+ if (cached && cached.provider.connectionStatus !== _abraca_dabra.WebSocketStatus.Disconnected) {
21709
21764
  cached.lastAccessed = Date.now();
21710
21765
  return cached.provider;
21711
21766
  }
21767
+ if (cached) {
21768
+ try {
21769
+ cached.provider.destroy();
21770
+ } catch {}
21771
+ this.childCache.delete(docId);
21772
+ }
21712
21773
  const activeProvider = this._activeConnection?.provider;
21713
21774
  if (!activeProvider) throw new Error("Not connected. Call connect() first.");
21714
21775
  if (!this.client.isTokenValid() && this._signFn && this._userId) {