@bastani/atomic 0.9.44-alpha.6 → 0.9.44-alpha.7
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 +14 -0
- package/dist/builtin/intercom/index.bundle.mjs +32 -4
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +141 -38
- package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +139 -30
- package/dist/builtin/workflows/src/index.js +139 -30
- package/dist/builtin/workflows/src/local-worker-entry.mjs +139 -30
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.44-alpha.7] - 2026-10-25
|
|
6
|
+
|
|
7
|
+
Workflow stages always get their queued Intercom messages and never wait forever to start, even around pauses, worker replacement and reconnects.
|
|
8
|
+
|
|
9
|
+
- **No stuck stages:** a stage no longer waits forever before its first turn for a pattern message it receives live, and never waits more than 60 seconds without delivery progress; any message still queued is delivered afterwards ([#3958](https://github.com/bastani-inc/atomic/pull/3958))
|
|
10
|
+
- **No lost messages:** a direct send to a paused, blocked or not-yet-started stage is queued for that stage and survives a pooled worker replacement, and messages missed while a stage was disconnected arrive after it reconnects, with their delivery mode and reply target intact ([#3958](https://github.com/bastani-inc/atomic/pull/3958), [#3959](https://github.com/bastani-inc/atomic/pull/3959))
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- An Intercom message sent to one specific workflow stage while that stage is paused, blocked or awaiting input and has not started yet is now queued for that stage and reaches it when it starts. Previously the send was accepted as a message for a possible future stage (`notInKnownSet`) and matched only the stage's old id, so it was lost when the stage started under a new id, as it does when a pooled worker is replaced. Messages sent to the whole run (`workflow:<rootRunId>/**`) were not affected ([#3869](https://github.com/bastani-inc/atomic/issues/3869))
|
|
15
|
+
- A workflow stage no longer waits forever before its first turn when an Intercom message to a pattern target such as `workflow:<run>/child-a/**` is queued just after the stage's queued messages were delivered at startup. The stage now starts once that startup delivery has finished, and later messages reach it as ordinary live messages. Before, the stage waited for a second delivery that never ran, so its prompt was never sent and its pooled work stayed leased with its lease still renewed. In a 640-child pooled load test this left 7 children (about 1%) stuck for 20–45 minutes.
|
|
16
|
+
- A workflow stage never waits more than 60 seconds without delivery progress for its queued Intercom messages before it starts. If a startup delivery stops making progress, the stage logs one warning that names the undelivered messages and whether the delivery is still running. It then starts, and the messages stay queued: they arrive live or on the stage's next delivery.
|
|
17
|
+
- A sticky Intercom message that could not reach a workflow stage while the stage was disconnected from the broker is now delivered when the stage reconnects, exactly as it would have arrived live: an `interrupt` still cancels the stage's running operation, and an ask becomes the stage's reply target. Messages the stage already has are not delivered again.
|
|
18
|
+
|
|
5
19
|
## [0.9.44-alpha.6] - 2026-10-25
|
|
6
20
|
|
|
7
21
|
Large workflow fan-outs stay fast for the whole run and recover cleanly from a crash, even with hundreds of pooled child workflows messaging each other.
|
|
@@ -7923,11 +7923,12 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
7923
7923
|
scheduleInboundFlush();
|
|
7924
7924
|
return plan.notices ?? [];
|
|
7925
7925
|
}
|
|
7926
|
-
|
|
7926
|
+
let redrainPendingStage = null;
|
|
7927
|
+
function handleIncomingMessage(ctx, from, message, channel, receivedBeforeStageStart = false, recoveredAfterStageStart = false) {
|
|
7927
7928
|
const messageGeneration = runtimeGeneration;
|
|
7928
7929
|
const liveContext = getLiveContext(ctx, messageGeneration);
|
|
7929
7930
|
if (!liveContext) {
|
|
7930
|
-
if (receivedBeforeStageStart)
|
|
7931
|
+
if (receivedBeforeStageStart || recoveredAfterStageStart)
|
|
7931
7932
|
throw new Error("Intercom session retired before pending-stage delivery; message remains queued");
|
|
7932
7933
|
return;
|
|
7933
7934
|
}
|
|
@@ -7988,6 +7989,13 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
7988
7989
|
});
|
|
7989
7990
|
}, () => foregroundDetachHandoff.claim(from, message, messageGeneration, () => Boolean(getLiveContext(liveContext, messageGeneration))), release);
|
|
7990
7991
|
if (activeDelivery !== false) {
|
|
7992
|
+
if (recoveredAfterStageStart) {
|
|
7993
|
+
return activeDelivery.then(commit, (error) => {
|
|
7994
|
+
replyTracker.forgetIncomingMessage(replyContext);
|
|
7995
|
+
inboundDeliveries.release(reservation, toError3(error));
|
|
7996
|
+
throw error;
|
|
7997
|
+
});
|
|
7998
|
+
}
|
|
7991
7999
|
activeDelivery.then(commit, release);
|
|
7992
8000
|
return;
|
|
7993
8001
|
}
|
|
@@ -8553,6 +8561,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
8553
8561
|
if (nextClient.sessionId && nextClient.sessionId !== preferredSessionId) {
|
|
8554
8562
|
await recordIntercomSessionIdentity(sessionIdAtStart, nextClient.sessionId);
|
|
8555
8563
|
}
|
|
8564
|
+
if (reason !== "startup")
|
|
8565
|
+
redrainPendingStage?.();
|
|
8556
8566
|
return nextClient;
|
|
8557
8567
|
} catch (error) {
|
|
8558
8568
|
if (client === nextClient) {
|
|
@@ -8788,18 +8798,36 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
8788
8798
|
await ensureConnected("startup");
|
|
8789
8799
|
return;
|
|
8790
8800
|
}
|
|
8791
|
-
const
|
|
8801
|
+
const generation = runtimeGeneration;
|
|
8802
|
+
const deliverPending = async (started = false) => {
|
|
8792
8803
|
const receivedMessageIds = ctx.sessionManager.getBranch().flatMap((entry) => {
|
|
8793
8804
|
if (entry.type !== "custom_message" || entry.customType !== "intercom_message")
|
|
8794
8805
|
return [];
|
|
8795
8806
|
const id = entry.details?.message?.id;
|
|
8796
8807
|
return typeof id === "string" ? [id] : [];
|
|
8797
8808
|
});
|
|
8798
|
-
await pendingStageDelivery.deliverPending((from, message) => handleIncomingMessage(ctx, from, message, undefined, true), { sessionId: ctx.sessionManager.getSessionId(), receivedMessageIds });
|
|
8809
|
+
await pendingStageDelivery.deliverPending((from, message) => started ? handleIncomingMessage(ctx, from, message, undefined, false, true) : handleIncomingMessage(ctx, from, message, undefined, true), { sessionId: ctx.sessionManager.getSessionId(), receivedMessageIds });
|
|
8799
8810
|
};
|
|
8811
|
+
let startupDrained = false;
|
|
8812
|
+
let redrainRequested = false;
|
|
8813
|
+
const redrain = () => {
|
|
8814
|
+
if (!getLiveContext(ctx, generation))
|
|
8815
|
+
return;
|
|
8816
|
+
if (!startupDrained) {
|
|
8817
|
+
redrainRequested = true;
|
|
8818
|
+
return;
|
|
8819
|
+
}
|
|
8820
|
+
deliverPending(true).catch(() => {});
|
|
8821
|
+
};
|
|
8822
|
+
redrainPendingStage = redrain;
|
|
8800
8823
|
await deliverPending();
|
|
8801
8824
|
await ensureConnected("startup");
|
|
8802
8825
|
await deliverPending();
|
|
8826
|
+
startupDrained = true;
|
|
8827
|
+
if (redrainRequested) {
|
|
8828
|
+
redrainRequested = false;
|
|
8829
|
+
redrain();
|
|
8830
|
+
}
|
|
8803
8831
|
});
|
|
8804
8832
|
pi.registerMessageRenderer("intercom_message", (message, _options, theme) => {
|
|
8805
8833
|
const details = message.details;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/intercom",
|
|
3
|
-
"version": "0.9.44-alpha.
|
|
3
|
+
"version": "0.9.44-alpha.7",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension providing a private coordination channel between parent and child agent sessions. Fork of: https://github.com/nicobailon/pi-intercom",
|
|
6
6
|
"contributors": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/subagents",
|
|
3
|
-
"version": "0.9.44-alpha.
|
|
3
|
+
"version": "0.9.44-alpha.7",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for delegating tasks to subagents with parallel execution. Fork of: https://github.com/nicobailon/pi-subagents",
|
|
6
6
|
"contributors": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/web-access",
|
|
3
|
-
"version": "0.9.44-alpha.
|
|
3
|
+
"version": "0.9.44-alpha.7",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for web search, URL fetching, GitHub repo cloning, PDF/video extraction. Fork of: https://github.com/nicobailon/pi-web-access",
|
|
6
6
|
"contributors": [
|
|
@@ -2072,6 +2072,9 @@ var init_workflow_stage_target = __esm(() => {
|
|
|
2072
2072
|
});
|
|
2073
2073
|
|
|
2074
2074
|
// dist/builtin/workflows/src/shared/pending-stage-status.ts
|
|
2075
|
+
function isAddressableStageStatus(status) {
|
|
2076
|
+
return ADDRESSABLE_STAGE_STATUSES.has(status);
|
|
2077
|
+
}
|
|
2075
2078
|
function workflowBoundarySegments(runs, runId) {
|
|
2076
2079
|
return createWorkflowBoundarySegmentsResolver(runs)(runId);
|
|
2077
2080
|
}
|
|
@@ -2220,9 +2223,17 @@ function pendingWorkflowStageStatuses(run, resolveOwningRunStatus, resolveBounda
|
|
|
2220
2223
|
return pending === undefined ? [] : [pending];
|
|
2221
2224
|
});
|
|
2222
2225
|
}
|
|
2226
|
+
var ADDRESSABLE_STAGE_STATUSES;
|
|
2223
2227
|
var init_pending_stage_status = __esm(() => {
|
|
2224
2228
|
init_store_internal();
|
|
2225
2229
|
init_workflow_stage_target();
|
|
2230
|
+
ADDRESSABLE_STAGE_STATUSES = new Set([
|
|
2231
|
+
"pending",
|
|
2232
|
+
"running",
|
|
2233
|
+
"awaiting_input",
|
|
2234
|
+
"paused",
|
|
2235
|
+
"blocked"
|
|
2236
|
+
]);
|
|
2226
2237
|
});
|
|
2227
2238
|
|
|
2228
2239
|
// dist/builtin/workflows/src/shared/timing.ts
|
|
@@ -62531,7 +62542,7 @@ function registerPendingStageIntercomBridge(pi, activeStore, ownsRun = () => tru
|
|
|
62531
62542
|
stageName: stage.name,
|
|
62532
62543
|
target: stageRouteTarget(runs, rootRunId, run.id, stage.id, resolveBoundarySegments),
|
|
62533
62544
|
lifecycle: stage.sessionId === undefined && stage.sessionFile === undefined ? "pending" : "running",
|
|
62534
|
-
routeEligible: stage.pendingStageDeliveryAvailable === true && (stage.status
|
|
62545
|
+
routeEligible: stage.pendingStageDeliveryAvailable === true && isAddressableStageStatus(stage.status),
|
|
62535
62546
|
group: stage.intercomGroup ?? workflowInvocationIntercomGroup(rootRunId)
|
|
62536
62547
|
})),
|
|
62537
62548
|
...nonAgentNodes(run).map((node) => ({
|
|
@@ -63034,7 +63045,7 @@ function knownUninitializedStage(run, stageKey) {
|
|
|
63034
63045
|
if (candidates.length !== 1)
|
|
63035
63046
|
return;
|
|
63036
63047
|
const stage = candidates[0];
|
|
63037
|
-
return (stage.status
|
|
63048
|
+
return isAddressableStageStatus(stage.status) && stage.sessionId === undefined && stage.sessionFile === undefined ? stage : undefined;
|
|
63038
63049
|
}
|
|
63039
63050
|
function pendingStageDestination(run, entry) {
|
|
63040
63051
|
if (entry.stageId !== undefined) {
|
|
@@ -67730,15 +67741,74 @@ function isWorkflowPendingStageDeliveryFailure(error) {
|
|
|
67730
67741
|
return true;
|
|
67731
67742
|
return error?.code === "pending_stage_delivery_failed";
|
|
67732
67743
|
}
|
|
67733
|
-
function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageName, commit = (action) => action()) {
|
|
67744
|
+
function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageName, commit = (action) => action(), options = {}) {
|
|
67734
67745
|
let resolveReady;
|
|
67735
67746
|
let rejectReady;
|
|
67736
67747
|
let readyPromise;
|
|
67737
67748
|
let drainError;
|
|
67738
67749
|
let terminalError;
|
|
67739
67750
|
let drainPromise;
|
|
67751
|
+
let drainedSessionId;
|
|
67740
67752
|
let currentRecipient;
|
|
67741
|
-
|
|
67753
|
+
let lastProgressAt = Date.now();
|
|
67754
|
+
let stallReported = false;
|
|
67755
|
+
const progress = () => {
|
|
67756
|
+
lastProgressAt = Date.now();
|
|
67757
|
+
};
|
|
67758
|
+
const progressingCommit = async (action) => {
|
|
67759
|
+
try {
|
|
67760
|
+
return await commit(action);
|
|
67761
|
+
} finally {
|
|
67762
|
+
progress();
|
|
67763
|
+
}
|
|
67764
|
+
};
|
|
67765
|
+
const reportStall = (sessionId) => {
|
|
67766
|
+
if (stallReported)
|
|
67767
|
+
return;
|
|
67768
|
+
stallReported = true;
|
|
67769
|
+
const undelivered = [
|
|
67770
|
+
...activeStore.pendingStageMessagesFor(runId, stageId),
|
|
67771
|
+
...stageId === stageName ? [] : activeStore.pendingStageMessagesFor(runId, stageName)
|
|
67772
|
+
].map((entry) => `${entry.message.id} (direct → ${entry.stageKey})`).concat(stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, sessionId === undefined ? undefined : { sessionId }).map((entry) => `${entry.message.id} (sticky → ${entry.targetPath ?? entry.stageKey})`));
|
|
67773
|
+
const listed = undelivered.slice(0, 10).join(", ");
|
|
67774
|
+
const more = undelivered.length > 10 ? `, and ${undelivered.length - 10} more` : "";
|
|
67775
|
+
const message = `atomic-workflows: stage "${stageName}" (${stageId}) is starting without its queued Intercom messages: ` + `no delivery progress for ${PENDING_STAGE_READY_STALL_MS / 1000}s; ` + `drain ${drainPromise === undefined ? "not running" : "running but hung"}; ` + `undelivered: ${listed.length === 0 ? "none" : `${listed}${more}`}. ` + "They stay queued and arrive live or on the stage's next drain.";
|
|
67776
|
+
try {
|
|
67777
|
+
(options.reportStall ?? console.warn)(message);
|
|
67778
|
+
} catch {}
|
|
67779
|
+
};
|
|
67780
|
+
const watchStall = (pending, sessionId, onStall) => {
|
|
67781
|
+
let timer;
|
|
67782
|
+
let settled = false;
|
|
67783
|
+
const check = () => {
|
|
67784
|
+
if (settled)
|
|
67785
|
+
return;
|
|
67786
|
+
const remaining = lastProgressAt + PENDING_STAGE_READY_STALL_MS - Date.now();
|
|
67787
|
+
if (remaining > 0) {
|
|
67788
|
+
timer = setTimeout(check, remaining);
|
|
67789
|
+
timer.unref?.();
|
|
67790
|
+
return;
|
|
67791
|
+
}
|
|
67792
|
+
reportStall(sessionId);
|
|
67793
|
+
onStall();
|
|
67794
|
+
};
|
|
67795
|
+
const stop = () => {
|
|
67796
|
+
settled = true;
|
|
67797
|
+
clearTimeout(timer);
|
|
67798
|
+
};
|
|
67799
|
+
pending.then(stop, stop);
|
|
67800
|
+
check();
|
|
67801
|
+
};
|
|
67802
|
+
const boundedDrain = (drain, sessionId) => {
|
|
67803
|
+
const waiting = new Promise((resolve, reject) => {
|
|
67804
|
+
drain.then(resolve, reject);
|
|
67805
|
+
watchStall(drain, sessionId, resolve);
|
|
67806
|
+
});
|
|
67807
|
+
waiting.catch(() => {});
|
|
67808
|
+
return waiting;
|
|
67809
|
+
};
|
|
67810
|
+
const hasUndeliveredExact = () => activeStore.pendingStageMessagesFor(runId, stageId).length > 0 || stageId !== stageName && activeStore.pendingStageMessagesFor(runId, stageName).length > 0;
|
|
67811
|
+
const hasUndelivered = (sessionId) => hasUndeliveredExact() || stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, sessionId === undefined ? undefined : { sessionId }).length > 0;
|
|
67742
67812
|
const pendingReady = () => {
|
|
67743
67813
|
if (readyPromise === undefined) {
|
|
67744
67814
|
readyPromise = new Promise((resolve, reject) => {
|
|
@@ -67748,35 +67818,64 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
67748
67818
|
}
|
|
67749
67819
|
return readyPromise;
|
|
67750
67820
|
};
|
|
67821
|
+
let followUp;
|
|
67822
|
+
const startDrain = (deliver, recipient) => {
|
|
67823
|
+
if (terminalError !== undefined)
|
|
67824
|
+
return Promise.resolve();
|
|
67825
|
+
drainError = undefined;
|
|
67826
|
+
progress();
|
|
67827
|
+
const attempt = deliverPendingStageMessages(activeStore, runId, stageId, stageName, async (from, message) => {
|
|
67828
|
+
progress();
|
|
67829
|
+
await deliver(from, message);
|
|
67830
|
+
progress();
|
|
67831
|
+
}, progressingCommit, recipient);
|
|
67832
|
+
const drain = attempt.then(() => {
|
|
67833
|
+
progress();
|
|
67834
|
+
drainedSessionId = recipient?.sessionId;
|
|
67835
|
+
resolveReady?.();
|
|
67836
|
+
readyPromise = undefined;
|
|
67837
|
+
resolveReady = undefined;
|
|
67838
|
+
rejectReady = undefined;
|
|
67839
|
+
if (drainPromise === drain)
|
|
67840
|
+
drainPromise = undefined;
|
|
67841
|
+
}, (error) => {
|
|
67842
|
+
progress();
|
|
67843
|
+
drainError = error;
|
|
67844
|
+
rejectReady?.(error);
|
|
67845
|
+
readyPromise = undefined;
|
|
67846
|
+
resolveReady = undefined;
|
|
67847
|
+
rejectReady = undefined;
|
|
67848
|
+
if (drainPromise === drain)
|
|
67849
|
+
drainPromise = undefined;
|
|
67850
|
+
throw error;
|
|
67851
|
+
});
|
|
67852
|
+
drainPromise = drain;
|
|
67853
|
+
return boundedDrain(drain, recipient?.sessionId);
|
|
67854
|
+
};
|
|
67855
|
+
const requestDrain = (deliver, recipient) => {
|
|
67856
|
+
const running = drainPromise;
|
|
67857
|
+
if (running === undefined)
|
|
67858
|
+
return startDrain(deliver, recipient);
|
|
67859
|
+
if (followUp !== undefined) {
|
|
67860
|
+
followUp.deliver = deliver;
|
|
67861
|
+
followUp.recipient = recipient;
|
|
67862
|
+
return boundedDrain(followUp.settled.promise, recipient?.sessionId);
|
|
67863
|
+
}
|
|
67864
|
+
const next = { deliver, recipient, settled: Promise.withResolvers() };
|
|
67865
|
+
next.settled.promise.catch(() => {});
|
|
67866
|
+
followUp = next;
|
|
67867
|
+
running.catch(() => {}).then(() => {
|
|
67868
|
+
if (followUp === next)
|
|
67869
|
+
followUp = undefined;
|
|
67870
|
+
return requestDrain(next.deliver, next.recipient);
|
|
67871
|
+
}).then(next.settled.resolve, next.settled.reject);
|
|
67872
|
+
return boundedDrain(next.settled.promise, recipient?.sessionId);
|
|
67873
|
+
};
|
|
67751
67874
|
return {
|
|
67752
67875
|
routeCapability: workflowPendingStageRouteCapability(activeStore, runId),
|
|
67753
67876
|
deliverPending(deliver, recipient) {
|
|
67754
67877
|
currentRecipient = recipient;
|
|
67755
|
-
|
|
67756
|
-
return drainPromise;
|
|
67757
|
-
if (terminalError !== undefined)
|
|
67758
|
-
return Promise.resolve();
|
|
67759
|
-
drainError = undefined;
|
|
67760
|
-
const attempt = deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver, commit, recipient);
|
|
67761
|
-
const drain = attempt.then(() => {
|
|
67762
|
-
resolveReady?.();
|
|
67763
|
-
readyPromise = undefined;
|
|
67764
|
-
resolveReady = undefined;
|
|
67765
|
-
rejectReady = undefined;
|
|
67766
|
-
if (drainPromise === drain)
|
|
67767
|
-
drainPromise = undefined;
|
|
67768
|
-
}, (error) => {
|
|
67769
|
-
drainError = error;
|
|
67770
|
-
rejectReady?.(error);
|
|
67771
|
-
readyPromise = undefined;
|
|
67772
|
-
resolveReady = undefined;
|
|
67773
|
-
rejectReady = undefined;
|
|
67774
|
-
if (drainPromise === drain)
|
|
67775
|
-
drainPromise = undefined;
|
|
67776
|
-
throw error;
|
|
67777
|
-
});
|
|
67778
|
-
drainPromise = drain;
|
|
67779
|
-
return drainPromise;
|
|
67878
|
+
return requestDrain(deliver, recipient);
|
|
67780
67879
|
},
|
|
67781
67880
|
ready(sessionId) {
|
|
67782
67881
|
if (!hasUndelivered(sessionId)) {
|
|
@@ -67786,6 +67885,8 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
67786
67885
|
return Promise.reject(terminalError);
|
|
67787
67886
|
if (drainError !== undefined)
|
|
67788
67887
|
return Promise.reject(drainError);
|
|
67888
|
+
if (drainPromise === undefined && sessionId !== undefined && drainedSessionId === sessionId && !hasUndeliveredExact())
|
|
67889
|
+
return;
|
|
67789
67890
|
const ready = pendingReady();
|
|
67790
67891
|
if (sessionId !== undefined && activeStore.pendingStageMessagesFor(runId, stageId).length === 0 && activeStore.pendingStageMessagesFor(runId, stageName).length === 0) {
|
|
67791
67892
|
const entries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, { sessionId });
|
|
@@ -67809,6 +67910,14 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
67809
67910
|
rejectReady?.(error);
|
|
67810
67911
|
});
|
|
67811
67912
|
}
|
|
67913
|
+
watchStall(ready, sessionId, () => {
|
|
67914
|
+
if (readyPromise !== ready)
|
|
67915
|
+
return;
|
|
67916
|
+
resolveReady?.();
|
|
67917
|
+
readyPromise = undefined;
|
|
67918
|
+
resolveReady = undefined;
|
|
67919
|
+
rejectReady = undefined;
|
|
67920
|
+
});
|
|
67812
67921
|
return ready;
|
|
67813
67922
|
},
|
|
67814
67923
|
fail(reason) {
|
|
@@ -67936,7 +68045,7 @@ function toPendingStageSender(entry) {
|
|
|
67936
68045
|
lastActivity: entry.from.lastActivity ?? entry.message.timestamp
|
|
67937
68046
|
};
|
|
67938
68047
|
}
|
|
67939
|
-
var pendingDeliveryClaims, WorkflowPendingStageDeliveryFailedError;
|
|
68048
|
+
var pendingDeliveryClaims, WorkflowPendingStageDeliveryFailedError, PENDING_STAGE_READY_STALL_MS = 60000;
|
|
67940
68049
|
var init_pending_stage_delivery2 = __esm(() => {
|
|
67941
68050
|
init_run_owner_backend();
|
|
67942
68051
|
init_store_backend();
|
|
@@ -90467,6 +90576,7 @@ init_sdk_recovery_scope();
|
|
|
90467
90576
|
init_intercom_group();
|
|
90468
90577
|
init_pending_stage_delivery();
|
|
90469
90578
|
init_pending_stage_route_capability();
|
|
90579
|
+
init_pending_stage_status();
|
|
90470
90580
|
|
|
90471
90581
|
// dist/builtin/workflows/src/shared/persistence-restore.ts
|
|
90472
90582
|
init_persistence_restore_helpers();
|
|
@@ -90587,13 +90697,6 @@ var PENDING_STAGE_MESSAGE_EVENT3 = "atomic:workflow-pending-stage-message";
|
|
|
90587
90697
|
var PENDING_STAGE_ROUTE_REVOKED_EVENT = "atomic:workflow-pending-stage-route-revoked";
|
|
90588
90698
|
var DORMANT_RUN_SUBAGENT_HOLD_EVENT = "atomic:workflow-dormant-run-subagent-hold";
|
|
90589
90699
|
var DORMANT_RUN_RECHECK_MS = 15000;
|
|
90590
|
-
var ADDRESSABLE_STAGE_STATUSES = new Set([
|
|
90591
|
-
"pending",
|
|
90592
|
-
"running",
|
|
90593
|
-
"awaiting_input",
|
|
90594
|
-
"paused",
|
|
90595
|
-
"blocked"
|
|
90596
|
-
]);
|
|
90597
90700
|
var DORMANT_ASK_REFUSAL = "Cannot ask a stage of an interrupted workflow run. Use send; Atomic will queue the message until the run is resumed.";
|
|
90598
90701
|
function registerDormantRunIntercomRoutes(pi, activeStore, deps) {
|
|
90599
90702
|
const reportWarning = createWorkflowBackgroundWarningReporter(pi);
|
|
@@ -90882,7 +90985,7 @@ function queueRefusal(result, target) {
|
|
|
90882
90985
|
return { outcome: "refused", reason: "Target workflow run is in a different intercom group" };
|
|
90883
90986
|
}
|
|
90884
90987
|
function isAddressableStage(stage) {
|
|
90885
|
-
return
|
|
90988
|
+
return isAddressableStageStatus(stage.status) && stage.nodeKind !== "tool" && stage.replayKey?.startsWith("prompt:") !== true;
|
|
90886
90989
|
}
|
|
90887
90990
|
function isDormantMessageEvent(value2) {
|
|
90888
90991
|
if (typeof value2 !== "object" || value2 === null)
|
|
@@ -58349,6 +58349,9 @@ var init_workflow_stage_target = __esm(() => {
|
|
|
58349
58349
|
});
|
|
58350
58350
|
|
|
58351
58351
|
// dist/builtin/workflows/src/shared/pending-stage-status.ts
|
|
58352
|
+
function isAddressableStageStatus(status) {
|
|
58353
|
+
return ADDRESSABLE_STAGE_STATUSES.has(status);
|
|
58354
|
+
}
|
|
58352
58355
|
function workflowBoundarySegments(runs, runId) {
|
|
58353
58356
|
return createWorkflowBoundarySegmentsResolver(runs)(runId);
|
|
58354
58357
|
}
|
|
@@ -58471,9 +58474,17 @@ function createStagePathPatternIndex(patterns) {
|
|
|
58471
58474
|
}
|
|
58472
58475
|
};
|
|
58473
58476
|
}
|
|
58477
|
+
var ADDRESSABLE_STAGE_STATUSES;
|
|
58474
58478
|
var init_pending_stage_status = __esm(() => {
|
|
58475
58479
|
init_store_internal();
|
|
58476
58480
|
init_workflow_stage_target();
|
|
58481
|
+
ADDRESSABLE_STAGE_STATUSES = new Set([
|
|
58482
|
+
"pending",
|
|
58483
|
+
"running",
|
|
58484
|
+
"awaiting_input",
|
|
58485
|
+
"paused",
|
|
58486
|
+
"blocked"
|
|
58487
|
+
]);
|
|
58477
58488
|
});
|
|
58478
58489
|
|
|
58479
58490
|
// dist/builtin/workflows/src/shared/sticky-delivery-state-bound.ts
|
|
@@ -59187,7 +59198,7 @@ function registerPendingStageIntercomBridge(pi, activeStore, ownsRun = () => tru
|
|
|
59187
59198
|
stageName: stage.name,
|
|
59188
59199
|
target: stageRouteTarget(runs, rootRunId, run.id, stage.id, resolveBoundarySegments),
|
|
59189
59200
|
lifecycle: stage.sessionId === undefined && stage.sessionFile === undefined ? "pending" : "running",
|
|
59190
|
-
routeEligible: stage.pendingStageDeliveryAvailable === true && (stage.status
|
|
59201
|
+
routeEligible: stage.pendingStageDeliveryAvailable === true && isAddressableStageStatus(stage.status),
|
|
59191
59202
|
group: stage.intercomGroup ?? workflowInvocationIntercomGroup(rootRunId)
|
|
59192
59203
|
})),
|
|
59193
59204
|
...nonAgentNodes(run).map((node) => ({
|
|
@@ -59690,7 +59701,7 @@ function knownUninitializedStage(run, stageKey) {
|
|
|
59690
59701
|
if (candidates.length !== 1)
|
|
59691
59702
|
return;
|
|
59692
59703
|
const stage = candidates[0];
|
|
59693
|
-
return (stage.status
|
|
59704
|
+
return isAddressableStageStatus(stage.status) && stage.sessionId === undefined && stage.sessionFile === undefined ? stage : undefined;
|
|
59694
59705
|
}
|
|
59695
59706
|
function pendingStageDestination(run, entry) {
|
|
59696
59707
|
if (entry.stageId !== undefined) {
|
|
@@ -64371,15 +64382,74 @@ function isWorkflowPendingStageDeliveryFailure(error) {
|
|
|
64371
64382
|
return true;
|
|
64372
64383
|
return error?.code === "pending_stage_delivery_failed";
|
|
64373
64384
|
}
|
|
64374
|
-
function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageName, commit = (action) => action()) {
|
|
64385
|
+
function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageName, commit = (action) => action(), options = {}) {
|
|
64375
64386
|
let resolveReady;
|
|
64376
64387
|
let rejectReady;
|
|
64377
64388
|
let readyPromise;
|
|
64378
64389
|
let drainError;
|
|
64379
64390
|
let terminalError;
|
|
64380
64391
|
let drainPromise;
|
|
64392
|
+
let drainedSessionId;
|
|
64381
64393
|
let currentRecipient;
|
|
64382
|
-
|
|
64394
|
+
let lastProgressAt = Date.now();
|
|
64395
|
+
let stallReported = false;
|
|
64396
|
+
const progress = () => {
|
|
64397
|
+
lastProgressAt = Date.now();
|
|
64398
|
+
};
|
|
64399
|
+
const progressingCommit = async (action) => {
|
|
64400
|
+
try {
|
|
64401
|
+
return await commit(action);
|
|
64402
|
+
} finally {
|
|
64403
|
+
progress();
|
|
64404
|
+
}
|
|
64405
|
+
};
|
|
64406
|
+
const reportStall = (sessionId) => {
|
|
64407
|
+
if (stallReported)
|
|
64408
|
+
return;
|
|
64409
|
+
stallReported = true;
|
|
64410
|
+
const undelivered = [
|
|
64411
|
+
...activeStore.pendingStageMessagesFor(runId, stageId),
|
|
64412
|
+
...stageId === stageName ? [] : activeStore.pendingStageMessagesFor(runId, stageName)
|
|
64413
|
+
].map((entry) => `${entry.message.id} (direct → ${entry.stageKey})`).concat(stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, sessionId === undefined ? undefined : { sessionId }).map((entry) => `${entry.message.id} (sticky → ${entry.targetPath ?? entry.stageKey})`));
|
|
64414
|
+
const listed = undelivered.slice(0, 10).join(", ");
|
|
64415
|
+
const more = undelivered.length > 10 ? `, and ${undelivered.length - 10} more` : "";
|
|
64416
|
+
const message = `atomic-workflows: stage "${stageName}" (${stageId}) is starting without its queued Intercom messages: ` + `no delivery progress for ${PENDING_STAGE_READY_STALL_MS / 1000}s; ` + `drain ${drainPromise === undefined ? "not running" : "running but hung"}; ` + `undelivered: ${listed.length === 0 ? "none" : `${listed}${more}`}. ` + "They stay queued and arrive live or on the stage's next drain.";
|
|
64417
|
+
try {
|
|
64418
|
+
(options.reportStall ?? console.warn)(message);
|
|
64419
|
+
} catch {}
|
|
64420
|
+
};
|
|
64421
|
+
const watchStall = (pending, sessionId, onStall) => {
|
|
64422
|
+
let timer;
|
|
64423
|
+
let settled = false;
|
|
64424
|
+
const check = () => {
|
|
64425
|
+
if (settled)
|
|
64426
|
+
return;
|
|
64427
|
+
const remaining = lastProgressAt + PENDING_STAGE_READY_STALL_MS - Date.now();
|
|
64428
|
+
if (remaining > 0) {
|
|
64429
|
+
timer = setTimeout(check, remaining);
|
|
64430
|
+
timer.unref?.();
|
|
64431
|
+
return;
|
|
64432
|
+
}
|
|
64433
|
+
reportStall(sessionId);
|
|
64434
|
+
onStall();
|
|
64435
|
+
};
|
|
64436
|
+
const stop = () => {
|
|
64437
|
+
settled = true;
|
|
64438
|
+
clearTimeout(timer);
|
|
64439
|
+
};
|
|
64440
|
+
pending.then(stop, stop);
|
|
64441
|
+
check();
|
|
64442
|
+
};
|
|
64443
|
+
const boundedDrain = (drain, sessionId) => {
|
|
64444
|
+
const waiting = new Promise((resolve, reject) => {
|
|
64445
|
+
drain.then(resolve, reject);
|
|
64446
|
+
watchStall(drain, sessionId, resolve);
|
|
64447
|
+
});
|
|
64448
|
+
waiting.catch(() => {});
|
|
64449
|
+
return waiting;
|
|
64450
|
+
};
|
|
64451
|
+
const hasUndeliveredExact = () => activeStore.pendingStageMessagesFor(runId, stageId).length > 0 || stageId !== stageName && activeStore.pendingStageMessagesFor(runId, stageName).length > 0;
|
|
64452
|
+
const hasUndelivered = (sessionId) => hasUndeliveredExact() || stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, sessionId === undefined ? undefined : { sessionId }).length > 0;
|
|
64383
64453
|
const pendingReady = () => {
|
|
64384
64454
|
if (readyPromise === undefined) {
|
|
64385
64455
|
readyPromise = new Promise((resolve, reject) => {
|
|
@@ -64389,35 +64459,64 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
64389
64459
|
}
|
|
64390
64460
|
return readyPromise;
|
|
64391
64461
|
};
|
|
64462
|
+
let followUp;
|
|
64463
|
+
const startDrain = (deliver, recipient) => {
|
|
64464
|
+
if (terminalError !== undefined)
|
|
64465
|
+
return Promise.resolve();
|
|
64466
|
+
drainError = undefined;
|
|
64467
|
+
progress();
|
|
64468
|
+
const attempt = deliverPendingStageMessages(activeStore, runId, stageId, stageName, async (from, message) => {
|
|
64469
|
+
progress();
|
|
64470
|
+
await deliver(from, message);
|
|
64471
|
+
progress();
|
|
64472
|
+
}, progressingCommit, recipient);
|
|
64473
|
+
const drain = attempt.then(() => {
|
|
64474
|
+
progress();
|
|
64475
|
+
drainedSessionId = recipient?.sessionId;
|
|
64476
|
+
resolveReady?.();
|
|
64477
|
+
readyPromise = undefined;
|
|
64478
|
+
resolveReady = undefined;
|
|
64479
|
+
rejectReady = undefined;
|
|
64480
|
+
if (drainPromise === drain)
|
|
64481
|
+
drainPromise = undefined;
|
|
64482
|
+
}, (error) => {
|
|
64483
|
+
progress();
|
|
64484
|
+
drainError = error;
|
|
64485
|
+
rejectReady?.(error);
|
|
64486
|
+
readyPromise = undefined;
|
|
64487
|
+
resolveReady = undefined;
|
|
64488
|
+
rejectReady = undefined;
|
|
64489
|
+
if (drainPromise === drain)
|
|
64490
|
+
drainPromise = undefined;
|
|
64491
|
+
throw error;
|
|
64492
|
+
});
|
|
64493
|
+
drainPromise = drain;
|
|
64494
|
+
return boundedDrain(drain, recipient?.sessionId);
|
|
64495
|
+
};
|
|
64496
|
+
const requestDrain = (deliver, recipient) => {
|
|
64497
|
+
const running = drainPromise;
|
|
64498
|
+
if (running === undefined)
|
|
64499
|
+
return startDrain(deliver, recipient);
|
|
64500
|
+
if (followUp !== undefined) {
|
|
64501
|
+
followUp.deliver = deliver;
|
|
64502
|
+
followUp.recipient = recipient;
|
|
64503
|
+
return boundedDrain(followUp.settled.promise, recipient?.sessionId);
|
|
64504
|
+
}
|
|
64505
|
+
const next = { deliver, recipient, settled: Promise.withResolvers() };
|
|
64506
|
+
next.settled.promise.catch(() => {});
|
|
64507
|
+
followUp = next;
|
|
64508
|
+
running.catch(() => {}).then(() => {
|
|
64509
|
+
if (followUp === next)
|
|
64510
|
+
followUp = undefined;
|
|
64511
|
+
return requestDrain(next.deliver, next.recipient);
|
|
64512
|
+
}).then(next.settled.resolve, next.settled.reject);
|
|
64513
|
+
return boundedDrain(next.settled.promise, recipient?.sessionId);
|
|
64514
|
+
};
|
|
64392
64515
|
return {
|
|
64393
64516
|
routeCapability: workflowPendingStageRouteCapability(activeStore, runId),
|
|
64394
64517
|
deliverPending(deliver, recipient) {
|
|
64395
64518
|
currentRecipient = recipient;
|
|
64396
|
-
|
|
64397
|
-
return drainPromise;
|
|
64398
|
-
if (terminalError !== undefined)
|
|
64399
|
-
return Promise.resolve();
|
|
64400
|
-
drainError = undefined;
|
|
64401
|
-
const attempt = deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver, commit, recipient);
|
|
64402
|
-
const drain = attempt.then(() => {
|
|
64403
|
-
resolveReady?.();
|
|
64404
|
-
readyPromise = undefined;
|
|
64405
|
-
resolveReady = undefined;
|
|
64406
|
-
rejectReady = undefined;
|
|
64407
|
-
if (drainPromise === drain)
|
|
64408
|
-
drainPromise = undefined;
|
|
64409
|
-
}, (error) => {
|
|
64410
|
-
drainError = error;
|
|
64411
|
-
rejectReady?.(error);
|
|
64412
|
-
readyPromise = undefined;
|
|
64413
|
-
resolveReady = undefined;
|
|
64414
|
-
rejectReady = undefined;
|
|
64415
|
-
if (drainPromise === drain)
|
|
64416
|
-
drainPromise = undefined;
|
|
64417
|
-
throw error;
|
|
64418
|
-
});
|
|
64419
|
-
drainPromise = drain;
|
|
64420
|
-
return drainPromise;
|
|
64519
|
+
return requestDrain(deliver, recipient);
|
|
64421
64520
|
},
|
|
64422
64521
|
ready(sessionId) {
|
|
64423
64522
|
if (!hasUndelivered(sessionId)) {
|
|
@@ -64427,6 +64526,8 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
64427
64526
|
return Promise.reject(terminalError);
|
|
64428
64527
|
if (drainError !== undefined)
|
|
64429
64528
|
return Promise.reject(drainError);
|
|
64529
|
+
if (drainPromise === undefined && sessionId !== undefined && drainedSessionId === sessionId && !hasUndeliveredExact())
|
|
64530
|
+
return;
|
|
64430
64531
|
const ready = pendingReady();
|
|
64431
64532
|
if (sessionId !== undefined && activeStore.pendingStageMessagesFor(runId, stageId).length === 0 && activeStore.pendingStageMessagesFor(runId, stageName).length === 0) {
|
|
64432
64533
|
const entries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, { sessionId });
|
|
@@ -64450,6 +64551,14 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
64450
64551
|
rejectReady?.(error);
|
|
64451
64552
|
});
|
|
64452
64553
|
}
|
|
64554
|
+
watchStall(ready, sessionId, () => {
|
|
64555
|
+
if (readyPromise !== ready)
|
|
64556
|
+
return;
|
|
64557
|
+
resolveReady?.();
|
|
64558
|
+
readyPromise = undefined;
|
|
64559
|
+
resolveReady = undefined;
|
|
64560
|
+
rejectReady = undefined;
|
|
64561
|
+
});
|
|
64453
64562
|
return ready;
|
|
64454
64563
|
},
|
|
64455
64564
|
fail(reason) {
|
|
@@ -64577,7 +64686,7 @@ function toPendingStageSender(entry) {
|
|
|
64577
64686
|
lastActivity: entry.from.lastActivity ?? entry.message.timestamp
|
|
64578
64687
|
};
|
|
64579
64688
|
}
|
|
64580
|
-
var pendingDeliveryClaims, WorkflowPendingStageDeliveryFailedError;
|
|
64689
|
+
var pendingDeliveryClaims, WorkflowPendingStageDeliveryFailedError, PENDING_STAGE_READY_STALL_MS = 60000;
|
|
64581
64690
|
var init_pending_stage_delivery2 = __esm(() => {
|
|
64582
64691
|
init_run_owner_backend();
|
|
64583
64692
|
init_store_backend();
|
|
@@ -59243,6 +59243,9 @@ var init_workflow_stage_target = __esm(() => {
|
|
|
59243
59243
|
});
|
|
59244
59244
|
|
|
59245
59245
|
// dist/builtin/workflows/src/shared/pending-stage-status.ts
|
|
59246
|
+
function isAddressableStageStatus(status) {
|
|
59247
|
+
return ADDRESSABLE_STAGE_STATUSES.has(status);
|
|
59248
|
+
}
|
|
59246
59249
|
function workflowBoundarySegments(runs, runId) {
|
|
59247
59250
|
return createWorkflowBoundarySegmentsResolver(runs)(runId);
|
|
59248
59251
|
}
|
|
@@ -59365,9 +59368,17 @@ function createStagePathPatternIndex(patterns) {
|
|
|
59365
59368
|
}
|
|
59366
59369
|
};
|
|
59367
59370
|
}
|
|
59371
|
+
var ADDRESSABLE_STAGE_STATUSES;
|
|
59368
59372
|
var init_pending_stage_status = __esm(() => {
|
|
59369
59373
|
init_store_internal();
|
|
59370
59374
|
init_workflow_stage_target();
|
|
59375
|
+
ADDRESSABLE_STAGE_STATUSES = new Set([
|
|
59376
|
+
"pending",
|
|
59377
|
+
"running",
|
|
59378
|
+
"awaiting_input",
|
|
59379
|
+
"paused",
|
|
59380
|
+
"blocked"
|
|
59381
|
+
]);
|
|
59371
59382
|
});
|
|
59372
59383
|
|
|
59373
59384
|
// dist/builtin/workflows/src/shared/sticky-delivery-state-bound.ts
|
|
@@ -60081,7 +60092,7 @@ function registerPendingStageIntercomBridge(pi, activeStore, ownsRun = () => tru
|
|
|
60081
60092
|
stageName: stage.name,
|
|
60082
60093
|
target: stageRouteTarget(runs, rootRunId, run.id, stage.id, resolveBoundarySegments),
|
|
60083
60094
|
lifecycle: stage.sessionId === undefined && stage.sessionFile === undefined ? "pending" : "running",
|
|
60084
|
-
routeEligible: stage.pendingStageDeliveryAvailable === true && (stage.status
|
|
60095
|
+
routeEligible: stage.pendingStageDeliveryAvailable === true && isAddressableStageStatus(stage.status),
|
|
60085
60096
|
group: stage.intercomGroup ?? workflowInvocationIntercomGroup(rootRunId)
|
|
60086
60097
|
})),
|
|
60087
60098
|
...nonAgentNodes(run).map((node) => ({
|
|
@@ -60584,7 +60595,7 @@ function knownUninitializedStage(run, stageKey) {
|
|
|
60584
60595
|
if (candidates.length !== 1)
|
|
60585
60596
|
return;
|
|
60586
60597
|
const stage = candidates[0];
|
|
60587
|
-
return (stage.status
|
|
60598
|
+
return isAddressableStageStatus(stage.status) && stage.sessionId === undefined && stage.sessionFile === undefined ? stage : undefined;
|
|
60588
60599
|
}
|
|
60589
60600
|
function pendingStageDestination(run, entry) {
|
|
60590
60601
|
if (entry.stageId !== undefined) {
|
|
@@ -64158,15 +64169,74 @@ function isWorkflowPendingStageDeliveryFailure(error) {
|
|
|
64158
64169
|
return true;
|
|
64159
64170
|
return error?.code === "pending_stage_delivery_failed";
|
|
64160
64171
|
}
|
|
64161
|
-
function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageName, commit = (action) => action()) {
|
|
64172
|
+
function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageName, commit = (action) => action(), options = {}) {
|
|
64162
64173
|
let resolveReady;
|
|
64163
64174
|
let rejectReady;
|
|
64164
64175
|
let readyPromise;
|
|
64165
64176
|
let drainError;
|
|
64166
64177
|
let terminalError;
|
|
64167
64178
|
let drainPromise;
|
|
64179
|
+
let drainedSessionId;
|
|
64168
64180
|
let currentRecipient;
|
|
64169
|
-
|
|
64181
|
+
let lastProgressAt = Date.now();
|
|
64182
|
+
let stallReported = false;
|
|
64183
|
+
const progress = () => {
|
|
64184
|
+
lastProgressAt = Date.now();
|
|
64185
|
+
};
|
|
64186
|
+
const progressingCommit = async (action) => {
|
|
64187
|
+
try {
|
|
64188
|
+
return await commit(action);
|
|
64189
|
+
} finally {
|
|
64190
|
+
progress();
|
|
64191
|
+
}
|
|
64192
|
+
};
|
|
64193
|
+
const reportStall = (sessionId) => {
|
|
64194
|
+
if (stallReported)
|
|
64195
|
+
return;
|
|
64196
|
+
stallReported = true;
|
|
64197
|
+
const undelivered = [
|
|
64198
|
+
...activeStore.pendingStageMessagesFor(runId, stageId),
|
|
64199
|
+
...stageId === stageName ? [] : activeStore.pendingStageMessagesFor(runId, stageName)
|
|
64200
|
+
].map((entry) => `${entry.message.id} (direct → ${entry.stageKey})`).concat(stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, sessionId === undefined ? undefined : { sessionId }).map((entry) => `${entry.message.id} (sticky → ${entry.targetPath ?? entry.stageKey})`));
|
|
64201
|
+
const listed = undelivered.slice(0, 10).join(", ");
|
|
64202
|
+
const more = undelivered.length > 10 ? `, and ${undelivered.length - 10} more` : "";
|
|
64203
|
+
const message = `atomic-workflows: stage "${stageName}" (${stageId}) is starting without its queued Intercom messages: ` + `no delivery progress for ${PENDING_STAGE_READY_STALL_MS / 1000}s; ` + `drain ${drainPromise === undefined ? "not running" : "running but hung"}; ` + `undelivered: ${listed.length === 0 ? "none" : `${listed}${more}`}. ` + "They stay queued and arrive live or on the stage's next drain.";
|
|
64204
|
+
try {
|
|
64205
|
+
(options.reportStall ?? console.warn)(message);
|
|
64206
|
+
} catch {}
|
|
64207
|
+
};
|
|
64208
|
+
const watchStall = (pending, sessionId, onStall) => {
|
|
64209
|
+
let timer;
|
|
64210
|
+
let settled = false;
|
|
64211
|
+
const check = () => {
|
|
64212
|
+
if (settled)
|
|
64213
|
+
return;
|
|
64214
|
+
const remaining = lastProgressAt + PENDING_STAGE_READY_STALL_MS - Date.now();
|
|
64215
|
+
if (remaining > 0) {
|
|
64216
|
+
timer = setTimeout(check, remaining);
|
|
64217
|
+
timer.unref?.();
|
|
64218
|
+
return;
|
|
64219
|
+
}
|
|
64220
|
+
reportStall(sessionId);
|
|
64221
|
+
onStall();
|
|
64222
|
+
};
|
|
64223
|
+
const stop = () => {
|
|
64224
|
+
settled = true;
|
|
64225
|
+
clearTimeout(timer);
|
|
64226
|
+
};
|
|
64227
|
+
pending.then(stop, stop);
|
|
64228
|
+
check();
|
|
64229
|
+
};
|
|
64230
|
+
const boundedDrain = (drain, sessionId) => {
|
|
64231
|
+
const waiting = new Promise((resolve, reject) => {
|
|
64232
|
+
drain.then(resolve, reject);
|
|
64233
|
+
watchStall(drain, sessionId, resolve);
|
|
64234
|
+
});
|
|
64235
|
+
waiting.catch(() => {});
|
|
64236
|
+
return waiting;
|
|
64237
|
+
};
|
|
64238
|
+
const hasUndeliveredExact = () => activeStore.pendingStageMessagesFor(runId, stageId).length > 0 || stageId !== stageName && activeStore.pendingStageMessagesFor(runId, stageName).length > 0;
|
|
64239
|
+
const hasUndelivered = (sessionId) => hasUndeliveredExact() || stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, sessionId === undefined ? undefined : { sessionId }).length > 0;
|
|
64170
64240
|
const pendingReady = () => {
|
|
64171
64241
|
if (readyPromise === undefined) {
|
|
64172
64242
|
readyPromise = new Promise((resolve, reject) => {
|
|
@@ -64176,35 +64246,64 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
64176
64246
|
}
|
|
64177
64247
|
return readyPromise;
|
|
64178
64248
|
};
|
|
64249
|
+
let followUp;
|
|
64250
|
+
const startDrain = (deliver, recipient) => {
|
|
64251
|
+
if (terminalError !== undefined)
|
|
64252
|
+
return Promise.resolve();
|
|
64253
|
+
drainError = undefined;
|
|
64254
|
+
progress();
|
|
64255
|
+
const attempt = deliverPendingStageMessages(activeStore, runId, stageId, stageName, async (from, message) => {
|
|
64256
|
+
progress();
|
|
64257
|
+
await deliver(from, message);
|
|
64258
|
+
progress();
|
|
64259
|
+
}, progressingCommit, recipient);
|
|
64260
|
+
const drain = attempt.then(() => {
|
|
64261
|
+
progress();
|
|
64262
|
+
drainedSessionId = recipient?.sessionId;
|
|
64263
|
+
resolveReady?.();
|
|
64264
|
+
readyPromise = undefined;
|
|
64265
|
+
resolveReady = undefined;
|
|
64266
|
+
rejectReady = undefined;
|
|
64267
|
+
if (drainPromise === drain)
|
|
64268
|
+
drainPromise = undefined;
|
|
64269
|
+
}, (error) => {
|
|
64270
|
+
progress();
|
|
64271
|
+
drainError = error;
|
|
64272
|
+
rejectReady?.(error);
|
|
64273
|
+
readyPromise = undefined;
|
|
64274
|
+
resolveReady = undefined;
|
|
64275
|
+
rejectReady = undefined;
|
|
64276
|
+
if (drainPromise === drain)
|
|
64277
|
+
drainPromise = undefined;
|
|
64278
|
+
throw error;
|
|
64279
|
+
});
|
|
64280
|
+
drainPromise = drain;
|
|
64281
|
+
return boundedDrain(drain, recipient?.sessionId);
|
|
64282
|
+
};
|
|
64283
|
+
const requestDrain = (deliver, recipient) => {
|
|
64284
|
+
const running = drainPromise;
|
|
64285
|
+
if (running === undefined)
|
|
64286
|
+
return startDrain(deliver, recipient);
|
|
64287
|
+
if (followUp !== undefined) {
|
|
64288
|
+
followUp.deliver = deliver;
|
|
64289
|
+
followUp.recipient = recipient;
|
|
64290
|
+
return boundedDrain(followUp.settled.promise, recipient?.sessionId);
|
|
64291
|
+
}
|
|
64292
|
+
const next = { deliver, recipient, settled: Promise.withResolvers() };
|
|
64293
|
+
next.settled.promise.catch(() => {});
|
|
64294
|
+
followUp = next;
|
|
64295
|
+
running.catch(() => {}).then(() => {
|
|
64296
|
+
if (followUp === next)
|
|
64297
|
+
followUp = undefined;
|
|
64298
|
+
return requestDrain(next.deliver, next.recipient);
|
|
64299
|
+
}).then(next.settled.resolve, next.settled.reject);
|
|
64300
|
+
return boundedDrain(next.settled.promise, recipient?.sessionId);
|
|
64301
|
+
};
|
|
64179
64302
|
return {
|
|
64180
64303
|
routeCapability: workflowPendingStageRouteCapability(activeStore, runId),
|
|
64181
64304
|
deliverPending(deliver, recipient) {
|
|
64182
64305
|
currentRecipient = recipient;
|
|
64183
|
-
|
|
64184
|
-
return drainPromise;
|
|
64185
|
-
if (terminalError !== undefined)
|
|
64186
|
-
return Promise.resolve();
|
|
64187
|
-
drainError = undefined;
|
|
64188
|
-
const attempt = deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver, commit, recipient);
|
|
64189
|
-
const drain = attempt.then(() => {
|
|
64190
|
-
resolveReady?.();
|
|
64191
|
-
readyPromise = undefined;
|
|
64192
|
-
resolveReady = undefined;
|
|
64193
|
-
rejectReady = undefined;
|
|
64194
|
-
if (drainPromise === drain)
|
|
64195
|
-
drainPromise = undefined;
|
|
64196
|
-
}, (error) => {
|
|
64197
|
-
drainError = error;
|
|
64198
|
-
rejectReady?.(error);
|
|
64199
|
-
readyPromise = undefined;
|
|
64200
|
-
resolveReady = undefined;
|
|
64201
|
-
rejectReady = undefined;
|
|
64202
|
-
if (drainPromise === drain)
|
|
64203
|
-
drainPromise = undefined;
|
|
64204
|
-
throw error;
|
|
64205
|
-
});
|
|
64206
|
-
drainPromise = drain;
|
|
64207
|
-
return drainPromise;
|
|
64306
|
+
return requestDrain(deliver, recipient);
|
|
64208
64307
|
},
|
|
64209
64308
|
ready(sessionId) {
|
|
64210
64309
|
if (!hasUndelivered(sessionId)) {
|
|
@@ -64214,6 +64313,8 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
64214
64313
|
return Promise.reject(terminalError);
|
|
64215
64314
|
if (drainError !== undefined)
|
|
64216
64315
|
return Promise.reject(drainError);
|
|
64316
|
+
if (drainPromise === undefined && sessionId !== undefined && drainedSessionId === sessionId && !hasUndeliveredExact())
|
|
64317
|
+
return;
|
|
64217
64318
|
const ready = pendingReady();
|
|
64218
64319
|
if (sessionId !== undefined && activeStore.pendingStageMessagesFor(runId, stageId).length === 0 && activeStore.pendingStageMessagesFor(runId, stageName).length === 0) {
|
|
64219
64320
|
const entries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, { sessionId });
|
|
@@ -64237,6 +64338,14 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
64237
64338
|
rejectReady?.(error);
|
|
64238
64339
|
});
|
|
64239
64340
|
}
|
|
64341
|
+
watchStall(ready, sessionId, () => {
|
|
64342
|
+
if (readyPromise !== ready)
|
|
64343
|
+
return;
|
|
64344
|
+
resolveReady?.();
|
|
64345
|
+
readyPromise = undefined;
|
|
64346
|
+
resolveReady = undefined;
|
|
64347
|
+
rejectReady = undefined;
|
|
64348
|
+
});
|
|
64240
64349
|
return ready;
|
|
64241
64350
|
},
|
|
64242
64351
|
fail(reason) {
|
|
@@ -64364,7 +64473,7 @@ function toPendingStageSender(entry) {
|
|
|
64364
64473
|
lastActivity: entry.from.lastActivity ?? entry.message.timestamp
|
|
64365
64474
|
};
|
|
64366
64475
|
}
|
|
64367
|
-
var pendingDeliveryClaims, WorkflowPendingStageDeliveryFailedError;
|
|
64476
|
+
var pendingDeliveryClaims, WorkflowPendingStageDeliveryFailedError, PENDING_STAGE_READY_STALL_MS = 60000;
|
|
64368
64477
|
var init_pending_stage_delivery2 = __esm(() => {
|
|
64369
64478
|
init_run_owner_backend();
|
|
64370
64479
|
init_store_backend();
|
|
@@ -58349,6 +58349,9 @@ var init_workflow_stage_target = __esm(() => {
|
|
|
58349
58349
|
});
|
|
58350
58350
|
|
|
58351
58351
|
// dist/builtin/workflows/src/shared/pending-stage-status.ts
|
|
58352
|
+
function isAddressableStageStatus(status) {
|
|
58353
|
+
return ADDRESSABLE_STAGE_STATUSES.has(status);
|
|
58354
|
+
}
|
|
58352
58355
|
function workflowBoundarySegments(runs, runId) {
|
|
58353
58356
|
return createWorkflowBoundarySegmentsResolver(runs)(runId);
|
|
58354
58357
|
}
|
|
@@ -58471,9 +58474,17 @@ function createStagePathPatternIndex(patterns) {
|
|
|
58471
58474
|
}
|
|
58472
58475
|
};
|
|
58473
58476
|
}
|
|
58477
|
+
var ADDRESSABLE_STAGE_STATUSES;
|
|
58474
58478
|
var init_pending_stage_status = __esm(() => {
|
|
58475
58479
|
init_store_internal();
|
|
58476
58480
|
init_workflow_stage_target();
|
|
58481
|
+
ADDRESSABLE_STAGE_STATUSES = new Set([
|
|
58482
|
+
"pending",
|
|
58483
|
+
"running",
|
|
58484
|
+
"awaiting_input",
|
|
58485
|
+
"paused",
|
|
58486
|
+
"blocked"
|
|
58487
|
+
]);
|
|
58477
58488
|
});
|
|
58478
58489
|
|
|
58479
58490
|
// dist/builtin/workflows/src/shared/sticky-delivery-state-bound.ts
|
|
@@ -59187,7 +59198,7 @@ function registerPendingStageIntercomBridge(pi, activeStore, ownsRun = () => tru
|
|
|
59187
59198
|
stageName: stage.name,
|
|
59188
59199
|
target: stageRouteTarget(runs, rootRunId, run.id, stage.id, resolveBoundarySegments),
|
|
59189
59200
|
lifecycle: stage.sessionId === undefined && stage.sessionFile === undefined ? "pending" : "running",
|
|
59190
|
-
routeEligible: stage.pendingStageDeliveryAvailable === true && (stage.status
|
|
59201
|
+
routeEligible: stage.pendingStageDeliveryAvailable === true && isAddressableStageStatus(stage.status),
|
|
59191
59202
|
group: stage.intercomGroup ?? workflowInvocationIntercomGroup(rootRunId)
|
|
59192
59203
|
})),
|
|
59193
59204
|
...nonAgentNodes(run).map((node) => ({
|
|
@@ -59690,7 +59701,7 @@ function knownUninitializedStage(run, stageKey) {
|
|
|
59690
59701
|
if (candidates.length !== 1)
|
|
59691
59702
|
return;
|
|
59692
59703
|
const stage = candidates[0];
|
|
59693
|
-
return (stage.status
|
|
59704
|
+
return isAddressableStageStatus(stage.status) && stage.sessionId === undefined && stage.sessionFile === undefined ? stage : undefined;
|
|
59694
59705
|
}
|
|
59695
59706
|
function pendingStageDestination(run, entry) {
|
|
59696
59707
|
if (entry.stageId !== undefined) {
|
|
@@ -64371,15 +64382,74 @@ function isWorkflowPendingStageDeliveryFailure(error) {
|
|
|
64371
64382
|
return true;
|
|
64372
64383
|
return error?.code === "pending_stage_delivery_failed";
|
|
64373
64384
|
}
|
|
64374
|
-
function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageName, commit = (action) => action()) {
|
|
64385
|
+
function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageName, commit = (action) => action(), options = {}) {
|
|
64375
64386
|
let resolveReady;
|
|
64376
64387
|
let rejectReady;
|
|
64377
64388
|
let readyPromise;
|
|
64378
64389
|
let drainError;
|
|
64379
64390
|
let terminalError;
|
|
64380
64391
|
let drainPromise;
|
|
64392
|
+
let drainedSessionId;
|
|
64381
64393
|
let currentRecipient;
|
|
64382
|
-
|
|
64394
|
+
let lastProgressAt = Date.now();
|
|
64395
|
+
let stallReported = false;
|
|
64396
|
+
const progress = () => {
|
|
64397
|
+
lastProgressAt = Date.now();
|
|
64398
|
+
};
|
|
64399
|
+
const progressingCommit = async (action) => {
|
|
64400
|
+
try {
|
|
64401
|
+
return await commit(action);
|
|
64402
|
+
} finally {
|
|
64403
|
+
progress();
|
|
64404
|
+
}
|
|
64405
|
+
};
|
|
64406
|
+
const reportStall = (sessionId) => {
|
|
64407
|
+
if (stallReported)
|
|
64408
|
+
return;
|
|
64409
|
+
stallReported = true;
|
|
64410
|
+
const undelivered = [
|
|
64411
|
+
...activeStore.pendingStageMessagesFor(runId, stageId),
|
|
64412
|
+
...stageId === stageName ? [] : activeStore.pendingStageMessagesFor(runId, stageName)
|
|
64413
|
+
].map((entry) => `${entry.message.id} (direct → ${entry.stageKey})`).concat(stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, sessionId === undefined ? undefined : { sessionId }).map((entry) => `${entry.message.id} (sticky → ${entry.targetPath ?? entry.stageKey})`));
|
|
64414
|
+
const listed = undelivered.slice(0, 10).join(", ");
|
|
64415
|
+
const more = undelivered.length > 10 ? `, and ${undelivered.length - 10} more` : "";
|
|
64416
|
+
const message = `atomic-workflows: stage "${stageName}" (${stageId}) is starting without its queued Intercom messages: ` + `no delivery progress for ${PENDING_STAGE_READY_STALL_MS / 1000}s; ` + `drain ${drainPromise === undefined ? "not running" : "running but hung"}; ` + `undelivered: ${listed.length === 0 ? "none" : `${listed}${more}`}. ` + "They stay queued and arrive live or on the stage's next drain.";
|
|
64417
|
+
try {
|
|
64418
|
+
(options.reportStall ?? console.warn)(message);
|
|
64419
|
+
} catch {}
|
|
64420
|
+
};
|
|
64421
|
+
const watchStall = (pending, sessionId, onStall) => {
|
|
64422
|
+
let timer;
|
|
64423
|
+
let settled = false;
|
|
64424
|
+
const check = () => {
|
|
64425
|
+
if (settled)
|
|
64426
|
+
return;
|
|
64427
|
+
const remaining = lastProgressAt + PENDING_STAGE_READY_STALL_MS - Date.now();
|
|
64428
|
+
if (remaining > 0) {
|
|
64429
|
+
timer = setTimeout(check, remaining);
|
|
64430
|
+
timer.unref?.();
|
|
64431
|
+
return;
|
|
64432
|
+
}
|
|
64433
|
+
reportStall(sessionId);
|
|
64434
|
+
onStall();
|
|
64435
|
+
};
|
|
64436
|
+
const stop = () => {
|
|
64437
|
+
settled = true;
|
|
64438
|
+
clearTimeout(timer);
|
|
64439
|
+
};
|
|
64440
|
+
pending.then(stop, stop);
|
|
64441
|
+
check();
|
|
64442
|
+
};
|
|
64443
|
+
const boundedDrain = (drain, sessionId) => {
|
|
64444
|
+
const waiting = new Promise((resolve, reject) => {
|
|
64445
|
+
drain.then(resolve, reject);
|
|
64446
|
+
watchStall(drain, sessionId, resolve);
|
|
64447
|
+
});
|
|
64448
|
+
waiting.catch(() => {});
|
|
64449
|
+
return waiting;
|
|
64450
|
+
};
|
|
64451
|
+
const hasUndeliveredExact = () => activeStore.pendingStageMessagesFor(runId, stageId).length > 0 || stageId !== stageName && activeStore.pendingStageMessagesFor(runId, stageName).length > 0;
|
|
64452
|
+
const hasUndelivered = (sessionId) => hasUndeliveredExact() || stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, sessionId === undefined ? undefined : { sessionId }).length > 0;
|
|
64383
64453
|
const pendingReady = () => {
|
|
64384
64454
|
if (readyPromise === undefined) {
|
|
64385
64455
|
readyPromise = new Promise((resolve, reject) => {
|
|
@@ -64389,35 +64459,64 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
64389
64459
|
}
|
|
64390
64460
|
return readyPromise;
|
|
64391
64461
|
};
|
|
64462
|
+
let followUp;
|
|
64463
|
+
const startDrain = (deliver, recipient) => {
|
|
64464
|
+
if (terminalError !== undefined)
|
|
64465
|
+
return Promise.resolve();
|
|
64466
|
+
drainError = undefined;
|
|
64467
|
+
progress();
|
|
64468
|
+
const attempt = deliverPendingStageMessages(activeStore, runId, stageId, stageName, async (from, message) => {
|
|
64469
|
+
progress();
|
|
64470
|
+
await deliver(from, message);
|
|
64471
|
+
progress();
|
|
64472
|
+
}, progressingCommit, recipient);
|
|
64473
|
+
const drain = attempt.then(() => {
|
|
64474
|
+
progress();
|
|
64475
|
+
drainedSessionId = recipient?.sessionId;
|
|
64476
|
+
resolveReady?.();
|
|
64477
|
+
readyPromise = undefined;
|
|
64478
|
+
resolveReady = undefined;
|
|
64479
|
+
rejectReady = undefined;
|
|
64480
|
+
if (drainPromise === drain)
|
|
64481
|
+
drainPromise = undefined;
|
|
64482
|
+
}, (error) => {
|
|
64483
|
+
progress();
|
|
64484
|
+
drainError = error;
|
|
64485
|
+
rejectReady?.(error);
|
|
64486
|
+
readyPromise = undefined;
|
|
64487
|
+
resolveReady = undefined;
|
|
64488
|
+
rejectReady = undefined;
|
|
64489
|
+
if (drainPromise === drain)
|
|
64490
|
+
drainPromise = undefined;
|
|
64491
|
+
throw error;
|
|
64492
|
+
});
|
|
64493
|
+
drainPromise = drain;
|
|
64494
|
+
return boundedDrain(drain, recipient?.sessionId);
|
|
64495
|
+
};
|
|
64496
|
+
const requestDrain = (deliver, recipient) => {
|
|
64497
|
+
const running = drainPromise;
|
|
64498
|
+
if (running === undefined)
|
|
64499
|
+
return startDrain(deliver, recipient);
|
|
64500
|
+
if (followUp !== undefined) {
|
|
64501
|
+
followUp.deliver = deliver;
|
|
64502
|
+
followUp.recipient = recipient;
|
|
64503
|
+
return boundedDrain(followUp.settled.promise, recipient?.sessionId);
|
|
64504
|
+
}
|
|
64505
|
+
const next = { deliver, recipient, settled: Promise.withResolvers() };
|
|
64506
|
+
next.settled.promise.catch(() => {});
|
|
64507
|
+
followUp = next;
|
|
64508
|
+
running.catch(() => {}).then(() => {
|
|
64509
|
+
if (followUp === next)
|
|
64510
|
+
followUp = undefined;
|
|
64511
|
+
return requestDrain(next.deliver, next.recipient);
|
|
64512
|
+
}).then(next.settled.resolve, next.settled.reject);
|
|
64513
|
+
return boundedDrain(next.settled.promise, recipient?.sessionId);
|
|
64514
|
+
};
|
|
64392
64515
|
return {
|
|
64393
64516
|
routeCapability: workflowPendingStageRouteCapability(activeStore, runId),
|
|
64394
64517
|
deliverPending(deliver, recipient) {
|
|
64395
64518
|
currentRecipient = recipient;
|
|
64396
|
-
|
|
64397
|
-
return drainPromise;
|
|
64398
|
-
if (terminalError !== undefined)
|
|
64399
|
-
return Promise.resolve();
|
|
64400
|
-
drainError = undefined;
|
|
64401
|
-
const attempt = deliverPendingStageMessages(activeStore, runId, stageId, stageName, deliver, commit, recipient);
|
|
64402
|
-
const drain = attempt.then(() => {
|
|
64403
|
-
resolveReady?.();
|
|
64404
|
-
readyPromise = undefined;
|
|
64405
|
-
resolveReady = undefined;
|
|
64406
|
-
rejectReady = undefined;
|
|
64407
|
-
if (drainPromise === drain)
|
|
64408
|
-
drainPromise = undefined;
|
|
64409
|
-
}, (error) => {
|
|
64410
|
-
drainError = error;
|
|
64411
|
-
rejectReady?.(error);
|
|
64412
|
-
readyPromise = undefined;
|
|
64413
|
-
resolveReady = undefined;
|
|
64414
|
-
rejectReady = undefined;
|
|
64415
|
-
if (drainPromise === drain)
|
|
64416
|
-
drainPromise = undefined;
|
|
64417
|
-
throw error;
|
|
64418
|
-
});
|
|
64419
|
-
drainPromise = drain;
|
|
64420
|
-
return drainPromise;
|
|
64519
|
+
return requestDrain(deliver, recipient);
|
|
64421
64520
|
},
|
|
64422
64521
|
ready(sessionId) {
|
|
64423
64522
|
if (!hasUndelivered(sessionId)) {
|
|
@@ -64427,6 +64526,8 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
64427
64526
|
return Promise.reject(terminalError);
|
|
64428
64527
|
if (drainError !== undefined)
|
|
64429
64528
|
return Promise.reject(drainError);
|
|
64529
|
+
if (drainPromise === undefined && sessionId !== undefined && drainedSessionId === sessionId && !hasUndeliveredExact())
|
|
64530
|
+
return;
|
|
64430
64531
|
const ready = pendingReady();
|
|
64431
64532
|
if (sessionId !== undefined && activeStore.pendingStageMessagesFor(runId, stageId).length === 0 && activeStore.pendingStageMessagesFor(runId, stageName).length === 0) {
|
|
64432
64533
|
const entries = stickyPendingStageEntriesForStage(activeStore, runId, stageId, stageName, { sessionId });
|
|
@@ -64450,6 +64551,14 @@ function createWorkflowPendingStageDelivery(activeStore, runId, stageId, stageNa
|
|
|
64450
64551
|
rejectReady?.(error);
|
|
64451
64552
|
});
|
|
64452
64553
|
}
|
|
64554
|
+
watchStall(ready, sessionId, () => {
|
|
64555
|
+
if (readyPromise !== ready)
|
|
64556
|
+
return;
|
|
64557
|
+
resolveReady?.();
|
|
64558
|
+
readyPromise = undefined;
|
|
64559
|
+
resolveReady = undefined;
|
|
64560
|
+
rejectReady = undefined;
|
|
64561
|
+
});
|
|
64453
64562
|
return ready;
|
|
64454
64563
|
},
|
|
64455
64564
|
fail(reason) {
|
|
@@ -64577,7 +64686,7 @@ function toPendingStageSender(entry) {
|
|
|
64577
64686
|
lastActivity: entry.from.lastActivity ?? entry.message.timestamp
|
|
64578
64687
|
};
|
|
64579
64688
|
}
|
|
64580
|
-
var pendingDeliveryClaims, WorkflowPendingStageDeliveryFailedError;
|
|
64689
|
+
var pendingDeliveryClaims, WorkflowPendingStageDeliveryFailedError, PENDING_STAGE_READY_STALL_MS = 60000;
|
|
64581
64690
|
var init_pending_stage_delivery2 = __esm(() => {
|
|
64582
64691
|
init_run_owner_backend();
|
|
64583
64692
|
init_store_backend();
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/atomic",
|
|
3
|
-
"version": "0.9.44-alpha.
|
|
3
|
+
"version": "0.9.44-alpha.7",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bastani/atomic",
|
|
9
|
-
"version": "0.9.44-alpha.
|
|
9
|
+
"version": "0.9.44-alpha.7",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@bastani/atomic-natives": "0.9.44-alpha.
|
|
13
|
-
"@bastani/pi-ai": "0.9.44-alpha.
|
|
12
|
+
"@bastani/atomic-natives": "0.9.44-alpha.7",
|
|
13
|
+
"@bastani/pi-ai": "0.9.44-alpha.7",
|
|
14
14
|
"@earendil-works/pi-agent-core": "1.4.0",
|
|
15
15
|
"@earendil-works/pi-codemode": "1.4.0",
|
|
16
16
|
"@earendil-works/pi-tui": "1.4.0",
|
|
@@ -427,18 +427,18 @@
|
|
|
427
427
|
}
|
|
428
428
|
},
|
|
429
429
|
"node_modules/@bastani/atomic-natives": {
|
|
430
|
-
"version": "0.9.44-alpha.
|
|
431
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.44-alpha.
|
|
430
|
+
"version": "0.9.44-alpha.7",
|
|
431
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.44-alpha.7.tgz",
|
|
432
432
|
"license": "MIT",
|
|
433
433
|
"optionalDependencies": {
|
|
434
|
-
"@bastani/atomic-natives-darwin-arm64": "0.9.44-alpha.
|
|
435
|
-
"@bastani/atomic-natives-darwin-x64": "0.9.44-alpha.
|
|
436
|
-
"@bastani/atomic-natives-linux-arm64-gnu": "0.9.44-alpha.
|
|
437
|
-
"@bastani/atomic-natives-linux-arm64-musl": "0.9.44-alpha.
|
|
438
|
-
"@bastani/atomic-natives-linux-x64-gnu": "0.9.44-alpha.
|
|
439
|
-
"@bastani/atomic-natives-linux-x64-musl": "0.9.44-alpha.
|
|
440
|
-
"@bastani/atomic-natives-win32-arm64-msvc": "0.9.44-alpha.
|
|
441
|
-
"@bastani/atomic-natives-win32-x64-msvc": "0.9.44-alpha.
|
|
434
|
+
"@bastani/atomic-natives-darwin-arm64": "0.9.44-alpha.7",
|
|
435
|
+
"@bastani/atomic-natives-darwin-x64": "0.9.44-alpha.7",
|
|
436
|
+
"@bastani/atomic-natives-linux-arm64-gnu": "0.9.44-alpha.7",
|
|
437
|
+
"@bastani/atomic-natives-linux-arm64-musl": "0.9.44-alpha.7",
|
|
438
|
+
"@bastani/atomic-natives-linux-x64-gnu": "0.9.44-alpha.7",
|
|
439
|
+
"@bastani/atomic-natives-linux-x64-musl": "0.9.44-alpha.7",
|
|
440
|
+
"@bastani/atomic-natives-win32-arm64-msvc": "0.9.44-alpha.7",
|
|
441
|
+
"@bastani/atomic-natives-win32-x64-msvc": "0.9.44-alpha.7"
|
|
442
442
|
},
|
|
443
443
|
"engines": {
|
|
444
444
|
"bun": ">=1.4.2",
|
|
@@ -446,8 +446,8 @@
|
|
|
446
446
|
}
|
|
447
447
|
},
|
|
448
448
|
"node_modules/@bastani/atomic-natives-darwin-arm64": {
|
|
449
|
-
"version": "0.9.44-alpha.
|
|
450
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.44-alpha.
|
|
449
|
+
"version": "0.9.44-alpha.7",
|
|
450
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.44-alpha.7.tgz",
|
|
451
451
|
"license": "MIT",
|
|
452
452
|
"os": [
|
|
453
453
|
"darwin"
|
|
@@ -458,8 +458,8 @@
|
|
|
458
458
|
"optional": true
|
|
459
459
|
},
|
|
460
460
|
"node_modules/@bastani/atomic-natives-darwin-x64": {
|
|
461
|
-
"version": "0.9.44-alpha.
|
|
462
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.44-alpha.
|
|
461
|
+
"version": "0.9.44-alpha.7",
|
|
462
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.44-alpha.7.tgz",
|
|
463
463
|
"license": "MIT",
|
|
464
464
|
"os": [
|
|
465
465
|
"darwin"
|
|
@@ -470,8 +470,8 @@
|
|
|
470
470
|
"optional": true
|
|
471
471
|
},
|
|
472
472
|
"node_modules/@bastani/atomic-natives-linux-arm64-gnu": {
|
|
473
|
-
"version": "0.9.44-alpha.
|
|
474
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.44-alpha.
|
|
473
|
+
"version": "0.9.44-alpha.7",
|
|
474
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.44-alpha.7.tgz",
|
|
475
475
|
"license": "MIT",
|
|
476
476
|
"os": [
|
|
477
477
|
"linux"
|
|
@@ -485,8 +485,8 @@
|
|
|
485
485
|
"optional": true
|
|
486
486
|
},
|
|
487
487
|
"node_modules/@bastani/atomic-natives-linux-arm64-musl": {
|
|
488
|
-
"version": "0.9.44-alpha.
|
|
489
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-musl/-/atomic-natives-linux-arm64-musl-0.9.44-alpha.
|
|
488
|
+
"version": "0.9.44-alpha.7",
|
|
489
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-musl/-/atomic-natives-linux-arm64-musl-0.9.44-alpha.7.tgz",
|
|
490
490
|
"license": "MIT",
|
|
491
491
|
"os": [
|
|
492
492
|
"linux"
|
|
@@ -500,8 +500,8 @@
|
|
|
500
500
|
"optional": true
|
|
501
501
|
},
|
|
502
502
|
"node_modules/@bastani/atomic-natives-linux-x64-gnu": {
|
|
503
|
-
"version": "0.9.44-alpha.
|
|
504
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.44-alpha.
|
|
503
|
+
"version": "0.9.44-alpha.7",
|
|
504
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.44-alpha.7.tgz",
|
|
505
505
|
"license": "MIT",
|
|
506
506
|
"os": [
|
|
507
507
|
"linux"
|
|
@@ -515,8 +515,8 @@
|
|
|
515
515
|
"optional": true
|
|
516
516
|
},
|
|
517
517
|
"node_modules/@bastani/atomic-natives-linux-x64-musl": {
|
|
518
|
-
"version": "0.9.44-alpha.
|
|
519
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-musl/-/atomic-natives-linux-x64-musl-0.9.44-alpha.
|
|
518
|
+
"version": "0.9.44-alpha.7",
|
|
519
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-musl/-/atomic-natives-linux-x64-musl-0.9.44-alpha.7.tgz",
|
|
520
520
|
"license": "MIT",
|
|
521
521
|
"os": [
|
|
522
522
|
"linux"
|
|
@@ -530,8 +530,8 @@
|
|
|
530
530
|
"optional": true
|
|
531
531
|
},
|
|
532
532
|
"node_modules/@bastani/atomic-natives-win32-arm64-msvc": {
|
|
533
|
-
"version": "0.9.44-alpha.
|
|
534
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.44-alpha.
|
|
533
|
+
"version": "0.9.44-alpha.7",
|
|
534
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.44-alpha.7.tgz",
|
|
535
535
|
"license": "MIT",
|
|
536
536
|
"os": [
|
|
537
537
|
"win32"
|
|
@@ -542,8 +542,8 @@
|
|
|
542
542
|
"optional": true
|
|
543
543
|
},
|
|
544
544
|
"node_modules/@bastani/atomic-natives-win32-x64-msvc": {
|
|
545
|
-
"version": "0.9.44-alpha.
|
|
546
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.44-alpha.
|
|
545
|
+
"version": "0.9.44-alpha.7",
|
|
546
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.44-alpha.7.tgz",
|
|
547
547
|
"license": "MIT",
|
|
548
548
|
"os": [
|
|
549
549
|
"win32"
|
|
@@ -554,8 +554,8 @@
|
|
|
554
554
|
"optional": true
|
|
555
555
|
},
|
|
556
556
|
"node_modules/@bastani/pi-ai": {
|
|
557
|
-
"version": "0.9.44-alpha.
|
|
558
|
-
"resolved": "https://registry.npmjs.org/@bastani/pi-ai/-/pi-ai-0.9.44-alpha.
|
|
557
|
+
"version": "0.9.44-alpha.7",
|
|
558
|
+
"resolved": "https://registry.npmjs.org/@bastani/pi-ai/-/pi-ai-0.9.44-alpha.7.tgz",
|
|
559
559
|
"license": "MIT",
|
|
560
560
|
"dependencies": {
|
|
561
561
|
"@anthropic-ai/sdk": "0.129.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/atomic",
|
|
3
|
-
"version": "0.9.44-alpha.
|
|
3
|
+
"version": "0.9.44-alpha.7",
|
|
4
4
|
"description": "Atomic coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"atomicConfig": {
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
"prepublishOnly": "bun run clean && bun run build && bun run shrinkwrap"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"@bastani/atomic-natives": "0.9.44-alpha.
|
|
93
|
-
"@bastani/pi-ai": "0.9.44-alpha.
|
|
92
|
+
"@bastani/atomic-natives": "0.9.44-alpha.7",
|
|
93
|
+
"@bastani/pi-ai": "0.9.44-alpha.7",
|
|
94
94
|
"@earendil-works/pi-agent-core": "1.4.0",
|
|
95
95
|
"@earendil-works/pi-codemode": "1.4.0",
|
|
96
96
|
"@earendil-works/pi-tui": "1.4.0",
|