@bastani/atomic 0.9.28-alpha.4 → 0.9.28-alpha.5

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 (126) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  3. package/dist/builtin/intercom/README.md +3 -2
  4. package/dist/builtin/intercom/broker/broker.ts +90 -14
  5. package/dist/builtin/intercom/broker/paths.ts +4 -0
  6. package/dist/builtin/intercom/broker/socket-liveness.ts +32 -0
  7. package/dist/builtin/intercom/broker/socket-replacement-lock.ts +104 -0
  8. package/dist/builtin/intercom/broker/spawn.ts +108 -63
  9. package/dist/builtin/intercom/index.bundle.mjs +114 -61
  10. package/dist/builtin/intercom/package.json +1 -1
  11. package/dist/builtin/mcp/package.json +1 -1
  12. package/dist/builtin/subagents/package.json +1 -1
  13. package/dist/builtin/web-access/package.json +1 -1
  14. package/dist/builtin/workflows/CHANGELOG.md +6 -0
  15. package/dist/builtin/workflows/builtin/{chunk-aqv8ny38.js → chunk-9ywkdsa9.js} +1 -1
  16. package/dist/builtin/workflows/builtin/{chunk-p6jagvyf.js → chunk-bnz4knhy.js} +1 -1
  17. package/dist/builtin/workflows/builtin/{chunk-br4ac9a3.js → chunk-dx5sjaxe.js} +1 -1
  18. package/dist/builtin/workflows/builtin/{chunk-p3xmajmj.js → chunk-v4scsq3y.js} +41 -13
  19. package/dist/builtin/workflows/builtin/goal.js +2 -2
  20. package/dist/builtin/workflows/builtin/index.js +3 -3
  21. package/dist/builtin/workflows/builtin/ralph.js +2 -2
  22. package/dist/builtin/workflows/package.json +1 -1
  23. package/dist/builtin/workflows/src/extension/index.bundle.mjs +38 -14
  24. package/dist/builtin/workflows/src/index.js +38 -14
  25. package/dist/cli/startup-ui.d.ts +3 -2
  26. package/dist/cli/startup-ui.d.ts.map +1 -1
  27. package/dist/cli/startup-ui.js +19 -4
  28. package/dist/cli/startup-ui.js.map +1 -1
  29. package/dist/core/agent-session-runtime.d.ts +5 -1
  30. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  31. package/dist/core/agent-session-runtime.js +13 -9
  32. package/dist/core/agent-session-runtime.js.map +1 -1
  33. package/dist/core/extensions/session-events.d.ts +2 -0
  34. package/dist/core/extensions/session-events.d.ts.map +1 -1
  35. package/dist/core/extensions/session-events.js.map +1 -1
  36. package/dist/core/provider-alias.d.ts.map +1 -1
  37. package/dist/core/provider-alias.js +8 -0
  38. package/dist/core/provider-alias.js.map +1 -1
  39. package/dist/core/provider-composer-internal.d.ts.map +1 -1
  40. package/dist/core/provider-composer-internal.js +6 -3
  41. package/dist/core/provider-composer-internal.js.map +1 -1
  42. package/dist/core/resource-loader-reload.d.ts.map +1 -1
  43. package/dist/core/resource-loader-reload.js +1 -0
  44. package/dist/core/resource-loader-reload.js.map +1 -1
  45. package/dist/core/resource-loader-types.d.ts +1 -0
  46. package/dist/core/resource-loader-types.d.ts.map +1 -1
  47. package/dist/core/resource-loader-types.js.map +1 -1
  48. package/dist/extensions/herdr/index.d.ts.map +1 -1
  49. package/dist/extensions/herdr/index.js +20 -2
  50. package/dist/extensions/herdr/index.js.map +1 -1
  51. package/dist/extensions/herdr/pane-owner.d.ts +7 -0
  52. package/dist/extensions/herdr/pane-owner.d.ts.map +1 -1
  53. package/dist/extensions/herdr/pane-owner.js +53 -11
  54. package/dist/extensions/herdr/pane-owner.js.map +1 -1
  55. package/dist/main-deferred-startup.d.ts +8 -0
  56. package/dist/main-deferred-startup.d.ts.map +1 -1
  57. package/dist/main-deferred-startup.js +6 -0
  58. package/dist/main-deferred-startup.js.map +1 -1
  59. package/dist/main.d.ts.map +1 -1
  60. package/dist/main.js +11 -3
  61. package/dist/main.js.map +1 -1
  62. package/dist/modes/interactive/interactive-auth-routing.js +2 -2
  63. package/dist/modes/interactive/interactive-auth-routing.js.map +1 -1
  64. package/dist/modes/interactive/interactive-extension-dialogs.js +8 -0
  65. package/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  66. package/dist/modes/interactive/interactive-mode-base.d.ts +1 -0
  67. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  68. package/dist/modes/interactive/interactive-mode-base.js +1 -0
  69. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  70. package/dist/modes/interactive/interactive-mode-helpers.js +1 -1
  71. package/dist/modes/interactive/interactive-mode-helpers.js.map +1 -1
  72. package/dist/modes/interactive/interactive-mode-types.d.ts +1 -0
  73. package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
  74. package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
  75. package/dist/modes/interactive/interactive-process-lifecycle.js +1 -1
  76. package/dist/modes/interactive/interactive-process-lifecycle.js.map +1 -1
  77. package/dist/modes/interactive/interactive-startup-trust.d.ts +6 -0
  78. package/dist/modes/interactive/interactive-startup-trust.d.ts.map +1 -0
  79. package/dist/modes/interactive/interactive-startup-trust.js +15 -0
  80. package/dist/modes/interactive/interactive-startup-trust.js.map +1 -0
  81. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  82. package/dist/modes/interactive/interactive-startup.js +3 -0
  83. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  84. package/dist/modes/interactive-engine/engine-child-liveness.d.ts +1 -0
  85. package/dist/modes/interactive-engine/engine-child-liveness.d.ts.map +1 -1
  86. package/dist/modes/interactive-engine/engine-child-liveness.js +15 -1
  87. package/dist/modes/interactive-engine/engine-child-liveness.js.map +1 -1
  88. package/dist/modes/interactive-engine/engine-monitor.d.ts +4 -0
  89. package/dist/modes/interactive-engine/engine-monitor.d.ts.map +1 -1
  90. package/dist/modes/interactive-engine/engine-monitor.js +17 -0
  91. package/dist/modes/interactive-engine/engine-monitor.js.map +1 -1
  92. package/dist/modes/interactive-engine/engine-quit-intent.d.ts +16 -0
  93. package/dist/modes/interactive-engine/engine-quit-intent.d.ts.map +1 -0
  94. package/dist/modes/interactive-engine/engine-quit-intent.js +27 -0
  95. package/dist/modes/interactive-engine/engine-quit-intent.js.map +1 -0
  96. package/dist/modes/interactive-engine/extension-ui-bridge.d.ts +1 -0
  97. package/dist/modes/interactive-engine/extension-ui-bridge.d.ts.map +1 -1
  98. package/dist/modes/interactive-engine/extension-ui-bridge.js +5 -0
  99. package/dist/modes/interactive-engine/extension-ui-bridge.js.map +1 -1
  100. package/dist/modes/interactive-engine/isolated-runtime.d.ts +4 -1
  101. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
  102. package/dist/modes/interactive-engine/isolated-runtime.js +19 -2
  103. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  104. package/dist/modes/interactive-engine/protocol.d.ts +18 -1
  105. package/dist/modes/interactive-engine/protocol.d.ts.map +1 -1
  106. package/dist/modes/interactive-engine/protocol.js +6 -0
  107. package/dist/modes/interactive-engine/protocol.js.map +1 -1
  108. package/dist/modes/rpc/rpc-client.d.ts +11 -0
  109. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  110. package/dist/modes/rpc/rpc-client.js +42 -0
  111. package/dist/modes/rpc/rpc-client.js.map +1 -1
  112. package/dist/modes/rpc/rpc-input-scheduler.js +2 -2
  113. package/dist/modes/rpc/rpc-input-scheduler.js.map +1 -1
  114. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  115. package/dist/modes/rpc/rpc-mode.js +23 -6
  116. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  117. package/dist/modes/rpc/rpc-provider-auth.js +1 -1
  118. package/dist/modes/rpc/rpc-provider-auth.js.map +1 -1
  119. package/docs/extensions/events.md +3 -0
  120. package/docs/herdr.md +11 -2
  121. package/docs/models.md +1 -1
  122. package/docs/providers.md +2 -0
  123. package/docs/sdk.md +1 -1
  124. package/docs/settings.md +1 -1
  125. package/npm-shrinkwrap.json +32 -32
  126. package/package.json +3 -3
@@ -1406,13 +1406,43 @@ var init_client = __esm(() => {
1406
1406
  };
1407
1407
  });
1408
1408
 
1409
+ // dist/builtin/intercom/broker/socket-liveness.ts
1410
+ import net2 from "net";
1411
+ function isSocketAnswering(socketPath, timeoutMs = SOCKET_PROBE_TIMEOUT_MS) {
1412
+ return new Promise((resolve) => {
1413
+ const socket = net2.connect(socketPath);
1414
+ const finish = (isConnected) => {
1415
+ clearTimeout(timeout);
1416
+ socket.off("connect", onConnect);
1417
+ socket.off("error", onError);
1418
+ resolve(isConnected);
1419
+ };
1420
+ const onConnect = () => {
1421
+ socket.on("error", () => {});
1422
+ socket.end();
1423
+ finish(true);
1424
+ };
1425
+ const onError = () => {
1426
+ socket.destroy();
1427
+ finish(false);
1428
+ };
1429
+ socket.on("connect", onConnect);
1430
+ socket.on("error", onError);
1431
+ const timeout = setTimeout(() => {
1432
+ socket.destroy();
1433
+ finish(false);
1434
+ }, timeoutMs);
1435
+ });
1436
+ }
1437
+ var SOCKET_PROBE_TIMEOUT_MS = 1000;
1438
+ var init_socket_liveness = () => {};
1439
+
1409
1440
  // dist/builtin/intercom/broker/spawn.ts
1410
1441
  import { spawn } from "child_process";
1411
- import { chmodSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, readSync, statSync, unlinkSync, writeFileSync } from "fs";
1442
+ import { appendFileSync, chmodSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, readSync, statSync, unlinkSync, writeFileSync } from "fs";
1412
1443
  import { join as join2, dirname } from "path";
1413
1444
  import { fileURLToPath } from "url";
1414
1445
  import { createRequire } from "module";
1415
- import net2 from "net";
1416
1446
  import { createChildProcessEnvironment, isBunBinary } from "@bastani/atomic";
1417
1447
  function isIntercomPackageRoot(dir) {
1418
1448
  return existsSync(join2(dir, "package.json")) && existsSync(join2(dir, "broker"));
@@ -1537,7 +1567,15 @@ function getBrokerSpawnOptions(extensionDir = EXTENSION_DIR, stderr = "ignore")
1537
1567
  }
1538
1568
  function resetBrokerLog(logPath = BROKER_LOG) {
1539
1569
  ensurePrivateDirectory(dirname(logPath));
1540
- closeSync(openSync(logPath, "w"));
1570
+ try {
1571
+ closeSync(openSync(logPath, "w"));
1572
+ return true;
1573
+ } catch (error) {
1574
+ const code = error.code;
1575
+ if (process.platform === "win32" && (code === "EBUSY" || code === "EPERM"))
1576
+ return false;
1577
+ throw error;
1578
+ }
1541
1579
  }
1542
1580
  function readBrokerLogTail(logPath = BROKER_LOG, maxBytes = BROKER_LOG_TAIL_BYTES) {
1543
1581
  let fd;
@@ -1571,16 +1609,17 @@ ${tail}`;
1571
1609
  function toError2(error) {
1572
1610
  return error instanceof Error ? error : new Error(String(error));
1573
1611
  }
1574
- async function spawnBrokerIfNeeded(brokerCommand, brokerArgs) {
1612
+ async function spawnBrokerIfNeeded(brokerCommand, brokerArgs, readyTimeoutMs = BROKER_READY_TIMEOUT_MS) {
1575
1613
  ensurePrivateDirectory(INTERCOM_DIR);
1576
1614
  if (await isBrokerRunning()) {
1577
1615
  return;
1578
1616
  }
1579
- const ownsLock = acquireSpawnLock();
1580
- if (!ownsLock) {
1581
- await waitForBroker();
1617
+ const lockOwner = acquireSpawnLock();
1618
+ if (lockOwner === undefined) {
1619
+ await waitForBroker(readyTimeoutMs);
1582
1620
  return;
1583
1621
  }
1622
+ let keepLock = false;
1584
1623
  try {
1585
1624
  if (await isBrokerRunning()) {
1586
1625
  return;
@@ -1590,7 +1629,10 @@ async function spawnBrokerIfNeeded(brokerCommand, brokerArgs) {
1590
1629
  if (launch.kind === "windows-launcher") {
1591
1630
  writeWindowsHiddenLauncher(launch.launcherCommandLine, launch.launcherPath);
1592
1631
  }
1593
- resetBrokerLog();
1632
+ if (!resetBrokerLog()) {
1633
+ await waitForBroker(readyTimeoutMs);
1634
+ return;
1635
+ }
1594
1636
  const logFd = launch.kind === "direct" ? openSync(BROKER_LOG, "a") : undefined;
1595
1637
  let child;
1596
1638
  try {
@@ -1620,21 +1662,28 @@ ${describeBrokerLog()}`, { cause: error }));
1620
1662
  ${describeBrokerLog()}`));
1621
1663
  return;
1622
1664
  }
1623
- reject(new Error(`Intercom broker exited before startup with code ${code ?? "unknown"}
1624
- ${describeBrokerLog()}`));
1665
+ const exitedBeforeStartup = () => new Error(`Intercom broker exited before startup with code ${code ?? "unknown"}
1666
+ ${describeBrokerLog()}`);
1667
+ if (code === 0) {
1668
+ checkSocketConnectable().then((answering) => answering ? resolve() : reject(exitedBeforeStartup()));
1669
+ return;
1670
+ }
1671
+ reject(exitedBeforeStartup());
1625
1672
  };
1626
1673
  child.once("error", onError);
1627
1674
  child.once("exit", onExit);
1628
- waitForBroker().then(() => {
1675
+ waitForBroker(readyTimeoutMs).then(() => {
1629
1676
  cleanup();
1630
1677
  resolve();
1631
1678
  }, (error) => {
1632
1679
  cleanup();
1680
+ keepLock = launch.kind === "direct" && child.exitCode === null && child.signalCode === null && handSpawnLockToBroker(child.pid, lockOwner);
1633
1681
  reject(toError2(error));
1634
1682
  });
1635
1683
  });
1636
1684
  } finally {
1637
- releaseSpawnLock();
1685
+ if (!keepLock)
1686
+ releaseSpawnLock(lockOwner);
1638
1687
  }
1639
1688
  }
1640
1689
  async function isBrokerRunning() {
@@ -1654,39 +1703,35 @@ async function isBrokerRunning() {
1654
1703
  }
1655
1704
  }
1656
1705
  function checkSocketConnectable() {
1657
- return new Promise((resolve) => {
1658
- const socket = net2.connect(BROKER_SOCKET2);
1659
- const finish = (isConnected) => {
1660
- clearTimeout(timeout);
1661
- socket.off("connect", onConnect);
1662
- socket.off("error", onError);
1663
- resolve(isConnected);
1664
- };
1665
- const onConnect = () => {
1666
- socket.on("error", () => {});
1667
- socket.end();
1668
- finish(true);
1669
- };
1670
- const onError = () => {
1671
- socket.destroy();
1672
- finish(false);
1673
- };
1674
- socket.on("connect", onConnect);
1675
- socket.on("error", onError);
1676
- const timeout = setTimeout(() => {
1677
- socket.destroy();
1678
- finish(false);
1679
- }, 1000);
1680
- });
1706
+ return isSocketAnswering(BROKER_SOCKET2);
1707
+ }
1708
+ function handSpawnLockToBroker(pid, owner) {
1709
+ if (pid === undefined || !ownsSpawnLock(owner))
1710
+ return false;
1711
+ try {
1712
+ appendFileSync(BROKER_SPAWN_LOCK, `${pid}
1713
+ `);
1714
+ return true;
1715
+ } catch {
1716
+ return false;
1717
+ }
1718
+ }
1719
+ function ownsSpawnLock(owner, lockPath = BROKER_SPAWN_LOCK) {
1720
+ try {
1721
+ return readFileSync(lockPath, "utf-8").startsWith(owner);
1722
+ } catch {
1723
+ return false;
1724
+ }
1681
1725
  }
1682
1726
  function acquireSpawnLock() {
1683
1727
  const maxRetries = 5;
1684
1728
  for (let attempt = 0;attempt < maxRetries; attempt++) {
1685
- try {
1686
- writeFileSync(BROKER_SPAWN_LOCK, `${process.pid}
1729
+ const owner = `${process.pid}
1687
1730
  ${Date.now()}
1688
- `, { flag: "wx" });
1689
- return true;
1731
+ `;
1732
+ try {
1733
+ writeFileSync(BROKER_SPAWN_LOCK, owner, { flag: "wx" });
1734
+ return owner;
1690
1735
  } catch (error) {
1691
1736
  if (!(error instanceof Error) || error.code !== "EEXIST") {
1692
1737
  throw error;
@@ -1697,39 +1742,46 @@ ${Date.now()}
1697
1742
  } catch {}
1698
1743
  continue;
1699
1744
  }
1700
- return false;
1745
+ return;
1701
1746
  }
1702
1747
  }
1703
- return false;
1748
+ return;
1704
1749
  }
1705
- function isSpawnLockStale() {
1706
- if (!existsSync(BROKER_SPAWN_LOCK)) {
1750
+ function isProcessAlive(pid) {
1751
+ try {
1752
+ process.kill(pid, 0);
1753
+ return true;
1754
+ } catch (error) {
1755
+ return error.code === "EPERM";
1756
+ }
1757
+ }
1758
+ function isSpawnLockStale(lockPath = BROKER_SPAWN_LOCK, nowMs = Date.now()) {
1759
+ if (!existsSync(lockPath)) {
1707
1760
  return false;
1708
1761
  }
1709
1762
  try {
1710
- const [pidLine = "", createdAtLine = "0"] = readFileSync(BROKER_SPAWN_LOCK, "utf-8").trim().split(`
1763
+ const [spawnerLine = "", createdAtLine = "", brokerLine = ""] = readFileSync(lockPath, "utf-8").trim().split(`
1711
1764
  `);
1712
- const pid = Number.parseInt(pidLine, 10);
1765
+ const spawnerPid = Number.parseInt(spawnerLine, 10);
1713
1766
  const createdAt = Number.parseInt(createdAtLine, 10);
1714
- const ageMs = Date.now() - createdAt;
1715
- if (Number.isFinite(pid)) {
1716
- try {
1717
- process.kill(pid, 0);
1718
- } catch {
1719
- return true;
1720
- }
1721
- }
1722
- return !Number.isFinite(createdAt) || ageMs > 1e4;
1767
+ const brokerPid = Number.parseInt(brokerLine, 10);
1768
+ if (!Number.isFinite(spawnerPid) || !Number.isFinite(createdAt))
1769
+ return true;
1770
+ if (nowMs - createdAt > BROKER_SPAWN_LOCK_MAX_AGE_MS)
1771
+ return true;
1772
+ return !isProcessAlive(Number.isFinite(brokerPid) ? brokerPid : spawnerPid);
1723
1773
  } catch {
1724
1774
  return true;
1725
1775
  }
1726
1776
  }
1727
- function releaseSpawnLock() {
1777
+ function releaseSpawnLock(owner, lockPath = BROKER_SPAWN_LOCK) {
1778
+ if (!ownsSpawnLock(owner, lockPath))
1779
+ return;
1728
1780
  try {
1729
- unlinkSync(BROKER_SPAWN_LOCK);
1781
+ unlinkSync(lockPath);
1730
1782
  } catch {}
1731
1783
  }
1732
- async function waitForBroker(timeoutMs = 5000) {
1784
+ async function waitForBroker(timeoutMs = BROKER_READY_TIMEOUT_MS) {
1733
1785
  const start = Date.now();
1734
1786
  let interval = BROKER_POLL_INITIAL_INTERVAL_MS;
1735
1787
  while (Date.now() - start < timeoutMs) {
@@ -1742,8 +1794,9 @@ async function waitForBroker(timeoutMs = 5000) {
1742
1794
  throw new Error(`Broker failed to start within timeout
1743
1795
  ${describeBrokerLog()}`);
1744
1796
  }
1745
- var INTERCOM_DIR, EXTENSION_DIR, BROKER_SOCKET2, BROKER_PID, BROKER_SPAWN_LOCK, BROKER_LOG, BROKER_LOG_TAIL_BYTES, BROKER_POLL_INITIAL_INTERVAL_MS = 10, BROKER_POLL_MAX_INTERVAL_MS = 100, INTERNAL_INTERCOM_BROKER_ARG = "--atomic-internal-intercom-broker";
1797
+ var INTERCOM_DIR, EXTENSION_DIR, BROKER_SOCKET2, BROKER_PID, BROKER_SPAWN_LOCK, BROKER_LOG, BROKER_LOG_TAIL_BYTES, BROKER_POLL_INITIAL_INTERVAL_MS = 10, BROKER_POLL_MAX_INTERVAL_MS = 100, BROKER_READY_TIMEOUT_MS = 5000, BROKER_SPAWN_LOCK_MAX_AGE_MS = 60000, INTERNAL_INTERCOM_BROKER_ARG = "--atomic-internal-intercom-broker";
1746
1798
  var init_spawn = __esm(() => {
1799
+ init_socket_liveness();
1747
1800
  init_paths();
1748
1801
  INTERCOM_DIR = getIntercomDirPath();
1749
1802
  EXTENSION_DIR = resolveIntercomPackageRoot(import.meta.url);
@@ -6393,7 +6446,7 @@ __export(exports_index_heavy, {
6393
6446
  default: () => piIntercomExtension
6394
6447
  });
6395
6448
  import { APP_NAME, sessionScopedExtensionState } from "@bastani/atomic";
6396
- import { appendFileSync } from "node:fs";
6449
+ import { appendFileSync as appendFileSync2 } from "node:fs";
6397
6450
  function isPendingStageUndeliverableEvent(value) {
6398
6451
  if (typeof value !== "object" || value === null)
6399
6452
  return false;
@@ -7352,7 +7405,7 @@ var init_index_heavy = __esm(() => {
7352
7405
  process.env.ATOMIC_INTERCOM_HEAVY_IMPORTED = "1";
7353
7406
  }
7354
7407
  if (process.env.ATOMIC_TEST_LAZY_IMPORT_SENTINEL_FILE) {
7355
- appendFileSync(process.env.ATOMIC_TEST_LAZY_IMPORT_SENTINEL_FILE, `intercom
7408
+ appendFileSync2(process.env.ATOMIC_TEST_LAZY_IMPORT_SENTINEL_FILE, `intercom
7356
7409
  `);
7357
7410
  }
7358
7411
  INTERCOM_SESSION_ID_ENV = `${APP_NAME.toUpperCase()}_INTERCOM_SESSION_ID`;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/intercom",
3
- "version": "0.9.28-alpha.4",
3
+ "version": "0.9.28-alpha.5",
4
4
  "private": true,
5
5
  "description": "Atomic extension providing a private coordination channel between parent and child agent sessions. Fork of: https://github.com/nicobailon/pi-intercom",
6
6
  "contributors": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/mcp",
3
- "version": "0.9.28-alpha.4",
3
+ "version": "0.9.28-alpha.5",
4
4
  "private": true,
5
5
  "description": "Atomic's pi-compatible MCP integration for server connections, OAuth, tools, resources, and terminal management.",
6
6
  "contributors": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/subagents",
3
- "version": "0.9.28-alpha.4",
3
+ "version": "0.9.28-alpha.5",
4
4
  "private": true,
5
5
  "description": "Atomic extension for delegating tasks to subagents with parallel execution. Fork of: https://github.com/nicobailon/pi-subagents",
6
6
  "contributors": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/web-access",
3
- "version": "0.9.28-alpha.4",
3
+ "version": "0.9.28-alpha.5",
4
4
  "private": true,
5
5
  "description": "Atomic extension for web search, URL fetching, GitHub repo cloning, PDF/video extraction. Fork of: https://github.com/nicobailon/pi-web-access",
6
6
  "contributors": [
@@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.9.28-alpha.5] - 2026-10-08
10
+
11
+ ### Fixed
12
+
13
+ - Fixed managed PostgreSQL health checks failing a workflow stage on a healthy but busy host: an unanswered check now retries with a short backoff for up to 15 seconds, the connection limit is 3 seconds instead of 1, and the "did not answer a health check in time" diagnostic clears once PostgreSQL answers again ([#3491](https://github.com/bastani-inc/atomic/issues/3491))
14
+
9
15
  ## [0.9.28-alpha.4] - 2026-10-07
10
16
 
11
17
  ### Added
@@ -37,7 +37,7 @@ import {
37
37
  parseFailureDiagnostics,
38
38
  summarizeReviewConvergence,
39
39
  reverify_consolidated_batch
40
- } from "./chunk-p3xmajmj.js";
40
+ } from "./chunk-v4scsq3y.js";
41
41
  import {
42
42
  VERIFICATION_SCALE
43
43
  } from "./chunk-n1910xc4.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getDurableBackend2,
3
3
  getAvailableDurableBackend2
4
- } from "./chunk-p3xmajmj.js";
4
+ } from "./chunk-v4scsq3y.js";
5
5
  export {
6
6
  getAvailableDurableBackend2 as getAvailableDurableBackend,
7
7
  getDurableBackend2 as getDurableBackend
@@ -39,7 +39,7 @@ import {
39
39
  reviewerFailureText,
40
40
  summarizeReviewConvergence,
41
41
  reverify_consolidated_batch
42
- } from "./chunk-p3xmajmj.js";
42
+ } from "./chunk-v4scsq3y.js";
43
43
  import {
44
44
  fold_usage
45
45
  } from "./chunk-tgt0s5e5.js";
@@ -6542,6 +6542,9 @@ function resolveEmbeddedPostgresTarget(host) {
6542
6542
  // dist/builtin/workflows/src/durable/dbos-postgres-health.ts
6543
6543
  var HEALTH_INTERVAL_MS = 5000;
6544
6544
  var RECOVERY_ATTEMPTS = 3;
6545
+ var MONITORING_PROBE_RETRY_WINDOW_MS = 15000;
6546
+ var MONITORING_PROBE_RETRY_INITIAL_MS = 250;
6547
+ var MONITORING_PROBE_RETRY_MAX_MS = 2000;
6545
6548
  function isMonitoringConnectionTimeout(error) {
6546
6549
  if (!(error instanceof Error))
6547
6550
  return false;
@@ -6569,6 +6572,7 @@ class PostgresHealth {
6569
6572
  attempts = 0;
6570
6573
  nextRecoveryAt = 0;
6571
6574
  failure;
6575
+ failureUnanswered = false;
6572
6576
  healthySinceFailure = false;
6573
6577
  revision = 0;
6574
6578
  listeners = new Set;
@@ -6581,10 +6585,11 @@ class PostgresHealth {
6581
6585
  get endpoint() {
6582
6586
  return this.operations.url?.();
6583
6587
  }
6584
- retainFailure(error) {
6588
+ retainFailure(error, unanswered = false) {
6585
6589
  const message = error instanceof Error ? error.message : String(error);
6586
6590
  const safe = redactedDatabaseMessage(message, this.endpoint);
6587
6591
  this.failure = new Error(safe);
6592
+ this.failureUnanswered = unanswered;
6588
6593
  this.healthySinceFailure = false;
6589
6594
  }
6590
6595
  dependencyFailure(message) {
@@ -6612,7 +6617,7 @@ class PostgresHealth {
6612
6617
  await this.operations.validate?.(client);
6613
6618
  }
6614
6619
  } catch (error) {
6615
- this.retainFailure(error);
6620
+ this.retainFailure(error, isQueryReadTimeout(error));
6616
6621
  if (!isQueryReadTimeout(error)) {
6617
6622
  this.invalidate();
6618
6623
  if (this.endpoint === undefined)
@@ -6650,19 +6655,39 @@ class PostgresHealth {
6650
6655
  }
6651
6656
  async probe() {
6652
6657
  const revision = this.revision;
6658
+ const now = this.operations.now ?? Date.now;
6659
+ const wait = this.operations.wait ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
6653
6660
  let identity;
6654
6661
  try {
6655
6662
  identity = await this.operations.probe();
6656
6663
  } catch (error) {
6657
6664
  if (!(isMonitoringConnectionFailure(error) || isQueryReadTimeout(error)) || this.stopped)
6658
6665
  throw error;
6659
- try {
6660
- identity = await this.operations.probe();
6661
- } catch (retryError) {
6662
- if (isMonitoringConnectionTimeout(retryError) || !isMonitoringConnectionFailure(retryError))
6663
- throw retryError;
6664
- this.retainFailure(retryError);
6665
- return;
6666
+ const deadline = now() + MONITORING_PROBE_RETRY_WINDOW_MS;
6667
+ let delay = MONITORING_PROBE_RETRY_INITIAL_MS;
6668
+ let failure = error;
6669
+ for (;; ) {
6670
+ if (isMonitoringConnectionTimeout(failure) || isQueryReadTimeout(failure)) {
6671
+ if (now() >= deadline)
6672
+ throw failure;
6673
+ await wait(delay);
6674
+ delay = Math.min(delay * 2, MONITORING_PROBE_RETRY_MAX_MS);
6675
+ if (this.stopped)
6676
+ throw failure;
6677
+ }
6678
+ try {
6679
+ identity = await this.operations.probe();
6680
+ break;
6681
+ } catch (retryError) {
6682
+ if (isMonitoringConnectionTimeout(retryError) || isQueryReadTimeout(retryError)) {
6683
+ failure = retryError;
6684
+ continue;
6685
+ }
6686
+ if (!isMonitoringConnectionFailure(retryError))
6687
+ throw retryError;
6688
+ this.retainFailure(retryError);
6689
+ return;
6690
+ }
6666
6691
  }
6667
6692
  }
6668
6693
  if (revision !== this.revision)
@@ -6677,6 +6702,8 @@ class PostgresHealth {
6677
6702
  this.attempts = 0;
6678
6703
  this.nextRecoveryAt = 0;
6679
6704
  this.healthySinceFailure = true;
6705
+ if (this.failureUnanswered)
6706
+ this.failure = undefined;
6680
6707
  return identity.url;
6681
6708
  }
6682
6709
  async refresh() {
@@ -6686,7 +6713,7 @@ class PostgresHealth {
6686
6713
  return ready;
6687
6714
  } catch (error) {
6688
6715
  if (isQueryReadTimeout(error) || isMonitoringConnectionTimeout(error)) {
6689
- this.retainFailure(new Error("Managed PostgreSQL did not answer a health check in time."));
6716
+ this.retainFailure(new Error("Managed PostgreSQL did not answer a health check in time."), true);
6690
6717
  throw this.dependencyFailure("Managed PostgreSQL did not answer a health check in time.");
6691
6718
  }
6692
6719
  this.retainFailure(error);
@@ -6954,6 +6981,7 @@ var POSTGRES_IDENTITY_SQL = `SELECT current_setting('data_directory') AS data_di
6954
6981
  system_identifier::text, current_setting('server_version') AS server_version FROM pg_control_system()`;
6955
6982
  var POSTGRES_TIMEZONE_SQL = "SELECT set_config('timezone_abbreviations', 'Default', true)";
6956
6983
  var POSTGRES_HEALTH_QUERY_TIMEOUT_MS = 3000;
6984
+ var POSTGRES_HEALTH_CONNECT_TIMEOUT_MS = 3000;
6957
6985
  async function probePostgresTimezoneData(port) {
6958
6986
  const client = new Client({
6959
6987
  host: "127.0.0.1",
@@ -6962,7 +6990,7 @@ async function probePostgresTimezoneData(port) {
6962
6990
  password: "atomic",
6963
6991
  database: "postgres",
6964
6992
  ssl: false,
6965
- connectionTimeoutMillis: 1000,
6993
+ connectionTimeoutMillis: POSTGRES_HEALTH_CONNECT_TIMEOUT_MS,
6966
6994
  query_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS,
6967
6995
  statement_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS
6968
6996
  });
@@ -6982,7 +7010,7 @@ async function probePostgresIdentity(port) {
6982
7010
  password: "atomic",
6983
7011
  database: "postgres",
6984
7012
  ssl: false,
6985
- connectionTimeoutMillis: 1000,
7013
+ connectionTimeoutMillis: POSTGRES_HEALTH_CONNECT_TIMEOUT_MS,
6986
7014
  query_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS,
6987
7015
  statement_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS
6988
7016
  });
@@ -9894,7 +9922,7 @@ function createPendingStageDeliveryStoreMethods(context) {
9894
9922
  const run = context.findRun(input.runId);
9895
9923
  if (run === undefined)
9896
9924
  return;
9897
- const { getAvailableDurableBackend } = await import("./chunk-p6jagvyf.js");
9925
+ const { getAvailableDurableBackend } = await import("./chunk-bnz4knhy.js");
9898
9926
  const availableBackend = getAvailableDurableBackend();
9899
9927
  const backend = availableBackend === undefined ? undefined : durableBackendForRun(availableBackend, context.state.runs, input.runId);
9900
9928
  const receipt = await backend?.readSettledPendingStageMessage?.(input.runId, input.message.id);
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  goal_default
3
- } from "./chunk-aqv8ny38.js";
4
- import"./chunk-p3xmajmj.js";
3
+ } from "./chunk-9ywkdsa9.js";
4
+ import"./chunk-v4scsq3y.js";
5
5
  import"./chunk-2377r57g.js";
6
6
  import"./chunk-z0d03ktm.js";
7
7
  import"./chunk-n1910xc4.js";
@@ -16,8 +16,8 @@ import {
16
16
  } from "./chunk-kb7s3gx2.js";
17
17
  import {
18
18
  goal_default
19
- } from "./chunk-aqv8ny38.js";
20
- import"./chunk-p3xmajmj.js";
19
+ } from "./chunk-9ywkdsa9.js";
20
+ import"./chunk-v4scsq3y.js";
21
21
  import"./chunk-z0d03ktm.js";
22
22
  import {
23
23
  open_claude_design_default
@@ -27,7 +27,7 @@ import {
27
27
  } from "./chunk-94f8zfz1.js";
28
28
  import {
29
29
  ralph_default
30
- } from "./chunk-br4ac9a3.js";
30
+ } from "./chunk-dx5sjaxe.js";
31
31
  import {
32
32
  tournament_default
33
33
  } from "./chunk-wf876n16.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ralph_default
3
- } from "./chunk-br4ac9a3.js";
4
- import"./chunk-p3xmajmj.js";
3
+ } from "./chunk-dx5sjaxe.js";
4
+ import"./chunk-v4scsq3y.js";
5
5
  import"./chunk-2377r57g.js";
6
6
  import"./chunk-z0d03ktm.js";
7
7
  import"./chunk-n1910xc4.js";
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/workflows",
3
- "version": "0.9.28-alpha.4",
3
+ "version": "0.9.28-alpha.5",
4
4
  "private": true,
5
5
  "description": "Atomic extension for multi-stage workflow authoring and execution.",
6
6
  "contributors": [