@bastani/atomic 0.9.28-alpha.4 → 0.9.28

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 (128) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +13 -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/CHANGELOG.md +6 -0
  12. package/dist/builtin/mcp/package.json +1 -1
  13. package/dist/builtin/subagents/CHANGELOG.md +6 -0
  14. package/dist/builtin/subagents/package.json +1 -1
  15. package/dist/builtin/web-access/package.json +1 -1
  16. package/dist/builtin/workflows/CHANGELOG.md +41 -0
  17. package/dist/builtin/workflows/builtin/{chunk-aqv8ny38.js → chunk-9ywkdsa9.js} +1 -1
  18. package/dist/builtin/workflows/builtin/{chunk-p6jagvyf.js → chunk-bnz4knhy.js} +1 -1
  19. package/dist/builtin/workflows/builtin/{chunk-br4ac9a3.js → chunk-dx5sjaxe.js} +1 -1
  20. package/dist/builtin/workflows/builtin/{chunk-p3xmajmj.js → chunk-v4scsq3y.js} +41 -13
  21. package/dist/builtin/workflows/builtin/goal.js +2 -2
  22. package/dist/builtin/workflows/builtin/index.js +3 -3
  23. package/dist/builtin/workflows/builtin/ralph.js +2 -2
  24. package/dist/builtin/workflows/package.json +1 -1
  25. package/dist/builtin/workflows/src/extension/index.bundle.mjs +38 -14
  26. package/dist/builtin/workflows/src/index.js +38 -14
  27. package/dist/cli/startup-ui.d.ts +3 -2
  28. package/dist/cli/startup-ui.d.ts.map +1 -1
  29. package/dist/cli/startup-ui.js +19 -4
  30. package/dist/cli/startup-ui.js.map +1 -1
  31. package/dist/core/agent-session-runtime.d.ts +5 -1
  32. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  33. package/dist/core/agent-session-runtime.js +13 -9
  34. package/dist/core/agent-session-runtime.js.map +1 -1
  35. package/dist/core/extensions/session-events.d.ts +2 -0
  36. package/dist/core/extensions/session-events.d.ts.map +1 -1
  37. package/dist/core/extensions/session-events.js.map +1 -1
  38. package/dist/core/provider-alias.d.ts.map +1 -1
  39. package/dist/core/provider-alias.js +8 -0
  40. package/dist/core/provider-alias.js.map +1 -1
  41. package/dist/core/provider-composer-internal.d.ts.map +1 -1
  42. package/dist/core/provider-composer-internal.js +6 -3
  43. package/dist/core/provider-composer-internal.js.map +1 -1
  44. package/dist/core/resource-loader-reload.d.ts.map +1 -1
  45. package/dist/core/resource-loader-reload.js +1 -0
  46. package/dist/core/resource-loader-reload.js.map +1 -1
  47. package/dist/core/resource-loader-types.d.ts +1 -0
  48. package/dist/core/resource-loader-types.d.ts.map +1 -1
  49. package/dist/core/resource-loader-types.js.map +1 -1
  50. package/dist/extensions/herdr/index.d.ts.map +1 -1
  51. package/dist/extensions/herdr/index.js +20 -2
  52. package/dist/extensions/herdr/index.js.map +1 -1
  53. package/dist/extensions/herdr/pane-owner.d.ts +7 -0
  54. package/dist/extensions/herdr/pane-owner.d.ts.map +1 -1
  55. package/dist/extensions/herdr/pane-owner.js +53 -11
  56. package/dist/extensions/herdr/pane-owner.js.map +1 -1
  57. package/dist/main-deferred-startup.d.ts +8 -0
  58. package/dist/main-deferred-startup.d.ts.map +1 -1
  59. package/dist/main-deferred-startup.js +6 -0
  60. package/dist/main-deferred-startup.js.map +1 -1
  61. package/dist/main.d.ts.map +1 -1
  62. package/dist/main.js +11 -3
  63. package/dist/main.js.map +1 -1
  64. package/dist/modes/interactive/interactive-auth-routing.js +2 -2
  65. package/dist/modes/interactive/interactive-auth-routing.js.map +1 -1
  66. package/dist/modes/interactive/interactive-extension-dialogs.js +8 -0
  67. package/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  68. package/dist/modes/interactive/interactive-mode-base.d.ts +1 -0
  69. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  70. package/dist/modes/interactive/interactive-mode-base.js +1 -0
  71. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  72. package/dist/modes/interactive/interactive-mode-helpers.js +1 -1
  73. package/dist/modes/interactive/interactive-mode-helpers.js.map +1 -1
  74. package/dist/modes/interactive/interactive-mode-types.d.ts +1 -0
  75. package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
  76. package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
  77. package/dist/modes/interactive/interactive-process-lifecycle.js +1 -1
  78. package/dist/modes/interactive/interactive-process-lifecycle.js.map +1 -1
  79. package/dist/modes/interactive/interactive-startup-trust.d.ts +6 -0
  80. package/dist/modes/interactive/interactive-startup-trust.d.ts.map +1 -0
  81. package/dist/modes/interactive/interactive-startup-trust.js +15 -0
  82. package/dist/modes/interactive/interactive-startup-trust.js.map +1 -0
  83. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  84. package/dist/modes/interactive/interactive-startup.js +3 -0
  85. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  86. package/dist/modes/interactive-engine/engine-child-liveness.d.ts +1 -0
  87. package/dist/modes/interactive-engine/engine-child-liveness.d.ts.map +1 -1
  88. package/dist/modes/interactive-engine/engine-child-liveness.js +15 -1
  89. package/dist/modes/interactive-engine/engine-child-liveness.js.map +1 -1
  90. package/dist/modes/interactive-engine/engine-monitor.d.ts +4 -0
  91. package/dist/modes/interactive-engine/engine-monitor.d.ts.map +1 -1
  92. package/dist/modes/interactive-engine/engine-monitor.js +17 -0
  93. package/dist/modes/interactive-engine/engine-monitor.js.map +1 -1
  94. package/dist/modes/interactive-engine/engine-quit-intent.d.ts +16 -0
  95. package/dist/modes/interactive-engine/engine-quit-intent.d.ts.map +1 -0
  96. package/dist/modes/interactive-engine/engine-quit-intent.js +27 -0
  97. package/dist/modes/interactive-engine/engine-quit-intent.js.map +1 -0
  98. package/dist/modes/interactive-engine/extension-ui-bridge.d.ts +1 -0
  99. package/dist/modes/interactive-engine/extension-ui-bridge.d.ts.map +1 -1
  100. package/dist/modes/interactive-engine/extension-ui-bridge.js +5 -0
  101. package/dist/modes/interactive-engine/extension-ui-bridge.js.map +1 -1
  102. package/dist/modes/interactive-engine/isolated-runtime.d.ts +4 -1
  103. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
  104. package/dist/modes/interactive-engine/isolated-runtime.js +19 -2
  105. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  106. package/dist/modes/interactive-engine/protocol.d.ts +18 -1
  107. package/dist/modes/interactive-engine/protocol.d.ts.map +1 -1
  108. package/dist/modes/interactive-engine/protocol.js +6 -0
  109. package/dist/modes/interactive-engine/protocol.js.map +1 -1
  110. package/dist/modes/rpc/rpc-client.d.ts +11 -0
  111. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  112. package/dist/modes/rpc/rpc-client.js +42 -0
  113. package/dist/modes/rpc/rpc-client.js.map +1 -1
  114. package/dist/modes/rpc/rpc-input-scheduler.js +2 -2
  115. package/dist/modes/rpc/rpc-input-scheduler.js.map +1 -1
  116. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  117. package/dist/modes/rpc/rpc-mode.js +23 -6
  118. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  119. package/dist/modes/rpc/rpc-provider-auth.js +1 -1
  120. package/dist/modes/rpc/rpc-provider-auth.js.map +1 -1
  121. package/docs/extensions/events.md +3 -0
  122. package/docs/herdr.md +11 -2
  123. package/docs/models.md +1 -1
  124. package/docs/providers.md +2 -0
  125. package/docs/sdk.md +1 -1
  126. package/docs/settings.md +1 -1
  127. package/npm-shrinkwrap.json +32 -32
  128. package/package.json +3 -3
@@ -6,6 +6,47 @@ 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] - 2026-10-08
10
+
11
+ ### Added
12
+
13
+ - Added a Claude Haiku 5.5 prompt-engineering guide based on Anthropic's model-specific guidance, covering effort, search grounding, JSON/tool interactions, completion, verification, and refusal handling.
14
+ - Added `createAgentSessionAdapter(baseOptions?)`, which builds the default workflow stage-session adapter with `createAgentSession` options shared by every stage ([#3472](https://github.com/bastani-inc/atomic/issues/3472)).
15
+
16
+ ### Changed
17
+
18
+ - Updated the bundled Impeccable skill to 4.5.0 with engine 0.1.11, adding the `generate` playbook, component-review guidance, and reading, operating, and persuasion design modes. Atomic's telemetry and update-check defaults remain off.
19
+ - Changed the `resumeInFlight` default from `"ask"` to `"never"`. Atomic no longer prompts at startup to resume interrupted durable workflows; resume them with `/workflow resume`, or set `resumeInFlight` to `"ask"` or `"auto"` in the workflow config to restore startup recovery.
20
+
21
+ ### Fixed
22
+
23
+ - 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))
24
+ - Fixed Atomic hanging at startup, never accepting input, when the current directory had interrupted durable workflows and `resumeInFlight` was `ask`. Startup no longer waits for workflow recovery; the "Resume interrupted workflows?" prompt now appears after the session is ready.
25
+ - Fixed startup recovery and SDK crash recovery skipping interrupted workflows when the project directory was reached through a symlink, such as `/tmp` or `/var` on macOS.
26
+ - Fixed long workflow runs retaining a full metadata snapshot for every checkpoint and message update. Atomic now compacts superseded snapshots, removes their duplicate input payloads, and bounds settled delivery state across root and child runs, including failed-stage sticky receipts, while preserving resume and message deduplication ([#3467](https://github.com/bastani-inc/atomic/issues/3467)).
27
+ - Fixed archived sticky message receipts being ignored when a failed stage retries delivery without an explicit recipient or through live Intercom transport. Retry forwarding and confirmation deduplication survive cold resume, while a new recipient session can still receive the message ([#3467](https://github.com/bastani-inc/atomic/issues/3467)).
28
+ - Fixed sticky messages delivered as pre-start context being forwarded again to the same live session, including after receipt archival and cold resume. Concurrent confirmations remain deduplicated when a stage finishes before they are saved, while a new recipient session can still receive the message ([#3467](https://github.com/bastani-inc/atomic/issues/3467)).
29
+ - Fixed interrupted sticky receipt saves losing delivery counts after retry or cold resume and incorrectly reporting delivered messages as undeliverable ([#3467](https://github.com/bastani-inc/atomic/issues/3467)).
30
+ - Fixed Goal infrastructure failures incorrectly ending the goal as `needs_human`. The ledger now stays `active`, and direct resume in the same session retries the interrupted stage and completes its turn without quitting Atomic. Malformed reviewer output, including exhausted schema corrections, still requires human attention. Older synthetic failure verdicts with identifiable database/checkpoint diagnostics are also recoverable; ambiguous old failures remain unchanged ([#3466](https://github.com/bastani-inc/atomic/issues/3466)).
31
+ - Fixed Goal treating exhausted reviewer corrections for invalid `structured_output` inputs, including whitespace-only instructions and empty named state, as resumable infrastructure failures instead of `needs_human` ([#3466](https://github.com/bastani-inc/atomic/issues/3466)).
32
+ - Fixed Goal reviewer corrections hiding an earlier provider failure when a later `structured_output` call has invalid inputs. If no correction succeeds, the goal remains resumable instead of becoming `needs_human` ([#3466](https://github.com/bastani-inc/atomic/issues/3466)).
33
+ - Fixed `run()` failing at the first `ctx.task` or `ctx.stage` with "prompt adapter not configured" when `opts.adapters` was omitted. Stages now default to in-process `createAgentSession` sessions with in-memory session managers ([#3472](https://github.com/bastani-inc/atomic/issues/3472)).
34
+ - Fixed `resumeInFlight` having no effect at startup. `auto` now resumes eligible interrupted durable workflows, `ask` requests confirmation when a UI is available, and `never` leaves them for `/workflow resume`. Paused, quit, blocked, failed, awaiting-input, and live-owned runs are not automatically restarted ([#3468](https://github.com/bastani-inc/atomic/issues/3468)).
35
+ - Fixed startup recovery of agent-owned workflows retaining the previous session's ownership. Safely recovered runs now allow the current session's agent to inspect and control them ([#3468](https://github.com/bastani-inc/atomic/issues/3468)).
36
+ - Fixed recovered workflows disconnecting Intercom with pending-stage authorization errors when workflow extension modules load more than once ([#3468](https://github.com/bastani-inc/atomic/issues/3468)).
37
+ - Fixed recovered agent stages failing with a stale extension context after accepted startup recovery. Committed host generations hand off synchronously and retired Store observers detach before authority revocation, independently of shutdown handler order ([#3468](https://github.com/bastani-inc/atomic/issues/3468)).
38
+ - Fixed startup recovery offering or restarting another project's workflows when projects share a database. Automatic recovery now requires the original invocation directory to match the current working directory; cross-project recovery remains available through `/workflow resume` ([#3468](https://github.com/bastani-inc/atomic/issues/3468)).
39
+ - Fixed durable-workflow shutdown returning before ownership and protected SQL connections terminated, including pending SQL acquisitions, so immediate recovery no longer races a stale executor lock ([#3489](https://github.com/bastani-inc/atomic/issues/3489)).
40
+ - Attached stage chats honor configured transcript jump shortcuts, defaulting to Ctrl+Home and Ctrl+End, without intercepting the editor's Home and End keys.
41
+ - Fixed slow workflow discovery for imports of `@bastani/atomic`, `@bastani/pi-ai`, and `@bastani/pi-ai/providers/all` by sharing the running CLI's modules instead of loading them again for each workflow file. The host's versions take precedence over project copies for these three exact specifiers. These imports no longer need project-local packages in standalone-binary installs; workflow files and relative imports still refresh on reload ([#3454](https://github.com/bastani-inc/atomic/issues/3454)).
42
+ - Fixed workflow stage questions in one process hosting several SDK sessions reaching the wrong session. A stage's `ask_user_question`, readiness question, or `ctx.ui.custom` prompt could go to whichever sibling session started last, so its own `HostInput.questionnaire` was never called and the stage stayed `awaiting_input`. Each session now keeps its own workflow store, stage UI broker, and run registries ([#3456](https://github.com/bastani-inc/atomic/issues/3456)).
43
+
44
+ ## [0.9.28-alpha.5] - 2026-10-08
45
+
46
+ ### Fixed
47
+
48
+ - 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))
49
+
9
50
  ## [0.9.28-alpha.4] - 2026-10-07
10
51
 
11
52
  ### 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",
4
4
  "private": true,
5
5
  "description": "Atomic extension for multi-stage workflow authoring and execution.",
6
6
  "contributors": [
@@ -38352,6 +38352,7 @@ class PostgresHealth {
38352
38352
  attempts = 0;
38353
38353
  nextRecoveryAt = 0;
38354
38354
  failure;
38355
+ failureUnanswered = false;
38355
38356
  healthySinceFailure = false;
38356
38357
  revision = 0;
38357
38358
  listeners = new Set;
@@ -38364,10 +38365,11 @@ class PostgresHealth {
38364
38365
  get endpoint() {
38365
38366
  return this.operations.url?.();
38366
38367
  }
38367
- retainFailure(error) {
38368
+ retainFailure(error, unanswered = false) {
38368
38369
  const message = error instanceof Error ? error.message : String(error);
38369
38370
  const safe = redactedDatabaseMessage(message, this.endpoint);
38370
38371
  this.failure = new Error(safe);
38372
+ this.failureUnanswered = unanswered;
38371
38373
  this.healthySinceFailure = false;
38372
38374
  }
38373
38375
  dependencyFailure(message) {
@@ -38395,7 +38397,7 @@ class PostgresHealth {
38395
38397
  await this.operations.validate?.(client);
38396
38398
  }
38397
38399
  } catch (error) {
38398
- this.retainFailure(error);
38400
+ this.retainFailure(error, isQueryReadTimeout(error));
38399
38401
  if (!isQueryReadTimeout(error)) {
38400
38402
  this.invalidate();
38401
38403
  if (this.endpoint === undefined)
@@ -38433,19 +38435,39 @@ class PostgresHealth {
38433
38435
  }
38434
38436
  async probe() {
38435
38437
  const revision = this.revision;
38438
+ const now = this.operations.now ?? Date.now;
38439
+ const wait = this.operations.wait ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
38436
38440
  let identity;
38437
38441
  try {
38438
38442
  identity = await this.operations.probe();
38439
38443
  } catch (error) {
38440
38444
  if (!(isMonitoringConnectionFailure(error) || isQueryReadTimeout(error)) || this.stopped)
38441
38445
  throw error;
38442
- try {
38443
- identity = await this.operations.probe();
38444
- } catch (retryError) {
38445
- if (isMonitoringConnectionTimeout(retryError) || !isMonitoringConnectionFailure(retryError))
38446
- throw retryError;
38447
- this.retainFailure(retryError);
38448
- return;
38446
+ const deadline = now() + MONITORING_PROBE_RETRY_WINDOW_MS;
38447
+ let delay = MONITORING_PROBE_RETRY_INITIAL_MS;
38448
+ let failure = error;
38449
+ for (;; ) {
38450
+ if (isMonitoringConnectionTimeout(failure) || isQueryReadTimeout(failure)) {
38451
+ if (now() >= deadline)
38452
+ throw failure;
38453
+ await wait(delay);
38454
+ delay = Math.min(delay * 2, MONITORING_PROBE_RETRY_MAX_MS);
38455
+ if (this.stopped)
38456
+ throw failure;
38457
+ }
38458
+ try {
38459
+ identity = await this.operations.probe();
38460
+ break;
38461
+ } catch (retryError) {
38462
+ if (isMonitoringConnectionTimeout(retryError) || isQueryReadTimeout(retryError)) {
38463
+ failure = retryError;
38464
+ continue;
38465
+ }
38466
+ if (!isMonitoringConnectionFailure(retryError))
38467
+ throw retryError;
38468
+ this.retainFailure(retryError);
38469
+ return;
38470
+ }
38449
38471
  }
38450
38472
  }
38451
38473
  if (revision !== this.revision)
@@ -38460,6 +38482,8 @@ class PostgresHealth {
38460
38482
  this.attempts = 0;
38461
38483
  this.nextRecoveryAt = 0;
38462
38484
  this.healthySinceFailure = true;
38485
+ if (this.failureUnanswered)
38486
+ this.failure = undefined;
38463
38487
  return identity.url;
38464
38488
  }
38465
38489
  async refresh() {
@@ -38469,7 +38493,7 @@ class PostgresHealth {
38469
38493
  return ready;
38470
38494
  } catch (error) {
38471
38495
  if (isQueryReadTimeout(error) || isMonitoringConnectionTimeout(error)) {
38472
- this.retainFailure(new Error("Managed PostgreSQL did not answer a health check in time."));
38496
+ this.retainFailure(new Error("Managed PostgreSQL did not answer a health check in time."), true);
38473
38497
  throw this.dependencyFailure("Managed PostgreSQL did not answer a health check in time.");
38474
38498
  }
38475
38499
  this.retainFailure(error);
@@ -38504,7 +38528,7 @@ class PostgresHealth {
38504
38528
  throw this.dependencyFailure("Managed Postgres is unavailable after bounded recovery. Preserve its data and ownership records.");
38505
38529
  }
38506
38530
  }
38507
- var HEALTH_INTERVAL_MS = 5000, RECOVERY_ATTEMPTS = 3;
38531
+ var HEALTH_INTERVAL_MS = 5000, RECOVERY_ATTEMPTS = 3, MONITORING_PROBE_RETRY_WINDOW_MS = 15000, MONITORING_PROBE_RETRY_INITIAL_MS = 250, MONITORING_PROBE_RETRY_MAX_MS = 2000;
38508
38532
  var init_dbos_postgres_health = __esm(() => {
38509
38533
  init_dbos_admission();
38510
38534
  });
@@ -38742,7 +38766,7 @@ async function probePostgresTimezoneData(port) {
38742
38766
  password: "atomic",
38743
38767
  database: "postgres",
38744
38768
  ssl: false,
38745
- connectionTimeoutMillis: 1000,
38769
+ connectionTimeoutMillis: POSTGRES_HEALTH_CONNECT_TIMEOUT_MS,
38746
38770
  query_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS,
38747
38771
  statement_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS
38748
38772
  });
@@ -38762,7 +38786,7 @@ async function probePostgresIdentity(port) {
38762
38786
  password: "atomic",
38763
38787
  database: "postgres",
38764
38788
  ssl: false,
38765
- connectionTimeoutMillis: 1000,
38789
+ connectionTimeoutMillis: POSTGRES_HEALTH_CONNECT_TIMEOUT_MS,
38766
38790
  query_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS,
38767
38791
  statement_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS
38768
38792
  });
@@ -38838,7 +38862,7 @@ async function verifyPostgresIdentity(metadata, port, expectedPid, probe = probe
38838
38862
  var POSTGRES_IDENTITY_SQL = `SELECT current_setting('data_directory') AS data_dir,
38839
38863
  inet_server_port() AS port, host(inet_server_addr()) AS host,
38840
38864
  split_part(pg_read_file('postmaster.pid'), E'\\n', 3) AS started,
38841
- system_identifier::text, current_setting('server_version') AS server_version FROM pg_control_system()`, POSTGRES_TIMEZONE_SQL = "SELECT set_config('timezone_abbreviations', 'Default', true)", POSTGRES_HEALTH_QUERY_TIMEOUT_MS = 3000;
38865
+ system_identifier::text, current_setting('server_version') AS server_version FROM pg_control_system()`, POSTGRES_TIMEZONE_SQL = "SELECT set_config('timezone_abbreviations', 'Default', true)", POSTGRES_HEALTH_QUERY_TIMEOUT_MS = 3000, POSTGRES_HEALTH_CONNECT_TIMEOUT_MS = 3000;
38842
38866
  var init_dbos_postgres_identity = __esm(() => {
38843
38867
  init_esm();
38844
38868
  init_dbos_postgres_health();
@@ -36837,6 +36837,7 @@ class PostgresHealth {
36837
36837
  attempts = 0;
36838
36838
  nextRecoveryAt = 0;
36839
36839
  failure;
36840
+ failureUnanswered = false;
36840
36841
  healthySinceFailure = false;
36841
36842
  revision = 0;
36842
36843
  listeners = new Set;
@@ -36849,10 +36850,11 @@ class PostgresHealth {
36849
36850
  get endpoint() {
36850
36851
  return this.operations.url?.();
36851
36852
  }
36852
- retainFailure(error) {
36853
+ retainFailure(error, unanswered = false) {
36853
36854
  const message = error instanceof Error ? error.message : String(error);
36854
36855
  const safe = redactedDatabaseMessage(message, this.endpoint);
36855
36856
  this.failure = new Error(safe);
36857
+ this.failureUnanswered = unanswered;
36856
36858
  this.healthySinceFailure = false;
36857
36859
  }
36858
36860
  dependencyFailure(message) {
@@ -36880,7 +36882,7 @@ class PostgresHealth {
36880
36882
  await this.operations.validate?.(client);
36881
36883
  }
36882
36884
  } catch (error) {
36883
- this.retainFailure(error);
36885
+ this.retainFailure(error, isQueryReadTimeout(error));
36884
36886
  if (!isQueryReadTimeout(error)) {
36885
36887
  this.invalidate();
36886
36888
  if (this.endpoint === undefined)
@@ -36918,19 +36920,39 @@ class PostgresHealth {
36918
36920
  }
36919
36921
  async probe() {
36920
36922
  const revision = this.revision;
36923
+ const now = this.operations.now ?? Date.now;
36924
+ const wait = this.operations.wait ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
36921
36925
  let identity;
36922
36926
  try {
36923
36927
  identity = await this.operations.probe();
36924
36928
  } catch (error) {
36925
36929
  if (!(isMonitoringConnectionFailure(error) || isQueryReadTimeout(error)) || this.stopped)
36926
36930
  throw error;
36927
- try {
36928
- identity = await this.operations.probe();
36929
- } catch (retryError) {
36930
- if (isMonitoringConnectionTimeout(retryError) || !isMonitoringConnectionFailure(retryError))
36931
- throw retryError;
36932
- this.retainFailure(retryError);
36933
- return;
36931
+ const deadline = now() + MONITORING_PROBE_RETRY_WINDOW_MS;
36932
+ let delay = MONITORING_PROBE_RETRY_INITIAL_MS;
36933
+ let failure = error;
36934
+ for (;; ) {
36935
+ if (isMonitoringConnectionTimeout(failure) || isQueryReadTimeout(failure)) {
36936
+ if (now() >= deadline)
36937
+ throw failure;
36938
+ await wait(delay);
36939
+ delay = Math.min(delay * 2, MONITORING_PROBE_RETRY_MAX_MS);
36940
+ if (this.stopped)
36941
+ throw failure;
36942
+ }
36943
+ try {
36944
+ identity = await this.operations.probe();
36945
+ break;
36946
+ } catch (retryError) {
36947
+ if (isMonitoringConnectionTimeout(retryError) || isQueryReadTimeout(retryError)) {
36948
+ failure = retryError;
36949
+ continue;
36950
+ }
36951
+ if (!isMonitoringConnectionFailure(retryError))
36952
+ throw retryError;
36953
+ this.retainFailure(retryError);
36954
+ return;
36955
+ }
36934
36956
  }
36935
36957
  }
36936
36958
  if (revision !== this.revision)
@@ -36945,6 +36967,8 @@ class PostgresHealth {
36945
36967
  this.attempts = 0;
36946
36968
  this.nextRecoveryAt = 0;
36947
36969
  this.healthySinceFailure = true;
36970
+ if (this.failureUnanswered)
36971
+ this.failure = undefined;
36948
36972
  return identity.url;
36949
36973
  }
36950
36974
  async refresh() {
@@ -36954,7 +36978,7 @@ class PostgresHealth {
36954
36978
  return ready;
36955
36979
  } catch (error) {
36956
36980
  if (isQueryReadTimeout(error) || isMonitoringConnectionTimeout(error)) {
36957
- this.retainFailure(new Error("Managed PostgreSQL did not answer a health check in time."));
36981
+ this.retainFailure(new Error("Managed PostgreSQL did not answer a health check in time."), true);
36958
36982
  throw this.dependencyFailure("Managed PostgreSQL did not answer a health check in time.");
36959
36983
  }
36960
36984
  this.retainFailure(error);
@@ -36989,7 +37013,7 @@ class PostgresHealth {
36989
37013
  throw this.dependencyFailure("Managed Postgres is unavailable after bounded recovery. Preserve its data and ownership records.");
36990
37014
  }
36991
37015
  }
36992
- var HEALTH_INTERVAL_MS = 5000, RECOVERY_ATTEMPTS = 3;
37016
+ var HEALTH_INTERVAL_MS = 5000, RECOVERY_ATTEMPTS = 3, MONITORING_PROBE_RETRY_WINDOW_MS = 15000, MONITORING_PROBE_RETRY_INITIAL_MS = 250, MONITORING_PROBE_RETRY_MAX_MS = 2000;
36993
37017
  var init_dbos_postgres_health = __esm(() => {
36994
37018
  init_dbos_admission();
36995
37019
  });
@@ -37227,7 +37251,7 @@ async function probePostgresTimezoneData(port) {
37227
37251
  password: "atomic",
37228
37252
  database: "postgres",
37229
37253
  ssl: false,
37230
- connectionTimeoutMillis: 1000,
37254
+ connectionTimeoutMillis: POSTGRES_HEALTH_CONNECT_TIMEOUT_MS,
37231
37255
  query_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS,
37232
37256
  statement_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS
37233
37257
  });
@@ -37247,7 +37271,7 @@ async function probePostgresIdentity(port) {
37247
37271
  password: "atomic",
37248
37272
  database: "postgres",
37249
37273
  ssl: false,
37250
- connectionTimeoutMillis: 1000,
37274
+ connectionTimeoutMillis: POSTGRES_HEALTH_CONNECT_TIMEOUT_MS,
37251
37275
  query_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS,
37252
37276
  statement_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS
37253
37277
  });
@@ -37323,7 +37347,7 @@ async function verifyPostgresIdentity(metadata, port, expectedPid, probe = probe
37323
37347
  var POSTGRES_IDENTITY_SQL = `SELECT current_setting('data_directory') AS data_dir,
37324
37348
  inet_server_port() AS port, host(inet_server_addr()) AS host,
37325
37349
  split_part(pg_read_file('postmaster.pid'), E'\\n', 3) AS started,
37326
- system_identifier::text, current_setting('server_version') AS server_version FROM pg_control_system()`, POSTGRES_TIMEZONE_SQL = "SELECT set_config('timezone_abbreviations', 'Default', true)", POSTGRES_HEALTH_QUERY_TIMEOUT_MS = 3000;
37350
+ system_identifier::text, current_setting('server_version') AS server_version FROM pg_control_system()`, POSTGRES_TIMEZONE_SQL = "SELECT set_config('timezone_abbreviations', 'Default', true)", POSTGRES_HEALTH_QUERY_TIMEOUT_MS = 3000, POSTGRES_HEALTH_CONNECT_TIMEOUT_MS = 3000;
37327
37351
  var init_dbos_postgres_identity = __esm(() => {
37328
37352
  init_esm();
37329
37353
  init_dbos_postgres_health();
@@ -1,4 +1,5 @@
1
1
  import { type TUI } from "@earendil-works/pi-tui";
2
+ import type { ExtensionUIDialogOptions } from "../core/extensions/index.js";
2
3
  import type { SettingsManager } from "../core/settings-manager.ts";
3
4
  import { type TerminalTheme } from "../modes/interactive/theme/theme.js";
4
5
  /**
@@ -13,6 +14,6 @@ export declare function showFirstTimeSetup(settingsManager: SettingsManager): Pr
13
14
  export declare function showStartupSelector<T>(settingsManager: SettingsManager, title: string, options: Array<{
14
15
  label: string;
15
16
  value: T;
16
- }>): Promise<T | undefined>;
17
- export declare function showStartupInput(settingsManager: SettingsManager, title: string, placeholder?: string): Promise<string | undefined>;
17
+ }>, dialogOptions?: ExtensionUIDialogOptions): Promise<T | undefined>;
18
+ export declare function showStartupInput(settingsManager: SettingsManager, title: string, placeholder?: string, dialogOptions?: ExtensionUIDialogOptions): Promise<string | undefined>;
18
19
  //# sourceMappingURL=startup-ui.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"startup-ui.d.ts","sourceRoot":"","sources":["../../src/cli/startup-ui.ts"],"names":[],"mappings":"AACA,OAAO,EAIN,KAAK,GAAG,EAER,MAAM,wBAAwB,CAAC;AAGhC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAOnE,OAAO,EAIN,KAAK,aAAa,EAClB,MAAM,qCAAqC,CAAC;AAiB7C;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAExE;AAED,mGAAmG;AACnG,wBAAgB,uBAAuB,CAAC,YAAY,GAAE,MAA0B,GAAG,OAAO,CAEzF;AAED,wBAAsB,kBAAkB,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCxF;AAED,wBAAsB,mBAAmB,CAAC,CAAC,EAC1C,eAAe,EAAE,eAAe,EAChC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC,GACzC,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CA0BxB;AAED,wBAAsB,gBAAgB,CACrC,eAAe,EAAE,eAAe,EAChC,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA2B7B"}
1
+ {"version":3,"file":"startup-ui.d.ts","sourceRoot":"","sources":["../../src/cli/startup-ui.ts"],"names":[],"mappings":"AACA,OAAO,EAIN,KAAK,GAAG,EAER,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAOnE,OAAO,EAIN,KAAK,aAAa,EAClB,MAAM,qCAAqC,CAAC;AAiB7C;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAExE;AAED,mGAAmG;AACnG,wBAAgB,uBAAuB,CAAC,YAAY,GAAE,MAA0B,GAAG,OAAO,CAEzF;AAED,wBAAsB,kBAAkB,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCxF;AAED,wBAAsB,mBAAmB,CAAC,CAAC,EAC1C,eAAe,EAAE,eAAe,EAChC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC,EAC3C,aAAa,CAAC,EAAE,wBAAwB,GACtC,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAkCxB;AAED,wBAAsB,gBAAgB,CACrC,eAAe,EAAE,eAAe,EAChC,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,EACpB,aAAa,CAAC,EAAE,wBAAwB,GACtC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAkC7B"}
@@ -71,8 +71,12 @@ export async function showFirstTimeSetup(settingsManager) {
71
71
  })();
72
72
  });
73
73
  }
74
- export async function showStartupSelector(settingsManager, title, options) {
74
+ export async function showStartupSelector(settingsManager, title, options, dialogOptions) {
75
75
  return new Promise((resolve) => {
76
+ if (dialogOptions?.signal?.aborted) {
77
+ resolve(undefined);
78
+ return;
79
+ }
76
80
  const ui = createStartupTui(settingsManager);
77
81
  let settled = false;
78
82
  const finish = async (result) => {
@@ -80,18 +84,26 @@ export async function showStartupSelector(settingsManager, title, options) {
80
84
  return;
81
85
  }
82
86
  settled = true;
87
+ dialogOptions?.signal?.removeEventListener("abort", abandon);
88
+ selector.dispose();
83
89
  await clearStartupTui(ui);
84
90
  ui.stop();
85
91
  resolve(result);
86
92
  };
87
- const selector = new ExtensionSelectorComponent(title, options.map((option) => option.label), (option) => void finish(options.find((entry) => entry.label === option)?.value), () => void finish(undefined), { tui: ui });
93
+ const abandon = () => void finish(undefined);
94
+ dialogOptions?.signal?.addEventListener("abort", abandon, { once: true });
95
+ const selector = new ExtensionSelectorComponent(title, options.map((option) => option.label), (option) => void finish(options.find((entry) => entry.label === option)?.value), () => void finish(undefined), { tui: ui, timeout: dialogOptions?.timeout });
88
96
  ui.addChild(selector);
89
97
  ui.setFocus(selector);
90
98
  ui.start();
91
99
  });
92
100
  }
93
- export async function showStartupInput(settingsManager, title, placeholder) {
101
+ export async function showStartupInput(settingsManager, title, placeholder, dialogOptions) {
94
102
  return new Promise((resolve) => {
103
+ if (dialogOptions?.signal?.aborted) {
104
+ resolve(undefined);
105
+ return;
106
+ }
95
107
  const ui = createStartupTui(settingsManager);
96
108
  let settled = false;
97
109
  const finish = async (result) => {
@@ -99,12 +111,15 @@ export async function showStartupInput(settingsManager, title, placeholder) {
99
111
  return;
100
112
  }
101
113
  settled = true;
114
+ dialogOptions?.signal?.removeEventListener("abort", abandon);
102
115
  input.dispose();
103
116
  await clearStartupTui(ui);
104
117
  ui.stop();
105
118
  resolve(result);
106
119
  };
107
- const input = new ExtensionInputComponent(title, placeholder, (value) => void finish(value), () => void finish(undefined), { tui: ui });
120
+ const abandon = () => void finish(undefined);
121
+ dialogOptions?.signal?.addEventListener("abort", abandon, { once: true });
122
+ const input = new ExtensionInputComponent(title, placeholder, (value) => void finish(value), () => void finish(undefined), { tui: ui, timeout: dialogOptions?.timeout });
108
123
  ui.addChild(input);
109
124
  ui.setFocus(input);
110
125
  ui.start();