@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 CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.9.44-alpha.3] - 2026-10-25
6
+
7
+ Chatty workflow swarms stay fast and their journals stay small, and Atomic picks up a round of dependency security fixes.
8
+
9
+ - **Pattern sends at fan-out scale:** stages that message each other through `workflow:<rootRunId>/...` patterns no longer saturate the workflow host or time out their sends, so every send in a 150-child fan-out is delivered ([#3931](https://github.com/bastani-inc/atomic/issues/3931), [#3932](https://github.com/bastani-inc/atomic/pull/3932))
10
+ - **Journals that grow with the work, not the message count:** journal events record only what changed in a run's pending messages instead of the whole list ([#3929](https://github.com/bastani-inc/atomic/issues/3929), [#3930](https://github.com/bastani-inc/atomic/pull/3930))
11
+ - **Security updates:** `undici` 8.12.3, `zod` 4.6.7, `fast-uri` 3.1.9, `body-parser` 2.4.0 and `tokio` 1.54.1 close the published advisories against them ([#3935](https://github.com/bastani-inc/atomic/pull/3935))
12
+
13
+ ### Fixed
14
+
15
+ - Updated `undici`, which Atomic uses for HTTP requests, to 8.12.3. A server can no longer crash Atomic by sending more than five `Content-Encoding` values ([GHSA-xjj6-f33q-929c](https://github.com/advisories/GHSA-xjj6-f33q-929c)), Server-Sent Events streams can no longer grow parser memory without bound ([GHSA-4qv8-2p9j-2685](https://github.com/advisories/GHSA-4qv8-2p9j-2685)), and Subresource Integrity checks no longer skip uppercase algorithm names ([GHSA-f72v-6w45-q472](https://github.com/advisories/GHSA-f72v-6w45-q472)).
16
+ - Updated the MCP SDK dependencies in the published lockfile to `zod` 4.6.7 ([GHSA-mrhx-c7xc-m3w5](https://github.com/advisories/GHSA-mrhx-c7xc-m3w5)), `fast-uri` 3.1.9 ([GHSA-w74x-v6f9-j3xg](https://github.com/advisories/GHSA-w74x-v6f9-j3xg), [GHSA-wjr9-j795-jxcr](https://github.com/advisories/GHSA-wjr9-j795-jxcr), [GHSA-xhq7-xmqj-769h](https://github.com/advisories/GHSA-xhq7-xmqj-769h), [GHSA-333x-w4r6-6crp](https://github.com/advisories/GHSA-333x-w4r6-6crp)), and `body-parser` 2.4.0 ([GHSA-27r3-jxmh-p828](https://github.com/advisories/GHSA-27r3-jxmh-p828)).
17
+ - Updated the native module's `tokio` crate to 1.54.1, replacing the yanked 1.54.0 release and its `Interval` race ([GHSA-5wjr-9356-4wc8](https://github.com/advisories/GHSA-5wjr-9356-4wc8)).
18
+ - Updated the gondolin example extension's lockfile to `undici` 6.29.1, resolving [GHSA-xjj6-f33q-929c](https://github.com/advisories/GHSA-xjj6-f33q-929c) and [GHSA-4qv8-2p9j-2685](https://github.com/advisories/GHSA-4qv8-2p9j-2685) in its `@earendil-works/gondolin` dependency.
19
+
5
20
  ## [0.9.44-alpha.2] - 2026-10-24
6
21
 
7
22
  Workflow swarms now message each other without cancelling each other's work, and stages, replies and session exits behave reliably under fan-out.
@@ -4,6 +4,13 @@ All notable changes to the `pi-intercom` extension will be documented in this fi
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.9.44-alpha.3] - 2026-10-25
8
+
9
+ ### Fixed
10
+
11
+ - Intercom `send` and `ask` to a workflow-stage target (`workflow:<rootRunId>/...`, including patterns) no longer fetch the whole session list before sending. The broker resolves those targets itself, so the extra request only added load, and when many stages sent at once some sends failed with `List sessions timeout` ([#3931](https://github.com/bastani-inc/atomic/issues/3931))
12
+ - Receiving a large Intercom message (for example a big workflow roster) no longer copies its data again for every chunk that arrives, which made large frames cost quadratic time ([#3931](https://github.com/bastani-inc/atomic/issues/3931))
13
+
7
14
  ## [0.9.44-alpha.2] - 2026-10-24
8
15
 
9
16
  ### Changed
@@ -27,14 +27,31 @@ export function createMessageReader(
27
27
  onError: (error: Error) => void,
28
28
  ) {
29
29
  let buffer = Buffer.alloc(0);
30
+ // Chunks of a frame still arriving: joined once the frame is complete, not on every
31
+ // chunk, so a large frame costs linear rather than quadratic copying.
32
+ let pending: Buffer[] = [];
33
+ let pendingLength = 0;
34
+ let awaitedLength = 0;
30
35
 
31
36
  return (data: Buffer) => {
32
- buffer = Buffer.concat([buffer, data]);
37
+ if (pendingLength + data.length < awaitedLength) {
38
+ pending.push(data);
39
+ pendingLength += data.length;
40
+ return;
41
+ }
42
+ buffer = pending.length === 0 ? Buffer.concat([buffer, data]) : Buffer.concat([...pending, data]);
43
+ pending = [];
44
+ pendingLength = 0;
45
+ awaitedLength = 0;
33
46
 
34
47
  while (buffer.length >= 4) {
35
48
  const length = buffer.readUInt32BE(0);
36
49
 
37
50
  if (buffer.length < 4 + length) {
51
+ pending = [buffer];
52
+ pendingLength = buffer.length;
53
+ awaitedLength = 4 + length;
54
+ buffer = Buffer.alloc(0);
38
55
  break;
39
56
  }
40
57
 
@@ -565,11 +565,26 @@ function writeMessage(socket, msg, callback) {
565
565
  }
566
566
  function createMessageReader(onMessage, onError) {
567
567
  let buffer = Buffer.alloc(0);
568
+ let pending = [];
569
+ let pendingLength = 0;
570
+ let awaitedLength = 0;
568
571
  return (data) => {
569
- buffer = Buffer.concat([buffer, data]);
572
+ if (pendingLength + data.length < awaitedLength) {
573
+ pending.push(data);
574
+ pendingLength += data.length;
575
+ return;
576
+ }
577
+ buffer = pending.length === 0 ? Buffer.concat([buffer, data]) : Buffer.concat([...pending, data]);
578
+ pending = [];
579
+ pendingLength = 0;
580
+ awaitedLength = 0;
570
581
  while (buffer.length >= 4) {
571
582
  const length = buffer.readUInt32BE(0);
572
583
  if (buffer.length < 4 + length) {
584
+ pending = [buffer];
585
+ pendingLength = buffer.length;
586
+ awaitedLength = 4 + length;
587
+ buffer = Buffer.alloc(0);
573
588
  break;
574
589
  }
575
590
  const payload = buffer.subarray(4, 4 + length);
@@ -4073,6 +4088,7 @@ function registerIntercomTool(pi, deps) {
4073
4088
  const retryIdentities = new RetryIdentityReservations({ maxEntries: deps.retryIdentityMaxEntries });
4074
4089
  const { childOrchestratorMetadata, ensureConnected, syncPresenceIdentity, beginReplyWait } = deps;
4075
4090
  const resolveTarget = deps.resolveSessionTarget ?? resolveSessionTargetId;
4091
+ const resolveRecipient = async (client, target) => parseWorkflowStageTarget(target) === undefined ? await resolveTarget(client, target) ?? target : target;
4076
4092
  const getMetadata = typeof childOrchestratorMetadata === "function" ? childOrchestratorMetadata : () => childOrchestratorMetadata ?? null;
4077
4093
  const activeReplyTracker = () => typeof deps.replyTracker === "function" ? deps.replyTracker() : deps.replyTracker;
4078
4094
  pi.registerTool({
@@ -4440,7 +4456,7 @@ ${message}${attachmentText}`);
4440
4456
  details: { error: true, delivered: false, reason: goneChild }
4441
4457
  };
4442
4458
  }
4443
- const sendTo = await resolveTarget(connectedClient, to) ?? to;
4459
+ const sendTo = await resolveRecipient(connectedClient, to);
4444
4460
  if (_signal?.aborted) {
4445
4461
  const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
4446
4462
  retryIdentity = undefined;
@@ -4614,8 +4630,7 @@ ${message}${attachmentText}`);
4614
4630
  details: { error: true, delivered: false, reason: goneChild }
4615
4631
  };
4616
4632
  }
4617
- const listedTarget = await resolveTarget(connectedClient, to);
4618
- const sendTo = listedTarget ?? to;
4633
+ const sendTo = await resolveRecipient(connectedClient, to);
4619
4634
  if (_signal?.aborted) {
4620
4635
  const retained = retryIdentity === undefined ? undefined : retainInconclusiveRetry(retryIdentities, retryIdentity);
4621
4636
  retryIdentity = undefined;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/intercom",
3
- "version": "0.9.44-alpha.2",
3
+ "version": "0.9.44-alpha.3",
4
4
  "private": true,
5
5
  "description": "Atomic extension providing a private coordination channel between parent and child agent sessions. Fork of: https://github.com/nicobailon/pi-intercom",
6
6
  "contributors": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/mcp",
3
- "version": "0.9.44-alpha.2",
3
+ "version": "0.9.44-alpha.3",
4
4
  "private": true,
5
5
  "description": "Atomic's pi-compatible MCP integration for server connections, OAuth, tools, resources, and terminal management.",
6
6
  "contributors": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bastani/subagents",
3
- "version": "0.9.44-alpha.2",
3
+ "version": "0.9.44-alpha.3",
4
4
  "private": true,
5
5
  "description": "Atomic extension for delegating tasks to subagents with parallel execution. Fork of: https://github.com/nicobailon/pi-subagents",
6
6
  "contributors": [