@bastani/atomic 0.9.44-alpha.1 → 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.
Files changed (43) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +17 -0
  3. package/dist/builtin/intercom/broker/client-message-validation.ts +6 -0
  4. package/dist/builtin/intercom/broker/client.ts +4 -0
  5. package/dist/builtin/intercom/broker/framing.ts +18 -1
  6. package/dist/builtin/intercom/broker/send-signature.ts +4 -1
  7. package/dist/builtin/intercom/index.bundle.mjs +101 -18
  8. package/dist/builtin/intercom/package.json +1 -1
  9. package/dist/builtin/intercom/skills/intercom/SKILL.md +1 -0
  10. package/dist/builtin/intercom/types.ts +8 -0
  11. package/dist/builtin/mcp/package.json +1 -1
  12. package/dist/builtin/subagents/package.json +1 -1
  13. package/dist/builtin/web-access/index.bundle.mjs +2510 -1308
  14. package/dist/builtin/web-access/package.json +1 -1
  15. package/dist/builtin/workflows/CHANGELOG.md +13 -0
  16. package/dist/builtin/workflows/package.json +1 -1
  17. package/dist/builtin/workflows/src/extension/index.bundle.mjs +363 -37
  18. package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +363 -37
  19. package/dist/builtin/workflows/src/index.js +363 -37
  20. package/dist/builtin/workflows/src/local-worker-entry.mjs +363 -37
  21. package/dist/core/agent-session-custom-message-commit.d.ts.map +1 -1
  22. package/dist/core/agent-session-custom-message-commit.js +59 -0
  23. package/dist/core/agent-session-custom-message-commit.js.map +1 -1
  24. package/dist/core/agent-session-methods.d.ts +1 -0
  25. package/dist/core/agent-session-methods.d.ts.map +1 -1
  26. package/dist/core/agent-session-methods.js.map +1 -1
  27. package/dist/core/agent-session-prompt.d.ts +4 -0
  28. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  29. package/dist/core/agent-session-prompt.js +10 -2
  30. package/dist/core/agent-session-prompt.js.map +1 -1
  31. package/dist/core/agent-session.d.ts +2 -0
  32. package/dist/core/agent-session.d.ts.map +1 -1
  33. package/dist/core/agent-session.js +9 -0
  34. package/dist/core/agent-session.js.map +1 -1
  35. package/dist/core/builtin-packages.d.ts.map +1 -1
  36. package/dist/core/builtin-packages.js +13 -13
  37. package/dist/core/builtin-packages.js.map +1 -1
  38. package/docs/intercom/operations.md +1 -1
  39. package/docs/intercom.md +11 -1
  40. package/docs/subagents.md +9 -1
  41. package/examples/extensions/gondolin/package-lock.json +3 -3
  42. package/npm-shrinkwrap.json +67 -51
  43. package/package.json +4 -4
@@ -9870,6 +9870,17 @@ 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
+ }
9880
+ function snapshotNeedsHistory(tail) {
9881
+ const handle = writtenHandle(tail.snapshot.event);
9882
+ return handle !== undefined && (handle.pendingStageMessageChange !== undefined || hasPendingStageDeliveryDelta(handle.pendingStageMessages));
9883
+ }
9873
9884
  function* invoke(action) {
9874
9885
  try {
9875
9886
  const result = action();
@@ -9982,11 +9993,11 @@ class JournalDurableBackend {
9982
9993
  const payload = event.payload;
9983
9994
  this.projection.archivePendingStageDeliveryReceipt(entry.runId, payload.messageId, payload.delivery, payload.accounting);
9984
9995
  } else if (event.type === RUN_EVENT_TYPES.promptAsked || event.type === RUN_EVENT_TYPES.promptReleased) {
9985
- this.projection.applyWorkflowSnapshot(event.payload.handle);
9996
+ this.projection.applyWorkflowSnapshot(decodeHandle(event.payload.handle, this.projection.getWorkflow(entry.runId)?.pendingStageMessages));
9986
9997
  this.prompts.set(entry.runId, new PromptReservationState(event.payload.handle.pendingPrompts, event.payload.prompts));
9987
9998
  } else {
9988
- const handle = event.payload;
9989
9999
  const previous = this.projection.getWorkflow(entry.runId);
10000
+ const handle = decodeHandle(event.payload, previous?.pendingStageMessages);
9990
10001
  this.projection.applyWorkflowSnapshot(handle);
9991
10002
  if (event.type === RUN_EVENT_TYPES.runStarted || previous?.pendingPrompts !== handle.pendingPrompts)
9992
10003
  this.prompts.delete(entry.runId);
@@ -10106,6 +10117,20 @@ class JournalDurableBackend {
10106
10117
  }
10107
10118
  *append(runId, event, options) {
10108
10119
  const lease = yield* this.ownership(runId);
10120
+ const base = this.sequences.get(runId);
10121
+ const pinned = options?.expectSeq;
10122
+ const encoded = base !== undefined && (pinned === undefined || pinned === base) && event.type !== RUN_EVENT_TYPES.runStarted ? encodeHandleEvent(event, this.projection.getWorkflow(runId)?.pendingStageMessages) : undefined;
10123
+ if (encoded !== undefined) {
10124
+ try {
10125
+ return yield* this.write(runId, lease, encoded, { ...options, expectSeq: base });
10126
+ } catch (error) {
10127
+ if (!(error instanceof JournalCasConflictError) || pinned !== undefined)
10128
+ throw error;
10129
+ }
10130
+ }
10131
+ yield* this.write(runId, lease, event, options);
10132
+ }
10133
+ *write(runId, lease, event, options) {
10109
10134
  try {
10110
10135
  const outcome = yield* invoke(() => this.journal.append(lease, event, options));
10111
10136
  const nextSeq = (this.sequences.get(runId) ?? 0) + 1;
@@ -10282,11 +10307,12 @@ class JournalDurableBackend {
10282
10307
  for (const message of messages)
10283
10308
  if (message.runId !== logicalRunId)
10284
10309
  throw new JournalMessageScopeError(logicalRunId, message.runId);
10285
- yield* this.snapshot({
10310
+ const next = {
10286
10311
  ...handle,
10287
10312
  pendingStageMessages: replacePendingStageMessagesForRun(handle.pendingStageMessages ?? [], logicalRunId, messages),
10288
10313
  updatedAt: Math.max(Date.now(), handle.updatedAt + 1)
10289
- }, RUN_EVENT_TYPES.messageQueued);
10314
+ };
10315
+ yield* this.snapshot(next, RUN_EVENT_TYPES.messageQueued);
10290
10316
  return true;
10291
10317
  }
10292
10318
  async archivePendingStageMessage(runId, message) {
@@ -10380,7 +10406,7 @@ class JournalDurableBackend {
10380
10406
  if (summarized !== undefined && summarized.seq === version.seq && summarized.at === version.at)
10381
10407
  return;
10382
10408
  const tail = yield* invoke(() => journal.snapshotTail(runId));
10383
- if (tail !== undefined)
10409
+ if (tail !== undefined && !snapshotNeedsHistory(tail))
10384
10410
  return this.summarize(runId, tail);
10385
10411
  if (summarized === undefined && version.seq === 0)
10386
10412
  return;
@@ -10606,7 +10632,182 @@ class JournalDurableBackend {
10606
10632
  }
10607
10633
  }
10608
10634
  }
10609
- var PROCESS_HOLDER_ID, processExitCleanups, JournalOwnershipError, JournalBackendClosedError, JournalOperationAbortedError, JournalExecutionRetiredError, JournalMessageScopeError;
10635
+ function identity(message) {
10636
+ return JSON.stringify([message.runId, message.id]);
10637
+ }
10638
+ function uniqueByIdentity(messages) {
10639
+ const result = new Map;
10640
+ const repeated = new Set;
10641
+ for (const message of messages) {
10642
+ const key = identity(message);
10643
+ if (result.has(key))
10644
+ repeated.add(key);
10645
+ result.set(key, message);
10646
+ }
10647
+ for (const key of repeated)
10648
+ result.delete(key);
10649
+ return result;
10650
+ }
10651
+ function isDeltaEncoded(message) {
10652
+ return message.deliveryDelta !== undefined;
10653
+ }
10654
+ function deliveryDelta(base, deliveries) {
10655
+ const drop = [];
10656
+ let kept = 0;
10657
+ base.forEach((delivery, index) => {
10658
+ if (kept < deliveries.length && JSON.stringify(delivery) === JSON.stringify(deliveries[kept]))
10659
+ kept++;
10660
+ else
10661
+ drop.push(index);
10662
+ });
10663
+ const add = deliveries.slice(kept);
10664
+ return drop.length === 0 ? { add } : { drop, add };
10665
+ }
10666
+ function pendingStageFields(message) {
10667
+ return Object.keys(message);
10668
+ }
10669
+ function copyField(target, source, key) {
10670
+ target[key] = source[key];
10671
+ }
10672
+ function isRemovedField(message, key) {
10673
+ return message[key] === undefined;
10674
+ }
10675
+ function json(message) {
10676
+ let text = entryJson.get(message);
10677
+ if (text === undefined) {
10678
+ text = JSON.stringify(message);
10679
+ entryJson.set(message, text);
10680
+ }
10681
+ return text;
10682
+ }
10683
+ function patchEntry(index, base, message) {
10684
+ const set = {};
10685
+ const unset = pendingStageFields(base).filter((key) => base[key] !== undefined && isRemovedField(message, key));
10686
+ for (const key of pendingStageFields(message)) {
10687
+ if (message[key] === undefined || key === "deliveries")
10688
+ continue;
10689
+ if (JSON.stringify(message[key]) !== JSON.stringify(base[key]))
10690
+ copyField(set, message, key);
10691
+ }
10692
+ let delta;
10693
+ if (message.deliveries !== undefined) {
10694
+ if (base.deliveries === undefined)
10695
+ set.deliveries = message.deliveries;
10696
+ else if (JSON.stringify(base.deliveries) !== JSON.stringify(message.deliveries))
10697
+ delta = deliveryDelta(base.deliveries, message.deliveries);
10698
+ }
10699
+ return {
10700
+ patch: index,
10701
+ ...Object.keys(set).length === 0 ? {} : { set },
10702
+ ...unset.length === 0 ? {} : { unset },
10703
+ ...delta === undefined ? {} : { deliveryDelta: delta }
10704
+ };
10705
+ }
10706
+ function encodePendingStageList(previous, next) {
10707
+ const positions = new Map;
10708
+ const repeated = new Set;
10709
+ previous.forEach((message, index) => {
10710
+ const key = identity(message);
10711
+ if (positions.has(key))
10712
+ repeated.add(key);
10713
+ positions.set(key, index);
10714
+ });
10715
+ for (const key of repeated)
10716
+ positions.delete(key);
10717
+ const items = [];
10718
+ let reused = 0;
10719
+ for (const message of next) {
10720
+ const index = positions.get(identity(message));
10721
+ const base = index === undefined ? undefined : previous[index];
10722
+ if (base === undefined) {
10723
+ items.push(message);
10724
+ continue;
10725
+ }
10726
+ reused++;
10727
+ const patched = base === message || json(base) === json(message) ? undefined : patchEntry(index, base, message);
10728
+ if (patched === undefined || Object.keys(patched).length === 1) {
10729
+ const last = items.at(-1);
10730
+ if (Array.isArray(last) && last[0] + last[1] === index)
10731
+ last[1]++;
10732
+ else
10733
+ items.push([index, 1]);
10734
+ continue;
10735
+ }
10736
+ items.push(JSON.stringify(patched).length < json(message).length ? patched : message);
10737
+ }
10738
+ return reused > 0 ? items : undefined;
10739
+ }
10740
+ function decodePendingStageList(previous, items) {
10741
+ const base = (index) => {
10742
+ if (!Number.isInteger(index) || index < 0 || index >= previous.length)
10743
+ throw new Error(`atomic-workflows: journal pending-stage change names missing entry ${index}`);
10744
+ return previous[index];
10745
+ };
10746
+ const result = [];
10747
+ for (const item of items) {
10748
+ if (Array.isArray(item)) {
10749
+ const [start, count] = item;
10750
+ for (let index = start;index < start + count; index++)
10751
+ result.push(base(index));
10752
+ } else if (typeof item.patch === "number") {
10753
+ const { patch, set, unset, deliveryDelta: delta } = item;
10754
+ const entry = { ...base(patch), ...set };
10755
+ for (const key of unset ?? [])
10756
+ delete entry[key];
10757
+ if (delta !== undefined) {
10758
+ const dropped = new Set(delta.drop ?? []);
10759
+ const deliveries = base(patch).deliveries ?? [];
10760
+ entry.deliveries = [...deliveries.filter((_, index) => !dropped.has(index)), ...delta.add];
10761
+ }
10762
+ result.push(entry);
10763
+ } else
10764
+ result.push(item);
10765
+ }
10766
+ return result;
10767
+ }
10768
+ function encodeHandleEvent(event, previous) {
10769
+ const handle = writtenHandle(event);
10770
+ if (handle?.pendingStageMessages === undefined || previous === undefined)
10771
+ return;
10772
+ const change = encodePendingStageList(previous, handle.pendingStageMessages);
10773
+ if (change === undefined)
10774
+ return;
10775
+ const { pendingStageMessages: _full, ...rest } = handle;
10776
+ const encoded = { ...rest, pendingStageMessageChange: change };
10777
+ if (event.type === RUN_EVENT_TYPES.promptAsked || event.type === RUN_EVENT_TYPES.promptReleased)
10778
+ return { ...event, payload: { ...event.payload, handle: encoded } };
10779
+ return { ...event, payload: encoded };
10780
+ }
10781
+ function decodeHandle(handle, previous) {
10782
+ const { pendingStageMessageChange: change, ...rest } = handle;
10783
+ if (change !== undefined)
10784
+ return { ...rest, pendingStageMessages: decodePendingStageList(previous ?? [], change) };
10785
+ if (!hasPendingStageDeliveryDelta(handle.pendingStageMessages))
10786
+ return handle;
10787
+ return {
10788
+ ...handle,
10789
+ pendingStageMessages: decodePendingStageDeliveries(previous ?? [], handle.pendingStageMessages ?? [])
10790
+ };
10791
+ }
10792
+ function decodePendingStageDeliveries(previous, messages) {
10793
+ if (!messages.some(isDeltaEncoded))
10794
+ return messages;
10795
+ const bases = uniqueByIdentity(previous);
10796
+ return messages.map((message) => {
10797
+ if (!isDeltaEncoded(message))
10798
+ return message;
10799
+ const base = bases.get(identity(message))?.deliveries;
10800
+ if (base === undefined)
10801
+ throw new Error(`atomic-workflows: journal delivery change for ${identity(message)} has no base entry`);
10802
+ const { deliveryDelta, ...rest } = message;
10803
+ const dropped = new Set(deliveryDelta.drop ?? []);
10804
+ return { ...rest, deliveries: [...base.filter((_, index) => !dropped.has(index)), ...deliveryDelta.add] };
10805
+ });
10806
+ }
10807
+ function hasPendingStageDeliveryDelta(messages) {
10808
+ return messages?.some(isDeltaEncoded) === true;
10809
+ }
10810
+ var PROCESS_HOLDER_ID, processExitCleanups, JournalOwnershipError, JournalBackendClosedError, JournalOperationAbortedError, JournalExecutionRetiredError, JournalMessageScopeError, entryJson;
10610
10811
  var init_journal_backend = __esm(() => {
10611
10812
  init_workflow_instance_ownership_error();
10612
10813
  init_backend();
@@ -10664,6 +10865,7 @@ var init_journal_backend = __esm(() => {
10664
10865
  this.name = "JournalMessageScopeError";
10665
10866
  }
10666
10867
  };
10868
+ entryJson = new WeakMap;
10667
10869
  });
10668
10870
 
10669
10871
  // dist/builtin/workflows/src/durable/factory.ts
@@ -58130,7 +58332,20 @@ function createWorkflowBoundarySegmentsResolver(runs) {
58130
58332
  };
58131
58333
  }
58132
58334
  function workflowBoundaryHops(runs, runId) {
58335
+ return boundaryHopsFrom(new Map(runs.map((run) => [run.id, run])), runId);
58336
+ }
58337
+ function createWorkflowBoundaryHopsResolver(runs) {
58133
58338
  const runById = new Map(runs.map((run) => [run.id, run]));
58339
+ const cache = new Map;
58340
+ return (runId) => {
58341
+ if (cache.has(runId))
58342
+ return cache.get(runId);
58343
+ const hops = boundaryHopsFrom(runById, runId);
58344
+ cache.set(runId, hops);
58345
+ return hops;
58346
+ };
58347
+ }
58348
+ function boundaryHopsFrom(runById, runId) {
58134
58349
  const hops = [];
58135
58350
  let current = runById.get(runId);
58136
58351
  while (current !== undefined && current.parentRunId !== undefined) {
@@ -58156,6 +58371,35 @@ function workflowStagePathVariants(hops, stageSegments) {
58156
58371
  function stageMatchesPathPattern(patternSegments, hops, stageSegments) {
58157
58372
  return workflowStagePathVariants(hops, stageSegments).some((candidate) => matchStagePathSegments(patternSegments, candidate));
58158
58373
  }
58374
+ function createStagePathPatternIndex(patterns) {
58375
+ const byFirstSegment = new Map;
58376
+ const globFirst = [];
58377
+ patterns.forEach((pattern, index) => {
58378
+ const first = pattern[0];
58379
+ if (first === undefined || first.includes("*")) {
58380
+ globFirst.push(index);
58381
+ return;
58382
+ }
58383
+ const bucket = byFirstSegment.get(first);
58384
+ if (bucket === undefined)
58385
+ byFirstSegment.set(first, [index]);
58386
+ else
58387
+ bucket.push(index);
58388
+ });
58389
+ return {
58390
+ matching(hops, stageSegments) {
58391
+ if (patterns.length === 0)
58392
+ return [];
58393
+ const variants = workflowStagePathVariants(hops, stageSegments);
58394
+ const candidates = new Set(globFirst);
58395
+ for (const variant of variants) {
58396
+ for (const index of byFirstSegment.get(variant[0]) ?? [])
58397
+ candidates.add(index);
58398
+ }
58399
+ return [...candidates].sort((left, right) => left - right).filter((index) => variants.some((variant) => matchStagePathSegments(patterns[index], variant)));
58400
+ }
58401
+ };
58402
+ }
58159
58403
  var init_pending_stage_status = __esm(() => {
58160
58404
  init_store_internal();
58161
58405
  init_workflow_stage_target();
@@ -58166,24 +58410,63 @@ function stickyStageDeliveryStatuses(runs, rootRunId, availableBackend) {
58166
58410
  const root = runs.find((run) => run.id === rootRunId);
58167
58411
  const entries = (root?.pendingStageMessages ?? []).filter((entry) => entry.sticky === true);
58168
58412
  const result = [];
58413
+ const patternByTarget = new Map;
58414
+ const patterns = [];
58415
+ const entriesByPattern = [];
58416
+ const ownEntries = [];
58417
+ entries.forEach((entry, index) => {
58418
+ const target = entry.targetPath ?? entry.stageKey;
58419
+ let pattern = patternByTarget.get(target);
58420
+ if (pattern === undefined) {
58421
+ const parsed = parseWorkflowStageTarget(target);
58422
+ pattern = parsed?.rootRunId === rootRunId ? patterns.push(parsed.segments) - 1 : -1;
58423
+ if (pattern >= 0)
58424
+ entriesByPattern.push([]);
58425
+ patternByTarget.set(target, pattern);
58426
+ }
58427
+ if (pattern < 0)
58428
+ return;
58429
+ entriesByPattern[pattern].push(index);
58430
+ ownEntries.push(index);
58431
+ });
58432
+ if (ownEntries.length === 0)
58433
+ return result;
58434
+ const patternIndex = createStagePathPatternIndex(patterns);
58435
+ const deliveriesByEntry = new Map;
58436
+ const entryReceipts = (index, runId, stageId) => {
58437
+ let byStage = deliveriesByEntry.get(index);
58438
+ if (byStage === undefined) {
58439
+ byStage = new Map;
58440
+ for (const delivery of entries[index].deliveries ?? []) {
58441
+ const key = `${delivery.runId}\x00${delivery.stageId}`;
58442
+ const list = byStage.get(key);
58443
+ if (list === undefined)
58444
+ byStage.set(key, [delivery]);
58445
+ else
58446
+ list.push(delivery);
58447
+ }
58448
+ deliveriesByEntry.set(index, byStage);
58449
+ }
58450
+ return byStage.get(`${runId}\x00${stageId}`) ?? [];
58451
+ };
58169
58452
  availableBackend = availableRunDurableBackend(runs, rootRunId) ?? availableBackend;
58170
58453
  const backend = availableBackend === undefined ? undefined : durableBackendForRun(availableBackend, runs, rootRunId);
58454
+ const runById = new Map(runs.map((run) => [run.id, run]));
58455
+ const hopsFor = createWorkflowBoundaryHopsResolver(runs);
58171
58456
  for (const run of runs) {
58172
- if (run.id !== rootRunId && run.rootRunId !== rootRunId && durableRootRunIdForRun(runs, run.id) !== rootRunId)
58457
+ const durableRootRunId = reciprocalWorkflowRootRunId(runById, run.id);
58458
+ if (run.id !== rootRunId && run.rootRunId !== rootRunId && durableRootRunId !== rootRunId)
58173
58459
  continue;
58174
- const resolved = durableRootRunIdForRun(runs, run.id) === rootRunId;
58175
- const hops = workflowBoundaryHops(runs, run.id);
58460
+ const resolved = durableRootRunId === rootRunId;
58461
+ const hops = hopsFor(run.id);
58176
58462
  for (const stage of run.stages) {
58177
58463
  if (stage.nodeKind === "tool" || stage.replayKey?.startsWith("prompt:") === true || stage.replayKey?.startsWith("workflow:") === true || stage.workflowChildRun !== undefined || stage.workflowChild !== undefined)
58178
58464
  continue;
58179
- for (const entry of entries) {
58465
+ const matchedEntries = resolved && hops ? patternIndex.matching(hops, [stage.id, stage.name]).flatMap((pattern) => entriesByPattern[pattern]).sort((left, right) => left - right) : ownEntries;
58466
+ for (const index of matchedEntries) {
58467
+ const entry = entries[index];
58180
58468
  const target = entry.targetPath ?? entry.stageKey;
58181
- const parsed = parseWorkflowStageTarget(target);
58182
- if (!parsed || parsed.rootRunId !== rootRunId)
58183
- continue;
58184
- if (resolved && hops && !stageMatchesPathPattern(parsed.segments, hops, [stage.id, stage.name]))
58185
- continue;
58186
- const receipts = (entry.deliveries ?? []).filter((delivery) => delivery.runId === run.id && delivery.stageId === stage.id);
58469
+ const receipts = entryReceipts(index, run.id, stage.id);
58187
58470
  const delivered = backend?.hasCachedPendingStageDeliveryReceipt?.(rootRunId, entry.id, {
58188
58471
  runId: run.id,
58189
58472
  stageId: stage.id,
@@ -58501,20 +58784,27 @@ function possibleStageRows(runs, rootRunId, rootRun, backend) {
58501
58784
  if (isTerminalRunStatus(rootRun.status))
58502
58785
  return [];
58503
58786
  const stickyQueued = (rootRun.pendingStageMessages ?? []).filter((entry) => entry.sticky === true && entry.status === "queued");
58787
+ const segmentsByTarget = new Map;
58504
58788
  const stickySegments = (entry) => {
58505
- const parsed = parseWorkflowStageTarget(entry.targetPath ?? entry.stageKey);
58506
- return parsed?.rootRunId === rootRunId ? parsed.segments : undefined;
58789
+ const target = entry.targetPath ?? entry.stageKey;
58790
+ if (segmentsByTarget.has(target))
58791
+ return segmentsByTarget.get(target);
58792
+ const parsed = parseWorkflowStageTarget(target);
58793
+ const segments = parsed?.rootRunId === rootRunId ? parsed.segments : undefined;
58794
+ segmentsByTarget.set(target, segments);
58795
+ return segments;
58507
58796
  };
58508
58797
  const scanEntries = stickyQueued.filter((entry) => {
58509
58798
  const segments = stickySegments(entry);
58510
58799
  return !(segments !== undefined && segments.length === 1 && segments[0] === "**");
58511
58800
  });
58801
+ const liveStageMatches = materializedStageMatcher(runs, rootRunId);
58512
58802
  const rows = [];
58513
58803
  for (const scanEntry of rootRun.possibleStages ?? []) {
58514
58804
  const rowSegments = splitStagePathSegments(scanEntry);
58515
58805
  if (rowSegments.length === 0 || rowSegments.some((segment) => segment.length === 0))
58516
58806
  continue;
58517
- if (!rowSegments.some((segment) => segment.includes("*")) && materializedStageMatches(runs, rootRunId, rowSegments)) {
58807
+ if (!rowSegments.some((segment) => segment.includes("*")) && liveStageMatches(rowSegments)) {
58518
58808
  continue;
58519
58809
  }
58520
58810
  rows.push({
@@ -58535,28 +58825,43 @@ function possibleStageRows(runs, rootRunId, rootRun, backend) {
58535
58825
  }).length
58536
58826
  });
58537
58827
  const statuses = stickyStageDeliveryStatuses(runs, rootRunId, backend);
58538
- for (const target of new Set(statuses.map((status) => status.target))) {
58539
- if (rows.some((row) => row.target === target))
58828
+ const statusesByTarget = new Map;
58829
+ for (const status of statuses) {
58830
+ const forTarget = statusesByTarget.get(status.target);
58831
+ if (forTarget === undefined)
58832
+ statusesByTarget.set(status.target, [status]);
58833
+ else
58834
+ forTarget.push(status);
58835
+ }
58836
+ const queuedByTarget = new Map;
58837
+ for (const entry of stickyQueued) {
58838
+ const target = entry.targetPath ?? entry.stageKey;
58839
+ queuedByTarget.set(target, (queuedByTarget.get(target) ?? 0) + 1);
58840
+ }
58841
+ const rowTargets = new Set(rows.map((row) => row.target));
58842
+ for (const target of statusesByTarget.keys()) {
58843
+ if (rowTargets.has(target))
58540
58844
  continue;
58541
- rows.push({
58542
- target,
58543
- queuedCount: stickyQueued.filter((entry) => (entry.targetPath ?? entry.stageKey) === target).length,
58544
- deliveryOnly: true
58545
- });
58845
+ rowTargets.add(target);
58846
+ rows.push({ target, queuedCount: queuedByTarget.get(target) ?? 0, deliveryOnly: true });
58546
58847
  }
58547
58848
  for (let index = 0;index < rows.length; index++) {
58548
58849
  const row = rows[index];
58549
- const deliveryStates = statuses.filter((status) => status.target === row.target);
58550
- if (deliveryStates.length > 0)
58850
+ const deliveryStates = statusesByTarget.get(row.target);
58851
+ if (deliveryStates !== undefined)
58551
58852
  rows[index] = { ...row, deliveryStates };
58552
58853
  }
58553
58854
  return rows;
58554
58855
  }
58555
- function materializedStageMatches(runs, rootRunId, entrySegments) {
58556
- for (const run of runs) {
58557
- if (durableRootRunIdForRun(runs, run.id) !== rootRunId)
58558
- continue;
58559
- const hops = workflowBoundaryHops(runs, run.id);
58856
+ function materializedStageMatcher(runs, rootRunId) {
58857
+ const runById = new Map(runs.map((run) => [run.id, run]));
58858
+ const hopsFor = createWorkflowBoundaryHopsResolver(runs);
58859
+ const invocationRuns = runs.filter((run) => reciprocalWorkflowRootRunId(runById, run.id) === rootRunId);
58860
+ return (entrySegments) => materializedStageMatches(invocationRuns, hopsFor, entrySegments);
58861
+ }
58862
+ function materializedStageMatches(invocationRuns, hopsFor, entrySegments) {
58863
+ for (const run of invocationRuns) {
58864
+ const hops = hopsFor(run.id);
58560
58865
  if (hops === undefined)
58561
58866
  continue;
58562
58867
  for (const stage of run.stages) {
@@ -58831,10 +59136,12 @@ async function recordConfirmedStickyDeliveries(activeStore, event) {
58831
59136
  }
58832
59137
  function matchingLiveStages(runs, rootRunId, patternSegments) {
58833
59138
  const matches = [];
59139
+ const runById = new Map(runs.map((run) => [run.id, run]));
59140
+ const hopsFor = createWorkflowBoundaryHopsResolver(runs);
58834
59141
  for (const run of runs) {
58835
- if (durableRootRunIdForRun(runs, run.id) !== rootRunId)
59142
+ if (reciprocalWorkflowRootRunId(runById, run.id) !== rootRunId)
58836
59143
  continue;
58837
- const hops = workflowBoundaryHops(runs, run.id);
59144
+ const hops = hopsFor(run.id);
58838
59145
  if (hops === undefined)
58839
59146
  continue;
58840
59147
  for (const stage of run.stages) {
@@ -58970,11 +59277,26 @@ function writeMessage(socket, msg, callback) {
58970
59277
  }
58971
59278
  function createMessageReader(onMessage, onError) {
58972
59279
  let buffer = Buffer.alloc(0);
59280
+ let pending = [];
59281
+ let pendingLength = 0;
59282
+ let awaitedLength = 0;
58973
59283
  return (data) => {
58974
- buffer = Buffer.concat([buffer, data]);
59284
+ if (pendingLength + data.length < awaitedLength) {
59285
+ pending.push(data);
59286
+ pendingLength += data.length;
59287
+ return;
59288
+ }
59289
+ buffer = pending.length === 0 ? Buffer.concat([buffer, data]) : Buffer.concat([...pending, data]);
59290
+ pending = [];
59291
+ pendingLength = 0;
59292
+ awaitedLength = 0;
58975
59293
  while (buffer.length >= 4) {
58976
59294
  const length = buffer.readUInt32BE(0);
58977
59295
  if (buffer.length < 4 + length) {
59296
+ pending = [buffer];
59297
+ pendingLength = buffer.length;
59298
+ awaitedLength = 4 + length;
59299
+ buffer = Buffer.alloc(0);
58978
59300
  break;
58979
59301
  }
58980
59302
  const payload = buffer.subarray(4, 4 + length);
@@ -59086,7 +59408,8 @@ function buildSendSignature(to, options) {
59086
59408
  attachments: canonicalizeAttachmentsForSendSignature(options.attachments) ?? [],
59087
59409
  replyTo: options.replyTo ?? null,
59088
59410
  expectsReply: options.expectsReply ?? false,
59089
- replyError: options.replyError ?? null
59411
+ replyError: options.replyError ?? null,
59412
+ ...options.delivery === undefined || options.delivery === "steer" ? {} : { delivery: options.delivery }
59090
59413
  });
59091
59414
  }
59092
59415
 
@@ -59272,6 +59595,8 @@ function isMessage(value2) {
59272
59595
  return false;
59273
59596
  if (message.expectsReply !== undefined && typeof message.expectsReply !== "boolean")
59274
59597
  return false;
59598
+ if (message.delivery !== undefined && message.delivery !== "steer" && message.delivery !== "followUp" && message.delivery !== "interrupt")
59599
+ return false;
59275
59600
  if (message.replyError !== undefined && typeof message.replyError !== "string")
59276
59601
  return false;
59277
59602
  if (message.source !== undefined && !isMessageSource(message.source))
@@ -60481,6 +60806,7 @@ var init_client = __esm(() => {
60481
60806
  timestamp: Date.now(),
60482
60807
  replyTo: options.replyTo,
60483
60808
  expectsReply: options.expectsReply,
60809
+ ...options.delivery === undefined || options.delivery === "steer" ? {} : { delivery: options.delivery },
60484
60810
  replyError: options.replyError,
60485
60811
  source: this._messageSource,
60486
60812
  content: { text: options.text, attachments: options.attachments }