@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
|
@@ -1661,12 +1661,16 @@ function removeProcessExitCleanup(cleanup) {
|
|
|
1661
1661
|
if (processExitCleanups.delete(cleanup) && processExitCleanups.size === 0)
|
|
1662
1662
|
process.off("exit", runProcessExitCleanups);
|
|
1663
1663
|
}
|
|
1664
|
+
function writtenHandle(event) {
|
|
1665
|
+
if (event.type === RUN_EVENT_TYPES.promptAsked || event.type === RUN_EVENT_TYPES.promptReleased)
|
|
1666
|
+
return event.payload.handle;
|
|
1667
|
+
if (event.type === RUN_EVENT_TYPES.checkpointRecorded || event.type === RUN_EVENT_TYPES.messageSettled || event.type === RUN_EVENT_TYPES.messageDelivered)
|
|
1668
|
+
return;
|
|
1669
|
+
return event.payload;
|
|
1670
|
+
}
|
|
1664
1671
|
function snapshotNeedsHistory(tail) {
|
|
1665
|
-
const
|
|
1666
|
-
|
|
1667
|
-
return false;
|
|
1668
|
-
const payload = event.payload;
|
|
1669
|
-
return hasPendingStageDeliveryDelta(payload.pendingStageMessages);
|
|
1672
|
+
const handle = writtenHandle(tail.snapshot.event);
|
|
1673
|
+
return handle !== undefined && (handle.pendingStageMessageChange !== undefined || hasPendingStageDeliveryDelta(handle.pendingStageMessages));
|
|
1670
1674
|
}
|
|
1671
1675
|
function* invoke(action) {
|
|
1672
1676
|
try {
|
|
@@ -1780,14 +1784,11 @@ class JournalDurableBackend {
|
|
|
1780
1784
|
const payload = event.payload;
|
|
1781
1785
|
this.projection.archivePendingStageDeliveryReceipt(entry.runId, payload.messageId, payload.delivery, payload.accounting);
|
|
1782
1786
|
} else if (event.type === RUN_EVENT_TYPES.promptAsked || event.type === RUN_EVENT_TYPES.promptReleased) {
|
|
1783
|
-
this.projection.applyWorkflowSnapshot(event.payload.handle);
|
|
1787
|
+
this.projection.applyWorkflowSnapshot(decodeHandle(event.payload.handle, this.projection.getWorkflow(entry.runId)?.pendingStageMessages));
|
|
1784
1788
|
this.prompts.set(entry.runId, new PromptReservationState(event.payload.handle.pendingPrompts, event.payload.prompts));
|
|
1785
1789
|
} else {
|
|
1786
1790
|
const previous = this.projection.getWorkflow(entry.runId);
|
|
1787
|
-
const handle =
|
|
1788
|
-
...event.payload,
|
|
1789
|
-
pendingStageMessages: decodePendingStageDeliveries(previous?.pendingStageMessages ?? [], event.payload.pendingStageMessages ?? [])
|
|
1790
|
-
} : event.payload;
|
|
1791
|
+
const handle = decodeHandle(event.payload, previous?.pendingStageMessages);
|
|
1791
1792
|
this.projection.applyWorkflowSnapshot(handle);
|
|
1792
1793
|
if (event.type === RUN_EVENT_TYPES.runStarted || previous?.pendingPrompts !== handle.pendingPrompts)
|
|
1793
1794
|
this.prompts.delete(entry.runId);
|
|
@@ -1907,6 +1908,24 @@ class JournalDurableBackend {
|
|
|
1907
1908
|
}
|
|
1908
1909
|
*append(runId, event, options) {
|
|
1909
1910
|
const lease = yield* this.ownership(runId);
|
|
1911
|
+
const pinned = options?.expectSeq;
|
|
1912
|
+
for (let attempt = 0;attempt < CHANGE_APPEND_ATTEMPTS; attempt++) {
|
|
1913
|
+
const base = this.sequences.get(runId);
|
|
1914
|
+
const encoded = base !== undefined && (pinned === undefined || pinned === base) && event.type !== RUN_EVENT_TYPES.runStarted ? encodeHandleEvent(event, this.projection.getWorkflow(runId)?.pendingStageMessages) : undefined;
|
|
1915
|
+
if (encoded === undefined)
|
|
1916
|
+
break;
|
|
1917
|
+
try {
|
|
1918
|
+
return yield* this.write(runId, lease, encoded, { ...options, expectSeq: base });
|
|
1919
|
+
} catch (error) {
|
|
1920
|
+
if (!(error instanceof JournalCasConflictError) || pinned !== undefined)
|
|
1921
|
+
throw error;
|
|
1922
|
+
}
|
|
1923
|
+
for (const entry of yield* this.entries(runId, (this.sequences.get(runId) ?? 0) + 1))
|
|
1924
|
+
this.fold(entry);
|
|
1925
|
+
}
|
|
1926
|
+
yield* this.write(runId, lease, event, options);
|
|
1927
|
+
}
|
|
1928
|
+
*write(runId, lease, event, options) {
|
|
1910
1929
|
try {
|
|
1911
1930
|
const outcome = yield* invoke(() => this.journal.append(lease, event, options));
|
|
1912
1931
|
const nextSeq = (this.sequences.get(runId) ?? 0) + 1;
|
|
@@ -2088,17 +2107,6 @@ class JournalDurableBackend {
|
|
|
2088
2107
|
pendingStageMessages: replacePendingStageMessagesForRun(handle.pendingStageMessages ?? [], logicalRunId, messages),
|
|
2089
2108
|
updatedAt: Math.max(Date.now(), handle.updatedAt + 1)
|
|
2090
2109
|
};
|
|
2091
|
-
const encoded = encodePendingStageDeliveries(handle.pendingStageMessages ?? [], next.pendingStageMessages ?? []);
|
|
2092
|
-
const base = this.sequences.get(runId);
|
|
2093
|
-
if (encoded !== undefined && base !== undefined) {
|
|
2094
|
-
try {
|
|
2095
|
-
yield* this.append(runId, { type: RUN_EVENT_TYPES.messageQueued, payload: { ...next, pendingStageMessages: encoded } }, { expectSeq: base });
|
|
2096
|
-
return true;
|
|
2097
|
-
} catch (error) {
|
|
2098
|
-
if (!(error instanceof JournalCasConflictError))
|
|
2099
|
-
throw error;
|
|
2100
|
-
}
|
|
2101
|
-
}
|
|
2102
2110
|
yield* this.snapshot(next, RUN_EVENT_TYPES.messageQueued);
|
|
2103
2111
|
return true;
|
|
2104
2112
|
}
|
|
@@ -2438,31 +2446,143 @@ function uniqueByIdentity(messages) {
|
|
|
2438
2446
|
function isDeltaEncoded(message) {
|
|
2439
2447
|
return message.deliveryDelta !== undefined;
|
|
2440
2448
|
}
|
|
2441
|
-
function
|
|
2442
|
-
const
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2449
|
+
function deliveryDelta(base, deliveries) {
|
|
2450
|
+
const drop = [];
|
|
2451
|
+
let kept = 0;
|
|
2452
|
+
base.forEach((delivery, index) => {
|
|
2453
|
+
if (kept < deliveries.length && JSON.stringify(delivery) === JSON.stringify(deliveries[kept]))
|
|
2454
|
+
kept++;
|
|
2455
|
+
else
|
|
2456
|
+
drop.push(index);
|
|
2457
|
+
});
|
|
2458
|
+
const add = deliveries.slice(kept);
|
|
2459
|
+
return drop.length === 0 ? { add } : { drop, add };
|
|
2460
|
+
}
|
|
2461
|
+
function pendingStageFields(message) {
|
|
2462
|
+
return Object.keys(message);
|
|
2463
|
+
}
|
|
2464
|
+
function copyField(target, source, key) {
|
|
2465
|
+
target[key] = source[key];
|
|
2466
|
+
}
|
|
2467
|
+
function isRemovedField(message, key) {
|
|
2468
|
+
return message[key] === undefined;
|
|
2469
|
+
}
|
|
2470
|
+
function json(message) {
|
|
2471
|
+
let text = entryJson.get(message);
|
|
2472
|
+
if (text === undefined) {
|
|
2473
|
+
text = JSON.stringify(message);
|
|
2474
|
+
entryJson.set(message, text);
|
|
2475
|
+
}
|
|
2476
|
+
return text;
|
|
2477
|
+
}
|
|
2478
|
+
function patchEntry(index, base, message) {
|
|
2479
|
+
const set = {};
|
|
2480
|
+
const unset = pendingStageFields(base).filter((key) => base[key] !== undefined && isRemovedField(message, key));
|
|
2481
|
+
for (const key of pendingStageFields(message)) {
|
|
2482
|
+
if (message[key] === undefined || key === "deliveries")
|
|
2483
|
+
continue;
|
|
2484
|
+
if (JSON.stringify(message[key]) !== JSON.stringify(base[key]))
|
|
2485
|
+
copyField(set, message, key);
|
|
2486
|
+
}
|
|
2487
|
+
let delta;
|
|
2488
|
+
if (message.deliveries !== undefined) {
|
|
2489
|
+
if (base.deliveries === undefined)
|
|
2490
|
+
set.deliveries = message.deliveries;
|
|
2491
|
+
else if (JSON.stringify(base.deliveries) !== JSON.stringify(message.deliveries))
|
|
2492
|
+
delta = deliveryDelta(base.deliveries, message.deliveries);
|
|
2493
|
+
}
|
|
2494
|
+
return {
|
|
2495
|
+
patch: index,
|
|
2496
|
+
...Object.keys(set).length === 0 ? {} : { set },
|
|
2497
|
+
...unset.length === 0 ? {} : { unset },
|
|
2498
|
+
...delta === undefined ? {} : { deliveryDelta: delta }
|
|
2499
|
+
};
|
|
2500
|
+
}
|
|
2501
|
+
function encodePendingStageList(previous, next) {
|
|
2502
|
+
const positions = new Map;
|
|
2503
|
+
const repeated = new Set;
|
|
2504
|
+
previous.forEach((message, index) => {
|
|
2505
|
+
const key = identity(message);
|
|
2506
|
+
if (positions.has(key))
|
|
2507
|
+
repeated.add(key);
|
|
2508
|
+
positions.set(key, index);
|
|
2464
2509
|
});
|
|
2465
|
-
|
|
2510
|
+
for (const key of repeated)
|
|
2511
|
+
positions.delete(key);
|
|
2512
|
+
const items = [];
|
|
2513
|
+
let reused = 0;
|
|
2514
|
+
for (const message of next) {
|
|
2515
|
+
const index = positions.get(identity(message));
|
|
2516
|
+
const base = index === undefined ? undefined : previous[index];
|
|
2517
|
+
if (base === undefined) {
|
|
2518
|
+
items.push(message);
|
|
2519
|
+
continue;
|
|
2520
|
+
}
|
|
2521
|
+
reused++;
|
|
2522
|
+
const patched = base === message || json(base) === json(message) ? undefined : patchEntry(index, base, message);
|
|
2523
|
+
if (patched === undefined || Object.keys(patched).length === 1) {
|
|
2524
|
+
const last = items.at(-1);
|
|
2525
|
+
if (Array.isArray(last) && last[0] + last[1] === index)
|
|
2526
|
+
last[1]++;
|
|
2527
|
+
else
|
|
2528
|
+
items.push([index, 1]);
|
|
2529
|
+
continue;
|
|
2530
|
+
}
|
|
2531
|
+
items.push(JSON.stringify(patched).length < json(message).length ? patched : message);
|
|
2532
|
+
}
|
|
2533
|
+
return reused > 0 ? items : undefined;
|
|
2534
|
+
}
|
|
2535
|
+
function decodePendingStageList(previous, items) {
|
|
2536
|
+
const base = (index) => {
|
|
2537
|
+
if (!Number.isInteger(index) || index < 0 || index >= previous.length)
|
|
2538
|
+
throw new Error(`atomic-workflows: journal pending-stage change names missing entry ${index}`);
|
|
2539
|
+
return previous[index];
|
|
2540
|
+
};
|
|
2541
|
+
const result = [];
|
|
2542
|
+
for (const item of items) {
|
|
2543
|
+
if (Array.isArray(item)) {
|
|
2544
|
+
const [start, count] = item;
|
|
2545
|
+
for (let index = start;index < start + count; index++)
|
|
2546
|
+
result.push(base(index));
|
|
2547
|
+
} else if (typeof item.patch === "number") {
|
|
2548
|
+
const { patch, set, unset, deliveryDelta: delta } = item;
|
|
2549
|
+
const entry = { ...base(patch), ...set };
|
|
2550
|
+
for (const key of unset ?? [])
|
|
2551
|
+
delete entry[key];
|
|
2552
|
+
if (delta !== undefined) {
|
|
2553
|
+
const dropped = new Set(delta.drop ?? []);
|
|
2554
|
+
const deliveries = base(patch).deliveries ?? [];
|
|
2555
|
+
entry.deliveries = [...deliveries.filter((_, index) => !dropped.has(index)), ...delta.add];
|
|
2556
|
+
}
|
|
2557
|
+
result.push(entry);
|
|
2558
|
+
} else
|
|
2559
|
+
result.push(item);
|
|
2560
|
+
}
|
|
2561
|
+
return result;
|
|
2562
|
+
}
|
|
2563
|
+
function encodeHandleEvent(event, previous) {
|
|
2564
|
+
const handle = writtenHandle(event);
|
|
2565
|
+
if (handle?.pendingStageMessages === undefined || previous === undefined)
|
|
2566
|
+
return;
|
|
2567
|
+
const change = encodePendingStageList(previous, handle.pendingStageMessages);
|
|
2568
|
+
if (change === undefined)
|
|
2569
|
+
return;
|
|
2570
|
+
const { pendingStageMessages: _full, ...rest } = handle;
|
|
2571
|
+
const encoded = { ...rest, pendingStageMessageChange: change };
|
|
2572
|
+
if (event.type === RUN_EVENT_TYPES.promptAsked || event.type === RUN_EVENT_TYPES.promptReleased)
|
|
2573
|
+
return { ...event, payload: { ...event.payload, handle: encoded } };
|
|
2574
|
+
return { ...event, payload: encoded };
|
|
2575
|
+
}
|
|
2576
|
+
function decodeHandle(handle, previous) {
|
|
2577
|
+
const { pendingStageMessageChange: change, ...rest } = handle;
|
|
2578
|
+
if (change !== undefined)
|
|
2579
|
+
return { ...rest, pendingStageMessages: decodePendingStageList(previous ?? [], change) };
|
|
2580
|
+
if (!hasPendingStageDeliveryDelta(handle.pendingStageMessages))
|
|
2581
|
+
return handle;
|
|
2582
|
+
return {
|
|
2583
|
+
...handle,
|
|
2584
|
+
pendingStageMessages: decodePendingStageDeliveries(previous ?? [], handle.pendingStageMessages ?? [])
|
|
2585
|
+
};
|
|
2466
2586
|
}
|
|
2467
2587
|
function decodePendingStageDeliveries(previous, messages) {
|
|
2468
2588
|
if (!messages.some(isDeltaEncoded))
|
|
@@ -2482,7 +2602,7 @@ function decodePendingStageDeliveries(previous, messages) {
|
|
|
2482
2602
|
function hasPendingStageDeliveryDelta(messages) {
|
|
2483
2603
|
return messages?.some(isDeltaEncoded) === true;
|
|
2484
2604
|
}
|
|
2485
|
-
var PROCESS_HOLDER_ID, processExitCleanups, JournalOwnershipError, JournalBackendClosedError, JournalOperationAbortedError, JournalExecutionRetiredError, JournalMessageScopeError;
|
|
2605
|
+
var PROCESS_HOLDER_ID, CHANGE_APPEND_ATTEMPTS = 4, processExitCleanups, JournalOwnershipError, JournalBackendClosedError, JournalOperationAbortedError, JournalExecutionRetiredError, JournalMessageScopeError, entryJson;
|
|
2486
2606
|
var init_journal_backend = __esm(() => {
|
|
2487
2607
|
init_workflow_instance_ownership_error();
|
|
2488
2608
|
init_backend();
|
|
@@ -2540,6 +2660,7 @@ var init_journal_backend = __esm(() => {
|
|
|
2540
2660
|
this.name = "JournalMessageScopeError";
|
|
2541
2661
|
}
|
|
2542
2662
|
};
|
|
2663
|
+
entryJson = new WeakMap;
|
|
2543
2664
|
});
|
|
2544
2665
|
|
|
2545
2666
|
// dist/builtin/workflows/src/durable/journal/legacy-journal-tables.ts
|
|
@@ -57532,7 +57653,20 @@ function createWorkflowBoundarySegmentsResolver(runs) {
|
|
|
57532
57653
|
};
|
|
57533
57654
|
}
|
|
57534
57655
|
function workflowBoundaryHops(runs, runId) {
|
|
57656
|
+
return boundaryHopsFrom(new Map(runs.map((run) => [run.id, run])), runId);
|
|
57657
|
+
}
|
|
57658
|
+
function createWorkflowBoundaryHopsResolver(runs) {
|
|
57535
57659
|
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
57660
|
+
const cache = new Map;
|
|
57661
|
+
return (runId) => {
|
|
57662
|
+
if (cache.has(runId))
|
|
57663
|
+
return cache.get(runId);
|
|
57664
|
+
const hops = boundaryHopsFrom(runById, runId);
|
|
57665
|
+
cache.set(runId, hops);
|
|
57666
|
+
return hops;
|
|
57667
|
+
};
|
|
57668
|
+
}
|
|
57669
|
+
function boundaryHopsFrom(runById, runId) {
|
|
57536
57670
|
const hops = [];
|
|
57537
57671
|
let current = runById.get(runId);
|
|
57538
57672
|
while (current !== undefined && current.parentRunId !== undefined) {
|
|
@@ -57558,6 +57692,35 @@ function workflowStagePathVariants(hops, stageSegments) {
|
|
|
57558
57692
|
function stageMatchesPathPattern(patternSegments, hops, stageSegments) {
|
|
57559
57693
|
return workflowStagePathVariants(hops, stageSegments).some((candidate) => matchStagePathSegments(patternSegments, candidate));
|
|
57560
57694
|
}
|
|
57695
|
+
function createStagePathPatternIndex(patterns) {
|
|
57696
|
+
const byFirstSegment = new Map;
|
|
57697
|
+
const globFirst = [];
|
|
57698
|
+
patterns.forEach((pattern, index) => {
|
|
57699
|
+
const first = pattern[0];
|
|
57700
|
+
if (first === undefined || first.includes("*")) {
|
|
57701
|
+
globFirst.push(index);
|
|
57702
|
+
return;
|
|
57703
|
+
}
|
|
57704
|
+
const bucket = byFirstSegment.get(first);
|
|
57705
|
+
if (bucket === undefined)
|
|
57706
|
+
byFirstSegment.set(first, [index]);
|
|
57707
|
+
else
|
|
57708
|
+
bucket.push(index);
|
|
57709
|
+
});
|
|
57710
|
+
return {
|
|
57711
|
+
matching(hops, stageSegments) {
|
|
57712
|
+
if (patterns.length === 0)
|
|
57713
|
+
return [];
|
|
57714
|
+
const variants = workflowStagePathVariants(hops, stageSegments);
|
|
57715
|
+
const candidates = new Set(globFirst);
|
|
57716
|
+
for (const variant of variants) {
|
|
57717
|
+
for (const index of byFirstSegment.get(variant[0]) ?? [])
|
|
57718
|
+
candidates.add(index);
|
|
57719
|
+
}
|
|
57720
|
+
return [...candidates].sort((left, right) => left - right).filter((index) => variants.some((variant) => matchStagePathSegments(patterns[index], variant)));
|
|
57721
|
+
}
|
|
57722
|
+
};
|
|
57723
|
+
}
|
|
57561
57724
|
var init_pending_stage_status = __esm(() => {
|
|
57562
57725
|
init_store_internal();
|
|
57563
57726
|
init_workflow_stage_target();
|
|
@@ -57568,24 +57731,63 @@ function stickyStageDeliveryStatuses(runs, rootRunId, availableBackend) {
|
|
|
57568
57731
|
const root = runs.find((run) => run.id === rootRunId);
|
|
57569
57732
|
const entries = (root?.pendingStageMessages ?? []).filter((entry) => entry.sticky === true);
|
|
57570
57733
|
const result = [];
|
|
57734
|
+
const patternByTarget = new Map;
|
|
57735
|
+
const patterns = [];
|
|
57736
|
+
const entriesByPattern = [];
|
|
57737
|
+
const ownEntries = [];
|
|
57738
|
+
entries.forEach((entry, index) => {
|
|
57739
|
+
const target = entry.targetPath ?? entry.stageKey;
|
|
57740
|
+
let pattern = patternByTarget.get(target);
|
|
57741
|
+
if (pattern === undefined) {
|
|
57742
|
+
const parsed = parseWorkflowStageTarget(target);
|
|
57743
|
+
pattern = parsed?.rootRunId === rootRunId ? patterns.push(parsed.segments) - 1 : -1;
|
|
57744
|
+
if (pattern >= 0)
|
|
57745
|
+
entriesByPattern.push([]);
|
|
57746
|
+
patternByTarget.set(target, pattern);
|
|
57747
|
+
}
|
|
57748
|
+
if (pattern < 0)
|
|
57749
|
+
return;
|
|
57750
|
+
entriesByPattern[pattern].push(index);
|
|
57751
|
+
ownEntries.push(index);
|
|
57752
|
+
});
|
|
57753
|
+
if (ownEntries.length === 0)
|
|
57754
|
+
return result;
|
|
57755
|
+
const patternIndex = createStagePathPatternIndex(patterns);
|
|
57756
|
+
const deliveriesByEntry = new Map;
|
|
57757
|
+
const entryReceipts = (index, runId, stageId) => {
|
|
57758
|
+
let byStage = deliveriesByEntry.get(index);
|
|
57759
|
+
if (byStage === undefined) {
|
|
57760
|
+
byStage = new Map;
|
|
57761
|
+
for (const delivery of entries[index].deliveries ?? []) {
|
|
57762
|
+
const key = `${delivery.runId}\x00${delivery.stageId}`;
|
|
57763
|
+
const list = byStage.get(key);
|
|
57764
|
+
if (list === undefined)
|
|
57765
|
+
byStage.set(key, [delivery]);
|
|
57766
|
+
else
|
|
57767
|
+
list.push(delivery);
|
|
57768
|
+
}
|
|
57769
|
+
deliveriesByEntry.set(index, byStage);
|
|
57770
|
+
}
|
|
57771
|
+
return byStage.get(`${runId}\x00${stageId}`) ?? [];
|
|
57772
|
+
};
|
|
57571
57773
|
availableBackend = availableRunDurableBackend(runs, rootRunId) ?? availableBackend;
|
|
57572
57774
|
const backend = availableBackend === undefined ? undefined : durableBackendForRun(availableBackend, runs, rootRunId);
|
|
57775
|
+
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
57776
|
+
const hopsFor = createWorkflowBoundaryHopsResolver(runs);
|
|
57573
57777
|
for (const run of runs) {
|
|
57574
|
-
|
|
57778
|
+
const durableRootRunId = reciprocalWorkflowRootRunId(runById, run.id);
|
|
57779
|
+
if (run.id !== rootRunId && run.rootRunId !== rootRunId && durableRootRunId !== rootRunId)
|
|
57575
57780
|
continue;
|
|
57576
|
-
const resolved =
|
|
57577
|
-
const hops =
|
|
57781
|
+
const resolved = durableRootRunId === rootRunId;
|
|
57782
|
+
const hops = hopsFor(run.id);
|
|
57578
57783
|
for (const stage of run.stages) {
|
|
57579
57784
|
if (stage.nodeKind === "tool" || stage.replayKey?.startsWith("prompt:") === true || stage.replayKey?.startsWith("workflow:") === true || stage.workflowChildRun !== undefined || stage.workflowChild !== undefined)
|
|
57580
57785
|
continue;
|
|
57581
|
-
|
|
57786
|
+
const matchedEntries = resolved && hops ? patternIndex.matching(hops, [stage.id, stage.name]).flatMap((pattern) => entriesByPattern[pattern]).sort((left, right) => left - right) : ownEntries;
|
|
57787
|
+
for (const index of matchedEntries) {
|
|
57788
|
+
const entry = entries[index];
|
|
57582
57789
|
const target = entry.targetPath ?? entry.stageKey;
|
|
57583
|
-
const
|
|
57584
|
-
if (!parsed || parsed.rootRunId !== rootRunId)
|
|
57585
|
-
continue;
|
|
57586
|
-
if (resolved && hops && !stageMatchesPathPattern(parsed.segments, hops, [stage.id, stage.name]))
|
|
57587
|
-
continue;
|
|
57588
|
-
const receipts = (entry.deliveries ?? []).filter((delivery) => delivery.runId === run.id && delivery.stageId === stage.id);
|
|
57790
|
+
const receipts = entryReceipts(index, run.id, stage.id);
|
|
57589
57791
|
const delivered = backend?.hasCachedPendingStageDeliveryReceipt?.(rootRunId, entry.id, {
|
|
57590
57792
|
runId: run.id,
|
|
57591
57793
|
stageId: stage.id,
|
|
@@ -57903,20 +58105,27 @@ function possibleStageRows(runs, rootRunId, rootRun, backend) {
|
|
|
57903
58105
|
if (isTerminalRunStatus(rootRun.status))
|
|
57904
58106
|
return [];
|
|
57905
58107
|
const stickyQueued = (rootRun.pendingStageMessages ?? []).filter((entry) => entry.sticky === true && entry.status === "queued");
|
|
58108
|
+
const segmentsByTarget = new Map;
|
|
57906
58109
|
const stickySegments = (entry) => {
|
|
57907
|
-
const
|
|
57908
|
-
|
|
58110
|
+
const target = entry.targetPath ?? entry.stageKey;
|
|
58111
|
+
if (segmentsByTarget.has(target))
|
|
58112
|
+
return segmentsByTarget.get(target);
|
|
58113
|
+
const parsed = parseWorkflowStageTarget(target);
|
|
58114
|
+
const segments = parsed?.rootRunId === rootRunId ? parsed.segments : undefined;
|
|
58115
|
+
segmentsByTarget.set(target, segments);
|
|
58116
|
+
return segments;
|
|
57909
58117
|
};
|
|
57910
58118
|
const scanEntries = stickyQueued.filter((entry) => {
|
|
57911
58119
|
const segments = stickySegments(entry);
|
|
57912
58120
|
return !(segments !== undefined && segments.length === 1 && segments[0] === "**");
|
|
57913
58121
|
});
|
|
58122
|
+
const liveStageMatches = materializedStageMatcher(runs, rootRunId);
|
|
57914
58123
|
const rows = [];
|
|
57915
58124
|
for (const scanEntry of rootRun.possibleStages ?? []) {
|
|
57916
58125
|
const rowSegments = splitStagePathSegments(scanEntry);
|
|
57917
58126
|
if (rowSegments.length === 0 || rowSegments.some((segment) => segment.length === 0))
|
|
57918
58127
|
continue;
|
|
57919
|
-
if (!rowSegments.some((segment) => segment.includes("*")) &&
|
|
58128
|
+
if (!rowSegments.some((segment) => segment.includes("*")) && liveStageMatches(rowSegments)) {
|
|
57920
58129
|
continue;
|
|
57921
58130
|
}
|
|
57922
58131
|
rows.push({
|
|
@@ -57937,28 +58146,43 @@ function possibleStageRows(runs, rootRunId, rootRun, backend) {
|
|
|
57937
58146
|
}).length
|
|
57938
58147
|
});
|
|
57939
58148
|
const statuses = stickyStageDeliveryStatuses(runs, rootRunId, backend);
|
|
57940
|
-
|
|
57941
|
-
|
|
58149
|
+
const statusesByTarget = new Map;
|
|
58150
|
+
for (const status of statuses) {
|
|
58151
|
+
const forTarget = statusesByTarget.get(status.target);
|
|
58152
|
+
if (forTarget === undefined)
|
|
58153
|
+
statusesByTarget.set(status.target, [status]);
|
|
58154
|
+
else
|
|
58155
|
+
forTarget.push(status);
|
|
58156
|
+
}
|
|
58157
|
+
const queuedByTarget = new Map;
|
|
58158
|
+
for (const entry of stickyQueued) {
|
|
58159
|
+
const target = entry.targetPath ?? entry.stageKey;
|
|
58160
|
+
queuedByTarget.set(target, (queuedByTarget.get(target) ?? 0) + 1);
|
|
58161
|
+
}
|
|
58162
|
+
const rowTargets = new Set(rows.map((row) => row.target));
|
|
58163
|
+
for (const target of statusesByTarget.keys()) {
|
|
58164
|
+
if (rowTargets.has(target))
|
|
57942
58165
|
continue;
|
|
57943
|
-
|
|
57944
|
-
|
|
57945
|
-
queuedCount: stickyQueued.filter((entry) => (entry.targetPath ?? entry.stageKey) === target).length,
|
|
57946
|
-
deliveryOnly: true
|
|
57947
|
-
});
|
|
58166
|
+
rowTargets.add(target);
|
|
58167
|
+
rows.push({ target, queuedCount: queuedByTarget.get(target) ?? 0, deliveryOnly: true });
|
|
57948
58168
|
}
|
|
57949
58169
|
for (let index = 0;index < rows.length; index++) {
|
|
57950
58170
|
const row = rows[index];
|
|
57951
|
-
const deliveryStates =
|
|
57952
|
-
if (deliveryStates
|
|
58171
|
+
const deliveryStates = statusesByTarget.get(row.target);
|
|
58172
|
+
if (deliveryStates !== undefined)
|
|
57953
58173
|
rows[index] = { ...row, deliveryStates };
|
|
57954
58174
|
}
|
|
57955
58175
|
return rows;
|
|
57956
58176
|
}
|
|
57957
|
-
function
|
|
57958
|
-
|
|
57959
|
-
|
|
57960
|
-
|
|
57961
|
-
|
|
58177
|
+
function materializedStageMatcher(runs, rootRunId) {
|
|
58178
|
+
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
58179
|
+
const hopsFor = createWorkflowBoundaryHopsResolver(runs);
|
|
58180
|
+
const invocationRuns = runs.filter((run) => reciprocalWorkflowRootRunId(runById, run.id) === rootRunId);
|
|
58181
|
+
return (entrySegments) => materializedStageMatches(invocationRuns, hopsFor, entrySegments);
|
|
58182
|
+
}
|
|
58183
|
+
function materializedStageMatches(invocationRuns, hopsFor, entrySegments) {
|
|
58184
|
+
for (const run of invocationRuns) {
|
|
58185
|
+
const hops = hopsFor(run.id);
|
|
57962
58186
|
if (hops === undefined)
|
|
57963
58187
|
continue;
|
|
57964
58188
|
for (const stage of run.stages) {
|
|
@@ -58233,10 +58457,12 @@ async function recordConfirmedStickyDeliveries(activeStore, event) {
|
|
|
58233
58457
|
}
|
|
58234
58458
|
function matchingLiveStages(runs, rootRunId, patternSegments) {
|
|
58235
58459
|
const matches = [];
|
|
58460
|
+
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
58461
|
+
const hopsFor = createWorkflowBoundaryHopsResolver(runs);
|
|
58236
58462
|
for (const run of runs) {
|
|
58237
|
-
if (
|
|
58463
|
+
if (reciprocalWorkflowRootRunId(runById, run.id) !== rootRunId)
|
|
58238
58464
|
continue;
|
|
58239
|
-
const hops =
|
|
58465
|
+
const hops = hopsFor(run.id);
|
|
58240
58466
|
if (hops === undefined)
|
|
58241
58467
|
continue;
|
|
58242
58468
|
for (const stage of run.stages) {
|
|
@@ -58372,11 +58598,26 @@ function writeMessage(socket, msg, callback) {
|
|
|
58372
58598
|
}
|
|
58373
58599
|
function createMessageReader(onMessage, onError) {
|
|
58374
58600
|
let buffer = Buffer.alloc(0);
|
|
58601
|
+
let pending = [];
|
|
58602
|
+
let pendingLength = 0;
|
|
58603
|
+
let awaitedLength = 0;
|
|
58375
58604
|
return (data) => {
|
|
58376
|
-
|
|
58605
|
+
if (pendingLength + data.length < awaitedLength) {
|
|
58606
|
+
pending.push(data);
|
|
58607
|
+
pendingLength += data.length;
|
|
58608
|
+
return;
|
|
58609
|
+
}
|
|
58610
|
+
buffer = pending.length === 0 ? Buffer.concat([buffer, data]) : Buffer.concat([...pending, data]);
|
|
58611
|
+
pending = [];
|
|
58612
|
+
pendingLength = 0;
|
|
58613
|
+
awaitedLength = 0;
|
|
58377
58614
|
while (buffer.length >= 4) {
|
|
58378
58615
|
const length = buffer.readUInt32BE(0);
|
|
58379
58616
|
if (buffer.length < 4 + length) {
|
|
58617
|
+
pending = [buffer];
|
|
58618
|
+
pendingLength = buffer.length;
|
|
58619
|
+
awaitedLength = 4 + length;
|
|
58620
|
+
buffer = Buffer.alloc(0);
|
|
58380
58621
|
break;
|
|
58381
58622
|
}
|
|
58382
58623
|
const payload = buffer.subarray(4, 4 + length);
|
|
@@ -163,9 +163,9 @@
|
|
|
163
163
|
"license": "Unlicense"
|
|
164
164
|
},
|
|
165
165
|
"node_modules/undici": {
|
|
166
|
-
"version": "6.29.
|
|
167
|
-
"resolved": "https://registry.npmjs.org/undici/-/undici-6.29.
|
|
168
|
-
"integrity": "sha512-
|
|
166
|
+
"version": "6.29.1",
|
|
167
|
+
"resolved": "https://registry.npmjs.org/undici/-/undici-6.29.1.tgz",
|
|
168
|
+
"integrity": "sha512-EvRlUt/QqAEvXdQeRMYUfwOQsfzpDztykrG2owGEE/rBOBoYv9uF39ZzsNDh4lTFHhTr2XOZjKkYgueD12ZmGA==",
|
|
169
169
|
"license": "MIT",
|
|
170
170
|
"engines": {
|
|
171
171
|
"node": ">=18.17"
|