@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.
- package/CHANGELOG.md +16 -0
- package/dist/builtin/intercom/CHANGELOG.md +6 -0
- package/dist/builtin/intercom/broker/broker.ts +9 -1
- package/dist/builtin/intercom/index.bundle.mjs +11 -2
- package/dist/builtin/intercom/package.json +2 -2
- package/dist/builtin/intercom/types.ts +13 -0
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +3 -3
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +16 -0
- package/dist/builtin/workflows/builtin/{chunk-kfsnh3w7.js → chunk-613yaa53.js} +128 -45
- package/dist/builtin/workflows/builtin/{chunk-rqmasd3d.js → chunk-6kqrk0pf.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-wz783pvd.js → chunk-ea6nrbn3.js} +1 -1
- package/dist/builtin/workflows/builtin/goal.js +2 -2
- package/dist/builtin/workflows/builtin/index.js +3 -3
- package/dist/builtin/workflows/builtin/ralph.js +2 -2
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +653 -303
- package/dist/builtin/workflows/src/index.js +201 -77
- package/dist/core/agent-session-export.js +1 -1
- package/dist/core/agent-session-export.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts +3 -3
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +3 -3
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/api-types.d.ts +3 -1
- package/dist/core/extensions/api-types.d.ts.map +1 -1
- package/dist/core/extensions/api-types.js.map +1 -1
- package/dist/core/extensions/context-types.d.ts +5 -2
- package/dist/core/extensions/context-types.d.ts.map +1 -1
- package/dist/core/extensions/context-types.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader-api.d.ts.map +1 -1
- package/dist/core/extensions/loader-api.js +5 -0
- package/dist/core/extensions/loader-api.js.map +1 -1
- package/dist/core/extensions/loader-bindings.d.ts +1 -1
- package/dist/core/extensions/loader-bindings.d.ts.map +1 -1
- package/dist/core/extensions/loader-bindings.js +1 -0
- package/dist/core/extensions/loader-bindings.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +6 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/runtime-types.d.ts +2 -1
- package/dist/core/extensions/runtime-types.d.ts.map +1 -1
- package/dist/core/extensions/runtime-types.js.map +1 -1
- package/dist/core/extensions/tool-types.d.ts +3 -0
- package/dist/core/extensions/tool-types.d.ts.map +1 -1
- package/dist/core/extensions/tool-types.js.map +1 -1
- package/dist/core/extensions/ui-types.d.ts +2 -2
- package/dist/core/extensions/ui-types.d.ts.map +1 -1
- package/dist/core/extensions/ui-types.js.map +1 -1
- package/dist/core/model-resolver-defaults.js +1 -1
- package/dist/core/model-resolver-defaults.js.map +1 -1
- package/dist/core/package-manager-auto-resources.d.ts.map +1 -1
- package/dist/core/package-manager-auto-resources.js +6 -2
- package/dist/core/package-manager-auto-resources.js.map +1 -1
- package/dist/core/package-manager-resolver.d.ts.map +1 -1
- package/dist/core/package-manager-resolver.js +4 -2
- package/dist/core/package-manager-resolver.js.map +1 -1
- package/dist/core/settings-manager-resource-accessors.js +7 -3
- package/dist/core/settings-manager-resource-accessors.js.map +1 -1
- package/dist/core/settings-merge.d.ts.map +1 -1
- package/dist/core/settings-merge.js +10 -0
- package/dist/core/settings-merge.js.map +1 -1
- package/dist/core/settings-types.d.ts +7 -1
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/extensions/mcp/index.d.ts.map +1 -1
- package/dist/extensions/mcp/index.js +20 -1
- package/dist/extensions/mcp/index.js.map +1 -1
- package/dist/extensions/mcp/tools.d.ts +3 -1
- package/dist/extensions/mcp/tools.d.ts.map +1 -1
- package/dist/extensions/mcp/tools.js +19 -13
- package/dist/extensions/mcp/tools.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.d.ts +2 -3
- package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
- package/dist/modes/interactive/components/config-selector-list.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector-list.js +3 -1
- package/dist/modes/interactive/components/config-selector-list.js.map +1 -1
- package/dist/modes/interactive/components/config-selector-project-scope.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector-project-scope.js +2 -1
- package/dist/modes/interactive/components/config-selector-project-scope.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +2 -5
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +14 -40
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +3 -3
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-session-runtime.js +6 -1
- package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +5 -0
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-custom-ui.js +9 -0
- package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -1
- package/dist/modes/interactive-engine/engine-render-service.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-render-service.js +10 -1
- package/dist/modes/interactive-engine/engine-render-service.js.map +1 -1
- package/dist/utils/image-convert.d.ts +5 -0
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js +36 -6
- package/dist/utils/image-convert.js.map +1 -1
- package/docs/extensions.md +6 -0
- package/docs/intercom/reference.md +13 -1
- package/docs/providers.md +10 -0
- package/docs/settings.md +28 -1
- package/docs/workflows/operations.md +27 -3
- package/npm-shrinkwrap.json +71 -92
- package/package.json +9 -9
|
@@ -76,6 +76,92 @@ function raceAbort(operation, signal) {
|
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
// dist/builtin/workflows/src/durable/dbos-database-diagnostics.ts
|
|
80
|
+
function redactedDatabaseEndpoint(url) {
|
|
81
|
+
try {
|
|
82
|
+
const parsed = new URL(url);
|
|
83
|
+
parsed.username = "";
|
|
84
|
+
parsed.password = "";
|
|
85
|
+
parsed.search = "";
|
|
86
|
+
parsed.hash = "";
|
|
87
|
+
return parsed.toString();
|
|
88
|
+
} catch {
|
|
89
|
+
return "unparseable PostgreSQL endpoint";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function redactedDatabaseMessage(message, url) {
|
|
93
|
+
let safe = message.replace(/postgres(?:ql)?:\/\/[^\s"'<>]+/gi, (value2) => redactedDatabaseEndpoint(value2));
|
|
94
|
+
let configuredSecrets = [];
|
|
95
|
+
if (url !== undefined) {
|
|
96
|
+
try {
|
|
97
|
+
const parsed = new URL(url);
|
|
98
|
+
configuredSecrets = [parsed.username, parsed.password, ...parsed.searchParams.values()].flatMap((secret) => {
|
|
99
|
+
try {
|
|
100
|
+
return [secret, decodeURIComponent(secret)];
|
|
101
|
+
} catch {
|
|
102
|
+
return [secret];
|
|
103
|
+
}
|
|
104
|
+
}).filter((secret) => secret.length > 0);
|
|
105
|
+
} catch {
|
|
106
|
+
return "PostgreSQL diagnostic could not be safely redacted; check the configured endpoint.";
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
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) => {
|
|
110
|
+
const value2 = doubleQuoted ?? singleQuoted ?? bare ?? "";
|
|
111
|
+
const isUserContext = /^user(?:name)?$/i.test(key);
|
|
112
|
+
if (separator === undefined && !isUserContext && !configuredSecrets.includes(value2))
|
|
113
|
+
return match;
|
|
114
|
+
const rendered = doubleQuoted !== undefined ? '"[redacted]"' : singleQuoted !== undefined ? "'[redacted]'" : "[redacted]";
|
|
115
|
+
return `${key}${separator ?? " "}${filler ?? ""}${rendered}`;
|
|
116
|
+
});
|
|
117
|
+
for (const secret of new Set(configuredSecrets)) {
|
|
118
|
+
if (secret.length < 4)
|
|
119
|
+
continue;
|
|
120
|
+
const escaped = secret.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
121
|
+
const expression = new RegExp(`(?<![\\p{L}\\p{N}_\\[])${escaped}(?![\\p{L}\\p{N}_\\]])`, "gu");
|
|
122
|
+
safe = safe.replace(expression, "[redacted]");
|
|
123
|
+
}
|
|
124
|
+
return safe;
|
|
125
|
+
}
|
|
126
|
+
function databaseDependencyMessage(message, diagnostics) {
|
|
127
|
+
const safe = redactedDatabaseMessage(message, diagnostics?.url);
|
|
128
|
+
if (diagnostics === undefined)
|
|
129
|
+
return safe;
|
|
130
|
+
const failure = diagnostics.failure === undefined ? "" : ` Last probe/recovery failure: ${redactedDatabaseMessage(diagnostics.failure, diagnostics.url)}`;
|
|
131
|
+
return `${safe} Provider: ${diagnostics.provider}; endpoint: ${redactedDatabaseEndpoint(diagnostics.url)}.${failure}`;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// dist/builtin/workflows/src/durable/dbos-process-owner.ts
|
|
135
|
+
function emptyOwner2() {
|
|
136
|
+
return {
|
|
137
|
+
version: 1,
|
|
138
|
+
state: "uninitialized",
|
|
139
|
+
configured: undefined,
|
|
140
|
+
active: undefined,
|
|
141
|
+
launchPromise: undefined,
|
|
142
|
+
shutdownPromise: undefined,
|
|
143
|
+
failure: undefined,
|
|
144
|
+
wrappers: undefined,
|
|
145
|
+
leases: new Set
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function ownerBag2() {
|
|
149
|
+
return globalThis;
|
|
150
|
+
}
|
|
151
|
+
function getDbosProcessOwner() {
|
|
152
|
+
const bag = ownerBag2();
|
|
153
|
+
const existing = bag[DBOS_PROCESS_OWNER_KEY];
|
|
154
|
+
if (existing !== undefined && existing.version === 1)
|
|
155
|
+
return existing;
|
|
156
|
+
const created = emptyOwner2();
|
|
157
|
+
bag[DBOS_PROCESS_OWNER_KEY] = created;
|
|
158
|
+
return created;
|
|
159
|
+
}
|
|
160
|
+
var DBOS_PROCESS_OWNER_KEY;
|
|
161
|
+
var init_dbos_process_owner = __esm(() => {
|
|
162
|
+
DBOS_PROCESS_OWNER_KEY = Symbol.for("atomic-workflows/dbos-process-owner@1");
|
|
163
|
+
});
|
|
164
|
+
|
|
79
165
|
// dist/builtin/workflows/src/durable/dbos-admission.ts
|
|
80
166
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
81
167
|
function isDbosDependencyError(error) {
|
|
@@ -94,6 +180,8 @@ async function boundedAdmission(operation, signal, timeoutMs = DBOS_ADMISSION_TI
|
|
|
94
180
|
return await raceAbort(operation(controller.signal), controller.signal);
|
|
95
181
|
} catch (error) {
|
|
96
182
|
controller.abort(error);
|
|
183
|
+
if (isDbosDependencyError(error) && error.admissionDetail !== undefined)
|
|
184
|
+
throw new DbosDependencyError(error.admissionDetail, null);
|
|
97
185
|
throw error;
|
|
98
186
|
} finally {
|
|
99
187
|
clearTimeout(timer);
|
|
@@ -102,10 +190,13 @@ async function boundedAdmission(operation, signal, timeoutMs = DBOS_ADMISSION_TI
|
|
|
102
190
|
}
|
|
103
191
|
var DBOS_ADMISSION_TIMEOUT_MS = 1e4, DbosDependencyError, key2, bag, dbosAdmissionContext;
|
|
104
192
|
var init_dbos_admission = __esm(() => {
|
|
193
|
+
init_dbos_process_owner();
|
|
105
194
|
DbosDependencyError = class DbosDependencyError extends Error {
|
|
106
195
|
code = "ATOMIC_DBOS_DEPENDENCY";
|
|
107
|
-
|
|
108
|
-
|
|
196
|
+
admissionDetail;
|
|
197
|
+
constructor(message = "Workflow database unavailable during admission. Restore PostgreSQL before retrying.", diagnostics = getDbosProcessOwner().databaseDiagnostics?.(), admissionDetail) {
|
|
198
|
+
super(databaseDependencyMessage(message, diagnostics ?? undefined));
|
|
199
|
+
this.admissionDetail = admissionDetail === undefined ? undefined : redactedDatabaseMessage(admissionDetail);
|
|
109
200
|
this.name = "DbosDependencyError";
|
|
110
201
|
}
|
|
111
202
|
};
|
|
@@ -30276,11 +30367,11 @@ function fenceDbosAdmissionPool(pool) {
|
|
|
30276
30367
|
const connect = pool.connect.bind(pool);
|
|
30277
30368
|
async function acquire(signal) {
|
|
30278
30369
|
if (signal.aborted)
|
|
30279
|
-
throw
|
|
30370
|
+
throw sdkDependencyError();
|
|
30280
30371
|
const pending = connect().then((client) => {
|
|
30281
30372
|
if (signal.aborted) {
|
|
30282
30373
|
client.release(true);
|
|
30283
|
-
throw
|
|
30374
|
+
throw sdkDependencyError();
|
|
30284
30375
|
}
|
|
30285
30376
|
return fencedClient(client, signal);
|
|
30286
30377
|
});
|
|
@@ -30324,7 +30415,7 @@ function fencedClient(client, signal) {
|
|
|
30324
30415
|
const callback = typeof last === "function" ? values.pop() : undefined;
|
|
30325
30416
|
const pending = (async () => {
|
|
30326
30417
|
if (signal.aborted || released)
|
|
30327
|
-
throw
|
|
30418
|
+
throw sdkDependencyError();
|
|
30328
30419
|
try {
|
|
30329
30420
|
return await raceAbort(new Promise((resolve, reject) => {
|
|
30330
30421
|
Reflect.apply(target, client, [
|
|
@@ -30356,9 +30447,15 @@ function fencedClient(client, signal) {
|
|
|
30356
30447
|
}
|
|
30357
30448
|
});
|
|
30358
30449
|
}
|
|
30450
|
+
function sdkDependencyError(message) {
|
|
30451
|
+
const reported = message === undefined ? new DbosDependencyError : new DbosDependencyError(message, null);
|
|
30452
|
+
return new DbosDependencyError(undefined, null, reported.message);
|
|
30453
|
+
}
|
|
30359
30454
|
function databaseError(error, signal) {
|
|
30360
30455
|
if (signal.aborted)
|
|
30361
|
-
return
|
|
30456
|
+
return sdkDependencyError();
|
|
30457
|
+
if (isDbosDependencyError(error))
|
|
30458
|
+
return sdkDependencyError(error.admissionDetail ?? error.message);
|
|
30362
30459
|
const pending = [error];
|
|
30363
30460
|
const seen = new Set;
|
|
30364
30461
|
while (pending.length > 0) {
|
|
@@ -30375,7 +30472,7 @@ function databaseError(error, signal) {
|
|
|
30375
30472
|
const code = "code" in value2 && typeof value2.code === "string" ? value2.code : undefined;
|
|
30376
30473
|
const message = value2 instanceof Error ? value2.message : "";
|
|
30377
30474
|
if (code !== undefined && (/^(?:08|53|57)[0-9A-Z]{3}$|^40003$/.test(code) || connectionErrnos.has(code)) || code === undefined && connectionMessages.has(message)) {
|
|
30378
|
-
return
|
|
30475
|
+
return sdkDependencyError();
|
|
30379
30476
|
}
|
|
30380
30477
|
}
|
|
30381
30478
|
return error;
|
|
@@ -30398,7 +30495,9 @@ var init_dbos_admission_pool = __esm(() => {
|
|
|
30398
30495
|
"Connection terminated unexpectedly",
|
|
30399
30496
|
"Connection terminated due to connection timeout",
|
|
30400
30497
|
"Client has encountered a connection error and is not queryable",
|
|
30401
|
-
"timeout exceeded when trying to connect"
|
|
30498
|
+
"timeout exceeded when trying to connect",
|
|
30499
|
+
"Client was closed and is not queryable",
|
|
30500
|
+
"Postgres connection pool changed while acquiring a connection"
|
|
30402
30501
|
]);
|
|
30403
30502
|
});
|
|
30404
30503
|
|
|
@@ -30686,6 +30785,11 @@ function defaultDatabaseUrl(name) {
|
|
|
30686
30785
|
function configureAdmissionDatabase(sdk, config, launchLock = withDbosLaunchLock) {
|
|
30687
30786
|
const systemDatabaseUrl = config.systemDatabaseUrl ?? defaultDatabaseUrl(config.name);
|
|
30688
30787
|
const health = resolvedPostgresHealth(systemDatabaseUrl);
|
|
30788
|
+
getDbosProcessOwner().databaseDiagnostics = () => ({
|
|
30789
|
+
provider: health === undefined ? config.systemDatabaseUrl === undefined ? "docker" : "configured" : "managed",
|
|
30790
|
+
url: health?.endpoint ?? systemDatabaseUrl,
|
|
30791
|
+
failure: health?.lastFailure?.message
|
|
30792
|
+
});
|
|
30689
30793
|
const createPool = () => {
|
|
30690
30794
|
let unsubscribe;
|
|
30691
30795
|
const managed = createRecoverablePostgresPool(systemDatabaseUrl, {
|
|
@@ -30723,6 +30827,7 @@ var import_datasource2;
|
|
|
30723
30827
|
var init_dbos_admission_config = __esm(() => {
|
|
30724
30828
|
init_dbos_admission_pool();
|
|
30725
30829
|
init_dbos_launch_lock();
|
|
30830
|
+
init_dbos_process_owner();
|
|
30726
30831
|
init_dbos_recoverable_pool();
|
|
30727
30832
|
import_datasource2 = __toESM(require_datasource(), 1);
|
|
30728
30833
|
});
|
|
@@ -67501,10 +67606,10 @@ function recordPendingStageMessageDeliveries(messages, runId, messageId, records
|
|
|
67501
67606
|
if (index < 0)
|
|
67502
67607
|
return messages;
|
|
67503
67608
|
const entry = messages[index];
|
|
67504
|
-
const recorded = new Set((entry.deliveries ?? []).map((delivery) =>
|
|
67609
|
+
const recorded = new Set((entry.deliveries ?? []).map((delivery) => JSON.stringify([delivery.runId, delivery.stageId, delivery.sessionId, delivery.admission])));
|
|
67505
67610
|
const additions = [];
|
|
67506
67611
|
for (const record of records) {
|
|
67507
|
-
const key =
|
|
67612
|
+
const key = JSON.stringify([record.runId, record.stageId, record.sessionId, record.admission]);
|
|
67508
67613
|
if (recorded.has(key))
|
|
67509
67614
|
continue;
|
|
67510
67615
|
recorded.add(key);
|
|
@@ -67512,6 +67617,8 @@ function recordPendingStageMessageDeliveries(messages, runId, messageId, records
|
|
|
67512
67617
|
runId: record.runId,
|
|
67513
67618
|
stageId: record.stageId,
|
|
67514
67619
|
...record.stageName === undefined ? {} : { stageName: record.stageName },
|
|
67620
|
+
...record.sessionId === undefined ? {} : { sessionId: record.sessionId },
|
|
67621
|
+
...record.admission === undefined ? {} : { admission: record.admission },
|
|
67515
67622
|
deliveredAt
|
|
67516
67623
|
});
|
|
67517
67624
|
}
|
|
@@ -85894,33 +86001,8 @@ function classifyDbosDeletionTombstone(records, workflowId) {
|
|
|
85894
86001
|
return isCurrentDurableFormat(raw.version) ? "current" : "unknown";
|
|
85895
86002
|
}
|
|
85896
86003
|
|
|
85897
|
-
// dist/builtin/workflows/src/durable/dbos-
|
|
85898
|
-
|
|
85899
|
-
function emptyOwner2() {
|
|
85900
|
-
return {
|
|
85901
|
-
version: 1,
|
|
85902
|
-
state: "uninitialized",
|
|
85903
|
-
configured: undefined,
|
|
85904
|
-
active: undefined,
|
|
85905
|
-
launchPromise: undefined,
|
|
85906
|
-
shutdownPromise: undefined,
|
|
85907
|
-
failure: undefined,
|
|
85908
|
-
wrappers: undefined,
|
|
85909
|
-
leases: new Set
|
|
85910
|
-
};
|
|
85911
|
-
}
|
|
85912
|
-
function ownerBag2() {
|
|
85913
|
-
return globalThis;
|
|
85914
|
-
}
|
|
85915
|
-
function getDbosProcessOwner() {
|
|
85916
|
-
const bag = ownerBag2();
|
|
85917
|
-
const existing = bag[DBOS_PROCESS_OWNER_KEY];
|
|
85918
|
-
if (existing !== undefined && existing.version === 1)
|
|
85919
|
-
return existing;
|
|
85920
|
-
const created = emptyOwner2();
|
|
85921
|
-
bag[DBOS_PROCESS_OWNER_KEY] = created;
|
|
85922
|
-
return created;
|
|
85923
|
-
}
|
|
86004
|
+
// dist/builtin/workflows/src/durable/dbos-backend.ts
|
|
86005
|
+
init_dbos_process_owner();
|
|
85924
86006
|
|
|
85925
86007
|
// dist/builtin/workflows/src/durable/dbos-sdk-handle.ts
|
|
85926
86008
|
var ATOMIC_EXECUTOR_ID = `atomic-${process.pid.toString(36)}-${crypto.randomUUID().slice(0, 8)}`;
|
|
@@ -86041,6 +86123,7 @@ function statusToInfo(status, fallbackId) {
|
|
|
86041
86123
|
}
|
|
86042
86124
|
|
|
86043
86125
|
// dist/builtin/workflows/src/durable/dbos-system-database-url.ts
|
|
86126
|
+
init_dbos_process_owner();
|
|
86044
86127
|
function nonEmptyTrimmed(value2) {
|
|
86045
86128
|
const trimmed = value2?.trim();
|
|
86046
86129
|
return trimmed === undefined || trimmed.length === 0 ? undefined : trimmed;
|
|
@@ -86055,9 +86138,7 @@ class DbosSystemDatabaseConflictError extends Error {
|
|
|
86055
86138
|
function redactDatabaseUrl(url) {
|
|
86056
86139
|
try {
|
|
86057
86140
|
const parsed = new URL(url);
|
|
86058
|
-
|
|
86059
|
-
parsed.password = "***";
|
|
86060
|
-
return parsed.toString();
|
|
86141
|
+
return parsed.host;
|
|
86061
86142
|
} catch {
|
|
86062
86143
|
return "the requested database";
|
|
86063
86144
|
}
|
|
@@ -87774,6 +87855,7 @@ class PostgresHealth {
|
|
|
87774
87855
|
attempts = 0;
|
|
87775
87856
|
nextRecoveryAt = 0;
|
|
87776
87857
|
failure;
|
|
87858
|
+
healthySinceFailure = false;
|
|
87777
87859
|
revision = 0;
|
|
87778
87860
|
listeners = new Set;
|
|
87779
87861
|
constructor(operations) {
|
|
@@ -87782,6 +87864,18 @@ class PostgresHealth {
|
|
|
87782
87864
|
get lastFailure() {
|
|
87783
87865
|
return this.failure;
|
|
87784
87866
|
}
|
|
87867
|
+
get endpoint() {
|
|
87868
|
+
return this.operations.url?.();
|
|
87869
|
+
}
|
|
87870
|
+
retainFailure(error) {
|
|
87871
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
87872
|
+
const safe = redactedDatabaseMessage(message, this.endpoint);
|
|
87873
|
+
this.failure = new Error(safe);
|
|
87874
|
+
this.healthySinceFailure = false;
|
|
87875
|
+
}
|
|
87876
|
+
dependencyFailure(message) {
|
|
87877
|
+
return new DbosDependencyError(message, this.endpoint === undefined ? undefined : { provider: "managed", url: this.endpoint, failure: this.failure?.message });
|
|
87878
|
+
}
|
|
87785
87879
|
subscribe(listener) {
|
|
87786
87880
|
this.listeners.add(listener);
|
|
87787
87881
|
return () => this.listeners.delete(listener);
|
|
@@ -87804,12 +87898,15 @@ class PostgresHealth {
|
|
|
87804
87898
|
await this.operations.validate?.(client);
|
|
87805
87899
|
}
|
|
87806
87900
|
} catch (error) {
|
|
87807
|
-
this.
|
|
87901
|
+
this.retainFailure(error);
|
|
87808
87902
|
if (!isQueryReadTimeout(error)) {
|
|
87809
87903
|
this.invalidate();
|
|
87810
|
-
|
|
87904
|
+
if (this.endpoint === undefined)
|
|
87905
|
+
throw error;
|
|
87906
|
+
const failure = this.dependencyFailure("Managed PostgreSQL connection validation refused. Preserve its data and ownership records.");
|
|
87907
|
+
throw error instanceof DbosDependencyError ? failure : new Error(failure.message);
|
|
87811
87908
|
}
|
|
87812
|
-
throw
|
|
87909
|
+
throw this.dependencyFailure("Managed PostgreSQL did not answer a connection identity check in time.");
|
|
87813
87910
|
}
|
|
87814
87911
|
}
|
|
87815
87912
|
check() {
|
|
@@ -87850,7 +87947,7 @@ class PostgresHealth {
|
|
|
87850
87947
|
} catch (retryError) {
|
|
87851
87948
|
if (!isMonitoringConnectionFailure(retryError))
|
|
87852
87949
|
throw retryError;
|
|
87853
|
-
this.
|
|
87950
|
+
this.retainFailure(retryError);
|
|
87854
87951
|
return;
|
|
87855
87952
|
}
|
|
87856
87953
|
}
|
|
@@ -87865,6 +87962,7 @@ class PostgresHealth {
|
|
|
87865
87962
|
this.available = identity;
|
|
87866
87963
|
this.attempts = 0;
|
|
87867
87964
|
this.nextRecoveryAt = 0;
|
|
87965
|
+
this.healthySinceFailure = true;
|
|
87868
87966
|
return identity.url;
|
|
87869
87967
|
}
|
|
87870
87968
|
async refresh() {
|
|
@@ -87874,19 +87972,21 @@ class PostgresHealth {
|
|
|
87874
87972
|
return ready;
|
|
87875
87973
|
} catch (error) {
|
|
87876
87974
|
if (isQueryReadTimeout(error)) {
|
|
87877
|
-
this.
|
|
87878
|
-
throw this.
|
|
87975
|
+
this.retainFailure(new Error("Managed PostgreSQL did not answer a health check in time."));
|
|
87976
|
+
throw this.dependencyFailure("Managed PostgreSQL did not answer a health check in time.");
|
|
87879
87977
|
}
|
|
87880
|
-
this.
|
|
87978
|
+
this.retainFailure(error);
|
|
87881
87979
|
if (!(error instanceof Error && ("code" in error) && error.code === "53300"))
|
|
87882
87980
|
this.invalidate();
|
|
87883
|
-
throw error;
|
|
87981
|
+
throw this.endpoint === undefined ? error : this.dependencyFailure("Managed PostgreSQL recovery refused after a health probe failure. Preserve its data and ownership records.");
|
|
87982
|
+
}
|
|
87983
|
+
if (this.attempts === 0 && (this.failure === undefined || this.healthySinceFailure)) {
|
|
87984
|
+
this.retainFailure(new Error("Managed PostgreSQL failed its live health check."));
|
|
87985
|
+
this.healthySinceFailure = false;
|
|
87884
87986
|
}
|
|
87885
|
-
if (this.attempts === 0)
|
|
87886
|
-
this.failure = new DbosDependencyError("Managed PostgreSQL failed its live health check.");
|
|
87887
87987
|
this.invalidate();
|
|
87888
87988
|
if ((this.operations.now ?? Date.now)() < this.nextRecoveryAt)
|
|
87889
|
-
throw
|
|
87989
|
+
throw this.dependencyFailure("Managed Postgres recovery is cooling down after bounded attempts.");
|
|
87890
87990
|
while (!this.stopped && this.attempts < RECOVERY_ATTEMPTS) {
|
|
87891
87991
|
const attempt = this.attempts++;
|
|
87892
87992
|
if (attempt > 0)
|
|
@@ -87899,12 +87999,12 @@ class PostgresHealth {
|
|
|
87899
87999
|
if (ready !== undefined)
|
|
87900
88000
|
return ready;
|
|
87901
88001
|
} catch (error) {
|
|
87902
|
-
this.
|
|
88002
|
+
this.retainFailure(error);
|
|
87903
88003
|
}
|
|
87904
88004
|
}
|
|
87905
88005
|
this.attempts = 0;
|
|
87906
88006
|
this.nextRecoveryAt = (this.operations.now ?? Date.now)() + HEALTH_INTERVAL_MS;
|
|
87907
|
-
throw
|
|
88007
|
+
throw this.dependencyFailure("Managed Postgres is unavailable after bounded recovery. Preserve its data and ownership records.");
|
|
87908
88008
|
}
|
|
87909
88009
|
}
|
|
87910
88010
|
|
|
@@ -88560,6 +88660,8 @@ async function ensureCluster(options = {}) {
|
|
|
88560
88660
|
const server = current.server;
|
|
88561
88661
|
if (!server)
|
|
88562
88662
|
throw new Error("Managed Postgres published identity is missing.");
|
|
88663
|
+
if (managedPostmaster(current) === undefined)
|
|
88664
|
+
return;
|
|
88563
88665
|
if (!managedPostgresRuntimeHealthy(current, server.port)) {
|
|
88564
88666
|
verifyManagedPostmasterProcess(current, server);
|
|
88565
88667
|
return;
|
|
@@ -88576,6 +88678,7 @@ async function ensureCluster(options = {}) {
|
|
|
88576
88678
|
};
|
|
88577
88679
|
health = new PostgresHealth({
|
|
88578
88680
|
probe: () => inspect(),
|
|
88681
|
+
url: embeddedDbosSystemDatabaseUrl,
|
|
88579
88682
|
validate: async (client) => {
|
|
88580
88683
|
const identity = await inspect(async () => {
|
|
88581
88684
|
const query = { text: POSTGRES_IDENTITY_SQL, query_timeout: POSTGRES_HEALTH_QUERY_TIMEOUT_MS };
|
|
@@ -89663,6 +89766,9 @@ async function requireDockerSuccess(action, args) {
|
|
|
89663
89766
|
throw new Error(`Could not ${action}: ${commandFailureDetail(result)}`);
|
|
89664
89767
|
}
|
|
89665
89768
|
|
|
89769
|
+
// dist/builtin/workflows/src/durable/dbos-lifecycle.ts
|
|
89770
|
+
init_dbos_process_owner();
|
|
89771
|
+
|
|
89666
89772
|
// dist/builtin/workflows/src/durable/dbos-registration-diagnostics.ts
|
|
89667
89773
|
var cachedErrorModule;
|
|
89668
89774
|
var errorModuleLoad;
|
|
@@ -92282,6 +92388,292 @@ function observeRunExecution(run, now = Date.now()) {
|
|
|
92282
92388
|
};
|
|
92283
92389
|
}
|
|
92284
92390
|
|
|
92391
|
+
// dist/builtin/workflows/src/durable/prompt-reservations.ts
|
|
92392
|
+
function durablePromptScope(backend, workflowId) {
|
|
92393
|
+
return backend.promptReservationScope(workflowId);
|
|
92394
|
+
}
|
|
92395
|
+
function claimDurablePromptToken(backend, workflowId, reservationId) {
|
|
92396
|
+
return backend.pendingPromptToken(workflowId, reservationId);
|
|
92397
|
+
}
|
|
92398
|
+
function reserveDurablePrompt(backend, workflowId, reservationId) {
|
|
92399
|
+
return backend.reservePendingPrompt(workflowId, reservationId);
|
|
92400
|
+
}
|
|
92401
|
+
function releaseDurablePrompt(backend, workflowId, reservationId, token) {
|
|
92402
|
+
backend.releasePendingPrompt(workflowId, reservationId, token);
|
|
92403
|
+
}
|
|
92404
|
+
|
|
92405
|
+
// dist/builtin/workflows/src/durable/scoped-backend.ts
|
|
92406
|
+
class ScopedDurableBackend {
|
|
92407
|
+
persistent;
|
|
92408
|
+
inner;
|
|
92409
|
+
scope;
|
|
92410
|
+
constructor(inner, scope) {
|
|
92411
|
+
this.inner = inner;
|
|
92412
|
+
this.scope = scope;
|
|
92413
|
+
this.persistent = inner.persistent;
|
|
92414
|
+
}
|
|
92415
|
+
registerWorkflow(_handle) {}
|
|
92416
|
+
persistPendingStageMessages(workflowId, messages, logicalRunId = workflowId) {
|
|
92417
|
+
return this.inner.persistPendingStageMessages(this.scope.rootWorkflowId, messages, logicalRunId);
|
|
92418
|
+
}
|
|
92419
|
+
recordCheckpoint(checkpoint) {
|
|
92420
|
+
this.inner.recordCheckpoint(this.remap(checkpoint));
|
|
92421
|
+
}
|
|
92422
|
+
async recordCheckpointAsync(checkpoint, options) {
|
|
92423
|
+
await this.inner.recordCheckpointAsync(this.remap(checkpoint), options);
|
|
92424
|
+
}
|
|
92425
|
+
async recordAdditiveCheckpointBestEffort(checkpoint) {
|
|
92426
|
+
return await this.inner.recordAdditiveCheckpointBestEffort(this.remap(checkpoint));
|
|
92427
|
+
}
|
|
92428
|
+
flush(workflowId) {
|
|
92429
|
+
return workflowId === undefined ? this.inner.flush() : this.inner.flush(this.scope.rootWorkflowId);
|
|
92430
|
+
}
|
|
92431
|
+
getToolOutput(_workflowId, argsHash) {
|
|
92432
|
+
return this.inner.getToolOutput(this.scope.rootWorkflowId, this.scopeKey(argsHash));
|
|
92433
|
+
}
|
|
92434
|
+
getToolCheckpoint(_workflowId, argsHash) {
|
|
92435
|
+
return this.inner.getToolCheckpoint(this.scope.rootWorkflowId, this.scopeKey(argsHash));
|
|
92436
|
+
}
|
|
92437
|
+
getUiResponse(_workflowId, promptHash) {
|
|
92438
|
+
return this.inner.getUiResponse(this.scope.rootWorkflowId, this.scopeKey(promptHash));
|
|
92439
|
+
}
|
|
92440
|
+
getStageOutput(_workflowId, replayKey) {
|
|
92441
|
+
return this.inner.getStageOutput(this.scope.rootWorkflowId, this.scopeKey(replayKey));
|
|
92442
|
+
}
|
|
92443
|
+
getStageSession(_workflowId, replayKey) {
|
|
92444
|
+
return this.inner.getStageSession(this.scope.rootWorkflowId, this.scopeKey(replayKey));
|
|
92445
|
+
}
|
|
92446
|
+
listCheckpoints(workflowId) {
|
|
92447
|
+
const prefix = `${this.scope.scopePrefix}:`;
|
|
92448
|
+
return this.inner.listCheckpoints(this.scope.rootWorkflowId).filter((checkpoint) => checkpointHasPrefix(checkpoint, prefix)).map((checkpoint) => localCheckpoint(checkpoint, workflowId, prefix));
|
|
92449
|
+
}
|
|
92450
|
+
getWorkflow(_workflowId) {
|
|
92451
|
+
return;
|
|
92452
|
+
}
|
|
92453
|
+
getLoadableWorkflow(_workflowId) {
|
|
92454
|
+
return;
|
|
92455
|
+
}
|
|
92456
|
+
setWorkflowStatus(_workflowId, _status, _pendingPrompts, _resumable) {}
|
|
92457
|
+
async transitionWorkflowStatus(_workflowId, _expectedStatuses, _status, _pendingPrompts, _resumable) {
|
|
92458
|
+
return false;
|
|
92459
|
+
}
|
|
92460
|
+
adjustPendingPrompts(_workflowId, delta) {
|
|
92461
|
+
this.inner.adjustPendingPrompts(this.scope.rootWorkflowId, delta);
|
|
92462
|
+
}
|
|
92463
|
+
promptReservationScope(_workflowId) {
|
|
92464
|
+
return this.effectivePromptScope();
|
|
92465
|
+
}
|
|
92466
|
+
pendingPromptToken(_workflowId, reservationId) {
|
|
92467
|
+
return claimDurablePromptToken(this.inner, this.scope.rootWorkflowId, reservationId);
|
|
92468
|
+
}
|
|
92469
|
+
reservePendingPrompt(_workflowId, reservationId) {
|
|
92470
|
+
return reserveDurablePrompt(this.inner, this.scope.rootWorkflowId, reservationId);
|
|
92471
|
+
}
|
|
92472
|
+
releasePendingPrompt(_workflowId, reservationId, token) {
|
|
92473
|
+
releaseDurablePrompt(this.inner, this.scope.rootWorkflowId, reservationId, token);
|
|
92474
|
+
}
|
|
92475
|
+
listResumableWorkflows() {
|
|
92476
|
+
return [];
|
|
92477
|
+
}
|
|
92478
|
+
listCompletedWorkflows() {
|
|
92479
|
+
return [];
|
|
92480
|
+
}
|
|
92481
|
+
async prepareWorkflowCatalog() {
|
|
92482
|
+
return { resumable: [], completed: [] };
|
|
92483
|
+
}
|
|
92484
|
+
toMetadata(_workflowId) {
|
|
92485
|
+
return;
|
|
92486
|
+
}
|
|
92487
|
+
async deleteWorkflow(_workflowId) {}
|
|
92488
|
+
async deleteWorkflowIfInactive(_workflowId) {
|
|
92489
|
+
return { ok: false, reason: "not_found" };
|
|
92490
|
+
}
|
|
92491
|
+
isWorkflowLoadable(_workflowId) {
|
|
92492
|
+
return false;
|
|
92493
|
+
}
|
|
92494
|
+
reset() {}
|
|
92495
|
+
hydrateWorkflow(_workflowId) {
|
|
92496
|
+
return Promise.resolve();
|
|
92497
|
+
}
|
|
92498
|
+
hydrateWorkflowForInspection(_workflowId) {
|
|
92499
|
+
return Promise.resolve({ kind: "absent" });
|
|
92500
|
+
}
|
|
92501
|
+
hydrateResumableWorkflows() {
|
|
92502
|
+
return Promise.resolve();
|
|
92503
|
+
}
|
|
92504
|
+
effectivePromptScope() {
|
|
92505
|
+
const parent = durablePromptScope(this.inner, this.scope.rootWorkflowId);
|
|
92506
|
+
const scope = parent.scope === "root" ? this.scope.scopePrefix : `${parent.scope}:${this.scope.scopePrefix}`;
|
|
92507
|
+
return {
|
|
92508
|
+
rootWorkflowId: parent.rootWorkflowId,
|
|
92509
|
+
scope
|
|
92510
|
+
};
|
|
92511
|
+
}
|
|
92512
|
+
scopeKey(key) {
|
|
92513
|
+
return `${this.scope.scopePrefix}:${key}`;
|
|
92514
|
+
}
|
|
92515
|
+
remap(checkpoint) {
|
|
92516
|
+
const workflowId = this.scope.rootWorkflowId;
|
|
92517
|
+
if (checkpoint.kind === "tool") {
|
|
92518
|
+
return {
|
|
92519
|
+
...checkpoint,
|
|
92520
|
+
workflowId,
|
|
92521
|
+
checkpointId: this.scopeKey(checkpoint.checkpointId),
|
|
92522
|
+
argsHash: this.scopeKey(checkpoint.argsHash)
|
|
92523
|
+
};
|
|
92524
|
+
}
|
|
92525
|
+
if (checkpoint.kind === "ui") {
|
|
92526
|
+
return {
|
|
92527
|
+
...checkpoint,
|
|
92528
|
+
workflowId,
|
|
92529
|
+
checkpointId: this.scopeKey(checkpoint.checkpointId),
|
|
92530
|
+
promptHash: this.scopeKey(checkpoint.promptHash)
|
|
92531
|
+
};
|
|
92532
|
+
}
|
|
92533
|
+
return {
|
|
92534
|
+
...checkpoint,
|
|
92535
|
+
workflowId,
|
|
92536
|
+
checkpointId: this.scopeKey(checkpoint.checkpointId),
|
|
92537
|
+
replayKey: this.scopeKey(checkpoint.replayKey),
|
|
92538
|
+
...remappedBoundaryScope(checkpoint, this.scopeKey(checkpoint.topology?.boundary?.replayScope ?? ""))
|
|
92539
|
+
};
|
|
92540
|
+
}
|
|
92541
|
+
}
|
|
92542
|
+
function checkpointHasPrefix(checkpoint, prefix) {
|
|
92543
|
+
if (!checkpoint.checkpointId.startsWith(prefix))
|
|
92544
|
+
return false;
|
|
92545
|
+
if (checkpoint.kind === "tool")
|
|
92546
|
+
return checkpoint.argsHash.startsWith(prefix);
|
|
92547
|
+
if (checkpoint.kind === "ui")
|
|
92548
|
+
return checkpoint.promptHash.startsWith(prefix);
|
|
92549
|
+
return checkpoint.replayKey.startsWith(prefix);
|
|
92550
|
+
}
|
|
92551
|
+
function localCheckpoint(checkpoint, workflowId, prefix) {
|
|
92552
|
+
const checkpointId = checkpoint.checkpointId.slice(prefix.length);
|
|
92553
|
+
if (checkpoint.kind === "tool") {
|
|
92554
|
+
return { ...checkpoint, workflowId, checkpointId, argsHash: checkpoint.argsHash.slice(prefix.length) };
|
|
92555
|
+
}
|
|
92556
|
+
if (checkpoint.kind === "ui") {
|
|
92557
|
+
return { ...checkpoint, workflowId, checkpointId, promptHash: checkpoint.promptHash.slice(prefix.length) };
|
|
92558
|
+
}
|
|
92559
|
+
const replayKey = checkpoint.replayKey.slice(prefix.length);
|
|
92560
|
+
const replayScope = stripOnePrefix(checkpoint.topology?.boundary?.replayScope, prefix);
|
|
92561
|
+
return {
|
|
92562
|
+
...checkpoint,
|
|
92563
|
+
workflowId,
|
|
92564
|
+
checkpointId,
|
|
92565
|
+
replayKey,
|
|
92566
|
+
...remappedBoundaryScope(checkpoint, replayScope)
|
|
92567
|
+
};
|
|
92568
|
+
}
|
|
92569
|
+
function remappedBoundaryScope(checkpoint, replayScope) {
|
|
92570
|
+
const topology = checkpoint.topology;
|
|
92571
|
+
if (topology?.boundary === undefined || replayScope === undefined)
|
|
92572
|
+
return {};
|
|
92573
|
+
return {
|
|
92574
|
+
topology: {
|
|
92575
|
+
...topology,
|
|
92576
|
+
boundary: { ...topology.boundary, replayScope }
|
|
92577
|
+
}
|
|
92578
|
+
};
|
|
92579
|
+
}
|
|
92580
|
+
function stripOnePrefix(value2, prefix) {
|
|
92581
|
+
if (value2 === undefined || !value2.startsWith(prefix))
|
|
92582
|
+
return value2;
|
|
92583
|
+
return value2.slice(prefix.length);
|
|
92584
|
+
}
|
|
92585
|
+
|
|
92586
|
+
// dist/builtin/workflows/src/durable/run-owner-backend.ts
|
|
92587
|
+
function durableRootRunIdForRun(runs, runId) {
|
|
92588
|
+
return reciprocalWorkflowRootRunId(new Map(runs.map((run) => [run.id, run])), runId);
|
|
92589
|
+
}
|
|
92590
|
+
function durableBackendForRun(backend, runs, runId) {
|
|
92591
|
+
const rootRunId = durableRootRunIdForRun(runs, runId);
|
|
92592
|
+
if (rootRunId === undefined)
|
|
92593
|
+
return;
|
|
92594
|
+
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
92595
|
+
if (rootRunId === runId)
|
|
92596
|
+
return backend;
|
|
92597
|
+
const scopes = [];
|
|
92598
|
+
let current = runById.get(runId);
|
|
92599
|
+
while (current !== undefined && current.id !== rootRunId) {
|
|
92600
|
+
const parent = current.parentRunId === undefined ? undefined : runById.get(current.parentRunId);
|
|
92601
|
+
const boundary = parent?.stages.find((stage) => stage.id === current?.parentStageId);
|
|
92602
|
+
if (parent === undefined || boundary?.replayKey === undefined)
|
|
92603
|
+
return;
|
|
92604
|
+
scopes.push(boundary.replayKey);
|
|
92605
|
+
current = parent;
|
|
92606
|
+
}
|
|
92607
|
+
if (current?.id !== rootRunId)
|
|
92608
|
+
return;
|
|
92609
|
+
let view = backend;
|
|
92610
|
+
for (const scopePrefix of scopes.reverse()) {
|
|
92611
|
+
view = new ScopedDurableBackend(view, { rootWorkflowId: rootRunId, scopePrefix });
|
|
92612
|
+
}
|
|
92613
|
+
return view;
|
|
92614
|
+
}
|
|
92615
|
+
|
|
92616
|
+
// dist/builtin/workflows/src/shared/sticky-stage-delivery-status.ts
|
|
92617
|
+
function stickyStageDeliveryStatuses(runs, rootRunId) {
|
|
92618
|
+
const root = runs.find((run) => run.id === rootRunId);
|
|
92619
|
+
const entries = (root?.pendingStageMessages ?? []).filter((entry) => entry.sticky === true);
|
|
92620
|
+
const result = [];
|
|
92621
|
+
for (const run of runs) {
|
|
92622
|
+
if (run.id !== rootRunId && run.rootRunId !== rootRunId && durableRootRunIdForRun(runs, run.id) !== rootRunId)
|
|
92623
|
+
continue;
|
|
92624
|
+
const resolved = durableRootRunIdForRun(runs, run.id) === rootRunId;
|
|
92625
|
+
const hops = workflowBoundaryHops(runs, run.id);
|
|
92626
|
+
for (const stage of run.stages) {
|
|
92627
|
+
if (stage.nodeKind === "tool" || stage.replayKey?.startsWith("prompt:") === true || stage.replayKey?.startsWith("workflow:") === true || stage.workflowChildRun !== undefined || stage.workflowChild !== undefined)
|
|
92628
|
+
continue;
|
|
92629
|
+
for (const entry of entries) {
|
|
92630
|
+
const target = entry.targetPath ?? entry.stageKey;
|
|
92631
|
+
const parsed = parseWorkflowStageTarget(target);
|
|
92632
|
+
if (!parsed || parsed.rootRunId !== rootRunId)
|
|
92633
|
+
continue;
|
|
92634
|
+
if (resolved && hops && !stageMatchesPathPattern(parsed.segments, hops, [stage.id, stage.name]))
|
|
92635
|
+
continue;
|
|
92636
|
+
const receipts = (entry.deliveries ?? []).filter((delivery) => delivery.runId === run.id && delivery.stageId === stage.id);
|
|
92637
|
+
const delivered = receipts.some((delivery) => delivery.admission === "context" && delivery.sessionId !== undefined && (stage.sessionId === undefined || delivery.sessionId === stage.sessionId));
|
|
92638
|
+
let state;
|
|
92639
|
+
let reason;
|
|
92640
|
+
if (!resolved || !hops) {
|
|
92641
|
+
state = "root-unresolved";
|
|
92642
|
+
reason = "Repair reciprocal parent/boundary ownership before startup";
|
|
92643
|
+
} else if (delivered) {
|
|
92644
|
+
state = "delivered";
|
|
92645
|
+
reason = "Startup context admission confirmed; sticky subscription remains for future stages";
|
|
92646
|
+
} else if (["completed", "failed", "skipped"].includes(stage.status)) {
|
|
92647
|
+
state = "stage-terminal";
|
|
92648
|
+
reason = `${stage.error ? `${stage.error}; ` : ""}Stage ended without confirmed context admission; steer a live stage or start a new stage`;
|
|
92649
|
+
} else if (receipts.some((delivery) => delivery.admission !== "context" && (delivery.sessionId === undefined || stage.sessionId === undefined || delivery.sessionId === stage.sessionId))) {
|
|
92650
|
+
state = "receipt-unverified";
|
|
92651
|
+
reason = "Legacy or live transport receipt only; inspect the session transcript to confirm context admission";
|
|
92652
|
+
} else if (stage.pendingStageDeliveryAvailable !== true) {
|
|
92653
|
+
state = "delivery-unavailable";
|
|
92654
|
+
reason = "Stage has no pre-start Intercom helper; enable Intercom in the invocation group";
|
|
92655
|
+
} else if (receipts.length > 0) {
|
|
92656
|
+
state = "session-replaced";
|
|
92657
|
+
reason = "Only a previous session has a receipt; replacement must drain before its first turn";
|
|
92658
|
+
} else {
|
|
92659
|
+
state = "queued";
|
|
92660
|
+
reason = "No delivery receipt; stage startup must drain before its first turn";
|
|
92661
|
+
}
|
|
92662
|
+
result.push({
|
|
92663
|
+
messageId: entry.message.id,
|
|
92664
|
+
target,
|
|
92665
|
+
runId: run.id,
|
|
92666
|
+
stageId: stage.id,
|
|
92667
|
+
...stage.sessionId === undefined ? {} : { sessionId: stage.sessionId },
|
|
92668
|
+
state,
|
|
92669
|
+
reason
|
|
92670
|
+
});
|
|
92671
|
+
}
|
|
92672
|
+
}
|
|
92673
|
+
}
|
|
92674
|
+
return result;
|
|
92675
|
+
}
|
|
92676
|
+
|
|
92285
92677
|
// dist/builtin/workflows/src/runs/background/run-inspect.ts
|
|
92286
92678
|
function inspectRun(runId, opts) {
|
|
92287
92679
|
const activeStore = opts?.store ?? store;
|
|
@@ -92312,6 +92704,7 @@ function inspectRun(runId, opts) {
|
|
|
92312
92704
|
inputs: copy.inputs,
|
|
92313
92705
|
stages: expandedStages.map((stage) => structuredClone(stage)),
|
|
92314
92706
|
tools: expandedGraph.tools.map((tool) => structuredClone(tool)),
|
|
92707
|
+
deliveryStates: stickyStageDeliveryStatuses(activeStore.runs(), copy.rootRunId ?? copy.id).filter((delivery) => copy.id === (copy.rootRunId ?? copy.id) || delivery.runId === copy.id),
|
|
92315
92708
|
result: copy.result,
|
|
92316
92709
|
error: copy.error ?? (strandedRoot ? IMPOSSIBLE_ROOT_LIVENESS_MESSAGE : effectiveRunStatus(copy) === copy.status ? undefined : structuredRecoverableWorkflowFailureText(copy) ?? actionableReturnedStatusText(copy.result)),
|
|
92317
92710
|
exited: copy.exited,
|
|
@@ -94096,6 +94489,9 @@ function registerWorkflowLifecycleHandlers(pi, deps) {
|
|
|
94096
94489
|
});
|
|
94097
94490
|
}
|
|
94098
94491
|
|
|
94492
|
+
// dist/builtin/workflows/src/extension/extension-runtime-state.ts
|
|
94493
|
+
init_dbos_process_owner();
|
|
94494
|
+
|
|
94099
94495
|
// dist/builtin/workflows/src/durable/workflow-heartbeat-anchor.ts
|
|
94100
94496
|
var WORKFLOW_HEARTBEAT_ANCHOR_CHECKPOINT_NAME = "workflow-heartbeat-anchor";
|
|
94101
94497
|
function asPersistedAnchorOutput(output) {
|
|
@@ -102243,201 +102639,7 @@ function hasInvocationData(checkpoints, replayKey) {
|
|
|
102243
102639
|
|
|
102244
102640
|
// dist/builtin/workflows/src/engine/run.ts
|
|
102245
102641
|
init_dbos_admission();
|
|
102246
|
-
|
|
102247
|
-
// dist/builtin/workflows/src/durable/prompt-reservations.ts
|
|
102248
|
-
function durablePromptScope(backend, workflowId) {
|
|
102249
|
-
return backend.promptReservationScope(workflowId);
|
|
102250
|
-
}
|
|
102251
|
-
function claimDurablePromptToken(backend, workflowId, reservationId) {
|
|
102252
|
-
return backend.pendingPromptToken(workflowId, reservationId);
|
|
102253
|
-
}
|
|
102254
|
-
function reserveDurablePrompt(backend, workflowId, reservationId) {
|
|
102255
|
-
return backend.reservePendingPrompt(workflowId, reservationId);
|
|
102256
|
-
}
|
|
102257
|
-
function releaseDurablePrompt(backend, workflowId, reservationId, token) {
|
|
102258
|
-
backend.releasePendingPrompt(workflowId, reservationId, token);
|
|
102259
|
-
}
|
|
102260
|
-
|
|
102261
|
-
// dist/builtin/workflows/src/durable/scoped-backend.ts
|
|
102262
|
-
class ScopedDurableBackend {
|
|
102263
|
-
persistent;
|
|
102264
|
-
inner;
|
|
102265
|
-
scope;
|
|
102266
|
-
constructor(inner, scope) {
|
|
102267
|
-
this.inner = inner;
|
|
102268
|
-
this.scope = scope;
|
|
102269
|
-
this.persistent = inner.persistent;
|
|
102270
|
-
}
|
|
102271
|
-
registerWorkflow(_handle) {}
|
|
102272
|
-
persistPendingStageMessages(workflowId, messages, logicalRunId = workflowId) {
|
|
102273
|
-
return this.inner.persistPendingStageMessages(this.scope.rootWorkflowId, messages, logicalRunId);
|
|
102274
|
-
}
|
|
102275
|
-
recordCheckpoint(checkpoint) {
|
|
102276
|
-
this.inner.recordCheckpoint(this.remap(checkpoint));
|
|
102277
|
-
}
|
|
102278
|
-
async recordCheckpointAsync(checkpoint, options) {
|
|
102279
|
-
await this.inner.recordCheckpointAsync(this.remap(checkpoint), options);
|
|
102280
|
-
}
|
|
102281
|
-
async recordAdditiveCheckpointBestEffort(checkpoint) {
|
|
102282
|
-
return await this.inner.recordAdditiveCheckpointBestEffort(this.remap(checkpoint));
|
|
102283
|
-
}
|
|
102284
|
-
flush(workflowId) {
|
|
102285
|
-
return workflowId === undefined ? this.inner.flush() : this.inner.flush(this.scope.rootWorkflowId);
|
|
102286
|
-
}
|
|
102287
|
-
getToolOutput(_workflowId, argsHash) {
|
|
102288
|
-
return this.inner.getToolOutput(this.scope.rootWorkflowId, this.scopeKey(argsHash));
|
|
102289
|
-
}
|
|
102290
|
-
getToolCheckpoint(_workflowId, argsHash) {
|
|
102291
|
-
return this.inner.getToolCheckpoint(this.scope.rootWorkflowId, this.scopeKey(argsHash));
|
|
102292
|
-
}
|
|
102293
|
-
getUiResponse(_workflowId, promptHash) {
|
|
102294
|
-
return this.inner.getUiResponse(this.scope.rootWorkflowId, this.scopeKey(promptHash));
|
|
102295
|
-
}
|
|
102296
|
-
getStageOutput(_workflowId, replayKey) {
|
|
102297
|
-
return this.inner.getStageOutput(this.scope.rootWorkflowId, this.scopeKey(replayKey));
|
|
102298
|
-
}
|
|
102299
|
-
getStageSession(_workflowId, replayKey) {
|
|
102300
|
-
return this.inner.getStageSession(this.scope.rootWorkflowId, this.scopeKey(replayKey));
|
|
102301
|
-
}
|
|
102302
|
-
listCheckpoints(workflowId) {
|
|
102303
|
-
const prefix = `${this.scope.scopePrefix}:`;
|
|
102304
|
-
return this.inner.listCheckpoints(this.scope.rootWorkflowId).filter((checkpoint) => checkpointHasPrefix(checkpoint, prefix)).map((checkpoint) => localCheckpoint(checkpoint, workflowId, prefix));
|
|
102305
|
-
}
|
|
102306
|
-
getWorkflow(_workflowId) {
|
|
102307
|
-
return;
|
|
102308
|
-
}
|
|
102309
|
-
getLoadableWorkflow(_workflowId) {
|
|
102310
|
-
return;
|
|
102311
|
-
}
|
|
102312
|
-
setWorkflowStatus(_workflowId, _status, _pendingPrompts, _resumable) {}
|
|
102313
|
-
async transitionWorkflowStatus(_workflowId, _expectedStatuses, _status, _pendingPrompts, _resumable) {
|
|
102314
|
-
return false;
|
|
102315
|
-
}
|
|
102316
|
-
adjustPendingPrompts(_workflowId, delta) {
|
|
102317
|
-
this.inner.adjustPendingPrompts(this.scope.rootWorkflowId, delta);
|
|
102318
|
-
}
|
|
102319
|
-
promptReservationScope(_workflowId) {
|
|
102320
|
-
return this.effectivePromptScope();
|
|
102321
|
-
}
|
|
102322
|
-
pendingPromptToken(_workflowId, reservationId) {
|
|
102323
|
-
return claimDurablePromptToken(this.inner, this.scope.rootWorkflowId, reservationId);
|
|
102324
|
-
}
|
|
102325
|
-
reservePendingPrompt(_workflowId, reservationId) {
|
|
102326
|
-
return reserveDurablePrompt(this.inner, this.scope.rootWorkflowId, reservationId);
|
|
102327
|
-
}
|
|
102328
|
-
releasePendingPrompt(_workflowId, reservationId, token) {
|
|
102329
|
-
releaseDurablePrompt(this.inner, this.scope.rootWorkflowId, reservationId, token);
|
|
102330
|
-
}
|
|
102331
|
-
listResumableWorkflows() {
|
|
102332
|
-
return [];
|
|
102333
|
-
}
|
|
102334
|
-
listCompletedWorkflows() {
|
|
102335
|
-
return [];
|
|
102336
|
-
}
|
|
102337
|
-
async prepareWorkflowCatalog() {
|
|
102338
|
-
return { resumable: [], completed: [] };
|
|
102339
|
-
}
|
|
102340
|
-
toMetadata(_workflowId) {
|
|
102341
|
-
return;
|
|
102342
|
-
}
|
|
102343
|
-
async deleteWorkflow(_workflowId) {}
|
|
102344
|
-
async deleteWorkflowIfInactive(_workflowId) {
|
|
102345
|
-
return { ok: false, reason: "not_found" };
|
|
102346
|
-
}
|
|
102347
|
-
isWorkflowLoadable(_workflowId) {
|
|
102348
|
-
return false;
|
|
102349
|
-
}
|
|
102350
|
-
reset() {}
|
|
102351
|
-
hydrateWorkflow(_workflowId) {
|
|
102352
|
-
return Promise.resolve();
|
|
102353
|
-
}
|
|
102354
|
-
hydrateWorkflowForInspection(_workflowId) {
|
|
102355
|
-
return Promise.resolve({ kind: "absent" });
|
|
102356
|
-
}
|
|
102357
|
-
hydrateResumableWorkflows() {
|
|
102358
|
-
return Promise.resolve();
|
|
102359
|
-
}
|
|
102360
|
-
effectivePromptScope() {
|
|
102361
|
-
const parent = durablePromptScope(this.inner, this.scope.rootWorkflowId);
|
|
102362
|
-
const scope = parent.scope === "root" ? this.scope.scopePrefix : `${parent.scope}:${this.scope.scopePrefix}`;
|
|
102363
|
-
return {
|
|
102364
|
-
rootWorkflowId: parent.rootWorkflowId,
|
|
102365
|
-
scope
|
|
102366
|
-
};
|
|
102367
|
-
}
|
|
102368
|
-
scopeKey(key) {
|
|
102369
|
-
return `${this.scope.scopePrefix}:${key}`;
|
|
102370
|
-
}
|
|
102371
|
-
remap(checkpoint) {
|
|
102372
|
-
const workflowId = this.scope.rootWorkflowId;
|
|
102373
|
-
if (checkpoint.kind === "tool") {
|
|
102374
|
-
return {
|
|
102375
|
-
...checkpoint,
|
|
102376
|
-
workflowId,
|
|
102377
|
-
checkpointId: this.scopeKey(checkpoint.checkpointId),
|
|
102378
|
-
argsHash: this.scopeKey(checkpoint.argsHash)
|
|
102379
|
-
};
|
|
102380
|
-
}
|
|
102381
|
-
if (checkpoint.kind === "ui") {
|
|
102382
|
-
return {
|
|
102383
|
-
...checkpoint,
|
|
102384
|
-
workflowId,
|
|
102385
|
-
checkpointId: this.scopeKey(checkpoint.checkpointId),
|
|
102386
|
-
promptHash: this.scopeKey(checkpoint.promptHash)
|
|
102387
|
-
};
|
|
102388
|
-
}
|
|
102389
|
-
return {
|
|
102390
|
-
...checkpoint,
|
|
102391
|
-
workflowId,
|
|
102392
|
-
checkpointId: this.scopeKey(checkpoint.checkpointId),
|
|
102393
|
-
replayKey: this.scopeKey(checkpoint.replayKey),
|
|
102394
|
-
...remappedBoundaryScope(checkpoint, this.scopeKey(checkpoint.topology?.boundary?.replayScope ?? ""))
|
|
102395
|
-
};
|
|
102396
|
-
}
|
|
102397
|
-
}
|
|
102398
|
-
function checkpointHasPrefix(checkpoint, prefix) {
|
|
102399
|
-
if (!checkpoint.checkpointId.startsWith(prefix))
|
|
102400
|
-
return false;
|
|
102401
|
-
if (checkpoint.kind === "tool")
|
|
102402
|
-
return checkpoint.argsHash.startsWith(prefix);
|
|
102403
|
-
if (checkpoint.kind === "ui")
|
|
102404
|
-
return checkpoint.promptHash.startsWith(prefix);
|
|
102405
|
-
return checkpoint.replayKey.startsWith(prefix);
|
|
102406
|
-
}
|
|
102407
|
-
function localCheckpoint(checkpoint, workflowId, prefix) {
|
|
102408
|
-
const checkpointId = checkpoint.checkpointId.slice(prefix.length);
|
|
102409
|
-
if (checkpoint.kind === "tool") {
|
|
102410
|
-
return { ...checkpoint, workflowId, checkpointId, argsHash: checkpoint.argsHash.slice(prefix.length) };
|
|
102411
|
-
}
|
|
102412
|
-
if (checkpoint.kind === "ui") {
|
|
102413
|
-
return { ...checkpoint, workflowId, checkpointId, promptHash: checkpoint.promptHash.slice(prefix.length) };
|
|
102414
|
-
}
|
|
102415
|
-
const replayKey = checkpoint.replayKey.slice(prefix.length);
|
|
102416
|
-
const replayScope = stripOnePrefix(checkpoint.topology?.boundary?.replayScope, prefix);
|
|
102417
|
-
return {
|
|
102418
|
-
...checkpoint,
|
|
102419
|
-
workflowId,
|
|
102420
|
-
checkpointId,
|
|
102421
|
-
replayKey,
|
|
102422
|
-
...remappedBoundaryScope(checkpoint, replayScope)
|
|
102423
|
-
};
|
|
102424
|
-
}
|
|
102425
|
-
function remappedBoundaryScope(checkpoint, replayScope) {
|
|
102426
|
-
const topology = checkpoint.topology;
|
|
102427
|
-
if (topology?.boundary === undefined || replayScope === undefined)
|
|
102428
|
-
return {};
|
|
102429
|
-
return {
|
|
102430
|
-
topology: {
|
|
102431
|
-
...topology,
|
|
102432
|
-
boundary: { ...topology.boundary, replayScope }
|
|
102433
|
-
}
|
|
102434
|
-
};
|
|
102435
|
-
}
|
|
102436
|
-
function stripOnePrefix(value2, prefix) {
|
|
102437
|
-
if (value2 === undefined || !value2.startsWith(prefix))
|
|
102438
|
-
return value2;
|
|
102439
|
-
return value2.slice(prefix.length);
|
|
102440
|
-
}
|
|
102642
|
+
init_dbos_process_owner();
|
|
102441
102643
|
|
|
102442
102644
|
// dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts
|
|
102443
102645
|
import { isAbsolute as isAbsolute12, join as join28, resolve as resolve12 } from "node:path";
|
|
@@ -109433,36 +109635,6 @@ function createReplayStageContext(input) {
|
|
|
109433
109635
|
};
|
|
109434
109636
|
}
|
|
109435
109637
|
|
|
109436
|
-
// dist/builtin/workflows/src/durable/run-owner-backend.ts
|
|
109437
|
-
function durableRootRunIdForRun(runs, runId) {
|
|
109438
|
-
return reciprocalWorkflowRootRunId(new Map(runs.map((run) => [run.id, run])), runId);
|
|
109439
|
-
}
|
|
109440
|
-
function durableBackendForRun(backend, runs, runId) {
|
|
109441
|
-
const rootRunId = durableRootRunIdForRun(runs, runId);
|
|
109442
|
-
if (rootRunId === undefined)
|
|
109443
|
-
return;
|
|
109444
|
-
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
109445
|
-
if (rootRunId === runId)
|
|
109446
|
-
return backend;
|
|
109447
|
-
const scopes = [];
|
|
109448
|
-
let current = runById.get(runId);
|
|
109449
|
-
while (current !== undefined && current.id !== rootRunId) {
|
|
109450
|
-
const parent = current.parentRunId === undefined ? undefined : runById.get(current.parentRunId);
|
|
109451
|
-
const boundary = parent?.stages.find((stage) => stage.id === current?.parentStageId);
|
|
109452
|
-
if (parent === undefined || boundary?.replayKey === undefined)
|
|
109453
|
-
return;
|
|
109454
|
-
scopes.push(boundary.replayKey);
|
|
109455
|
-
current = parent;
|
|
109456
|
-
}
|
|
109457
|
-
if (current?.id !== rootRunId)
|
|
109458
|
-
return;
|
|
109459
|
-
let view = backend;
|
|
109460
|
-
for (const scopePrefix of scopes.reverse()) {
|
|
109461
|
-
view = new ScopedDurableBackend(view, { rootWorkflowId: rootRunId, scopePrefix });
|
|
109462
|
-
}
|
|
109463
|
-
return view;
|
|
109464
|
-
}
|
|
109465
|
-
|
|
109466
109638
|
// dist/builtin/workflows/src/shared/pending-stage-route-capability.ts
|
|
109467
109639
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
109468
109640
|
var routeCapabilities = new WeakMap;
|
|
@@ -109521,14 +109693,21 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
109521
109693
|
};
|
|
109522
109694
|
return {
|
|
109523
109695
|
routeCapability: workflowPendingStageRouteCapability(activeStore, runId),
|
|
109524
|
-
deliverPending(deliver) {
|
|
109696
|
+
deliverPending(deliver, recipient) {
|
|
109525
109697
|
if (drainPromise !== undefined)
|
|
109526
109698
|
return drainPromise;
|
|
109527
109699
|
if (terminalError !== undefined)
|
|
109528
109700
|
return Promise.resolve();
|
|
109529
109701
|
drainError = undefined;
|
|
109530
|
-
const attempt = deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver);
|
|
109531
|
-
const drain = attempt.then(() =>
|
|
109702
|
+
const attempt = deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver, recipient);
|
|
109703
|
+
const drain = attempt.then(() => {
|
|
109704
|
+
resolveReady?.();
|
|
109705
|
+
readyPromise = undefined;
|
|
109706
|
+
resolveReady = undefined;
|
|
109707
|
+
rejectReady = undefined;
|
|
109708
|
+
if (drainPromise === drain)
|
|
109709
|
+
drainPromise = undefined;
|
|
109710
|
+
}, (error) => {
|
|
109532
109711
|
drainError = error;
|
|
109533
109712
|
rejectReady?.(error);
|
|
109534
109713
|
readyPromise = undefined;
|
|
@@ -109541,8 +109720,8 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
109541
109720
|
drainPromise = drain;
|
|
109542
109721
|
return drainPromise;
|
|
109543
109722
|
},
|
|
109544
|
-
ready() {
|
|
109545
|
-
if (activeStore.pendingStageMessagesFor(runId, stageId).length === 0 && (stageId === stageName || activeStore.pendingStageMessagesFor(runId, stageName).length === 0) && stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName).length === 0) {
|
|
109723
|
+
ready(sessionId) {
|
|
109724
|
+
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) {
|
|
109546
109725
|
return;
|
|
109547
109726
|
}
|
|
109548
109727
|
if (terminalError !== undefined)
|
|
@@ -109560,8 +109739,8 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
109560
109739
|
}
|
|
109561
109740
|
};
|
|
109562
109741
|
}
|
|
109563
|
-
async function deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver) {
|
|
109564
|
-
const stickyEntries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName);
|
|
109742
|
+
async function deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver, recipient) {
|
|
109743
|
+
const stickyEntries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient);
|
|
109565
109744
|
const candidateIds = new Set([
|
|
109566
109745
|
...activeStore.pendingStageMessagesFor(runId, stageId),
|
|
109567
109746
|
...activeStore.pendingStageMessagesFor(runId, stageName),
|
|
@@ -109583,7 +109762,8 @@ async function deliverPendingStageMessages(activeStore, runId, stageId, stageNam
|
|
|
109583
109762
|
if (releaseClaim === undefined)
|
|
109584
109763
|
continue;
|
|
109585
109764
|
try {
|
|
109586
|
-
|
|
109765
|
+
if (!recipient?.receivedMessageIds.includes(entry.message.id))
|
|
109766
|
+
await deliver(toPendingStageSender(entry), entry.message);
|
|
109587
109767
|
if (entry.sticky === true) {
|
|
109588
109768
|
const entryBackend = durableBackendForRun(rootBackend, activeStore.runs(), entry.runId);
|
|
109589
109769
|
if (entryBackend === undefined) {
|
|
@@ -109593,7 +109773,8 @@ async function deliverPendingStageMessages(activeStore, runId, stageId, stageNam
|
|
|
109593
109773
|
{
|
|
109594
109774
|
runId,
|
|
109595
109775
|
stageId,
|
|
109596
|
-
...stageName === stageId ? {} : { stageName }
|
|
109776
|
+
...stageName === stageId ? {} : { stageName },
|
|
109777
|
+
...recipient === undefined ? {} : { sessionId: recipient.sessionId, admission: "context" }
|
|
109597
109778
|
}
|
|
109598
109779
|
], new Date().toISOString(), entryBackend)) {
|
|
109599
109780
|
throw new Error(`atomic-workflows: pending-stage message ${entry.id} changed during delivery`);
|
|
@@ -109608,7 +109789,7 @@ async function deliverPendingStageMessages(activeStore, runId, stageId, stageNam
|
|
|
109608
109789
|
}
|
|
109609
109790
|
}
|
|
109610
109791
|
}
|
|
109611
|
-
function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName) {
|
|
109792
|
+
function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, recipient) {
|
|
109612
109793
|
const runs = activeStore.runs();
|
|
109613
109794
|
const rootRunId = durableRootRunIdForRun(runs, runId);
|
|
109614
109795
|
if (rootRunId === undefined)
|
|
@@ -109625,9 +109806,8 @@ function stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageNam
|
|
|
109625
109806
|
const parsed = entry.targetPath === undefined ? undefined : parseWorkflowStageTarget(entry.targetPath);
|
|
109626
109807
|
if (parsed === undefined || parsed.rootRunId !== rootRunId)
|
|
109627
109808
|
return false;
|
|
109628
|
-
if ((entry.deliveries ?? []).some((delivery) => delivery.runId === runId && delivery.stageId === stageId))
|
|
109809
|
+
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)))))
|
|
109629
109810
|
return false;
|
|
109630
|
-
}
|
|
109631
109811
|
return stageMatchesPathPattern(parsed.segments, hops, [stageId, stageName]);
|
|
109632
109812
|
});
|
|
109633
109813
|
}
|
|
@@ -112155,7 +112335,7 @@ class StageSessionController {
|
|
|
112155
112335
|
const attachedSession = session instanceof Promise ? await session : session;
|
|
112156
112336
|
this.reportStartupPhase("delivery-readiness");
|
|
112157
112337
|
try {
|
|
112158
|
-
await this.sharedOrchestrationContext?.pendingStageDelivery?.ready();
|
|
112338
|
+
await this.sharedOrchestrationContext?.pendingStageDelivery?.ready(attachedSession.sessionId);
|
|
112159
112339
|
await this.opts.onSessionReady?.();
|
|
112160
112340
|
if (this.disposed || this.opts.signal?.aborted || this.abortGeneration !== startGeneration)
|
|
112161
112341
|
throw this.staleCreationReason(startGeneration);
|
|
@@ -114130,7 +114310,7 @@ async function run(def, inputs, opts = {}) {
|
|
|
114130
114310
|
if (control === latestControl && !ownController.signal.aborted && isDbosDependencyError(error)) {
|
|
114131
114311
|
activeStore.recordRunExecutionState(runId, {
|
|
114132
114312
|
phase: "blocked_dependency",
|
|
114133
|
-
dependencyError: `Workflow database unavailable during ${status === "paused" ? "pause" : "resume"}; persistence not confirmed
|
|
114313
|
+
dependencyError: `Workflow database unavailable during ${status === "paused" ? "pause" : "resume"}; persistence not confirmed. ${error.message}`
|
|
114134
114314
|
});
|
|
114135
114315
|
if (status === "paused")
|
|
114136
114316
|
return;
|
|
@@ -114177,7 +114357,7 @@ async function run(def, inputs, opts = {}) {
|
|
|
114177
114357
|
if (!admission.admitting)
|
|
114178
114358
|
return pausePersistence;
|
|
114179
114359
|
backgroundAdmissionControl(durableBackend, runId, pausePersistence, (error, resumable) => {
|
|
114180
|
-
admissionControlError = unknownErrorMessage(error);
|
|
114360
|
+
admissionControlError = databaseDependencyMessage(unknownErrorMessage(error), getDbosProcessOwner().databaseDiagnostics?.());
|
|
114181
114361
|
runSnapshot.error = admissionControlError;
|
|
114182
114362
|
activeStore.recordRunPaused(runId, undefined, { resumable });
|
|
114183
114363
|
return runSnapshot.error;
|
|
@@ -114194,7 +114374,7 @@ async function run(def, inputs, opts = {}) {
|
|
|
114194
114374
|
} catch (error) {
|
|
114195
114375
|
if (admission.failed) {
|
|
114196
114376
|
scheduler.releaseRun();
|
|
114197
|
-
throw error;
|
|
114377
|
+
throw new Error(admissionControlError ?? databaseDependencyMessage(unknownErrorMessage(error), getDbosProcessOwner().databaseDiagnostics?.()));
|
|
114198
114378
|
}
|
|
114199
114379
|
}
|
|
114200
114380
|
if (generation !== pauseGeneration)
|
|
@@ -114267,12 +114447,21 @@ async function run(def, inputs, opts = {}) {
|
|
|
114267
114447
|
}).catch((error) => {
|
|
114268
114448
|
const isTopologyError = typeof error === "object" && error !== null && "name" in error && error.name === "DurableNestedTopologyError";
|
|
114269
114449
|
if (!isDbosDependencyError(error) && !isTopologyError) {
|
|
114270
|
-
|
|
114271
|
-
|
|
114450
|
+
const admissionDetail = unknownErrorMessage(error);
|
|
114451
|
+
const diagnostics = getDbosProcessOwner().databaseDiagnostics?.();
|
|
114452
|
+
const safeMessage = databaseDependencyMessage(admissionDetail, diagnostics);
|
|
114453
|
+
activeStore.recordRunExecutionState(runId, {
|
|
114454
|
+
phase: "blocked_dependency",
|
|
114455
|
+
dependencyError: safeMessage
|
|
114456
|
+
});
|
|
114457
|
+
const safeError = new Error(safeMessage);
|
|
114458
|
+
durableAdmissionFailure = { error: safeError };
|
|
114459
|
+
classifiedFailures.set(safeError, classifyWorkflowFailure({
|
|
114272
114460
|
code: "ATOMIC_DURABLE_ADMISSION_REJECTED",
|
|
114273
|
-
message:
|
|
114274
|
-
cause:
|
|
114461
|
+
message: safeMessage,
|
|
114462
|
+
cause: safeError
|
|
114275
114463
|
}));
|
|
114464
|
+
throw safeError;
|
|
114276
114465
|
}
|
|
114277
114466
|
throw error;
|
|
114278
114467
|
}), ownController.signal);
|
|
@@ -115582,7 +115771,11 @@ function createExtensionRuntime(opts = {}) {
|
|
|
115582
115771
|
const resolvePossibleStageEntry = opts.resolvePossibleStageEntry;
|
|
115583
115772
|
const beforeRestoreCompleted = opts.beforeRestoreCompleted;
|
|
115584
115773
|
const ensureDbosReady = async () => {
|
|
115585
|
-
|
|
115774
|
+
if (opts.prepareDatabase !== undefined)
|
|
115775
|
+
await opts.prepareDatabase();
|
|
115776
|
+
const backend = await initializeDurableBackend(durabilityWarningSink);
|
|
115777
|
+
opts.databaseReady?.();
|
|
115778
|
+
return backend;
|
|
115586
115779
|
};
|
|
115587
115780
|
function runOptions(policy) {
|
|
115588
115781
|
const defaultSessionDir = resolveDefaultStageSessionDir?.();
|
|
@@ -115853,6 +116046,95 @@ function createStatusWriter(store, config, opts = {}) {
|
|
|
115853
116046
|
};
|
|
115854
116047
|
}
|
|
115855
116048
|
|
|
116049
|
+
// dist/builtin/workflows/src/extension/workflow-database-settings.ts
|
|
116050
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
116051
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
116052
|
+
import { homedir as homedir3 } from "node:os";
|
|
116053
|
+
import { join as join33, resolve as resolve15 } from "node:path";
|
|
116054
|
+
import { getAgentDir as getAgentDir3, getAgentDirs as getAgentDirs3, getProjectConfigDirs, SettingsManager } from "@bastani/atomic";
|
|
116055
|
+
var DATABASE_SETTING_KEYS = new Set(["systemDatabaseUrl", "systemDatabaseUrlFile"]);
|
|
116056
|
+
function databaseSettings(settings) {
|
|
116057
|
+
const workflows = settings.workflows;
|
|
116058
|
+
if (workflows === undefined || workflows === null || Array.isArray(workflows))
|
|
116059
|
+
return;
|
|
116060
|
+
if (typeof workflows !== "object")
|
|
116061
|
+
throw new TypeError("workflows must be an array of paths or an object");
|
|
116062
|
+
return workflows.durability;
|
|
116063
|
+
}
|
|
116064
|
+
function readSettingsFile(directory) {
|
|
116065
|
+
let parsed;
|
|
116066
|
+
try {
|
|
116067
|
+
parsed = JSON.parse(readFileSync7(join33(directory, "settings.json"), "utf8").replace(/^\uFEFF/, ""));
|
|
116068
|
+
} catch {
|
|
116069
|
+
return;
|
|
116070
|
+
}
|
|
116071
|
+
return parsed !== null && typeof parsed === "object" ? parsed : undefined;
|
|
116072
|
+
}
|
|
116073
|
+
function settingsDirectoryDeclaringDatabase(directories) {
|
|
116074
|
+
let declaring;
|
|
116075
|
+
for (const directory of directories) {
|
|
116076
|
+
const settings = readSettingsFile(directory);
|
|
116077
|
+
if (settings !== undefined && databaseSettings(settings) !== undefined)
|
|
116078
|
+
declaring ??= directory;
|
|
116079
|
+
}
|
|
116080
|
+
return declaring ?? directories[0];
|
|
116081
|
+
}
|
|
116082
|
+
async function resolveWorkflowDatabaseSettings(global2, project, directories) {
|
|
116083
|
+
const projectDatabase = databaseSettings(project);
|
|
116084
|
+
const database = projectDatabase !== undefined ? projectDatabase : databaseSettings(global2);
|
|
116085
|
+
if (database === undefined)
|
|
116086
|
+
return;
|
|
116087
|
+
if (database === null || typeof database !== "object" || Array.isArray(database)) {
|
|
116088
|
+
throw new TypeError("workflows.durability must be an object");
|
|
116089
|
+
}
|
|
116090
|
+
if (Object.keys(database).some((key) => !DATABASE_SETTING_KEYS.has(key))) {
|
|
116091
|
+
throw new TypeError("workflows.durability supports only systemDatabaseUrl or systemDatabaseUrlFile");
|
|
116092
|
+
}
|
|
116093
|
+
const { systemDatabaseUrl: url, systemDatabaseUrlFile: file } = database;
|
|
116094
|
+
if (url !== undefined && file !== undefined) {
|
|
116095
|
+
throw new TypeError("Set only one of workflows.durability.systemDatabaseUrl and systemDatabaseUrlFile");
|
|
116096
|
+
}
|
|
116097
|
+
let value2 = url;
|
|
116098
|
+
if (file !== undefined) {
|
|
116099
|
+
if (typeof file !== "string" || file.trim() === "") {
|
|
116100
|
+
throw new TypeError("workflows.durability.systemDatabaseUrlFile must be a non-empty path");
|
|
116101
|
+
}
|
|
116102
|
+
const path = file.startsWith("~/") || file.startsWith("~\\") ? join33(homedir3(), file.slice(2)) : resolve15(projectDatabase === undefined ? directories.global : directories.project, file);
|
|
116103
|
+
try {
|
|
116104
|
+
value2 = await readFile6(path, "utf8");
|
|
116105
|
+
} catch {
|
|
116106
|
+
throw new Error("Cannot read workflows.durability.systemDatabaseUrlFile; check its path and permissions");
|
|
116107
|
+
}
|
|
116108
|
+
}
|
|
116109
|
+
if (value2 === undefined)
|
|
116110
|
+
return;
|
|
116111
|
+
if (typeof value2 !== "string" || value2.trim() === "") {
|
|
116112
|
+
throw new TypeError("Workflow database selection must contain a non-empty Postgres URL");
|
|
116113
|
+
}
|
|
116114
|
+
try {
|
|
116115
|
+
const parsed = new URL(value2.trim());
|
|
116116
|
+
if (!["postgres:", "postgresql:"].includes(parsed.protocol) || parsed.hostname === "")
|
|
116117
|
+
throw new Error;
|
|
116118
|
+
} catch {
|
|
116119
|
+
throw new TypeError("Workflow database selection must contain a valid Postgres URL");
|
|
116120
|
+
}
|
|
116121
|
+
return value2.trim();
|
|
116122
|
+
}
|
|
116123
|
+
async function prepareWorkflowDatabaseSettings(cwd, projectTrusted) {
|
|
116124
|
+
if (process.env.DBOS_SYSTEM_DATABASE_URL?.trim())
|
|
116125
|
+
return;
|
|
116126
|
+
const manager = SettingsManager.create(cwd, getAgentDir3(), { projectTrusted });
|
|
116127
|
+
if (manager.drainErrors().length > 0)
|
|
116128
|
+
throw new Error("Cannot read workflow database settings; repair settings.json");
|
|
116129
|
+
const projectDirectories = getProjectConfigDirs(cwd);
|
|
116130
|
+
const url = await resolveWorkflowDatabaseSettings(manager.getGlobalSettings(), manager.getProjectSettings(), {
|
|
116131
|
+
global: settingsDirectoryDeclaringDatabase(getAgentDirs3()),
|
|
116132
|
+
project: projectTrusted ? settingsDirectoryDeclaringDatabase(projectDirectories) : projectDirectories[0]
|
|
116133
|
+
});
|
|
116134
|
+
if (url !== undefined)
|
|
116135
|
+
requestDbosSystemDatabaseUrl(url);
|
|
116136
|
+
}
|
|
116137
|
+
|
|
115856
116138
|
// dist/builtin/workflows/src/extension/workflow-heartbeat-notice.ts
|
|
115857
116139
|
var WORKFLOW_HEARTBEAT_TITLE = "WORKFLOW HEARTBEAT";
|
|
115858
116140
|
var WORKFLOW_HEARTBEAT_GLYPH = "♥";
|
|
@@ -117004,6 +117286,45 @@ function createWorkflowExtensionRuntimeState(pi, adapters, options = {}) {
|
|
|
117004
117286
|
const resolveDefaultStageSessionDir = () => hostStageSessionDir.current;
|
|
117005
117287
|
const discoveryRef = { current: null };
|
|
117006
117288
|
const resolvePossibleStageEntry = (normalizedName) => discoveryRef.current?.sources.find((source) => source.id === normalizedName)?.filePath ?? resolveBuiltinDefinitionSource(normalizedName);
|
|
117289
|
+
let databasePreparation;
|
|
117290
|
+
const prepareDatabase = () => {
|
|
117291
|
+
const cwd = resolveCwd();
|
|
117292
|
+
const trusted = pi.getResourceLoaderInheritanceSnapshot?.()?.projectTrusted ?? false;
|
|
117293
|
+
const key = JSON.stringify([cwd, trusted]);
|
|
117294
|
+
if (databasePreparation?.key === key)
|
|
117295
|
+
return databasePreparation.promise;
|
|
117296
|
+
const promise = prepareWorkflowDatabaseSettings(cwd, trusted).catch((error) => {
|
|
117297
|
+
if (databasePreparation?.promise === promise)
|
|
117298
|
+
databasePreparation = undefined;
|
|
117299
|
+
throw error;
|
|
117300
|
+
});
|
|
117301
|
+
databasePreparation = { key, promise };
|
|
117302
|
+
return promise;
|
|
117303
|
+
};
|
|
117304
|
+
const databaseReady = (ctx) => {
|
|
117305
|
+
const owner = getDbosProcessOwner();
|
|
117306
|
+
const describeDatabase = owner.databaseDiagnostics;
|
|
117307
|
+
if (owner.state !== "ready" || describeDatabase === undefined)
|
|
117308
|
+
return;
|
|
117309
|
+
if (owner.announcedDatabaseDiagnostics === describeDatabase)
|
|
117310
|
+
return;
|
|
117311
|
+
const diagnostics = describeDatabase();
|
|
117312
|
+
const dockerFallback = diagnostics.provider === "docker";
|
|
117313
|
+
let host = "unknown host";
|
|
117314
|
+
try {
|
|
117315
|
+
host = new URL(diagnostics.url).host;
|
|
117316
|
+
} catch {}
|
|
117317
|
+
const message = `Workflow database: ${dockerFallback ? "Docker fallback" : diagnostics.provider} (${host})`;
|
|
117318
|
+
if (ctx?.hasUI && ctx.ui?.notify) {
|
|
117319
|
+
try {
|
|
117320
|
+
ctx.ui.notify(message, "info");
|
|
117321
|
+
owner.announcedDatabaseDiagnostics = describeDatabase;
|
|
117322
|
+
} catch {}
|
|
117323
|
+
} else if (dockerFallback) {
|
|
117324
|
+
owner.announcedDatabaseDiagnostics = describeDatabase;
|
|
117325
|
+
console.error(message);
|
|
117326
|
+
}
|
|
117327
|
+
};
|
|
117007
117328
|
const startupDiscovery = discoverStartupWorkflowsSync();
|
|
117008
117329
|
const runtimeRef = {
|
|
117009
117330
|
current: createExtensionRuntime({
|
|
@@ -117017,7 +117338,9 @@ function createWorkflowExtensionRuntimeState(pi, adapters, options = {}) {
|
|
|
117017
117338
|
config: runtimeConfigRef.current,
|
|
117018
117339
|
resolvePossibleStageEntry,
|
|
117019
117340
|
resolveDefaultStageSessionDir,
|
|
117020
|
-
beforeRestoreCompleted
|
|
117341
|
+
beforeRestoreCompleted,
|
|
117342
|
+
prepareDatabase,
|
|
117343
|
+
databaseReady
|
|
117021
117344
|
})
|
|
117022
117345
|
};
|
|
117023
117346
|
const configLoadRef = { current: null };
|
|
@@ -117082,7 +117405,9 @@ function createWorkflowExtensionRuntimeState(pi, adapters, options = {}) {
|
|
|
117082
117405
|
...models === undefined ? {} : { models },
|
|
117083
117406
|
...durabilityWarningSink === undefined ? {} : { durabilityWarningSink },
|
|
117084
117407
|
resolveDefaultStageSessionDir,
|
|
117085
|
-
beforeRestoreCompleted
|
|
117408
|
+
beforeRestoreCompleted,
|
|
117409
|
+
prepareDatabase,
|
|
117410
|
+
databaseReady: () => databaseReady(ctx)
|
|
117086
117411
|
});
|
|
117087
117412
|
}
|
|
117088
117413
|
let lazyDiscoveryPromise = null;
|
|
@@ -117121,7 +117446,9 @@ function createWorkflowExtensionRuntimeState(pi, adapters, options = {}) {
|
|
|
117121
117446
|
config: runtimeConfigRef.current,
|
|
117122
117447
|
resolvePossibleStageEntry,
|
|
117123
117448
|
resolveDefaultStageSessionDir,
|
|
117124
|
-
beforeRestoreCompleted
|
|
117449
|
+
beforeRestoreCompleted,
|
|
117450
|
+
prepareDatabase,
|
|
117451
|
+
databaseReady
|
|
117125
117452
|
});
|
|
117126
117453
|
}
|
|
117127
117454
|
function isWorkflowDiscoveryCurrent(generation) {
|
|
@@ -117623,6 +117950,22 @@ function possibleStageRows(runs, rootRunId, rootRun) {
|
|
|
117623
117950
|
return segments !== undefined && segments.length === 1 && segments[0] === "**";
|
|
117624
117951
|
}).length
|
|
117625
117952
|
});
|
|
117953
|
+
const statuses = stickyStageDeliveryStatuses(runs, rootRunId);
|
|
117954
|
+
for (const target of new Set(statuses.map((status) => status.target))) {
|
|
117955
|
+
if (rows.some((row) => row.target === target))
|
|
117956
|
+
continue;
|
|
117957
|
+
rows.push({
|
|
117958
|
+
target,
|
|
117959
|
+
queuedCount: stickyQueued.filter((entry) => (entry.targetPath ?? entry.stageKey) === target).length,
|
|
117960
|
+
deliveryOnly: true
|
|
117961
|
+
});
|
|
117962
|
+
}
|
|
117963
|
+
for (let index = 0;index < rows.length; index++) {
|
|
117964
|
+
const row = rows[index];
|
|
117965
|
+
const deliveryStates = statuses.filter((status) => status.target === row.target);
|
|
117966
|
+
if (deliveryStates.length > 0)
|
|
117967
|
+
rows[index] = { ...row, deliveryStates };
|
|
117968
|
+
}
|
|
117626
117969
|
return rows;
|
|
117627
117970
|
}
|
|
117628
117971
|
function materializedStageMatches(runs, rootRunId, entrySegments) {
|
|
@@ -117863,7 +118206,9 @@ async function recordConfirmedStickyDeliveries(activeStore, event) {
|
|
|
117863
118206
|
const records = matchingLiveStages(runs, rootRunId, parsedTarget.segments).filter((match) => delivered.has(match.target)).map((match) => ({
|
|
117864
118207
|
runId: match.run.id,
|
|
117865
118208
|
stageId: match.stage.id,
|
|
117866
|
-
...match.stage.name === match.stage.id ? {} : { stageName: match.stage.name }
|
|
118209
|
+
...match.stage.name === match.stage.id ? {} : { stageName: match.stage.name },
|
|
118210
|
+
...match.stage.sessionId === undefined ? {} : { sessionId: match.stage.sessionId },
|
|
118211
|
+
admission: "transport"
|
|
117867
118212
|
}));
|
|
117868
118213
|
if (records.length === 0)
|
|
117869
118214
|
return false;
|
|
@@ -120870,6 +121215,7 @@ function summarizeRunSnapshot(run, now = Date.now(), options) {
|
|
|
120870
121215
|
status: stage.status
|
|
120871
121216
|
})),
|
|
120872
121217
|
pendingStages: pendingWorkflowStageStatuses(run, options?.owningRunStatus, options?.resolveBoundarySegments),
|
|
121218
|
+
deliveryStates: stickyStageDeliveryStatuses(options?.allRuns ?? [run], run.id),
|
|
120873
121219
|
tools: (run.toolNodes ?? []).map((tool) => {
|
|
120874
121220
|
const owner = tool;
|
|
120875
121221
|
return {
|
|
@@ -121158,6 +121504,9 @@ function renderStatusToolContent(result) {
|
|
|
121158
121504
|
}
|
|
121159
121505
|
for (const entry of run.awaitingInput)
|
|
121160
121506
|
lines.push(statusAwaitingInputLine(entry));
|
|
121507
|
+
for (const delivery of run.deliveryStates ?? stickyStageDeliveryStatuses(allRuns, run.runId)) {
|
|
121508
|
+
lines.push(` Intercom delivery ${delivery.messageId} target=${delivery.target} stage=${delivery.runId}/${delivery.stageId}${delivery.sessionId === undefined ? "" : ` session=${delivery.sessionId}`} state=${delivery.state} — ${delivery.reason}`);
|
|
121509
|
+
}
|
|
121161
121510
|
for (const stage of run.pendingStages.slice(0, STATUS_PENDING_STAGE_LIMIT)) {
|
|
121162
121511
|
lines.push(statusPendingStageLine(stage));
|
|
121163
121512
|
}
|
|
@@ -122334,6 +122683,7 @@ function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflo
|
|
|
122334
122683
|
const statusByRunId = new Map(capturedRuns.map((run) => [run.id, run.status]));
|
|
122335
122684
|
const listing = buildWorkflowStatusListing(topLevelExpandedSnapshots(store), args.statusFilter ?? "all", Date.now(), {
|
|
122336
122685
|
toolControlRegistry,
|
|
122686
|
+
allRuns: capturedRuns,
|
|
122337
122687
|
owningRunStatus: (owningRunId) => statusByRunId.get(owningRunId),
|
|
122338
122688
|
resolveBoundarySegments: (runId) => workflowBoundarySegments(capturedRuns, runId)
|
|
122339
122689
|
});
|