@bastani/atomic 0.9.26-alpha.3 → 0.9.26-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 (118) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  3. package/dist/builtin/intercom/broker/broker.ts +9 -1
  4. package/dist/builtin/intercom/index.bundle.mjs +11 -2
  5. package/dist/builtin/intercom/package.json +2 -2
  6. package/dist/builtin/intercom/types.ts +13 -0
  7. package/dist/builtin/mcp/package.json +1 -1
  8. package/dist/builtin/subagents/package.json +3 -3
  9. package/dist/builtin/web-access/package.json +2 -2
  10. package/dist/builtin/workflows/CHANGELOG.md +16 -0
  11. package/dist/builtin/workflows/builtin/{chunk-kfsnh3w7.js → chunk-613yaa53.js} +128 -45
  12. package/dist/builtin/workflows/builtin/{chunk-rqmasd3d.js → chunk-6kqrk0pf.js} +1 -1
  13. package/dist/builtin/workflows/builtin/{chunk-wz783pvd.js → chunk-ea6nrbn3.js} +1 -1
  14. package/dist/builtin/workflows/builtin/goal.js +2 -2
  15. package/dist/builtin/workflows/builtin/index.js +3 -3
  16. package/dist/builtin/workflows/builtin/ralph.js +2 -2
  17. package/dist/builtin/workflows/package.json +2 -2
  18. package/dist/builtin/workflows/src/extension/index.bundle.mjs +653 -303
  19. package/dist/builtin/workflows/src/index.js +201 -77
  20. package/dist/core/agent-session-export.js +1 -1
  21. package/dist/core/agent-session-export.js.map +1 -1
  22. package/dist/core/export-html/tool-renderer.d.ts +3 -3
  23. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  24. package/dist/core/export-html/tool-renderer.js +3 -3
  25. package/dist/core/export-html/tool-renderer.js.map +1 -1
  26. package/dist/core/extensions/api-types.d.ts +3 -1
  27. package/dist/core/extensions/api-types.d.ts.map +1 -1
  28. package/dist/core/extensions/api-types.js.map +1 -1
  29. package/dist/core/extensions/context-types.d.ts +5 -2
  30. package/dist/core/extensions/context-types.d.ts.map +1 -1
  31. package/dist/core/extensions/context-types.js.map +1 -1
  32. package/dist/core/extensions/index.d.ts +1 -1
  33. package/dist/core/extensions/index.d.ts.map +1 -1
  34. package/dist/core/extensions/index.js.map +1 -1
  35. package/dist/core/extensions/loader-api.d.ts.map +1 -1
  36. package/dist/core/extensions/loader-api.js +5 -0
  37. package/dist/core/extensions/loader-api.js.map +1 -1
  38. package/dist/core/extensions/loader-bindings.d.ts +1 -1
  39. package/dist/core/extensions/loader-bindings.d.ts.map +1 -1
  40. package/dist/core/extensions/loader-bindings.js +1 -0
  41. package/dist/core/extensions/loader-bindings.js.map +1 -1
  42. package/dist/core/extensions/runner.d.ts +3 -1
  43. package/dist/core/extensions/runner.d.ts.map +1 -1
  44. package/dist/core/extensions/runner.js +6 -0
  45. package/dist/core/extensions/runner.js.map +1 -1
  46. package/dist/core/extensions/runtime-types.d.ts +2 -1
  47. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  48. package/dist/core/extensions/runtime-types.js.map +1 -1
  49. package/dist/core/extensions/tool-types.d.ts +3 -0
  50. package/dist/core/extensions/tool-types.d.ts.map +1 -1
  51. package/dist/core/extensions/tool-types.js.map +1 -1
  52. package/dist/core/extensions/ui-types.d.ts +2 -2
  53. package/dist/core/extensions/ui-types.d.ts.map +1 -1
  54. package/dist/core/extensions/ui-types.js.map +1 -1
  55. package/dist/core/model-resolver-defaults.js +1 -1
  56. package/dist/core/model-resolver-defaults.js.map +1 -1
  57. package/dist/core/package-manager-auto-resources.d.ts.map +1 -1
  58. package/dist/core/package-manager-auto-resources.js +6 -2
  59. package/dist/core/package-manager-auto-resources.js.map +1 -1
  60. package/dist/core/package-manager-resolver.d.ts.map +1 -1
  61. package/dist/core/package-manager-resolver.js +4 -2
  62. package/dist/core/package-manager-resolver.js.map +1 -1
  63. package/dist/core/settings-manager-resource-accessors.js +7 -3
  64. package/dist/core/settings-manager-resource-accessors.js.map +1 -1
  65. package/dist/core/settings-merge.d.ts.map +1 -1
  66. package/dist/core/settings-merge.js +10 -0
  67. package/dist/core/settings-merge.js.map +1 -1
  68. package/dist/core/settings-types.d.ts +7 -1
  69. package/dist/core/settings-types.d.ts.map +1 -1
  70. package/dist/core/settings-types.js.map +1 -1
  71. package/dist/extensions/mcp/index.d.ts.map +1 -1
  72. package/dist/extensions/mcp/index.js +20 -1
  73. package/dist/extensions/mcp/index.js.map +1 -1
  74. package/dist/extensions/mcp/tools.d.ts +3 -1
  75. package/dist/extensions/mcp/tools.d.ts.map +1 -1
  76. package/dist/extensions/mcp/tools.js +19 -13
  77. package/dist/extensions/mcp/tools.js.map +1 -1
  78. package/dist/index.d.ts +2 -2
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js.map +1 -1
  81. package/dist/modes/interactive/components/chat-message-renderer.d.ts +2 -3
  82. package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
  83. package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
  84. package/dist/modes/interactive/components/config-selector-list.d.ts.map +1 -1
  85. package/dist/modes/interactive/components/config-selector-list.js +3 -1
  86. package/dist/modes/interactive/components/config-selector-list.js.map +1 -1
  87. package/dist/modes/interactive/components/config-selector-project-scope.d.ts.map +1 -1
  88. package/dist/modes/interactive/components/config-selector-project-scope.js +2 -1
  89. package/dist/modes/interactive/components/config-selector-project-scope.js.map +1 -1
  90. package/dist/modes/interactive/components/tool-execution.d.ts +2 -5
  91. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  92. package/dist/modes/interactive/components/tool-execution.js +14 -40
  93. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  94. package/dist/modes/interactive/interactive-mode-surface.d.ts +3 -3
  95. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  96. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  97. package/dist/modes/interactive/interactive-session-runtime.js +6 -1
  98. package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
  99. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  100. package/dist/modes/interactive/interactive-startup.js +5 -0
  101. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  102. package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -1
  103. package/dist/modes/interactive-engine/engine-custom-ui.js +9 -0
  104. package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -1
  105. package/dist/modes/interactive-engine/engine-render-service.d.ts.map +1 -1
  106. package/dist/modes/interactive-engine/engine-render-service.js +10 -1
  107. package/dist/modes/interactive-engine/engine-render-service.js.map +1 -1
  108. package/dist/utils/image-convert.d.ts +5 -0
  109. package/dist/utils/image-convert.d.ts.map +1 -1
  110. package/dist/utils/image-convert.js +36 -6
  111. package/dist/utils/image-convert.js.map +1 -1
  112. package/docs/extensions.md +6 -0
  113. package/docs/intercom/reference.md +13 -1
  114. package/docs/providers.md +10 -0
  115. package/docs/settings.md +28 -1
  116. package/docs/workflows/operations.md +27 -3
  117. package/npm-shrinkwrap.json +71 -92
  118. package/package.json +9 -9
@@ -63,6 +63,92 @@ function raceAbort2(operation, signal) {
63
63
  });
64
64
  }
65
65
 
66
+ // dist/builtin/workflows/src/durable/dbos-database-diagnostics.ts
67
+ function redactedDatabaseEndpoint(url) {
68
+ try {
69
+ const parsed = new URL(url);
70
+ parsed.username = "";
71
+ parsed.password = "";
72
+ parsed.search = "";
73
+ parsed.hash = "";
74
+ return parsed.toString();
75
+ } catch {
76
+ return "unparseable PostgreSQL endpoint";
77
+ }
78
+ }
79
+ function redactedDatabaseMessage(message, url) {
80
+ let safe = message.replace(/postgres(?:ql)?:\/\/[^\s"'<>]+/gi, (value) => redactedDatabaseEndpoint(value));
81
+ let configuredSecrets = [];
82
+ if (url !== undefined) {
83
+ try {
84
+ const parsed = new URL(url);
85
+ configuredSecrets = [parsed.username, parsed.password, ...parsed.searchParams.values()].flatMap((secret) => {
86
+ try {
87
+ return [secret, decodeURIComponent(secret)];
88
+ } catch {
89
+ return [secret];
90
+ }
91
+ }).filter((secret) => secret.length > 0);
92
+ } catch {
93
+ return "PostgreSQL diagnostic could not be safely redacted; check the configured endpoint.";
94
+ }
95
+ }
96
+ safe = safe.replace(/\b(password|passwd|token|secret|sslpassword|user(?:name)?)\s*(?:([=:])\s*|((?:is|was)\s+)|\s+)(?:"([^"]*)"|'([^']*)'|([^\s,;]+))/gi, (match, key, separator, filler, doubleQuoted, singleQuoted, bare) => {
97
+ const value = doubleQuoted ?? singleQuoted ?? bare ?? "";
98
+ const isUserContext = /^user(?:name)?$/i.test(key);
99
+ if (separator === undefined && !isUserContext && !configuredSecrets.includes(value))
100
+ return match;
101
+ const rendered = doubleQuoted !== undefined ? '"[redacted]"' : singleQuoted !== undefined ? "'[redacted]'" : "[redacted]";
102
+ return `${key}${separator ?? " "}${filler ?? ""}${rendered}`;
103
+ });
104
+ for (const secret of new Set(configuredSecrets)) {
105
+ if (secret.length < 4)
106
+ continue;
107
+ const escaped = secret.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
108
+ const expression = new RegExp(`(?<![\\p{L}\\p{N}_\\[])${escaped}(?![\\p{L}\\p{N}_\\]])`, "gu");
109
+ safe = safe.replace(expression, "[redacted]");
110
+ }
111
+ return safe;
112
+ }
113
+ function databaseDependencyMessage(message, diagnostics) {
114
+ const safe = redactedDatabaseMessage(message, diagnostics?.url);
115
+ if (diagnostics === undefined)
116
+ return safe;
117
+ const failure = diagnostics.failure === undefined ? "" : ` Last probe/recovery failure: ${redactedDatabaseMessage(diagnostics.failure, diagnostics.url)}`;
118
+ return `${safe} Provider: ${diagnostics.provider}; endpoint: ${redactedDatabaseEndpoint(diagnostics.url)}.${failure}`;
119
+ }
120
+
121
+ // dist/builtin/workflows/src/durable/dbos-process-owner.ts
122
+ function emptyOwner() {
123
+ return {
124
+ version: 1,
125
+ state: "uninitialized",
126
+ configured: undefined,
127
+ active: undefined,
128
+ launchPromise: undefined,
129
+ shutdownPromise: undefined,
130
+ failure: undefined,
131
+ wrappers: undefined,
132
+ leases: new Set
133
+ };
134
+ }
135
+ function ownerBag() {
136
+ return globalThis;
137
+ }
138
+ function getDbosProcessOwner() {
139
+ const bag = ownerBag();
140
+ const existing = bag[DBOS_PROCESS_OWNER_KEY];
141
+ if (existing !== undefined && existing.version === 1)
142
+ return existing;
143
+ const created = emptyOwner();
144
+ bag[DBOS_PROCESS_OWNER_KEY] = created;
145
+ return created;
146
+ }
147
+ var DBOS_PROCESS_OWNER_KEY;
148
+ var init_dbos_process_owner = __esm(() => {
149
+ DBOS_PROCESS_OWNER_KEY = Symbol.for("atomic-workflows/dbos-process-owner@1");
150
+ });
151
+
66
152
  // dist/builtin/workflows/src/durable/dbos-admission.ts
67
153
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
68
154
  function isDbosDependencyError(error) {
@@ -81,6 +167,8 @@ async function boundedAdmission(operation, signal, timeoutMs = DBOS_ADMISSION_TI
81
167
  return await raceAbort2(operation(controller.signal), controller.signal);
82
168
  } catch (error) {
83
169
  controller.abort(error);
170
+ if (isDbosDependencyError(error) && error.admissionDetail !== undefined)
171
+ throw new DbosDependencyError(error.admissionDetail, null);
84
172
  throw error;
85
173
  } finally {
86
174
  clearTimeout(timer);
@@ -89,10 +177,13 @@ async function boundedAdmission(operation, signal, timeoutMs = DBOS_ADMISSION_TI
89
177
  }
90
178
  var DBOS_ADMISSION_TIMEOUT_MS = 1e4, DbosDependencyError, key2, bag, dbosAdmissionContext;
91
179
  var init_dbos_admission = __esm(() => {
180
+ init_dbos_process_owner();
92
181
  DbosDependencyError = class DbosDependencyError extends Error {
93
182
  code = "ATOMIC_DBOS_DEPENDENCY";
94
- constructor(message = "Workflow database unavailable during admission. Restore PostgreSQL before retrying.") {
95
- super(message);
183
+ admissionDetail;
184
+ constructor(message = "Workflow database unavailable during admission. Restore PostgreSQL before retrying.", diagnostics = getDbosProcessOwner().databaseDiagnostics?.(), admissionDetail) {
185
+ super(databaseDependencyMessage(message, diagnostics ?? undefined));
186
+ this.admissionDetail = admissionDetail === undefined ? undefined : redactedDatabaseMessage(admissionDetail);
96
187
  this.name = "DbosDependencyError";
97
188
  }
98
189
  };
@@ -30263,11 +30354,11 @@ function fenceDbosAdmissionPool(pool) {
30263
30354
  const connect = pool.connect.bind(pool);
30264
30355
  async function acquire(signal) {
30265
30356
  if (signal.aborted)
30266
- throw new DbosDependencyError;
30357
+ throw sdkDependencyError();
30267
30358
  const pending = connect().then((client) => {
30268
30359
  if (signal.aborted) {
30269
30360
  client.release(true);
30270
- throw new DbosDependencyError;
30361
+ throw sdkDependencyError();
30271
30362
  }
30272
30363
  return fencedClient(client, signal);
30273
30364
  });
@@ -30311,7 +30402,7 @@ function fencedClient(client, signal) {
30311
30402
  const callback = typeof last === "function" ? values.pop() : undefined;
30312
30403
  const pending = (async () => {
30313
30404
  if (signal.aborted || released)
30314
- throw new DbosDependencyError;
30405
+ throw sdkDependencyError();
30315
30406
  try {
30316
30407
  return await raceAbort2(new Promise((resolve, reject) => {
30317
30408
  Reflect.apply(target, client, [
@@ -30343,9 +30434,15 @@ function fencedClient(client, signal) {
30343
30434
  }
30344
30435
  });
30345
30436
  }
30437
+ function sdkDependencyError(message) {
30438
+ const reported = message === undefined ? new DbosDependencyError : new DbosDependencyError(message, null);
30439
+ return new DbosDependencyError(undefined, null, reported.message);
30440
+ }
30346
30441
  function databaseError(error, signal) {
30347
30442
  if (signal.aborted)
30348
- return new DbosDependencyError;
30443
+ return sdkDependencyError();
30444
+ if (isDbosDependencyError(error))
30445
+ return sdkDependencyError(error.admissionDetail ?? error.message);
30349
30446
  const pending = [error];
30350
30447
  const seen = new Set;
30351
30448
  while (pending.length > 0) {
@@ -30362,7 +30459,7 @@ function databaseError(error, signal) {
30362
30459
  const code = "code" in value && typeof value.code === "string" ? value.code : undefined;
30363
30460
  const message = value instanceof Error ? value.message : "";
30364
30461
  if (code !== undefined && (/^(?:08|53|57)[0-9A-Z]{3}$|^40003$/.test(code) || connectionErrnos.has(code)) || code === undefined && connectionMessages.has(message)) {
30365
- return new DbosDependencyError;
30462
+ return sdkDependencyError();
30366
30463
  }
30367
30464
  }
30368
30465
  return error;
@@ -30385,7 +30482,9 @@ var init_dbos_admission_pool = __esm(() => {
30385
30482
  "Connection terminated unexpectedly",
30386
30483
  "Connection terminated due to connection timeout",
30387
30484
  "Client has encountered a connection error and is not queryable",
30388
- "timeout exceeded when trying to connect"
30485
+ "timeout exceeded when trying to connect",
30486
+ "Client was closed and is not queryable",
30487
+ "Postgres connection pool changed while acquiring a connection"
30389
30488
  ]);
30390
30489
  });
30391
30490
 
@@ -30673,6 +30772,11 @@ function defaultDatabaseUrl(name) {
30673
30772
  function configureAdmissionDatabase(sdk, config, launchLock = withDbosLaunchLock) {
30674
30773
  const systemDatabaseUrl = config.systemDatabaseUrl ?? defaultDatabaseUrl(config.name);
30675
30774
  const health = resolvedPostgresHealth(systemDatabaseUrl);
30775
+ getDbosProcessOwner().databaseDiagnostics = () => ({
30776
+ provider: health === undefined ? config.systemDatabaseUrl === undefined ? "docker" : "configured" : "managed",
30777
+ url: health?.endpoint ?? systemDatabaseUrl,
30778
+ failure: health?.lastFailure?.message
30779
+ });
30676
30780
  const createPool = () => {
30677
30781
  let unsubscribe;
30678
30782
  const managed = createRecoverablePostgresPool(systemDatabaseUrl, {
@@ -30710,6 +30814,7 @@ var import_datasource2;
30710
30814
  var init_dbos_admission_config = __esm(() => {
30711
30815
  init_dbos_admission_pool();
30712
30816
  init_dbos_launch_lock();
30817
+ init_dbos_process_owner();
30713
30818
  init_dbos_recoverable_pool();
30714
30819
  import_datasource2 = __toESM(require_datasource(), 1);
30715
30820
  });
@@ -32519,10 +32624,10 @@ function recordPendingStageMessageDeliveries(messages, runId, messageId, records
32519
32624
  if (index < 0)
32520
32625
  return messages;
32521
32626
  const entry = messages[index];
32522
- const recorded = new Set((entry.deliveries ?? []).map((delivery) => `${delivery.runId}\x00${delivery.stageId}`));
32627
+ const recorded = new Set((entry.deliveries ?? []).map((delivery) => JSON.stringify([delivery.runId, delivery.stageId, delivery.sessionId, delivery.admission])));
32523
32628
  const additions = [];
32524
32629
  for (const record of records) {
32525
- const key = `${record.runId}\x00${record.stageId}`;
32630
+ const key = JSON.stringify([record.runId, record.stageId, record.sessionId, record.admission]);
32526
32631
  if (recorded.has(key))
32527
32632
  continue;
32528
32633
  recorded.add(key);
@@ -32530,6 +32635,8 @@ function recordPendingStageMessageDeliveries(messages, runId, messageId, records
32530
32635
  runId: record.runId,
32531
32636
  stageId: record.stageId,
32532
32637
  ...record.stageName === undefined ? {} : { stageName: record.stageName },
32638
+ ...record.sessionId === undefined ? {} : { sessionId: record.sessionId },
32639
+ ...record.admission === undefined ? {} : { admission: record.admission },
32533
32640
  deliveredAt
32534
32641
  });
32535
32642
  }
@@ -37789,10 +37896,11 @@ function hasInvocationData(checkpoints, replayKey) {
37789
37896
 
37790
37897
  // dist/builtin/workflows/src/engine/run.ts
37791
37898
  init_dbos_admission();
37899
+ init_dbos_process_owner();
37792
37900
 
37793
37901
  // dist/builtin/workflows/src/durable/backend-process-owner.ts
37794
37902
  var DURABLE_BACKEND_PROCESS_OWNER_KEY = Symbol.for("atomic-workflows/durable-backend-process-owner@1");
37795
- function emptyOwner() {
37903
+ function emptyOwner2() {
37796
37904
  return {
37797
37905
  version: 1,
37798
37906
  injectedBackend: undefined,
@@ -37802,15 +37910,15 @@ function emptyOwner() {
37802
37910
  warningReported: false
37803
37911
  };
37804
37912
  }
37805
- function ownerBag() {
37913
+ function ownerBag2() {
37806
37914
  return globalThis;
37807
37915
  }
37808
37916
  function getDurableBackendProcessOwner() {
37809
- const bag = ownerBag();
37917
+ const bag = ownerBag2();
37810
37918
  const existing = bag[DURABLE_BACKEND_PROCESS_OWNER_KEY];
37811
37919
  if (existing !== undefined && existing.version === 1)
37812
37920
  return existing;
37813
- const created = emptyOwner();
37921
+ const created = emptyOwner2();
37814
37922
  bag[DURABLE_BACKEND_PROCESS_OWNER_KEY] = created;
37815
37923
  return created;
37816
37924
  }
@@ -39022,33 +39130,8 @@ function classifyDbosDeletionTombstone(records, workflowId) {
39022
39130
  return isCurrentDurableFormat(raw.version) ? "current" : "unknown";
39023
39131
  }
39024
39132
 
39025
- // dist/builtin/workflows/src/durable/dbos-process-owner.ts
39026
- var DBOS_PROCESS_OWNER_KEY = Symbol.for("atomic-workflows/dbos-process-owner@1");
39027
- function emptyOwner2() {
39028
- return {
39029
- version: 1,
39030
- state: "uninitialized",
39031
- configured: undefined,
39032
- active: undefined,
39033
- launchPromise: undefined,
39034
- shutdownPromise: undefined,
39035
- failure: undefined,
39036
- wrappers: undefined,
39037
- leases: new Set
39038
- };
39039
- }
39040
- function ownerBag2() {
39041
- return globalThis;
39042
- }
39043
- function getDbosProcessOwner() {
39044
- const bag = ownerBag2();
39045
- const existing = bag[DBOS_PROCESS_OWNER_KEY];
39046
- if (existing !== undefined && existing.version === 1)
39047
- return existing;
39048
- const created = emptyOwner2();
39049
- bag[DBOS_PROCESS_OWNER_KEY] = created;
39050
- return created;
39051
- }
39133
+ // dist/builtin/workflows/src/durable/dbos-backend.ts
39134
+ init_dbos_process_owner();
39052
39135
 
39053
39136
  // dist/builtin/workflows/src/durable/dbos-sdk-handle.ts
39054
39137
  var ATOMIC_EXECUTOR_ID = `atomic-${process.pid.toString(36)}-${crypto.randomUUID().slice(0, 8)}`;
@@ -39169,6 +39252,7 @@ function statusToInfo(status, fallbackId) {
39169
39252
  }
39170
39253
 
39171
39254
  // dist/builtin/workflows/src/durable/dbos-system-database-url.ts
39255
+ init_dbos_process_owner();
39172
39256
  function nonEmptyTrimmed(value) {
39173
39257
  const trimmed = value?.trim();
39174
39258
  return trimmed === undefined || trimmed.length === 0 ? undefined : trimmed;
@@ -39183,9 +39267,7 @@ class DbosSystemDatabaseConflictError extends Error {
39183
39267
  function redactDatabaseUrl(url) {
39184
39268
  try {
39185
39269
  const parsed = new URL(url);
39186
- if (parsed.password !== "")
39187
- parsed.password = "***";
39188
- return parsed.toString();
39270
+ return parsed.host;
39189
39271
  } catch {
39190
39272
  return "the requested database";
39191
39273
  }
@@ -40902,6 +40984,7 @@ class PostgresHealth {
40902
40984
  attempts = 0;
40903
40985
  nextRecoveryAt = 0;
40904
40986
  failure;
40987
+ healthySinceFailure = false;
40905
40988
  revision = 0;
40906
40989
  listeners = new Set;
40907
40990
  constructor(operations) {
@@ -40910,6 +40993,18 @@ class PostgresHealth {
40910
40993
  get lastFailure() {
40911
40994
  return this.failure;
40912
40995
  }
40996
+ get endpoint() {
40997
+ return this.operations.url?.();
40998
+ }
40999
+ retainFailure(error) {
41000
+ const message = error instanceof Error ? error.message : String(error);
41001
+ const safe = redactedDatabaseMessage(message, this.endpoint);
41002
+ this.failure = new Error(safe);
41003
+ this.healthySinceFailure = false;
41004
+ }
41005
+ dependencyFailure(message) {
41006
+ return new DbosDependencyError(message, this.endpoint === undefined ? undefined : { provider: "managed", url: this.endpoint, failure: this.failure?.message });
41007
+ }
40913
41008
  subscribe(listener) {
40914
41009
  this.listeners.add(listener);
40915
41010
  return () => this.listeners.delete(listener);
@@ -40932,12 +41027,15 @@ class PostgresHealth {
40932
41027
  await this.operations.validate?.(client);
40933
41028
  }
40934
41029
  } catch (error) {
40935
- this.failure = error instanceof Error ? error : new Error(String(error));
41030
+ this.retainFailure(error);
40936
41031
  if (!isQueryReadTimeout(error)) {
40937
41032
  this.invalidate();
40938
- throw error;
41033
+ if (this.endpoint === undefined)
41034
+ throw error;
41035
+ const failure = this.dependencyFailure("Managed PostgreSQL connection validation refused. Preserve its data and ownership records.");
41036
+ throw error instanceof DbosDependencyError ? failure : new Error(failure.message);
40939
41037
  }
40940
- throw new DbosDependencyError("Managed PostgreSQL did not answer a connection identity check in time.");
41038
+ throw this.dependencyFailure("Managed PostgreSQL did not answer a connection identity check in time.");
40941
41039
  }
40942
41040
  }
40943
41041
  check() {
@@ -40978,7 +41076,7 @@ class PostgresHealth {
40978
41076
  } catch (retryError) {
40979
41077
  if (!isMonitoringConnectionFailure(retryError))
40980
41078
  throw retryError;
40981
- this.failure = retryError;
41079
+ this.retainFailure(retryError);
40982
41080
  return;
40983
41081
  }
40984
41082
  }
@@ -40993,6 +41091,7 @@ class PostgresHealth {
40993
41091
  this.available = identity;
40994
41092
  this.attempts = 0;
40995
41093
  this.nextRecoveryAt = 0;
41094
+ this.healthySinceFailure = true;
40996
41095
  return identity.url;
40997
41096
  }
40998
41097
  async refresh() {
@@ -41002,19 +41101,21 @@ class PostgresHealth {
41002
41101
  return ready;
41003
41102
  } catch (error) {
41004
41103
  if (isQueryReadTimeout(error)) {
41005
- this.failure = new DbosDependencyError("Managed PostgreSQL did not answer a health check in time.");
41006
- throw this.failure;
41104
+ this.retainFailure(new Error("Managed PostgreSQL did not answer a health check in time."));
41105
+ throw this.dependencyFailure("Managed PostgreSQL did not answer a health check in time.");
41007
41106
  }
41008
- this.failure = error instanceof Error ? error : new Error(String(error));
41107
+ this.retainFailure(error);
41009
41108
  if (!(error instanceof Error && ("code" in error) && error.code === "53300"))
41010
41109
  this.invalidate();
41011
- throw error;
41110
+ throw this.endpoint === undefined ? error : this.dependencyFailure("Managed PostgreSQL recovery refused after a health probe failure. Preserve its data and ownership records.");
41111
+ }
41112
+ if (this.attempts === 0 && (this.failure === undefined || this.healthySinceFailure)) {
41113
+ this.retainFailure(new Error("Managed PostgreSQL failed its live health check."));
41114
+ this.healthySinceFailure = false;
41012
41115
  }
41013
- if (this.attempts === 0)
41014
- this.failure = new DbosDependencyError("Managed PostgreSQL failed its live health check.");
41015
41116
  this.invalidate();
41016
41117
  if ((this.operations.now ?? Date.now)() < this.nextRecoveryAt)
41017
- throw new DbosDependencyError("Managed Postgres recovery is cooling down after bounded attempts.");
41118
+ throw this.dependencyFailure("Managed Postgres recovery is cooling down after bounded attempts.");
41018
41119
  while (!this.stopped && this.attempts < RECOVERY_ATTEMPTS) {
41019
41120
  const attempt = this.attempts++;
41020
41121
  if (attempt > 0)
@@ -41027,12 +41128,12 @@ class PostgresHealth {
41027
41128
  if (ready !== undefined)
41028
41129
  return ready;
41029
41130
  } catch (error) {
41030
- this.failure = error instanceof Error ? error : new Error(String(error));
41131
+ this.retainFailure(error);
41031
41132
  }
41032
41133
  }
41033
41134
  this.attempts = 0;
41034
41135
  this.nextRecoveryAt = (this.operations.now ?? Date.now)() + HEALTH_INTERVAL_MS;
41035
- throw new DbosDependencyError("Managed Postgres is unavailable after bounded recovery. Preserve its data and ownership records.");
41136
+ throw this.dependencyFailure("Managed Postgres is unavailable after bounded recovery. Preserve its data and ownership records.");
41036
41137
  }
41037
41138
  }
41038
41139
 
@@ -41688,6 +41789,8 @@ async function ensureCluster(options = {}) {
41688
41789
  const server = current.server;
41689
41790
  if (!server)
41690
41791
  throw new Error("Managed Postgres published identity is missing.");
41792
+ if (managedPostmaster(current) === undefined)
41793
+ return;
41691
41794
  if (!managedPostgresRuntimeHealthy(current, server.port)) {
41692
41795
  verifyManagedPostmasterProcess(current, server);
41693
41796
  return;
@@ -41704,6 +41807,7 @@ async function ensureCluster(options = {}) {
41704
41807
  };
41705
41808
  health = new PostgresHealth({
41706
41809
  probe: () => inspect(),
41810
+ url: embeddedDbosSystemDatabaseUrl,
41707
41811
  validate: async (client) => {
41708
41812
  const identity = await inspect(async () => {
41709
41813
  const query = { text: POSTGRES_IDENTITY_SQL, query_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS };
@@ -42791,6 +42895,9 @@ async function requireDockerSuccess(action, args) {
42791
42895
  throw new Error(`Could not ${action}: ${commandFailureDetail(result)}`);
42792
42896
  }
42793
42897
 
42898
+ // dist/builtin/workflows/src/durable/dbos-lifecycle.ts
42899
+ init_dbos_process_owner();
42900
+
42794
42901
  // dist/builtin/workflows/src/durable/dbos-registration-diagnostics.ts
42795
42902
  var cachedErrorModule;
42796
42903
  var errorModuleLoad;
@@ -51124,14 +51231,21 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
51124
51231
  };
51125
51232
  return {
51126
51233
  routeCapability: workflowPendingStageRouteCapability(activeStore, runId),
51127
- deliverPending(deliver) {
51234
+ deliverPending(deliver, recipient) {
51128
51235
  if (drainPromise !== undefined)
51129
51236
  return drainPromise;
51130
51237
  if (terminalError !== undefined)
51131
51238
  return Promise.resolve();
51132
51239
  drainError = undefined;
51133
- const attempt = deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver);
51134
- const drain = attempt.then(() => resolveReady?.(), (error) => {
51240
+ const attempt = deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver, recipient);
51241
+ const drain = attempt.then(() => {
51242
+ resolveReady?.();
51243
+ readyPromise = undefined;
51244
+ resolveReady = undefined;
51245
+ rejectReady = undefined;
51246
+ if (drainPromise === drain)
51247
+ drainPromise = undefined;
51248
+ }, (error) => {
51135
51249
  drainError = error;
51136
51250
  rejectReady?.(error);
51137
51251
  readyPromise = undefined;
@@ -51144,8 +51258,8 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
51144
51258
  drainPromise = drain;
51145
51259
  return drainPromise;
51146
51260
  },
51147
- ready() {
51148
- if (activeStore.pendingStageMessagesFor(runId, stageId).length === 0 && (stageId === stageName || activeStore.pendingStageMessagesFor(runId, stageName).length === 0) && stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName).length === 0) {
51261
+ ready(sessionId) {
51262
+ if (activeStore.pendingStageMessagesFor(runId, stageId).length === 0 && (stageId === stageName || activeStore.pendingStageMessagesFor(runId, stageName).length === 0) && stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, sessionId === undefined ? undefined : { sessionId }).length === 0) {
51149
51263
  return;
51150
51264
  }
51151
51265
  if (terminalError !== undefined)
@@ -51163,8 +51277,8 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
51163
51277
  }
51164
51278
  };
51165
51279
  }
51166
- async function deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver) {
51167
- const stickyEntries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName);
51280
+ async function deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver, recipient) {
51281
+ const stickyEntries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient);
51168
51282
  const candidateIds = new Set([
51169
51283
  ...activeStore.pendingStageMessagesFor(runId, stageId),
51170
51284
  ...activeStore.pendingStageMessagesFor(runId, stageName),
@@ -51186,7 +51300,8 @@ async function deliverPendingStageMessages(activeStore, runId, stageId, stageNam
51186
51300
  if (releaseClaim === undefined)
51187
51301
  continue;
51188
51302
  try {
51189
- await deliver(toPendingStageSender(entry), entry.message);
51303
+ if (!recipient?.receivedMessageIds.includes(entry.message.id))
51304
+ await deliver(toPendingStageSender(entry), entry.message);
51190
51305
  if (entry.sticky === true) {
51191
51306
  const entryBackend = durableBackendForRun(rootBackend, activeStore.runs(), entry.runId);
51192
51307
  if (entryBackend === undefined) {
@@ -51196,7 +51311,8 @@ async function deliverPendingStageMessages(activeStore, runId, stageId, stageNam
51196
51311
  {
51197
51312
  runId,
51198
51313
  stageId,
51199
- ...stageName === stageId ? {} : { stageName }
51314
+ ...stageName === stageId ? {} : { stageName },
51315
+ ...recipient === undefined ? {} : { sessionId: recipient.sessionId, admission: "context" }
51200
51316
  }
51201
51317
  ], new Date().toISOString(), entryBackend)) {
51202
51318
  throw new Error(`atomic-workflows: pending-stage message ${entry.id} changed during delivery`);
@@ -51211,7 +51327,7 @@ async function deliverPendingStageMessages(activeStore, runId, stageId, stageNam
51211
51327
  }
51212
51328
  }
51213
51329
  }
51214
- function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName) {
51330
+ function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient) {
51215
51331
  const runs = activeStore.runs();
51216
51332
  const rootRunId = durableRootRunIdForRun(runs, runId);
51217
51333
  if (rootRunId === undefined)
@@ -51228,9 +51344,8 @@ function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageNam
51228
51344
  const parsed = entry.targetPath === undefined ? undefined : parseWorkflowStageTarget(entry.targetPath);
51229
51345
  if (parsed === undefined || parsed.rootRunId !== rootRunId)
51230
51346
  return false;
51231
- if ((entry.deliveries ?? []).some((delivery) => delivery.runId === runId && delivery.stageId === stageId)) {
51347
+ if ((entry.deliveries ?? []).some((delivery) => delivery.runId === runId && delivery.stageId === stageId && (recipient === undefined || delivery.admission === "context" && delivery.sessionId === recipient.sessionId && (recipient.receivedMessageIds === undefined || recipient.receivedMessageIds.includes(entry.message.id)))))
51232
51348
  return false;
51233
- }
51234
51349
  return stageMatchesPathPattern(parsed.segments, hops, [stageId, stageName]);
51235
51350
  });
51236
51351
  }
@@ -53758,7 +53873,7 @@ class StageSessionController {
53758
53873
  const attachedSession = session instanceof Promise ? await session : session;
53759
53874
  this.reportStartupPhase("delivery-readiness");
53760
53875
  try {
53761
- await this.sharedOrchestrationContext?.pendingStageDelivery?.ready();
53876
+ await this.sharedOrchestrationContext?.pendingStageDelivery?.ready(attachedSession.sessionId);
53762
53877
  await this.opts.onSessionReady?.();
53763
53878
  if (this.disposed || this.opts.signal?.aborted || this.abortGeneration !== startGeneration)
53764
53879
  throw this.staleCreationReason(startGeneration);
@@ -55733,7 +55848,7 @@ async function run(def, inputs, opts = {}) {
55733
55848
  if (control === latestControl && !ownController.signal.aborted && isDbosDependencyError(error)) {
55734
55849
  activeStore.recordRunExecutionState(runId, {
55735
55850
  phase: "blocked_dependency",
55736
- dependencyError: `Workflow database unavailable during ${status === "paused" ? "pause" : "resume"}; persistence not confirmed.`
55851
+ dependencyError: `Workflow database unavailable during ${status === "paused" ? "pause" : "resume"}; persistence not confirmed. ${error.message}`
55737
55852
  });
55738
55853
  if (status === "paused")
55739
55854
  return;
@@ -55780,7 +55895,7 @@ async function run(def, inputs, opts = {}) {
55780
55895
  if (!admission.admitting)
55781
55896
  return pausePersistence;
55782
55897
  backgroundAdmissionControl(durableBackend, runId, pausePersistence, (error, resumable) => {
55783
- admissionControlError = unknownErrorMessage(error);
55898
+ admissionControlError = databaseDependencyMessage(unknownErrorMessage(error), getDbosProcessOwner().databaseDiagnostics?.());
55784
55899
  runSnapshot.error = admissionControlError;
55785
55900
  activeStore.recordRunPaused(runId, undefined, { resumable });
55786
55901
  return runSnapshot.error;
@@ -55797,7 +55912,7 @@ async function run(def, inputs, opts = {}) {
55797
55912
  } catch (error) {
55798
55913
  if (admission.failed) {
55799
55914
  scheduler.releaseRun();
55800
- throw error;
55915
+ throw new Error(admissionControlError ?? databaseDependencyMessage(unknownErrorMessage(error), getDbosProcessOwner().databaseDiagnostics?.()));
55801
55916
  }
55802
55917
  }
55803
55918
  if (generation !== pauseGeneration)
@@ -55870,12 +55985,21 @@ async function run(def, inputs, opts = {}) {
55870
55985
  }).catch((error) => {
55871
55986
  const isTopologyError = typeof error === "object" && error !== null && "name" in error && error.name === "DurableNestedTopologyError";
55872
55987
  if (!isDbosDependencyError(error) && !isTopologyError) {
55873
- durableAdmissionFailure = { error };
55874
- classifiedFailures.set(error, classifyWorkflowFailure({
55988
+ const admissionDetail = unknownErrorMessage(error);
55989
+ const diagnostics = getDbosProcessOwner().databaseDiagnostics?.();
55990
+ const safeMessage = databaseDependencyMessage(admissionDetail, diagnostics);
55991
+ activeStore.recordRunExecutionState(runId, {
55992
+ phase: "blocked_dependency",
55993
+ dependencyError: safeMessage
55994
+ });
55995
+ const safeError = new Error(safeMessage);
55996
+ durableAdmissionFailure = { error: safeError };
55997
+ classifiedFailures.set(safeError, classifyWorkflowFailure({
55875
55998
  code: "ATOMIC_DURABLE_ADMISSION_REJECTED",
55876
- message: unknownErrorMessage(error),
55877
- cause: error
55999
+ message: safeMessage,
56000
+ cause: safeError
55878
56001
  }));
56002
+ throw safeError;
55879
56003
  }
55880
56004
  throw error;
55881
56005
  }), ownController.signal);
@@ -114,7 +114,7 @@ export async function exportToHtml(outputPath, options = {}) {
114
114
  ]);
115
115
  // Create tool renderer if we have an extension runner (for custom tool HTML rendering)
116
116
  const toolRenderer = createToolHtmlRenderer({
117
- getToolDefinition: (name) => this.getToolDefinition(name),
117
+ getToolRenderers: (name) => this.extensionRunner.resolveToolRenderers(name, () => this.getToolDefinition(name)),
118
118
  theme,
119
119
  cwd: this.sessionManager.getCwd(),
120
120
  });