@bastani/atomic 0.9.44-alpha.2 → 0.9.44-alpha.4
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 +21 -0
- package/dist/builtin/intercom/CHANGELOG.md +7 -0
- package/dist/builtin/intercom/broker/framing.ts +18 -1
- package/dist/builtin/intercom/index.bundle.mjs +19 -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/index.bundle.mjs +2510 -1308
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +13 -0
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +317 -76
- package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +317 -76
- package/dist/builtin/workflows/src/index.js +317 -76
- package/dist/builtin/workflows/src/local-worker-entry.mjs +317 -76
- package/examples/extensions/gondolin/package-lock.json +3 -3
- package/npm-shrinkwrap.json +67 -51
- package/package.json +4 -4
|
@@ -9870,12 +9870,16 @@ function removeProcessExitCleanup(cleanup) {
|
|
|
9870
9870
|
if (processExitCleanups.delete(cleanup) && processExitCleanups.size === 0)
|
|
9871
9871
|
process.off("exit", runProcessExitCleanups);
|
|
9872
9872
|
}
|
|
9873
|
+
function writtenHandle(event) {
|
|
9874
|
+
if (event.type === RUN_EVENT_TYPES.promptAsked || event.type === RUN_EVENT_TYPES.promptReleased)
|
|
9875
|
+
return event.payload.handle;
|
|
9876
|
+
if (event.type === RUN_EVENT_TYPES.checkpointRecorded || event.type === RUN_EVENT_TYPES.messageSettled || event.type === RUN_EVENT_TYPES.messageDelivered)
|
|
9877
|
+
return;
|
|
9878
|
+
return event.payload;
|
|
9879
|
+
}
|
|
9873
9880
|
function snapshotNeedsHistory(tail) {
|
|
9874
|
-
const
|
|
9875
|
-
|
|
9876
|
-
return false;
|
|
9877
|
-
const payload = event.payload;
|
|
9878
|
-
return hasPendingStageDeliveryDelta(payload.pendingStageMessages);
|
|
9881
|
+
const handle = writtenHandle(tail.snapshot.event);
|
|
9882
|
+
return handle !== undefined && (handle.pendingStageMessageChange !== undefined || hasPendingStageDeliveryDelta(handle.pendingStageMessages));
|
|
9879
9883
|
}
|
|
9880
9884
|
function* invoke(action) {
|
|
9881
9885
|
try {
|
|
@@ -9989,14 +9993,11 @@ class JournalDurableBackend {
|
|
|
9989
9993
|
const payload = event.payload;
|
|
9990
9994
|
this.projection.archivePendingStageDeliveryReceipt(entry.runId, payload.messageId, payload.delivery, payload.accounting);
|
|
9991
9995
|
} else if (event.type === RUN_EVENT_TYPES.promptAsked || event.type === RUN_EVENT_TYPES.promptReleased) {
|
|
9992
|
-
this.projection.applyWorkflowSnapshot(event.payload.handle);
|
|
9996
|
+
this.projection.applyWorkflowSnapshot(decodeHandle(event.payload.handle, this.projection.getWorkflow(entry.runId)?.pendingStageMessages));
|
|
9993
9997
|
this.prompts.set(entry.runId, new PromptReservationState(event.payload.handle.pendingPrompts, event.payload.prompts));
|
|
9994
9998
|
} else {
|
|
9995
9999
|
const previous = this.projection.getWorkflow(entry.runId);
|
|
9996
|
-
const handle =
|
|
9997
|
-
...event.payload,
|
|
9998
|
-
pendingStageMessages: decodePendingStageDeliveries(previous?.pendingStageMessages ?? [], event.payload.pendingStageMessages ?? [])
|
|
9999
|
-
} : event.payload;
|
|
10000
|
+
const handle = decodeHandle(event.payload, previous?.pendingStageMessages);
|
|
10000
10001
|
this.projection.applyWorkflowSnapshot(handle);
|
|
10001
10002
|
if (event.type === RUN_EVENT_TYPES.runStarted || previous?.pendingPrompts !== handle.pendingPrompts)
|
|
10002
10003
|
this.prompts.delete(entry.runId);
|
|
@@ -10116,6 +10117,24 @@ class JournalDurableBackend {
|
|
|
10116
10117
|
}
|
|
10117
10118
|
*append(runId, event, options) {
|
|
10118
10119
|
const lease = yield* this.ownership(runId);
|
|
10120
|
+
const pinned = options?.expectSeq;
|
|
10121
|
+
for (let attempt = 0;attempt < CHANGE_APPEND_ATTEMPTS; attempt++) {
|
|
10122
|
+
const base = this.sequences.get(runId);
|
|
10123
|
+
const encoded = base !== undefined && (pinned === undefined || pinned === base) && event.type !== RUN_EVENT_TYPES.runStarted ? encodeHandleEvent(event, this.projection.getWorkflow(runId)?.pendingStageMessages) : undefined;
|
|
10124
|
+
if (encoded === undefined)
|
|
10125
|
+
break;
|
|
10126
|
+
try {
|
|
10127
|
+
return yield* this.write(runId, lease, encoded, { ...options, expectSeq: base });
|
|
10128
|
+
} catch (error) {
|
|
10129
|
+
if (!(error instanceof JournalCasConflictError) || pinned !== undefined)
|
|
10130
|
+
throw error;
|
|
10131
|
+
}
|
|
10132
|
+
for (const entry of yield* this.entries(runId, (this.sequences.get(runId) ?? 0) + 1))
|
|
10133
|
+
this.fold(entry);
|
|
10134
|
+
}
|
|
10135
|
+
yield* this.write(runId, lease, event, options);
|
|
10136
|
+
}
|
|
10137
|
+
*write(runId, lease, event, options) {
|
|
10119
10138
|
try {
|
|
10120
10139
|
const outcome = yield* invoke(() => this.journal.append(lease, event, options));
|
|
10121
10140
|
const nextSeq = (this.sequences.get(runId) ?? 0) + 1;
|
|
@@ -10297,17 +10316,6 @@ class JournalDurableBackend {
|
|
|
10297
10316
|
pendingStageMessages: replacePendingStageMessagesForRun(handle.pendingStageMessages ?? [], logicalRunId, messages),
|
|
10298
10317
|
updatedAt: Math.max(Date.now(), handle.updatedAt + 1)
|
|
10299
10318
|
};
|
|
10300
|
-
const encoded = encodePendingStageDeliveries(handle.pendingStageMessages ?? [], next.pendingStageMessages ?? []);
|
|
10301
|
-
const base = this.sequences.get(runId);
|
|
10302
|
-
if (encoded !== undefined && base !== undefined) {
|
|
10303
|
-
try {
|
|
10304
|
-
yield* this.append(runId, { type: RUN_EVENT_TYPES.messageQueued, payload: { ...next, pendingStageMessages: encoded } }, { expectSeq: base });
|
|
10305
|
-
return true;
|
|
10306
|
-
} catch (error) {
|
|
10307
|
-
if (!(error instanceof JournalCasConflictError))
|
|
10308
|
-
throw error;
|
|
10309
|
-
}
|
|
10310
|
-
}
|
|
10311
10319
|
yield* this.snapshot(next, RUN_EVENT_TYPES.messageQueued);
|
|
10312
10320
|
return true;
|
|
10313
10321
|
}
|
|
@@ -10647,31 +10655,143 @@ function uniqueByIdentity(messages) {
|
|
|
10647
10655
|
function isDeltaEncoded(message) {
|
|
10648
10656
|
return message.deliveryDelta !== undefined;
|
|
10649
10657
|
}
|
|
10650
|
-
function
|
|
10651
|
-
const
|
|
10652
|
-
|
|
10653
|
-
|
|
10654
|
-
|
|
10655
|
-
|
|
10656
|
-
|
|
10657
|
-
|
|
10658
|
-
|
|
10659
|
-
|
|
10660
|
-
|
|
10661
|
-
|
|
10662
|
-
|
|
10663
|
-
|
|
10664
|
-
|
|
10665
|
-
|
|
10666
|
-
|
|
10667
|
-
|
|
10668
|
-
|
|
10669
|
-
|
|
10670
|
-
|
|
10671
|
-
|
|
10672
|
-
|
|
10658
|
+
function deliveryDelta(base, deliveries) {
|
|
10659
|
+
const drop = [];
|
|
10660
|
+
let kept = 0;
|
|
10661
|
+
base.forEach((delivery, index) => {
|
|
10662
|
+
if (kept < deliveries.length && JSON.stringify(delivery) === JSON.stringify(deliveries[kept]))
|
|
10663
|
+
kept++;
|
|
10664
|
+
else
|
|
10665
|
+
drop.push(index);
|
|
10666
|
+
});
|
|
10667
|
+
const add = deliveries.slice(kept);
|
|
10668
|
+
return drop.length === 0 ? { add } : { drop, add };
|
|
10669
|
+
}
|
|
10670
|
+
function pendingStageFields(message) {
|
|
10671
|
+
return Object.keys(message);
|
|
10672
|
+
}
|
|
10673
|
+
function copyField(target, source, key) {
|
|
10674
|
+
target[key] = source[key];
|
|
10675
|
+
}
|
|
10676
|
+
function isRemovedField(message, key) {
|
|
10677
|
+
return message[key] === undefined;
|
|
10678
|
+
}
|
|
10679
|
+
function json(message) {
|
|
10680
|
+
let text = entryJson.get(message);
|
|
10681
|
+
if (text === undefined) {
|
|
10682
|
+
text = JSON.stringify(message);
|
|
10683
|
+
entryJson.set(message, text);
|
|
10684
|
+
}
|
|
10685
|
+
return text;
|
|
10686
|
+
}
|
|
10687
|
+
function patchEntry(index, base, message) {
|
|
10688
|
+
const set = {};
|
|
10689
|
+
const unset = pendingStageFields(base).filter((key) => base[key] !== undefined && isRemovedField(message, key));
|
|
10690
|
+
for (const key of pendingStageFields(message)) {
|
|
10691
|
+
if (message[key] === undefined || key === "deliveries")
|
|
10692
|
+
continue;
|
|
10693
|
+
if (JSON.stringify(message[key]) !== JSON.stringify(base[key]))
|
|
10694
|
+
copyField(set, message, key);
|
|
10695
|
+
}
|
|
10696
|
+
let delta;
|
|
10697
|
+
if (message.deliveries !== undefined) {
|
|
10698
|
+
if (base.deliveries === undefined)
|
|
10699
|
+
set.deliveries = message.deliveries;
|
|
10700
|
+
else if (JSON.stringify(base.deliveries) !== JSON.stringify(message.deliveries))
|
|
10701
|
+
delta = deliveryDelta(base.deliveries, message.deliveries);
|
|
10702
|
+
}
|
|
10703
|
+
return {
|
|
10704
|
+
patch: index,
|
|
10705
|
+
...Object.keys(set).length === 0 ? {} : { set },
|
|
10706
|
+
...unset.length === 0 ? {} : { unset },
|
|
10707
|
+
...delta === undefined ? {} : { deliveryDelta: delta }
|
|
10708
|
+
};
|
|
10709
|
+
}
|
|
10710
|
+
function encodePendingStageList(previous, next) {
|
|
10711
|
+
const positions = new Map;
|
|
10712
|
+
const repeated = new Set;
|
|
10713
|
+
previous.forEach((message, index) => {
|
|
10714
|
+
const key = identity(message);
|
|
10715
|
+
if (positions.has(key))
|
|
10716
|
+
repeated.add(key);
|
|
10717
|
+
positions.set(key, index);
|
|
10673
10718
|
});
|
|
10674
|
-
|
|
10719
|
+
for (const key of repeated)
|
|
10720
|
+
positions.delete(key);
|
|
10721
|
+
const items = [];
|
|
10722
|
+
let reused = 0;
|
|
10723
|
+
for (const message of next) {
|
|
10724
|
+
const index = positions.get(identity(message));
|
|
10725
|
+
const base = index === undefined ? undefined : previous[index];
|
|
10726
|
+
if (base === undefined) {
|
|
10727
|
+
items.push(message);
|
|
10728
|
+
continue;
|
|
10729
|
+
}
|
|
10730
|
+
reused++;
|
|
10731
|
+
const patched = base === message || json(base) === json(message) ? undefined : patchEntry(index, base, message);
|
|
10732
|
+
if (patched === undefined || Object.keys(patched).length === 1) {
|
|
10733
|
+
const last = items.at(-1);
|
|
10734
|
+
if (Array.isArray(last) && last[0] + last[1] === index)
|
|
10735
|
+
last[1]++;
|
|
10736
|
+
else
|
|
10737
|
+
items.push([index, 1]);
|
|
10738
|
+
continue;
|
|
10739
|
+
}
|
|
10740
|
+
items.push(JSON.stringify(patched).length < json(message).length ? patched : message);
|
|
10741
|
+
}
|
|
10742
|
+
return reused > 0 ? items : undefined;
|
|
10743
|
+
}
|
|
10744
|
+
function decodePendingStageList(previous, items) {
|
|
10745
|
+
const base = (index) => {
|
|
10746
|
+
if (!Number.isInteger(index) || index < 0 || index >= previous.length)
|
|
10747
|
+
throw new Error(`atomic-workflows: journal pending-stage change names missing entry ${index}`);
|
|
10748
|
+
return previous[index];
|
|
10749
|
+
};
|
|
10750
|
+
const result = [];
|
|
10751
|
+
for (const item of items) {
|
|
10752
|
+
if (Array.isArray(item)) {
|
|
10753
|
+
const [start, count] = item;
|
|
10754
|
+
for (let index = start;index < start + count; index++)
|
|
10755
|
+
result.push(base(index));
|
|
10756
|
+
} else if (typeof item.patch === "number") {
|
|
10757
|
+
const { patch, set, unset, deliveryDelta: delta } = item;
|
|
10758
|
+
const entry = { ...base(patch), ...set };
|
|
10759
|
+
for (const key of unset ?? [])
|
|
10760
|
+
delete entry[key];
|
|
10761
|
+
if (delta !== undefined) {
|
|
10762
|
+
const dropped = new Set(delta.drop ?? []);
|
|
10763
|
+
const deliveries = base(patch).deliveries ?? [];
|
|
10764
|
+
entry.deliveries = [...deliveries.filter((_, index) => !dropped.has(index)), ...delta.add];
|
|
10765
|
+
}
|
|
10766
|
+
result.push(entry);
|
|
10767
|
+
} else
|
|
10768
|
+
result.push(item);
|
|
10769
|
+
}
|
|
10770
|
+
return result;
|
|
10771
|
+
}
|
|
10772
|
+
function encodeHandleEvent(event, previous) {
|
|
10773
|
+
const handle = writtenHandle(event);
|
|
10774
|
+
if (handle?.pendingStageMessages === undefined || previous === undefined)
|
|
10775
|
+
return;
|
|
10776
|
+
const change = encodePendingStageList(previous, handle.pendingStageMessages);
|
|
10777
|
+
if (change === undefined)
|
|
10778
|
+
return;
|
|
10779
|
+
const { pendingStageMessages: _full, ...rest } = handle;
|
|
10780
|
+
const encoded = { ...rest, pendingStageMessageChange: change };
|
|
10781
|
+
if (event.type === RUN_EVENT_TYPES.promptAsked || event.type === RUN_EVENT_TYPES.promptReleased)
|
|
10782
|
+
return { ...event, payload: { ...event.payload, handle: encoded } };
|
|
10783
|
+
return { ...event, payload: encoded };
|
|
10784
|
+
}
|
|
10785
|
+
function decodeHandle(handle, previous) {
|
|
10786
|
+
const { pendingStageMessageChange: change, ...rest } = handle;
|
|
10787
|
+
if (change !== undefined)
|
|
10788
|
+
return { ...rest, pendingStageMessages: decodePendingStageList(previous ?? [], change) };
|
|
10789
|
+
if (!hasPendingStageDeliveryDelta(handle.pendingStageMessages))
|
|
10790
|
+
return handle;
|
|
10791
|
+
return {
|
|
10792
|
+
...handle,
|
|
10793
|
+
pendingStageMessages: decodePendingStageDeliveries(previous ?? [], handle.pendingStageMessages ?? [])
|
|
10794
|
+
};
|
|
10675
10795
|
}
|
|
10676
10796
|
function decodePendingStageDeliveries(previous, messages) {
|
|
10677
10797
|
if (!messages.some(isDeltaEncoded))
|
|
@@ -10691,7 +10811,7 @@ function decodePendingStageDeliveries(previous, messages) {
|
|
|
10691
10811
|
function hasPendingStageDeliveryDelta(messages) {
|
|
10692
10812
|
return messages?.some(isDeltaEncoded) === true;
|
|
10693
10813
|
}
|
|
10694
|
-
var PROCESS_HOLDER_ID, processExitCleanups, JournalOwnershipError, JournalBackendClosedError, JournalOperationAbortedError, JournalExecutionRetiredError, JournalMessageScopeError;
|
|
10814
|
+
var PROCESS_HOLDER_ID, CHANGE_APPEND_ATTEMPTS = 4, processExitCleanups, JournalOwnershipError, JournalBackendClosedError, JournalOperationAbortedError, JournalExecutionRetiredError, JournalMessageScopeError, entryJson;
|
|
10695
10815
|
var init_journal_backend = __esm(() => {
|
|
10696
10816
|
init_workflow_instance_ownership_error();
|
|
10697
10817
|
init_backend();
|
|
@@ -10749,6 +10869,7 @@ var init_journal_backend = __esm(() => {
|
|
|
10749
10869
|
this.name = "JournalMessageScopeError";
|
|
10750
10870
|
}
|
|
10751
10871
|
};
|
|
10872
|
+
entryJson = new WeakMap;
|
|
10752
10873
|
});
|
|
10753
10874
|
|
|
10754
10875
|
// dist/builtin/workflows/src/durable/factory.ts
|
|
@@ -58215,7 +58336,20 @@ function createWorkflowBoundarySegmentsResolver(runs) {
|
|
|
58215
58336
|
};
|
|
58216
58337
|
}
|
|
58217
58338
|
function workflowBoundaryHops(runs, runId) {
|
|
58339
|
+
return boundaryHopsFrom(new Map(runs.map((run) => [run.id, run])), runId);
|
|
58340
|
+
}
|
|
58341
|
+
function createWorkflowBoundaryHopsResolver(runs) {
|
|
58218
58342
|
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
58343
|
+
const cache = new Map;
|
|
58344
|
+
return (runId) => {
|
|
58345
|
+
if (cache.has(runId))
|
|
58346
|
+
return cache.get(runId);
|
|
58347
|
+
const hops = boundaryHopsFrom(runById, runId);
|
|
58348
|
+
cache.set(runId, hops);
|
|
58349
|
+
return hops;
|
|
58350
|
+
};
|
|
58351
|
+
}
|
|
58352
|
+
function boundaryHopsFrom(runById, runId) {
|
|
58219
58353
|
const hops = [];
|
|
58220
58354
|
let current = runById.get(runId);
|
|
58221
58355
|
while (current !== undefined && current.parentRunId !== undefined) {
|
|
@@ -58241,6 +58375,35 @@ function workflowStagePathVariants(hops, stageSegments) {
|
|
|
58241
58375
|
function stageMatchesPathPattern(patternSegments, hops, stageSegments) {
|
|
58242
58376
|
return workflowStagePathVariants(hops, stageSegments).some((candidate) => matchStagePathSegments(patternSegments, candidate));
|
|
58243
58377
|
}
|
|
58378
|
+
function createStagePathPatternIndex(patterns) {
|
|
58379
|
+
const byFirstSegment = new Map;
|
|
58380
|
+
const globFirst = [];
|
|
58381
|
+
patterns.forEach((pattern, index) => {
|
|
58382
|
+
const first = pattern[0];
|
|
58383
|
+
if (first === undefined || first.includes("*")) {
|
|
58384
|
+
globFirst.push(index);
|
|
58385
|
+
return;
|
|
58386
|
+
}
|
|
58387
|
+
const bucket = byFirstSegment.get(first);
|
|
58388
|
+
if (bucket === undefined)
|
|
58389
|
+
byFirstSegment.set(first, [index]);
|
|
58390
|
+
else
|
|
58391
|
+
bucket.push(index);
|
|
58392
|
+
});
|
|
58393
|
+
return {
|
|
58394
|
+
matching(hops, stageSegments) {
|
|
58395
|
+
if (patterns.length === 0)
|
|
58396
|
+
return [];
|
|
58397
|
+
const variants = workflowStagePathVariants(hops, stageSegments);
|
|
58398
|
+
const candidates = new Set(globFirst);
|
|
58399
|
+
for (const variant of variants) {
|
|
58400
|
+
for (const index of byFirstSegment.get(variant[0]) ?? [])
|
|
58401
|
+
candidates.add(index);
|
|
58402
|
+
}
|
|
58403
|
+
return [...candidates].sort((left, right) => left - right).filter((index) => variants.some((variant) => matchStagePathSegments(patterns[index], variant)));
|
|
58404
|
+
}
|
|
58405
|
+
};
|
|
58406
|
+
}
|
|
58244
58407
|
var init_pending_stage_status = __esm(() => {
|
|
58245
58408
|
init_store_internal();
|
|
58246
58409
|
init_workflow_stage_target();
|
|
@@ -58251,24 +58414,63 @@ function stickyStageDeliveryStatuses(runs, rootRunId, availableBackend) {
|
|
|
58251
58414
|
const root = runs.find((run) => run.id === rootRunId);
|
|
58252
58415
|
const entries = (root?.pendingStageMessages ?? []).filter((entry) => entry.sticky === true);
|
|
58253
58416
|
const result = [];
|
|
58417
|
+
const patternByTarget = new Map;
|
|
58418
|
+
const patterns = [];
|
|
58419
|
+
const entriesByPattern = [];
|
|
58420
|
+
const ownEntries = [];
|
|
58421
|
+
entries.forEach((entry, index) => {
|
|
58422
|
+
const target = entry.targetPath ?? entry.stageKey;
|
|
58423
|
+
let pattern = patternByTarget.get(target);
|
|
58424
|
+
if (pattern === undefined) {
|
|
58425
|
+
const parsed = parseWorkflowStageTarget(target);
|
|
58426
|
+
pattern = parsed?.rootRunId === rootRunId ? patterns.push(parsed.segments) - 1 : -1;
|
|
58427
|
+
if (pattern >= 0)
|
|
58428
|
+
entriesByPattern.push([]);
|
|
58429
|
+
patternByTarget.set(target, pattern);
|
|
58430
|
+
}
|
|
58431
|
+
if (pattern < 0)
|
|
58432
|
+
return;
|
|
58433
|
+
entriesByPattern[pattern].push(index);
|
|
58434
|
+
ownEntries.push(index);
|
|
58435
|
+
});
|
|
58436
|
+
if (ownEntries.length === 0)
|
|
58437
|
+
return result;
|
|
58438
|
+
const patternIndex = createStagePathPatternIndex(patterns);
|
|
58439
|
+
const deliveriesByEntry = new Map;
|
|
58440
|
+
const entryReceipts = (index, runId, stageId) => {
|
|
58441
|
+
let byStage = deliveriesByEntry.get(index);
|
|
58442
|
+
if (byStage === undefined) {
|
|
58443
|
+
byStage = new Map;
|
|
58444
|
+
for (const delivery of entries[index].deliveries ?? []) {
|
|
58445
|
+
const key = `${delivery.runId}\x00${delivery.stageId}`;
|
|
58446
|
+
const list = byStage.get(key);
|
|
58447
|
+
if (list === undefined)
|
|
58448
|
+
byStage.set(key, [delivery]);
|
|
58449
|
+
else
|
|
58450
|
+
list.push(delivery);
|
|
58451
|
+
}
|
|
58452
|
+
deliveriesByEntry.set(index, byStage);
|
|
58453
|
+
}
|
|
58454
|
+
return byStage.get(`${runId}\x00${stageId}`) ?? [];
|
|
58455
|
+
};
|
|
58254
58456
|
availableBackend = availableRunDurableBackend(runs, rootRunId) ?? availableBackend;
|
|
58255
58457
|
const backend = availableBackend === undefined ? undefined : durableBackendForRun(availableBackend, runs, rootRunId);
|
|
58458
|
+
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
58459
|
+
const hopsFor = createWorkflowBoundaryHopsResolver(runs);
|
|
58256
58460
|
for (const run of runs) {
|
|
58257
|
-
|
|
58461
|
+
const durableRootRunId = reciprocalWorkflowRootRunId(runById, run.id);
|
|
58462
|
+
if (run.id !== rootRunId && run.rootRunId !== rootRunId && durableRootRunId !== rootRunId)
|
|
58258
58463
|
continue;
|
|
58259
|
-
const resolved =
|
|
58260
|
-
const hops =
|
|
58464
|
+
const resolved = durableRootRunId === rootRunId;
|
|
58465
|
+
const hops = hopsFor(run.id);
|
|
58261
58466
|
for (const stage of run.stages) {
|
|
58262
58467
|
if (stage.nodeKind === "tool" || stage.replayKey?.startsWith("prompt:") === true || stage.replayKey?.startsWith("workflow:") === true || stage.workflowChildRun !== undefined || stage.workflowChild !== undefined)
|
|
58263
58468
|
continue;
|
|
58264
|
-
|
|
58469
|
+
const matchedEntries = resolved && hops ? patternIndex.matching(hops, [stage.id, stage.name]).flatMap((pattern) => entriesByPattern[pattern]).sort((left, right) => left - right) : ownEntries;
|
|
58470
|
+
for (const index of matchedEntries) {
|
|
58471
|
+
const entry = entries[index];
|
|
58265
58472
|
const target = entry.targetPath ?? entry.stageKey;
|
|
58266
|
-
const
|
|
58267
|
-
if (!parsed || parsed.rootRunId !== rootRunId)
|
|
58268
|
-
continue;
|
|
58269
|
-
if (resolved && hops && !stageMatchesPathPattern(parsed.segments, hops, [stage.id, stage.name]))
|
|
58270
|
-
continue;
|
|
58271
|
-
const receipts = (entry.deliveries ?? []).filter((delivery) => delivery.runId === run.id && delivery.stageId === stage.id);
|
|
58473
|
+
const receipts = entryReceipts(index, run.id, stage.id);
|
|
58272
58474
|
const delivered = backend?.hasCachedPendingStageDeliveryReceipt?.(rootRunId, entry.id, {
|
|
58273
58475
|
runId: run.id,
|
|
58274
58476
|
stageId: stage.id,
|
|
@@ -58586,20 +58788,27 @@ function possibleStageRows(runs, rootRunId, rootRun, backend) {
|
|
|
58586
58788
|
if (isTerminalRunStatus(rootRun.status))
|
|
58587
58789
|
return [];
|
|
58588
58790
|
const stickyQueued = (rootRun.pendingStageMessages ?? []).filter((entry) => entry.sticky === true && entry.status === "queued");
|
|
58791
|
+
const segmentsByTarget = new Map;
|
|
58589
58792
|
const stickySegments = (entry) => {
|
|
58590
|
-
const
|
|
58591
|
-
|
|
58793
|
+
const target = entry.targetPath ?? entry.stageKey;
|
|
58794
|
+
if (segmentsByTarget.has(target))
|
|
58795
|
+
return segmentsByTarget.get(target);
|
|
58796
|
+
const parsed = parseWorkflowStageTarget(target);
|
|
58797
|
+
const segments = parsed?.rootRunId === rootRunId ? parsed.segments : undefined;
|
|
58798
|
+
segmentsByTarget.set(target, segments);
|
|
58799
|
+
return segments;
|
|
58592
58800
|
};
|
|
58593
58801
|
const scanEntries = stickyQueued.filter((entry) => {
|
|
58594
58802
|
const segments = stickySegments(entry);
|
|
58595
58803
|
return !(segments !== undefined && segments.length === 1 && segments[0] === "**");
|
|
58596
58804
|
});
|
|
58805
|
+
const liveStageMatches = materializedStageMatcher(runs, rootRunId);
|
|
58597
58806
|
const rows = [];
|
|
58598
58807
|
for (const scanEntry of rootRun.possibleStages ?? []) {
|
|
58599
58808
|
const rowSegments = splitStagePathSegments(scanEntry);
|
|
58600
58809
|
if (rowSegments.length === 0 || rowSegments.some((segment) => segment.length === 0))
|
|
58601
58810
|
continue;
|
|
58602
|
-
if (!rowSegments.some((segment) => segment.includes("*")) &&
|
|
58811
|
+
if (!rowSegments.some((segment) => segment.includes("*")) && liveStageMatches(rowSegments)) {
|
|
58603
58812
|
continue;
|
|
58604
58813
|
}
|
|
58605
58814
|
rows.push({
|
|
@@ -58620,28 +58829,43 @@ function possibleStageRows(runs, rootRunId, rootRun, backend) {
|
|
|
58620
58829
|
}).length
|
|
58621
58830
|
});
|
|
58622
58831
|
const statuses = stickyStageDeliveryStatuses(runs, rootRunId, backend);
|
|
58623
|
-
|
|
58624
|
-
|
|
58832
|
+
const statusesByTarget = new Map;
|
|
58833
|
+
for (const status of statuses) {
|
|
58834
|
+
const forTarget = statusesByTarget.get(status.target);
|
|
58835
|
+
if (forTarget === undefined)
|
|
58836
|
+
statusesByTarget.set(status.target, [status]);
|
|
58837
|
+
else
|
|
58838
|
+
forTarget.push(status);
|
|
58839
|
+
}
|
|
58840
|
+
const queuedByTarget = new Map;
|
|
58841
|
+
for (const entry of stickyQueued) {
|
|
58842
|
+
const target = entry.targetPath ?? entry.stageKey;
|
|
58843
|
+
queuedByTarget.set(target, (queuedByTarget.get(target) ?? 0) + 1);
|
|
58844
|
+
}
|
|
58845
|
+
const rowTargets = new Set(rows.map((row) => row.target));
|
|
58846
|
+
for (const target of statusesByTarget.keys()) {
|
|
58847
|
+
if (rowTargets.has(target))
|
|
58625
58848
|
continue;
|
|
58626
|
-
|
|
58627
|
-
|
|
58628
|
-
queuedCount: stickyQueued.filter((entry) => (entry.targetPath ?? entry.stageKey) === target).length,
|
|
58629
|
-
deliveryOnly: true
|
|
58630
|
-
});
|
|
58849
|
+
rowTargets.add(target);
|
|
58850
|
+
rows.push({ target, queuedCount: queuedByTarget.get(target) ?? 0, deliveryOnly: true });
|
|
58631
58851
|
}
|
|
58632
58852
|
for (let index = 0;index < rows.length; index++) {
|
|
58633
58853
|
const row = rows[index];
|
|
58634
|
-
const deliveryStates =
|
|
58635
|
-
if (deliveryStates
|
|
58854
|
+
const deliveryStates = statusesByTarget.get(row.target);
|
|
58855
|
+
if (deliveryStates !== undefined)
|
|
58636
58856
|
rows[index] = { ...row, deliveryStates };
|
|
58637
58857
|
}
|
|
58638
58858
|
return rows;
|
|
58639
58859
|
}
|
|
58640
|
-
function
|
|
58641
|
-
|
|
58642
|
-
|
|
58643
|
-
|
|
58644
|
-
|
|
58860
|
+
function materializedStageMatcher(runs, rootRunId) {
|
|
58861
|
+
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
58862
|
+
const hopsFor = createWorkflowBoundaryHopsResolver(runs);
|
|
58863
|
+
const invocationRuns = runs.filter((run) => reciprocalWorkflowRootRunId(runById, run.id) === rootRunId);
|
|
58864
|
+
return (entrySegments) => materializedStageMatches(invocationRuns, hopsFor, entrySegments);
|
|
58865
|
+
}
|
|
58866
|
+
function materializedStageMatches(invocationRuns, hopsFor, entrySegments) {
|
|
58867
|
+
for (const run of invocationRuns) {
|
|
58868
|
+
const hops = hopsFor(run.id);
|
|
58645
58869
|
if (hops === undefined)
|
|
58646
58870
|
continue;
|
|
58647
58871
|
for (const stage of run.stages) {
|
|
@@ -58916,10 +59140,12 @@ async function recordConfirmedStickyDeliveries(activeStore, event) {
|
|
|
58916
59140
|
}
|
|
58917
59141
|
function matchingLiveStages(runs, rootRunId, patternSegments) {
|
|
58918
59142
|
const matches = [];
|
|
59143
|
+
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
59144
|
+
const hopsFor = createWorkflowBoundaryHopsResolver(runs);
|
|
58919
59145
|
for (const run of runs) {
|
|
58920
|
-
if (
|
|
59146
|
+
if (reciprocalWorkflowRootRunId(runById, run.id) !== rootRunId)
|
|
58921
59147
|
continue;
|
|
58922
|
-
const hops =
|
|
59148
|
+
const hops = hopsFor(run.id);
|
|
58923
59149
|
if (hops === undefined)
|
|
58924
59150
|
continue;
|
|
58925
59151
|
for (const stage of run.stages) {
|
|
@@ -59055,11 +59281,26 @@ function writeMessage(socket, msg, callback) {
|
|
|
59055
59281
|
}
|
|
59056
59282
|
function createMessageReader(onMessage, onError) {
|
|
59057
59283
|
let buffer = Buffer.alloc(0);
|
|
59284
|
+
let pending = [];
|
|
59285
|
+
let pendingLength = 0;
|
|
59286
|
+
let awaitedLength = 0;
|
|
59058
59287
|
return (data) => {
|
|
59059
|
-
|
|
59288
|
+
if (pendingLength + data.length < awaitedLength) {
|
|
59289
|
+
pending.push(data);
|
|
59290
|
+
pendingLength += data.length;
|
|
59291
|
+
return;
|
|
59292
|
+
}
|
|
59293
|
+
buffer = pending.length === 0 ? Buffer.concat([buffer, data]) : Buffer.concat([...pending, data]);
|
|
59294
|
+
pending = [];
|
|
59295
|
+
pendingLength = 0;
|
|
59296
|
+
awaitedLength = 0;
|
|
59060
59297
|
while (buffer.length >= 4) {
|
|
59061
59298
|
const length = buffer.readUInt32BE(0);
|
|
59062
59299
|
if (buffer.length < 4 + length) {
|
|
59300
|
+
pending = [buffer];
|
|
59301
|
+
pendingLength = buffer.length;
|
|
59302
|
+
awaitedLength = 4 + length;
|
|
59303
|
+
buffer = Buffer.alloc(0);
|
|
59063
59304
|
break;
|
|
59064
59305
|
}
|
|
59065
59306
|
const payload = buffer.subarray(4, 4 + length);
|