@ai-matrx/agents 0.59.277 → 0.59.279

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.
package/CHANGELOG.md CHANGED
@@ -1,10 +1,24 @@
1
1
  # Changelog
2
2
 
3
- ## 0.59.277
3
+ ## 0.59.279
4
4
 
5
5
  UNVERIFIED: this release has no Unreleased entry and the source comparison could not be made (the caller supplied no source comparison). Whether source changed is unknown; consumer action is unknown.
6
6
  Check the package's gitHead on npm against this version's gitHead: `git diff <previous gitHead> <this gitHead> -- apps/shared/matrx-agents/src`.
7
7
 
8
+ ## 0.59.278
9
+
10
+ - `./models`: `followModelCatalogVisibility` never swallows a return. Every show / focus after the tab was
11
+ hidden or blurred reads the stamp; only repeated shows with no time away share a read for `minIntervalMs`.
12
+ The baseline is read at bind (one row) and on hide / blur after a change made it unknown; a tab's own
13
+ catch-up keeps the stamp it read. Live 2026-10-24: the admin audit page took focus for a search, the admin
14
+ renamed in another tab and came back inside 20 s, and the throttle read nothing. Test:
15
+ `models/react/hidden-tab-catches-up-on-visible.test.tsx`. Consumer action: none.
16
+
17
+ ## 0.59.277
18
+
19
+ Automatic changed-only republish (docs/metadata drift since the last published version; verified: `git diff a13dc14bcc 9798073998 -- apps/shared/matrx-agents/src`
20
+ has no shipped-source changes outside tests, fixtures and docs). No consumer action required.
21
+
8
22
  ## 0.59.276
9
23
 
10
24
  - `./models`: one catalog edit costs a page at most two requests, however many model labels are mounted.
@@ -1687,6 +1687,7 @@ function followModelCatalogVisibility(options) {
1687
1687
  let baseline;
1688
1688
  let inFlight = null;
1689
1689
  let lastShownRead = -Infinity;
1690
+ let awaySinceRead = true;
1690
1691
  const stamp = () => inFlight ??= readModelCatalogStamp(options.client).finally(() => {
1691
1692
  inFlight = null;
1692
1693
  });
@@ -1697,34 +1698,45 @@ function followModelCatalogVisibility(options) {
1697
1698
  if (baseline === void 0) baseline = s4;
1698
1699
  }, fail);
1699
1700
  };
1700
- const onHidden = () => {
1701
- if (page.document.visibilityState === "hidden") learnBaseline();
1701
+ const onAway = () => {
1702
+ awaySinceRead = true;
1703
+ learnBaseline();
1702
1704
  };
1703
1705
  const onShown = () => {
1704
1706
  if (page.document.visibilityState === "hidden") return;
1705
1707
  const t = now();
1706
- if (t - lastShownRead < minIntervalMs) return;
1708
+ if (!awaySinceRead && t - lastShownRead < minIntervalMs) return;
1709
+ awaySinceRead = false;
1707
1710
  lastShownRead = t;
1708
1711
  const known = baseline;
1709
1712
  if (known === void 0) return learnBaseline();
1710
1713
  void stamp().then((s4) => {
1711
- if (s4 === known) return;
1714
+ if (s4 === baseline || baseline === void 0) return;
1715
+ ownAnnounce = true;
1716
+ try {
1717
+ announceModelCatalogChanged({ catalog: "models", change: "catch_up_visible" });
1718
+ } finally {
1719
+ ownAnnounce = false;
1720
+ }
1712
1721
  baseline = s4;
1713
- announceModelCatalogChanged({ catalog: "models", change: "catch_up_visible" });
1714
1722
  }, fail);
1715
1723
  };
1724
+ let ownAnnounce = false;
1716
1725
  const offChanges = onModelCatalogChanged(() => {
1726
+ if (ownAnnounce) return;
1717
1727
  baseline = void 0;
1718
1728
  if (page.document.visibilityState === "hidden") learnBaseline();
1719
1729
  });
1720
- const onVisibility = () => page.document.visibilityState === "hidden" ? onHidden() : onShown();
1730
+ const onVisibility = () => page.document.visibilityState === "hidden" ? onAway() : onShown();
1721
1731
  page.document.addEventListener("visibilitychange", onVisibility);
1722
1732
  page.window.addEventListener("focus", onShown);
1723
- if (page.document.visibilityState === "hidden") learnBaseline();
1733
+ page.window.addEventListener("blur", onAway);
1734
+ learnBaseline();
1724
1735
  return () => {
1725
1736
  offChanges();
1726
1737
  page.document.removeEventListener("visibilitychange", onVisibility);
1727
1738
  page.window.removeEventListener("focus", onShown);
1739
+ page.window.removeEventListener("blur", onAway);
1728
1740
  };
1729
1741
  }
1730
1742
 
@@ -2141,10 +2141,13 @@ interface ModelCatalogVisibilityOptions {
2141
2141
  /**
2142
2142
  * When the tab shows or takes focus, read the catalog stamp (one row) and, when it moved since the tab
2143
2143
  * last knew it, announce a model catalog change through the SAME door as the bus (every catalog re-reads
2144
- * what it read; every reader following `onModelCatalogChanged` re-reads). The baseline is taken when the
2145
- * tab hides (or at bind when it starts hidden), and refreshed by every announced change. Reads already in
2146
- * flight are joined; shows/focuses within `minIntervalMs` share the last read. Returns the unbind. No-op
2147
- * where there is no document (a server render, a worker).
2144
+ * what it read; every reader following `onModelCatalogChanged` re-reads). The baseline is read at bind,
2145
+ * and again when the tab hides or loses focus after an announced change made it unknown. Every return
2146
+ * from away (hidden or blurred) reads the stamp; only repeated shows / focuses with no time away in
2147
+ * between share the last read for `minIntervalMs` (a tab that took focus to type a search, went to
2148
+ * another tab for a rename and came back inside 20 s used to read nothing — live 2026-10-24, the admin
2149
+ * audit page). Reads already in flight are joined. Returns the unbind. No-op where there is no document
2150
+ * (a server render, a worker).
2148
2151
  */
2149
2152
  declare function followModelCatalogVisibility(options: ModelCatalogVisibilityOptions): () => void;
2150
2153
 
@@ -2141,10 +2141,13 @@ interface ModelCatalogVisibilityOptions {
2141
2141
  /**
2142
2142
  * When the tab shows or takes focus, read the catalog stamp (one row) and, when it moved since the tab
2143
2143
  * last knew it, announce a model catalog change through the SAME door as the bus (every catalog re-reads
2144
- * what it read; every reader following `onModelCatalogChanged` re-reads). The baseline is taken when the
2145
- * tab hides (or at bind when it starts hidden), and refreshed by every announced change. Reads already in
2146
- * flight are joined; shows/focuses within `minIntervalMs` share the last read. Returns the unbind. No-op
2147
- * where there is no document (a server render, a worker).
2144
+ * what it read; every reader following `onModelCatalogChanged` re-reads). The baseline is read at bind,
2145
+ * and again when the tab hides or loses focus after an announced change made it unknown. Every return
2146
+ * from away (hidden or blurred) reads the stamp; only repeated shows / focuses with no time away in
2147
+ * between share the last read for `minIntervalMs` (a tab that took focus to type a search, went to
2148
+ * another tab for a rename and came back inside 20 s used to read nothing — live 2026-10-24, the admin
2149
+ * audit page). Reads already in flight are joined. Returns the unbind. No-op where there is no document
2150
+ * (a server render, a worker).
2148
2151
  */
2149
2152
  declare function followModelCatalogVisibility(options: ModelCatalogVisibilityOptions): () => void;
2150
2153
 
@@ -1503,6 +1503,7 @@ function followModelCatalogVisibility(options) {
1503
1503
  let baseline;
1504
1504
  let inFlight = null;
1505
1505
  let lastShownRead = -Infinity;
1506
+ let awaySinceRead = true;
1506
1507
  const stamp = () => inFlight ??= readModelCatalogStamp(options.client).finally(() => {
1507
1508
  inFlight = null;
1508
1509
  });
@@ -1513,34 +1514,45 @@ function followModelCatalogVisibility(options) {
1513
1514
  if (baseline === void 0) baseline = s4;
1514
1515
  }, fail);
1515
1516
  };
1516
- const onHidden = () => {
1517
- if (page.document.visibilityState === "hidden") learnBaseline();
1517
+ const onAway = () => {
1518
+ awaySinceRead = true;
1519
+ learnBaseline();
1518
1520
  };
1519
1521
  const onShown = () => {
1520
1522
  if (page.document.visibilityState === "hidden") return;
1521
1523
  const t = now();
1522
- if (t - lastShownRead < minIntervalMs) return;
1524
+ if (!awaySinceRead && t - lastShownRead < minIntervalMs) return;
1525
+ awaySinceRead = false;
1523
1526
  lastShownRead = t;
1524
1527
  const known = baseline;
1525
1528
  if (known === void 0) return learnBaseline();
1526
1529
  void stamp().then((s4) => {
1527
- if (s4 === known) return;
1530
+ if (s4 === baseline || baseline === void 0) return;
1531
+ ownAnnounce = true;
1532
+ try {
1533
+ announceModelCatalogChanged({ catalog: "models", change: "catch_up_visible" });
1534
+ } finally {
1535
+ ownAnnounce = false;
1536
+ }
1528
1537
  baseline = s4;
1529
- announceModelCatalogChanged({ catalog: "models", change: "catch_up_visible" });
1530
1538
  }, fail);
1531
1539
  };
1540
+ let ownAnnounce = false;
1532
1541
  const offChanges = onModelCatalogChanged(() => {
1542
+ if (ownAnnounce) return;
1533
1543
  baseline = void 0;
1534
1544
  if (page.document.visibilityState === "hidden") learnBaseline();
1535
1545
  });
1536
- const onVisibility = () => page.document.visibilityState === "hidden" ? onHidden() : onShown();
1546
+ const onVisibility = () => page.document.visibilityState === "hidden" ? onAway() : onShown();
1537
1547
  page.document.addEventListener("visibilitychange", onVisibility);
1538
1548
  page.window.addEventListener("focus", onShown);
1539
- if (page.document.visibilityState === "hidden") learnBaseline();
1549
+ page.window.addEventListener("blur", onAway);
1550
+ learnBaseline();
1540
1551
  return () => {
1541
1552
  offChanges();
1542
1553
  page.document.removeEventListener("visibilitychange", onVisibility);
1543
1554
  page.window.removeEventListener("focus", onShown);
1555
+ page.window.removeEventListener("blur", onAway);
1544
1556
  };
1545
1557
  }
1546
1558
 
@@ -1280,9 +1280,9 @@ function ContractBreak({ version, ports }) {
1280
1280
  return;
1281
1281
  }
1282
1282
  {
1283
- ports.notify.success(
1284
- kind ? `v${version.version_number} marked as a ${kind} contract break.` : `Contract-break declaration cleared for v${version.version_number}.`
1285
- );
1283
+ ports.notify.success(kind ? "Contract break marked" : "Contract break cleared", {
1284
+ description: kind ? `v${version.version_number}, ${kind}` : `v${version.version_number}`
1285
+ });
1286
1286
  }
1287
1287
  }
1288
1288
  const autoChange = version.contract_change || null;
@@ -96,7 +96,10 @@ interface VersionHistoryLoad {
96
96
 
97
97
  /** Where the timeline says a result: the host's toasts (sonner on the web). */
98
98
  interface VersionTimelineNotify {
99
- success: (message: string) => void;
99
+ /** A card: a short title and an optional line (design-system NOTICE_TEXT_BUDGET). */
100
+ success: (message: string, options?: {
101
+ description?: string;
102
+ }) => void;
100
103
  /** A card: a short title and an optional line (design-system NOTICE_TEXT_BUDGET). */
101
104
  error: (message: string, options?: {
102
105
  description?: string;
@@ -96,7 +96,10 @@ interface VersionHistoryLoad {
96
96
 
97
97
  /** Where the timeline says a result: the host's toasts (sonner on the web). */
98
98
  interface VersionTimelineNotify {
99
- success: (message: string) => void;
99
+ /** A card: a short title and an optional line (design-system NOTICE_TEXT_BUDGET). */
100
+ success: (message: string, options?: {
101
+ description?: string;
102
+ }) => void;
100
103
  /** A card: a short title and an optional line (design-system NOTICE_TEXT_BUDGET). */
101
104
  error: (message: string, options?: {
102
105
  description?: string;
@@ -1284,9 +1284,9 @@ function ContractBreak({ version, ports }) {
1284
1284
  return;
1285
1285
  }
1286
1286
  {
1287
- ports.notify.success(
1288
- kind ? `v${version.version_number} marked as a ${kind} contract break.` : `Contract-break declaration cleared for v${version.version_number}.`
1289
- );
1287
+ ports.notify.success(kind ? "Contract break marked" : "Contract break cleared", {
1288
+ description: kind ? `v${version.version_number}, ${kind}` : `v${version.version_number}`
1289
+ });
1290
1290
  }
1291
1291
  }
1292
1292
  const autoChange = version.contract_change || null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-matrx/agents",
3
- "version": "0.59.277",
3
+ "version": "0.59.279",
4
4
  "description": "Portable AI Matrx agent stream protocol, event projection, and safe result-presentation primitives.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -522,5 +522,5 @@
522
522
  "optional": true
523
523
  }
524
524
  },
525
- "gitHead": "9798073998e5fa0c03b673a38fda129a2bc7d19d"
525
+ "gitHead": "129b26d86cca439c51d2ec6bd4d421182b33922c"
526
526
  }