@bastani/atomic 0.9.44-alpha.2 → 0.9.44-alpha.3
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 +15 -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 +7 -0
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +313 -76
- package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +313 -76
- package/dist/builtin/workflows/src/index.js +313 -76
- package/dist/builtin/workflows/src/local-worker-entry.mjs +313 -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,20 @@ class JournalDurableBackend {
|
|
|
1907
1908
|
}
|
|
1908
1909
|
*append(runId, event, options) {
|
|
1909
1910
|
const lease = yield* this.ownership(runId);
|
|
1911
|
+
const base = this.sequences.get(runId);
|
|
1912
|
+
const pinned = options?.expectSeq;
|
|
1913
|
+
const encoded = base !== undefined && (pinned === undefined || pinned === base) && event.type !== RUN_EVENT_TYPES.runStarted ? encodeHandleEvent(event, this.projection.getWorkflow(runId)?.pendingStageMessages) : undefined;
|
|
1914
|
+
if (encoded !== undefined) {
|
|
1915
|
+
try {
|
|
1916
|
+
return yield* this.write(runId, lease, encoded, { ...options, expectSeq: base });
|
|
1917
|
+
} catch (error) {
|
|
1918
|
+
if (!(error instanceof JournalCasConflictError) || pinned !== undefined)
|
|
1919
|
+
throw error;
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
yield* this.write(runId, lease, event, options);
|
|
1923
|
+
}
|
|
1924
|
+
*write(runId, lease, event, options) {
|
|
1910
1925
|
try {
|
|
1911
1926
|
const outcome = yield* invoke(() => this.journal.append(lease, event, options));
|
|
1912
1927
|
const nextSeq = (this.sequences.get(runId) ?? 0) + 1;
|
|
@@ -2088,17 +2103,6 @@ class JournalDurableBackend {
|
|
|
2088
2103
|
pendingStageMessages: replacePendingStageMessagesForRun(handle.pendingStageMessages ?? [], logicalRunId, messages),
|
|
2089
2104
|
updatedAt: Math.max(Date.now(), handle.updatedAt + 1)
|
|
2090
2105
|
};
|
|
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
2106
|
yield* this.snapshot(next, RUN_EVENT_TYPES.messageQueued);
|
|
2103
2107
|
return true;
|
|
2104
2108
|
}
|
|
@@ -2438,31 +2442,143 @@ function uniqueByIdentity(messages) {
|
|
|
2438
2442
|
function isDeltaEncoded(message) {
|
|
2439
2443
|
return message.deliveryDelta !== undefined;
|
|
2440
2444
|
}
|
|
2441
|
-
function
|
|
2442
|
-
const
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
return message;
|
|
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
|
-
if (drop.length + add.length >= deliveries.length)
|
|
2460
|
-
return message;
|
|
2461
|
-
encodedAny = true;
|
|
2462
|
-
const { deliveries: _full, ...rest } = message;
|
|
2463
|
-
return { ...rest, deliveryDelta: drop.length === 0 ? { add } : { drop, add } };
|
|
2445
|
+
function deliveryDelta(base, deliveries) {
|
|
2446
|
+
const drop = [];
|
|
2447
|
+
let kept = 0;
|
|
2448
|
+
base.forEach((delivery, index) => {
|
|
2449
|
+
if (kept < deliveries.length && JSON.stringify(delivery) === JSON.stringify(deliveries[kept]))
|
|
2450
|
+
kept++;
|
|
2451
|
+
else
|
|
2452
|
+
drop.push(index);
|
|
2464
2453
|
});
|
|
2465
|
-
|
|
2454
|
+
const add = deliveries.slice(kept);
|
|
2455
|
+
return drop.length === 0 ? { add } : { drop, add };
|
|
2456
|
+
}
|
|
2457
|
+
function pendingStageFields(message) {
|
|
2458
|
+
return Object.keys(message);
|
|
2459
|
+
}
|
|
2460
|
+
function copyField(target, source, key) {
|
|
2461
|
+
target[key] = source[key];
|
|
2462
|
+
}
|
|
2463
|
+
function isRemovedField(message, key) {
|
|
2464
|
+
return message[key] === undefined;
|
|
2465
|
+
}
|
|
2466
|
+
function json(message) {
|
|
2467
|
+
let text = entryJson.get(message);
|
|
2468
|
+
if (text === undefined) {
|
|
2469
|
+
text = JSON.stringify(message);
|
|
2470
|
+
entryJson.set(message, text);
|
|
2471
|
+
}
|
|
2472
|
+
return text;
|
|
2473
|
+
}
|
|
2474
|
+
function patchEntry(index, base, message) {
|
|
2475
|
+
const set = {};
|
|
2476
|
+
const unset = pendingStageFields(base).filter((key) => base[key] !== undefined && isRemovedField(message, key));
|
|
2477
|
+
for (const key of pendingStageFields(message)) {
|
|
2478
|
+
if (message[key] === undefined || key === "deliveries")
|
|
2479
|
+
continue;
|
|
2480
|
+
if (JSON.stringify(message[key]) !== JSON.stringify(base[key]))
|
|
2481
|
+
copyField(set, message, key);
|
|
2482
|
+
}
|
|
2483
|
+
let delta;
|
|
2484
|
+
if (message.deliveries !== undefined) {
|
|
2485
|
+
if (base.deliveries === undefined)
|
|
2486
|
+
set.deliveries = message.deliveries;
|
|
2487
|
+
else if (JSON.stringify(base.deliveries) !== JSON.stringify(message.deliveries))
|
|
2488
|
+
delta = deliveryDelta(base.deliveries, message.deliveries);
|
|
2489
|
+
}
|
|
2490
|
+
return {
|
|
2491
|
+
patch: index,
|
|
2492
|
+
...Object.keys(set).length === 0 ? {} : { set },
|
|
2493
|
+
...unset.length === 0 ? {} : { unset },
|
|
2494
|
+
...delta === undefined ? {} : { deliveryDelta: delta }
|
|
2495
|
+
};
|
|
2496
|
+
}
|
|
2497
|
+
function encodePendingStageList(previous, next) {
|
|
2498
|
+
const positions = new Map;
|
|
2499
|
+
const repeated = new Set;
|
|
2500
|
+
previous.forEach((message, index) => {
|
|
2501
|
+
const key = identity(message);
|
|
2502
|
+
if (positions.has(key))
|
|
2503
|
+
repeated.add(key);
|
|
2504
|
+
positions.set(key, index);
|
|
2505
|
+
});
|
|
2506
|
+
for (const key of repeated)
|
|
2507
|
+
positions.delete(key);
|
|
2508
|
+
const items = [];
|
|
2509
|
+
let reused = 0;
|
|
2510
|
+
for (const message of next) {
|
|
2511
|
+
const index = positions.get(identity(message));
|
|
2512
|
+
const base = index === undefined ? undefined : previous[index];
|
|
2513
|
+
if (base === undefined) {
|
|
2514
|
+
items.push(message);
|
|
2515
|
+
continue;
|
|
2516
|
+
}
|
|
2517
|
+
reused++;
|
|
2518
|
+
const patched = base === message || json(base) === json(message) ? undefined : patchEntry(index, base, message);
|
|
2519
|
+
if (patched === undefined || Object.keys(patched).length === 1) {
|
|
2520
|
+
const last = items.at(-1);
|
|
2521
|
+
if (Array.isArray(last) && last[0] + last[1] === index)
|
|
2522
|
+
last[1]++;
|
|
2523
|
+
else
|
|
2524
|
+
items.push([index, 1]);
|
|
2525
|
+
continue;
|
|
2526
|
+
}
|
|
2527
|
+
items.push(JSON.stringify(patched).length < json(message).length ? patched : message);
|
|
2528
|
+
}
|
|
2529
|
+
return reused > 0 ? items : undefined;
|
|
2530
|
+
}
|
|
2531
|
+
function decodePendingStageList(previous, items) {
|
|
2532
|
+
const base = (index) => {
|
|
2533
|
+
if (!Number.isInteger(index) || index < 0 || index >= previous.length)
|
|
2534
|
+
throw new Error(`atomic-workflows: journal pending-stage change names missing entry ${index}`);
|
|
2535
|
+
return previous[index];
|
|
2536
|
+
};
|
|
2537
|
+
const result = [];
|
|
2538
|
+
for (const item of items) {
|
|
2539
|
+
if (Array.isArray(item)) {
|
|
2540
|
+
const [start, count] = item;
|
|
2541
|
+
for (let index = start;index < start + count; index++)
|
|
2542
|
+
result.push(base(index));
|
|
2543
|
+
} else if (typeof item.patch === "number") {
|
|
2544
|
+
const { patch, set, unset, deliveryDelta: delta } = item;
|
|
2545
|
+
const entry = { ...base(patch), ...set };
|
|
2546
|
+
for (const key of unset ?? [])
|
|
2547
|
+
delete entry[key];
|
|
2548
|
+
if (delta !== undefined) {
|
|
2549
|
+
const dropped = new Set(delta.drop ?? []);
|
|
2550
|
+
const deliveries = base(patch).deliveries ?? [];
|
|
2551
|
+
entry.deliveries = [...deliveries.filter((_, index) => !dropped.has(index)), ...delta.add];
|
|
2552
|
+
}
|
|
2553
|
+
result.push(entry);
|
|
2554
|
+
} else
|
|
2555
|
+
result.push(item);
|
|
2556
|
+
}
|
|
2557
|
+
return result;
|
|
2558
|
+
}
|
|
2559
|
+
function encodeHandleEvent(event, previous) {
|
|
2560
|
+
const handle = writtenHandle(event);
|
|
2561
|
+
if (handle?.pendingStageMessages === undefined || previous === undefined)
|
|
2562
|
+
return;
|
|
2563
|
+
const change = encodePendingStageList(previous, handle.pendingStageMessages);
|
|
2564
|
+
if (change === undefined)
|
|
2565
|
+
return;
|
|
2566
|
+
const { pendingStageMessages: _full, ...rest } = handle;
|
|
2567
|
+
const encoded = { ...rest, pendingStageMessageChange: change };
|
|
2568
|
+
if (event.type === RUN_EVENT_TYPES.promptAsked || event.type === RUN_EVENT_TYPES.promptReleased)
|
|
2569
|
+
return { ...event, payload: { ...event.payload, handle: encoded } };
|
|
2570
|
+
return { ...event, payload: encoded };
|
|
2571
|
+
}
|
|
2572
|
+
function decodeHandle(handle, previous) {
|
|
2573
|
+
const { pendingStageMessageChange: change, ...rest } = handle;
|
|
2574
|
+
if (change !== undefined)
|
|
2575
|
+
return { ...rest, pendingStageMessages: decodePendingStageList(previous ?? [], change) };
|
|
2576
|
+
if (!hasPendingStageDeliveryDelta(handle.pendingStageMessages))
|
|
2577
|
+
return handle;
|
|
2578
|
+
return {
|
|
2579
|
+
...handle,
|
|
2580
|
+
pendingStageMessages: decodePendingStageDeliveries(previous ?? [], handle.pendingStageMessages ?? [])
|
|
2581
|
+
};
|
|
2466
2582
|
}
|
|
2467
2583
|
function decodePendingStageDeliveries(previous, messages) {
|
|
2468
2584
|
if (!messages.some(isDeltaEncoded))
|
|
@@ -2482,7 +2598,7 @@ function decodePendingStageDeliveries(previous, messages) {
|
|
|
2482
2598
|
function hasPendingStageDeliveryDelta(messages) {
|
|
2483
2599
|
return messages?.some(isDeltaEncoded) === true;
|
|
2484
2600
|
}
|
|
2485
|
-
var PROCESS_HOLDER_ID, processExitCleanups, JournalOwnershipError, JournalBackendClosedError, JournalOperationAbortedError, JournalExecutionRetiredError, JournalMessageScopeError;
|
|
2601
|
+
var PROCESS_HOLDER_ID, processExitCleanups, JournalOwnershipError, JournalBackendClosedError, JournalOperationAbortedError, JournalExecutionRetiredError, JournalMessageScopeError, entryJson;
|
|
2486
2602
|
var init_journal_backend = __esm(() => {
|
|
2487
2603
|
init_workflow_instance_ownership_error();
|
|
2488
2604
|
init_backend();
|
|
@@ -2540,6 +2656,7 @@ var init_journal_backend = __esm(() => {
|
|
|
2540
2656
|
this.name = "JournalMessageScopeError";
|
|
2541
2657
|
}
|
|
2542
2658
|
};
|
|
2659
|
+
entryJson = new WeakMap;
|
|
2543
2660
|
});
|
|
2544
2661
|
|
|
2545
2662
|
// dist/builtin/workflows/src/durable/journal/legacy-journal-tables.ts
|
|
@@ -57532,7 +57649,20 @@ function createWorkflowBoundarySegmentsResolver(runs) {
|
|
|
57532
57649
|
};
|
|
57533
57650
|
}
|
|
57534
57651
|
function workflowBoundaryHops(runs, runId) {
|
|
57652
|
+
return boundaryHopsFrom(new Map(runs.map((run) => [run.id, run])), runId);
|
|
57653
|
+
}
|
|
57654
|
+
function createWorkflowBoundaryHopsResolver(runs) {
|
|
57535
57655
|
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
57656
|
+
const cache = new Map;
|
|
57657
|
+
return (runId) => {
|
|
57658
|
+
if (cache.has(runId))
|
|
57659
|
+
return cache.get(runId);
|
|
57660
|
+
const hops = boundaryHopsFrom(runById, runId);
|
|
57661
|
+
cache.set(runId, hops);
|
|
57662
|
+
return hops;
|
|
57663
|
+
};
|
|
57664
|
+
}
|
|
57665
|
+
function boundaryHopsFrom(runById, runId) {
|
|
57536
57666
|
const hops = [];
|
|
57537
57667
|
let current = runById.get(runId);
|
|
57538
57668
|
while (current !== undefined && current.parentRunId !== undefined) {
|
|
@@ -57558,6 +57688,35 @@ function workflowStagePathVariants(hops, stageSegments) {
|
|
|
57558
57688
|
function stageMatchesPathPattern(patternSegments, hops, stageSegments) {
|
|
57559
57689
|
return workflowStagePathVariants(hops, stageSegments).some((candidate) => matchStagePathSegments(patternSegments, candidate));
|
|
57560
57690
|
}
|
|
57691
|
+
function createStagePathPatternIndex(patterns) {
|
|
57692
|
+
const byFirstSegment = new Map;
|
|
57693
|
+
const globFirst = [];
|
|
57694
|
+
patterns.forEach((pattern, index) => {
|
|
57695
|
+
const first = pattern[0];
|
|
57696
|
+
if (first === undefined || first.includes("*")) {
|
|
57697
|
+
globFirst.push(index);
|
|
57698
|
+
return;
|
|
57699
|
+
}
|
|
57700
|
+
const bucket = byFirstSegment.get(first);
|
|
57701
|
+
if (bucket === undefined)
|
|
57702
|
+
byFirstSegment.set(first, [index]);
|
|
57703
|
+
else
|
|
57704
|
+
bucket.push(index);
|
|
57705
|
+
});
|
|
57706
|
+
return {
|
|
57707
|
+
matching(hops, stageSegments) {
|
|
57708
|
+
if (patterns.length === 0)
|
|
57709
|
+
return [];
|
|
57710
|
+
const variants = workflowStagePathVariants(hops, stageSegments);
|
|
57711
|
+
const candidates = new Set(globFirst);
|
|
57712
|
+
for (const variant of variants) {
|
|
57713
|
+
for (const index of byFirstSegment.get(variant[0]) ?? [])
|
|
57714
|
+
candidates.add(index);
|
|
57715
|
+
}
|
|
57716
|
+
return [...candidates].sort((left, right) => left - right).filter((index) => variants.some((variant) => matchStagePathSegments(patterns[index], variant)));
|
|
57717
|
+
}
|
|
57718
|
+
};
|
|
57719
|
+
}
|
|
57561
57720
|
var init_pending_stage_status = __esm(() => {
|
|
57562
57721
|
init_store_internal();
|
|
57563
57722
|
init_workflow_stage_target();
|
|
@@ -57568,24 +57727,63 @@ function stickyStageDeliveryStatuses(runs, rootRunId, availableBackend) {
|
|
|
57568
57727
|
const root = runs.find((run) => run.id === rootRunId);
|
|
57569
57728
|
const entries = (root?.pendingStageMessages ?? []).filter((entry) => entry.sticky === true);
|
|
57570
57729
|
const result = [];
|
|
57730
|
+
const patternByTarget = new Map;
|
|
57731
|
+
const patterns = [];
|
|
57732
|
+
const entriesByPattern = [];
|
|
57733
|
+
const ownEntries = [];
|
|
57734
|
+
entries.forEach((entry, index) => {
|
|
57735
|
+
const target = entry.targetPath ?? entry.stageKey;
|
|
57736
|
+
let pattern = patternByTarget.get(target);
|
|
57737
|
+
if (pattern === undefined) {
|
|
57738
|
+
const parsed = parseWorkflowStageTarget(target);
|
|
57739
|
+
pattern = parsed?.rootRunId === rootRunId ? patterns.push(parsed.segments) - 1 : -1;
|
|
57740
|
+
if (pattern >= 0)
|
|
57741
|
+
entriesByPattern.push([]);
|
|
57742
|
+
patternByTarget.set(target, pattern);
|
|
57743
|
+
}
|
|
57744
|
+
if (pattern < 0)
|
|
57745
|
+
return;
|
|
57746
|
+
entriesByPattern[pattern].push(index);
|
|
57747
|
+
ownEntries.push(index);
|
|
57748
|
+
});
|
|
57749
|
+
if (ownEntries.length === 0)
|
|
57750
|
+
return result;
|
|
57751
|
+
const patternIndex = createStagePathPatternIndex(patterns);
|
|
57752
|
+
const deliveriesByEntry = new Map;
|
|
57753
|
+
const entryReceipts = (index, runId, stageId) => {
|
|
57754
|
+
let byStage = deliveriesByEntry.get(index);
|
|
57755
|
+
if (byStage === undefined) {
|
|
57756
|
+
byStage = new Map;
|
|
57757
|
+
for (const delivery of entries[index].deliveries ?? []) {
|
|
57758
|
+
const key = `${delivery.runId}\x00${delivery.stageId}`;
|
|
57759
|
+
const list = byStage.get(key);
|
|
57760
|
+
if (list === undefined)
|
|
57761
|
+
byStage.set(key, [delivery]);
|
|
57762
|
+
else
|
|
57763
|
+
list.push(delivery);
|
|
57764
|
+
}
|
|
57765
|
+
deliveriesByEntry.set(index, byStage);
|
|
57766
|
+
}
|
|
57767
|
+
return byStage.get(`${runId}\x00${stageId}`) ?? [];
|
|
57768
|
+
};
|
|
57571
57769
|
availableBackend = availableRunDurableBackend(runs, rootRunId) ?? availableBackend;
|
|
57572
57770
|
const backend = availableBackend === undefined ? undefined : durableBackendForRun(availableBackend, runs, rootRunId);
|
|
57771
|
+
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
57772
|
+
const hopsFor = createWorkflowBoundaryHopsResolver(runs);
|
|
57573
57773
|
for (const run of runs) {
|
|
57574
|
-
|
|
57774
|
+
const durableRootRunId = reciprocalWorkflowRootRunId(runById, run.id);
|
|
57775
|
+
if (run.id !== rootRunId && run.rootRunId !== rootRunId && durableRootRunId !== rootRunId)
|
|
57575
57776
|
continue;
|
|
57576
|
-
const resolved =
|
|
57577
|
-
const hops =
|
|
57777
|
+
const resolved = durableRootRunId === rootRunId;
|
|
57778
|
+
const hops = hopsFor(run.id);
|
|
57578
57779
|
for (const stage of run.stages) {
|
|
57579
57780
|
if (stage.nodeKind === "tool" || stage.replayKey?.startsWith("prompt:") === true || stage.replayKey?.startsWith("workflow:") === true || stage.workflowChildRun !== undefined || stage.workflowChild !== undefined)
|
|
57580
57781
|
continue;
|
|
57581
|
-
|
|
57782
|
+
const matchedEntries = resolved && hops ? patternIndex.matching(hops, [stage.id, stage.name]).flatMap((pattern) => entriesByPattern[pattern]).sort((left, right) => left - right) : ownEntries;
|
|
57783
|
+
for (const index of matchedEntries) {
|
|
57784
|
+
const entry = entries[index];
|
|
57582
57785
|
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);
|
|
57786
|
+
const receipts = entryReceipts(index, run.id, stage.id);
|
|
57589
57787
|
const delivered = backend?.hasCachedPendingStageDeliveryReceipt?.(rootRunId, entry.id, {
|
|
57590
57788
|
runId: run.id,
|
|
57591
57789
|
stageId: stage.id,
|
|
@@ -57903,20 +58101,27 @@ function possibleStageRows(runs, rootRunId, rootRun, backend) {
|
|
|
57903
58101
|
if (isTerminalRunStatus(rootRun.status))
|
|
57904
58102
|
return [];
|
|
57905
58103
|
const stickyQueued = (rootRun.pendingStageMessages ?? []).filter((entry) => entry.sticky === true && entry.status === "queued");
|
|
58104
|
+
const segmentsByTarget = new Map;
|
|
57906
58105
|
const stickySegments = (entry) => {
|
|
57907
|
-
const
|
|
57908
|
-
|
|
58106
|
+
const target = entry.targetPath ?? entry.stageKey;
|
|
58107
|
+
if (segmentsByTarget.has(target))
|
|
58108
|
+
return segmentsByTarget.get(target);
|
|
58109
|
+
const parsed = parseWorkflowStageTarget(target);
|
|
58110
|
+
const segments = parsed?.rootRunId === rootRunId ? parsed.segments : undefined;
|
|
58111
|
+
segmentsByTarget.set(target, segments);
|
|
58112
|
+
return segments;
|
|
57909
58113
|
};
|
|
57910
58114
|
const scanEntries = stickyQueued.filter((entry) => {
|
|
57911
58115
|
const segments = stickySegments(entry);
|
|
57912
58116
|
return !(segments !== undefined && segments.length === 1 && segments[0] === "**");
|
|
57913
58117
|
});
|
|
58118
|
+
const liveStageMatches = materializedStageMatcher(runs, rootRunId);
|
|
57914
58119
|
const rows = [];
|
|
57915
58120
|
for (const scanEntry of rootRun.possibleStages ?? []) {
|
|
57916
58121
|
const rowSegments = splitStagePathSegments(scanEntry);
|
|
57917
58122
|
if (rowSegments.length === 0 || rowSegments.some((segment) => segment.length === 0))
|
|
57918
58123
|
continue;
|
|
57919
|
-
if (!rowSegments.some((segment) => segment.includes("*")) &&
|
|
58124
|
+
if (!rowSegments.some((segment) => segment.includes("*")) && liveStageMatches(rowSegments)) {
|
|
57920
58125
|
continue;
|
|
57921
58126
|
}
|
|
57922
58127
|
rows.push({
|
|
@@ -57937,28 +58142,43 @@ function possibleStageRows(runs, rootRunId, rootRun, backend) {
|
|
|
57937
58142
|
}).length
|
|
57938
58143
|
});
|
|
57939
58144
|
const statuses = stickyStageDeliveryStatuses(runs, rootRunId, backend);
|
|
57940
|
-
|
|
57941
|
-
|
|
58145
|
+
const statusesByTarget = new Map;
|
|
58146
|
+
for (const status of statuses) {
|
|
58147
|
+
const forTarget = statusesByTarget.get(status.target);
|
|
58148
|
+
if (forTarget === undefined)
|
|
58149
|
+
statusesByTarget.set(status.target, [status]);
|
|
58150
|
+
else
|
|
58151
|
+
forTarget.push(status);
|
|
58152
|
+
}
|
|
58153
|
+
const queuedByTarget = new Map;
|
|
58154
|
+
for (const entry of stickyQueued) {
|
|
58155
|
+
const target = entry.targetPath ?? entry.stageKey;
|
|
58156
|
+
queuedByTarget.set(target, (queuedByTarget.get(target) ?? 0) + 1);
|
|
58157
|
+
}
|
|
58158
|
+
const rowTargets = new Set(rows.map((row) => row.target));
|
|
58159
|
+
for (const target of statusesByTarget.keys()) {
|
|
58160
|
+
if (rowTargets.has(target))
|
|
57942
58161
|
continue;
|
|
57943
|
-
|
|
57944
|
-
|
|
57945
|
-
queuedCount: stickyQueued.filter((entry) => (entry.targetPath ?? entry.stageKey) === target).length,
|
|
57946
|
-
deliveryOnly: true
|
|
57947
|
-
});
|
|
58162
|
+
rowTargets.add(target);
|
|
58163
|
+
rows.push({ target, queuedCount: queuedByTarget.get(target) ?? 0, deliveryOnly: true });
|
|
57948
58164
|
}
|
|
57949
58165
|
for (let index = 0;index < rows.length; index++) {
|
|
57950
58166
|
const row = rows[index];
|
|
57951
|
-
const deliveryStates =
|
|
57952
|
-
if (deliveryStates
|
|
58167
|
+
const deliveryStates = statusesByTarget.get(row.target);
|
|
58168
|
+
if (deliveryStates !== undefined)
|
|
57953
58169
|
rows[index] = { ...row, deliveryStates };
|
|
57954
58170
|
}
|
|
57955
58171
|
return rows;
|
|
57956
58172
|
}
|
|
57957
|
-
function
|
|
57958
|
-
|
|
57959
|
-
|
|
57960
|
-
|
|
57961
|
-
|
|
58173
|
+
function materializedStageMatcher(runs, rootRunId) {
|
|
58174
|
+
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
58175
|
+
const hopsFor = createWorkflowBoundaryHopsResolver(runs);
|
|
58176
|
+
const invocationRuns = runs.filter((run) => reciprocalWorkflowRootRunId(runById, run.id) === rootRunId);
|
|
58177
|
+
return (entrySegments) => materializedStageMatches(invocationRuns, hopsFor, entrySegments);
|
|
58178
|
+
}
|
|
58179
|
+
function materializedStageMatches(invocationRuns, hopsFor, entrySegments) {
|
|
58180
|
+
for (const run of invocationRuns) {
|
|
58181
|
+
const hops = hopsFor(run.id);
|
|
57962
58182
|
if (hops === undefined)
|
|
57963
58183
|
continue;
|
|
57964
58184
|
for (const stage of run.stages) {
|
|
@@ -58233,10 +58453,12 @@ async function recordConfirmedStickyDeliveries(activeStore, event) {
|
|
|
58233
58453
|
}
|
|
58234
58454
|
function matchingLiveStages(runs, rootRunId, patternSegments) {
|
|
58235
58455
|
const matches = [];
|
|
58456
|
+
const runById = new Map(runs.map((run) => [run.id, run]));
|
|
58457
|
+
const hopsFor = createWorkflowBoundaryHopsResolver(runs);
|
|
58236
58458
|
for (const run of runs) {
|
|
58237
|
-
if (
|
|
58459
|
+
if (reciprocalWorkflowRootRunId(runById, run.id) !== rootRunId)
|
|
58238
58460
|
continue;
|
|
58239
|
-
const hops =
|
|
58461
|
+
const hops = hopsFor(run.id);
|
|
58240
58462
|
if (hops === undefined)
|
|
58241
58463
|
continue;
|
|
58242
58464
|
for (const stage of run.stages) {
|
|
@@ -58372,11 +58594,26 @@ function writeMessage(socket, msg, callback) {
|
|
|
58372
58594
|
}
|
|
58373
58595
|
function createMessageReader(onMessage, onError) {
|
|
58374
58596
|
let buffer = Buffer.alloc(0);
|
|
58597
|
+
let pending = [];
|
|
58598
|
+
let pendingLength = 0;
|
|
58599
|
+
let awaitedLength = 0;
|
|
58375
58600
|
return (data) => {
|
|
58376
|
-
|
|
58601
|
+
if (pendingLength + data.length < awaitedLength) {
|
|
58602
|
+
pending.push(data);
|
|
58603
|
+
pendingLength += data.length;
|
|
58604
|
+
return;
|
|
58605
|
+
}
|
|
58606
|
+
buffer = pending.length === 0 ? Buffer.concat([buffer, data]) : Buffer.concat([...pending, data]);
|
|
58607
|
+
pending = [];
|
|
58608
|
+
pendingLength = 0;
|
|
58609
|
+
awaitedLength = 0;
|
|
58377
58610
|
while (buffer.length >= 4) {
|
|
58378
58611
|
const length = buffer.readUInt32BE(0);
|
|
58379
58612
|
if (buffer.length < 4 + length) {
|
|
58613
|
+
pending = [buffer];
|
|
58614
|
+
pendingLength = buffer.length;
|
|
58615
|
+
awaitedLength = 4 + length;
|
|
58616
|
+
buffer = Buffer.alloc(0);
|
|
58380
58617
|
break;
|
|
58381
58618
|
}
|
|
58382
58619
|
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"
|