@ai-matrx/messaging 0.10.1 → 0.10.2

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
@@ -1,5 +1,29 @@
1
1
  # Changelog — `@ai-matrx/messaging`
2
2
 
3
+ ## 0.10.2 — 2026-09-08
4
+
5
+ **Agent-authored review events wore the human audit principal's name, avatar, alignment, and
6
+ delivery tick.** The event rows already carried the canonical flat
7
+ `actor_kind: "agent"` / `actor_label` envelope, but effective-actor resolution recognized only
8
+ the older nested `metadata.actor` shape. The UI therefore presented an automated review as if
9
+ the signed-in reviewer had written it.
10
+
11
+ ### Fixed
12
+
13
+ - Flat canonical actor envelopes now resolve to an agent presentation without inheriting the
14
+ human principal's name or avatar. Adjacent agent and human events sharing one audit principal
15
+ are grouped separately, and agent events never receive the human's right-aligned/delivery-tick
16
+ treatment.
17
+ - `<ConversationView showHeader showAi>` lets an embedding workspace remove duplicate thread
18
+ chrome and capabilities it does not offer.
19
+ - `<ConversationView renderComposerInput>` lets a host supply its canonical textarea component
20
+ while this package retains draft, reply, typing, Enter-key, and send ownership.
21
+
22
+ ### Consumer action (C28)
23
+
24
+ None for existing screens. Embedded workspaces may set `showHeader={false}`, `showAi={false}`,
25
+ or inject their canonical composer through `renderComposerInput`.
26
+
3
27
  ## 0.10.1 — 2026-09-07
4
28
 
5
29
  **Every AI call would have been refused by the real server.** `<MessagingProvider>` never forwarded
package/dist/index.cjs CHANGED
@@ -42,6 +42,7 @@ __export(src_exports, {
42
42
  createOutbox: () => createOutbox,
43
43
  createReadCache: () => createReadCache,
44
44
  createWebOutboxStorage: () => createWebOutboxStorage,
45
+ effectiveActorKey: () => effectiveActorKey,
45
46
  extractReferences: () => extractReferences,
46
47
  formatConversationTime: () => formatConversationTime,
47
48
  formatDateSeparator: () => formatDateSeparator,
@@ -141,19 +142,36 @@ function createActionRegistry() {
141
142
 
142
143
  // src/core/actor.ts
143
144
  function readActorHint(metadata) {
144
- const raw = metadata["actor"];
145
- if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return null;
146
- const record = raw;
147
- const agentId = record["agentId"] ?? record["agent_id"];
148
- if (typeof agentId !== "string" || agentId.length === 0) return null;
149
- const name = record["agentName"] ?? record["agent_name"];
150
- const avatar = record["agentAvatarUrl"] ?? record["agent_avatar_url"];
145
+ const envelope = metadata;
146
+ const raw = envelope["actor"];
147
+ if (typeof raw === "object" && raw !== null && !Array.isArray(raw)) {
148
+ const record = raw;
149
+ const agentId = record["agentId"] ?? record["agent_id"];
150
+ if (typeof agentId !== "string" || agentId.length === 0) return null;
151
+ const name2 = record["agentName"] ?? record["agent_name"];
152
+ const avatar2 = record["agentAvatarUrl"] ?? record["agent_avatar_url"];
153
+ return {
154
+ agentId,
155
+ ...typeof name2 === "string" && name2.length > 0 ? { agentName: name2 } : {},
156
+ ...typeof avatar2 === "string" && avatar2.length > 0 ? { agentAvatarUrl: avatar2 } : {}
157
+ };
158
+ }
159
+ const actorKind = envelope["actor_kind"] ?? envelope["actorKind"];
160
+ if (actorKind !== "agent") return null;
161
+ const id = envelope["actor_id"] ?? envelope["actorId"];
162
+ const name = envelope["actor_label"] ?? envelope["actorLabel"];
163
+ const avatar = envelope["actor_avatar_url"] ?? envelope["actorAvatarUrl"];
151
164
  return {
152
- agentId,
165
+ ...typeof id === "string" && id.length > 0 ? { agentId: id } : {},
153
166
  ...typeof name === "string" && name.length > 0 ? { agentName: name } : {},
154
167
  ...typeof avatar === "string" && avatar.length > 0 ? { agentAvatarUrl: avatar } : {}
155
168
  };
156
169
  }
170
+ function effectiveActorKey(message) {
171
+ const hint = readActorHint(message.metadata);
172
+ if (hint === null) return `principal:${message.senderId}`;
173
+ return `agent:${hint.agentId ?? hint.agentName ?? "anonymous"}`;
174
+ }
157
175
  function resolveActor(message, sender) {
158
176
  const hint = readActorHint(message.metadata);
159
177
  const humanName = sender?.displayName ?? message.senderId;
@@ -1517,18 +1535,20 @@ function groupMessages(messages, args = {}) {
1517
1535
  let current = null;
1518
1536
  let previousDay = null;
1519
1537
  for (const message of messages) {
1538
+ const actorKey = args.actorKey?.(message) ?? `principal:${message.senderId}`;
1520
1539
  const day = message.createdAt.slice(0, 10);
1521
1540
  const startsNewDay = day !== previousDay;
1522
1541
  previousDay = day;
1523
1542
  const last = current?.messages.at(-1);
1524
1543
  const withinWindow = last !== void 0 && Math.abs(Date.parse(message.createdAt) - Date.parse(last.createdAt)) <= windowMs;
1525
- if (current !== null && current.senderId === message.senderId && withinWindow && !startsNewDay) {
1544
+ if (current !== null && current.senderId === message.senderId && current.actorKey === actorKey && withinWindow && !startsNewDay) {
1526
1545
  current.messages.push(message);
1527
1546
  continue;
1528
1547
  }
1529
1548
  if (current !== null) groups.push(current);
1530
1549
  current = {
1531
1550
  senderId: message.senderId,
1551
+ actorKey,
1532
1552
  messages: [message],
1533
1553
  dateSeparator: startsNewDay ? formatDateSeparator(message.createdAt, now, args.locale) : null
1534
1554
  };