agent-comms 2.21.8 → 2.21.9

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.
@@ -15,7 +15,7 @@
15
15
  "url": "https://github.com/ExaDev/agent-comms.git"
16
16
  },
17
17
  "description": "Cross-harness LLM agent communication mesh — rooms, DMs, and presence",
18
- "version": "2.21.8"
18
+ "version": "2.21.9"
19
19
  }
20
20
  ]
21
21
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-comms",
3
3
  "description": "Cross-harness LLM agent communication mesh — rooms, DMs, and presence",
4
- "version": "2.21.8",
4
+ "version": "2.21.9",
5
5
  "author": {
6
6
  "name": "ExaDev"
7
7
  },
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![GitHub](https://img.shields.io/badge/GitHub-181717?logo=github&logoColor=white)](https://github.com/ExaDev/agent-comms)
4
4
  [![npm](https://img.shields.io/badge/npm-CB3837?logo=npm&logoColor=white)](https://www.npmjs.com/package/agent-comms)
5
- [![version](https://img.shields.io/badge/version-2.21.8-blue)](https://github.com/ExaDev/agent-comms/releases/tag/v2.21.8)
5
+ [![version](https://img.shields.io/badge/version-2.21.9-blue)](https://github.com/ExaDev/agent-comms/releases/tag/v2.21.9)
6
6
  [![CI](https://img.shields.io/github/actions/workflow/status/ExaDev/agent-comms/ci.yml?branch=main)](https://github.com/ExaDev/agent-comms/actions)
7
7
 
8
8
  Cross-harness communication mesh for LLM agents: rooms, DMs, presence, and visibility over TCP with zero filesystem dependencies.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mesh-store-shared.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mesh-store-shared.test.d.ts","sourceRoot":"","sources":["../../src/test/mesh-store-shared.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,89 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { mergeMessageHistories, ROOM_TOKEN_LIFETIME_MS, } from "../core/mesh-store-shared.js";
3
+ const DAYS = 30;
4
+ const HOURS_PER_DAY = 24;
5
+ const MINUTES_PER_HOUR = 60;
6
+ const SECONDS_PER_MINUTE = 60;
7
+ const MS_PER_SECOND = 1000;
8
+ describe("ROOM_TOKEN_LIFETIME_MS", () => {
9
+ it("is exactly 30 days, in milliseconds", () => {
10
+ expect(ROOM_TOKEN_LIFETIME_MS).toBe(DAYS *
11
+ HOURS_PER_DAY *
12
+ MINUTES_PER_HOUR *
13
+ SECONDS_PER_MINUTE *
14
+ MS_PER_SECOND);
15
+ });
16
+ });
17
+ function msg(id, readBy = []) {
18
+ return { id, readBy: [...readBy] };
19
+ }
20
+ describe("mergeMessageHistories", () => {
21
+ it("appends an incoming entry the local list does not have", () => {
22
+ const merged = mergeMessageHistories([msg("a")], [msg("b")]);
23
+ expect(merged.map((m) => m.id)).toEqual(["a", "b"]);
24
+ });
25
+ it("appends multiple new entries in incoming order", () => {
26
+ const merged = mergeMessageHistories([msg("a")], [msg("b"), msg("c")]);
27
+ expect(merged.map((m) => m.id)).toEqual(["a", "b", "c"]);
28
+ });
29
+ it("preserves local ordering -- new entries are appended, not inserted", () => {
30
+ const merged = mergeMessageHistories([msg("a"), msg("z")], [msg("m")]);
31
+ expect(merged.map((m) => m.id)).toEqual(["a", "z", "m"]);
32
+ });
33
+ it("unions a new reader onto an existing entry's readBy", () => {
34
+ const merged = mergeMessageHistories([msg("a", ["u1"])], [msg("a", ["u2"])]);
35
+ expect(merged[0]?.readBy.sort()).toEqual(["u1", "u2"]);
36
+ });
37
+ it("does not duplicate a reader already present locally", () => {
38
+ const merged = mergeMessageHistories([msg("a", ["u1"])], [msg("a", ["u1"])]);
39
+ expect(merged[0]?.readBy).toEqual(["u1"]);
40
+ });
41
+ it("unions several readers from one incoming entry", () => {
42
+ const merged = mergeMessageHistories([msg("a", ["u1"])], [msg("a", ["u1", "u2", "u3"])]);
43
+ expect(merged[0]?.readBy.sort()).toEqual(["u1", "u2", "u3"]);
44
+ });
45
+ it("leaves an existing entry's readBy untouched when incoming has none", () => {
46
+ const merged = mergeMessageHistories([msg("a", ["u1"])], [msg("a", [])]);
47
+ expect(merged[0]?.readBy).toEqual(["u1"]);
48
+ });
49
+ it("does not grow the merged length for an already-known entry", () => {
50
+ const merged = mergeMessageHistories([msg("a")], [msg("a")]);
51
+ expect(merged).toHaveLength(1);
52
+ });
53
+ it("handles an empty incoming list as a no-op, returning an equivalent copy", () => {
54
+ const merged = mergeMessageHistories([msg("a", ["u1"])], []);
55
+ expect(merged).toEqual([msg("a", ["u1"])]);
56
+ });
57
+ it("handles an empty local list, returning everything incoming", () => {
58
+ const merged = mergeMessageHistories([], [msg("a"), msg("b")]);
59
+ expect(merged.map((m) => m.id)).toEqual(["a", "b"]);
60
+ });
61
+ it("merges a mix of new and existing entries in one call", () => {
62
+ const merged = mergeMessageHistories([msg("a", ["u1"]), msg("b", [])], [msg("a", ["u2"]), msg("c", ["u3"])]);
63
+ expect(merged.map((m) => m.id)).toEqual(["a", "b", "c"]);
64
+ expect(merged[0]?.readBy.sort()).toEqual(["u1", "u2"]);
65
+ expect(merged[1]?.readBy).toEqual([]);
66
+ expect(merged[2]?.readBy).toEqual(["u3"]);
67
+ });
68
+ it("does not mutate either input array", () => {
69
+ const local = [msg("a", ["u1"])];
70
+ const incoming = [msg("a", ["u2"]), msg("b")];
71
+ mergeMessageHistories(local, incoming);
72
+ expect(local).toEqual([msg("a", ["u1"])]);
73
+ expect(incoming).toEqual([msg("a", ["u2"]), msg("b")]);
74
+ });
75
+ it("does not mutate an existing local entry's own readBy array in place", () => {
76
+ const originalEntry = msg("a", ["u1"]);
77
+ const local = [originalEntry];
78
+ mergeMessageHistories(local, [msg("a", ["u2"])]);
79
+ // The merged result's entry for "a" must be a distinct object/array from the one still referenced by the caller's own original local list -- otherwise a caller holding onto its own pre-merge array would see readers silently appear in it too.
80
+ expect(originalEntry.readBy).toEqual(["u1"]);
81
+ });
82
+ it("unions two same-id entries within one incoming batch into a single merged entry, not a duplicate", () => {
83
+ // A brand-new id appearing twice in the same incoming batch is the one case where the freshly-added entry must be looked up again within the same call, not just against local's own pre-existing entries -- proves the id-to-entry index is kept in sync as new entries are added mid-merge, not only seeded from local up front.
84
+ const merged = mergeMessageHistories([], [msg("a", ["u1"]), msg("a", ["u2"])]);
85
+ expect(merged.map((m) => m.id)).toEqual(["a"]);
86
+ expect(merged[0]?.readBy.sort()).toEqual(["u1", "u2"]);
87
+ });
88
+ });
89
+ //# sourceMappingURL=mesh-store-shared.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mesh-store-shared.test.js","sourceRoot":"","sources":["../../src/test/mesh-store-shared.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-comms",
3
- "version": "2.21.8",
3
+ "version": "2.21.9",
4
4
  "description": "Cross-harness communication mesh for LLM agents — rooms, DMs, presence, and real-time push delivery over TCP",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",