@ai-matrx/messaging 0.10.1 → 0.10.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 +40 -0
- package/dist/index.cjs +41 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +41 -10
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +77 -24
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +21 -2
- package/dist/react.d.ts +21 -2
- package/dist/react.js +83 -25
- package/dist/react.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# Changelog — `@ai-matrx/messaging`
|
|
2
2
|
|
|
3
|
+
## 0.10.3 — 2026-09-08
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Flat platform agent-event envelopes no longer display the human audit principal as a visible
|
|
8
|
+
“via” author. The principal remains immutable in `sender_id` and `principalUserId`; it is not
|
|
9
|
+
presentation identity for an automated event.
|
|
10
|
+
- The engine declares the conversation room's read-only presence shape on the first holder,
|
|
11
|
+
before subscribe. Typing and online-roster hooks can now attach without forcing a late-binding
|
|
12
|
+
room rebuild and its `channel.room.binding.refused` diagnostics.
|
|
13
|
+
|
|
14
|
+
### Consumer action (C28)
|
|
15
|
+
|
|
16
|
+
None. Upgrade `@ai-matrx/realtime` alongside this package so presence/typing holders also receive
|
|
17
|
+
the ephemeral-roster backfill fix.
|
|
18
|
+
|
|
19
|
+
## 0.10.2 — 2026-09-08
|
|
20
|
+
|
|
21
|
+
**Agent-authored review events wore the human audit principal's name, avatar, alignment, and
|
|
22
|
+
delivery tick.** The event rows already carried the canonical flat
|
|
23
|
+
`actor_kind: "agent"` / `actor_label` envelope, but effective-actor resolution recognized only
|
|
24
|
+
the older nested `metadata.actor` shape. The UI therefore presented an automated review as if
|
|
25
|
+
the signed-in reviewer had written it.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- Flat canonical actor envelopes now resolve to an agent presentation without inheriting the
|
|
30
|
+
human principal's name or avatar. Adjacent agent and human events sharing one audit principal
|
|
31
|
+
are grouped separately, and agent events never receive the human's right-aligned/delivery-tick
|
|
32
|
+
treatment.
|
|
33
|
+
- `<ConversationView showHeader showAi>` lets an embedding workspace remove duplicate thread
|
|
34
|
+
chrome and capabilities it does not offer.
|
|
35
|
+
- `<ConversationView renderComposerInput>` lets a host supply its canonical textarea component
|
|
36
|
+
while this package retains draft, reply, typing, Enter-key, and send ownership.
|
|
37
|
+
|
|
38
|
+
### Consumer action (C28)
|
|
39
|
+
|
|
40
|
+
None for existing screens. Embedded workspaces may set `showHeader={false}`, `showAi={false}`,
|
|
41
|
+
or inject their canonical composer through `renderComposerInput`.
|
|
42
|
+
|
|
3
43
|
## 0.10.1 — 2026-09-07
|
|
4
44
|
|
|
5
45
|
**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,38 @@ function createActionRegistry() {
|
|
|
141
142
|
|
|
142
143
|
// src/core/actor.ts
|
|
143
144
|
function readActorHint(metadata) {
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
+
showPrincipalAttribution: true,
|
|
156
|
+
...typeof name2 === "string" && name2.length > 0 ? { agentName: name2 } : {},
|
|
157
|
+
...typeof avatar2 === "string" && avatar2.length > 0 ? { agentAvatarUrl: avatar2 } : {}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
const actorKind = envelope["actor_kind"] ?? envelope["actorKind"];
|
|
161
|
+
if (actorKind !== "agent") return null;
|
|
162
|
+
const id = envelope["actor_id"] ?? envelope["actorId"];
|
|
163
|
+
const name = envelope["actor_label"] ?? envelope["actorLabel"];
|
|
164
|
+
const avatar = envelope["actor_avatar_url"] ?? envelope["actorAvatarUrl"];
|
|
151
165
|
return {
|
|
152
|
-
|
|
166
|
+
showPrincipalAttribution: false,
|
|
167
|
+
...typeof id === "string" && id.length > 0 ? { agentId: id } : {},
|
|
153
168
|
...typeof name === "string" && name.length > 0 ? { agentName: name } : {},
|
|
154
169
|
...typeof avatar === "string" && avatar.length > 0 ? { agentAvatarUrl: avatar } : {}
|
|
155
170
|
};
|
|
156
171
|
}
|
|
172
|
+
function effectiveActorKey(message) {
|
|
173
|
+
const hint = readActorHint(message.metadata);
|
|
174
|
+
if (hint === null) return `principal:${message.senderId}`;
|
|
175
|
+
return `agent:${hint.agentId ?? hint.agentName ?? "anonymous"}`;
|
|
176
|
+
}
|
|
157
177
|
function resolveActor(message, sender) {
|
|
158
178
|
const hint = readActorHint(message.metadata);
|
|
159
179
|
const humanName = sender?.displayName ?? message.senderId;
|
|
@@ -165,7 +185,11 @@ function resolveActor(message, sender) {
|
|
|
165
185
|
displayName: hint.agentName ?? "Agent",
|
|
166
186
|
avatarUrl: hint.agentAvatarUrl ?? null,
|
|
167
187
|
isAgent: true,
|
|
168
|
-
|
|
188
|
+
// The nested envelope explicitly models an agent acting on behalf of a
|
|
189
|
+
// session principal. Platform event rows use the flat actor envelope as
|
|
190
|
+
// the complete presentation identity; surfacing their audit writer as
|
|
191
|
+
// "via Human" wrongly re-attaches that person to an automated event.
|
|
192
|
+
onBehalfOfName: hint.showPrincipalAttribution ? humanName : null,
|
|
169
193
|
principalUserId: message.senderId
|
|
170
194
|
};
|
|
171
195
|
}
|
|
@@ -1352,6 +1376,11 @@ function createMessagingEngine(options) {
|
|
|
1352
1376
|
if (openChannels.has(id) || disposed) return;
|
|
1353
1377
|
const handle = manager.open({
|
|
1354
1378
|
topic: conversationTopic(id),
|
|
1379
|
+
// Presence callbacks are JOIN-TIME in supabase-js. Declare the
|
|
1380
|
+
// read-only room shape on the first holder (the engine) so the
|
|
1381
|
+
// composer/typist/online hooks can attach without forcing a rebuild
|
|
1382
|
+
// after this durable channel has already subscribed.
|
|
1383
|
+
presence: { publish: false, state: {} },
|
|
1355
1384
|
postgresChanges: [
|
|
1356
1385
|
{
|
|
1357
1386
|
event: "*",
|
|
@@ -1517,18 +1546,20 @@ function groupMessages(messages, args = {}) {
|
|
|
1517
1546
|
let current = null;
|
|
1518
1547
|
let previousDay = null;
|
|
1519
1548
|
for (const message of messages) {
|
|
1549
|
+
const actorKey = args.actorKey?.(message) ?? `principal:${message.senderId}`;
|
|
1520
1550
|
const day = message.createdAt.slice(0, 10);
|
|
1521
1551
|
const startsNewDay = day !== previousDay;
|
|
1522
1552
|
previousDay = day;
|
|
1523
1553
|
const last = current?.messages.at(-1);
|
|
1524
1554
|
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) {
|
|
1555
|
+
if (current !== null && current.senderId === message.senderId && current.actorKey === actorKey && withinWindow && !startsNewDay) {
|
|
1526
1556
|
current.messages.push(message);
|
|
1527
1557
|
continue;
|
|
1528
1558
|
}
|
|
1529
1559
|
if (current !== null) groups.push(current);
|
|
1530
1560
|
current = {
|
|
1531
1561
|
senderId: message.senderId,
|
|
1562
|
+
actorKey,
|
|
1532
1563
|
messages: [message],
|
|
1533
1564
|
dateSeparator: startsNewDay ? formatDateSeparator(message.createdAt, now, args.locale) : null
|
|
1534
1565
|
};
|