relay-companion 0.1.366 → 0.1.368
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/npm-shrinkwrap.json +2 -2
- package/overlay/inbox.html +34 -16
- package/package.json +1 -1
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "relay-companion",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.368",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "relay-companion",
|
|
9
|
-
"version": "0.1.
|
|
9
|
+
"version": "0.1.368",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@anthropic-ai/claude-agent-sdk": "0.3.195",
|
package/overlay/inbox.html
CHANGED
|
@@ -8051,7 +8051,17 @@
|
|
|
8051
8051
|
const add = (person, role) => {
|
|
8052
8052
|
if (!person) return;
|
|
8053
8053
|
const email = String(person.email || "").trim().toLowerCase();
|
|
8054
|
-
const
|
|
8054
|
+
const currentUser = Boolean(email && email === String(account.email || "").trim().toLowerCase());
|
|
8055
|
+
// A group's stored roster belongs to its owner, so its labels can differ
|
|
8056
|
+
// from how the viewer has saved the same person. Mentions and group info
|
|
8057
|
+
// are viewer-facing: their own contact book is authoritative there.
|
|
8058
|
+
const savedContact = !currentUser && email
|
|
8059
|
+
? contactsList.find((contact) => contactEmails(contact)
|
|
8060
|
+
.some((address) => String(address || "").trim().toLowerCase() === email))
|
|
8061
|
+
: null;
|
|
8062
|
+
const savedName = String((savedContact && savedContact.name) || "").trim();
|
|
8063
|
+
const shown = savedName ? { ...person, name:savedName } : person;
|
|
8064
|
+
const name = String(shown.name || "").trim();
|
|
8055
8065
|
if (!email && !name && !person.userId && !person.contactId && !person.id) return;
|
|
8056
8066
|
const key = email
|
|
8057
8067
|
? `email:${email}`
|
|
@@ -8063,9 +8073,9 @@
|
|
|
8063
8073
|
if (!key || seen.has(key)) return;
|
|
8064
8074
|
seen.add(key);
|
|
8065
8075
|
roster.push({
|
|
8066
|
-
...
|
|
8076
|
+
...shown,
|
|
8067
8077
|
role,
|
|
8068
|
-
currentUser
|
|
8078
|
+
currentUser,
|
|
8069
8079
|
});
|
|
8070
8080
|
};
|
|
8071
8081
|
// Owner mutations historically returned the compact owned view without an
|
|
@@ -9020,9 +9030,12 @@
|
|
|
9020
9030
|
t.unreadCount = t.msgs.filter((m) => m.unread).length;
|
|
9021
9031
|
// The thread's display party is the other side: prefer the latest
|
|
9022
9032
|
// inbound sender, else the latest outbound recipient.
|
|
9023
|
-
const lastIn = [...t.msgs].reverse().find((m) => m.direction === "in");
|
|
9024
|
-
|
|
9025
|
-
|
|
9033
|
+
const lastIn = [...t.msgs].reverse().find((m) => m.direction === "in" && !m.ownedAgent);
|
|
9034
|
+
const counterpart = lastIn || [...t.msgs].reverse().find((m) => !m.ownedAgent) || latest;
|
|
9035
|
+
// An owned agent is a speaking face inside the existing room, never a
|
|
9036
|
+
// new participant. Name and key the room from its human counterpart.
|
|
9037
|
+
t.party = counterpart.party || "Conversation";
|
|
9038
|
+
t.partyKey = counterpart.partyKey || `name:${String(t.party).trim().toLowerCase()}`;
|
|
9026
9039
|
t.isGroup = t.msgs.some((m) => m.isGroup);
|
|
9027
9040
|
t.groupId = (t.msgs.find((m) => m.groupId) || {}).groupId || "";
|
|
9028
9041
|
t.groupName = (t.msgs.find((m) => m.groupName) || {}).groupName || "";
|
|
@@ -9040,7 +9053,7 @@
|
|
|
9040
9053
|
const threads = buildThreads();
|
|
9041
9054
|
for (const t of threads) {
|
|
9042
9055
|
const peopleByIdentity = new Map();
|
|
9043
|
-
for (const m of t.msgs.filter((m) => m.direction === "in" && m.party)) {
|
|
9056
|
+
for (const m of t.msgs.filter((m) => m.direction === "in" && !m.ownedAgent && m.party)) {
|
|
9044
9057
|
peopleByIdentity.set(m.partyKey || `name:${String(m.party).trim().toLowerCase()}`, m.party);
|
|
9045
9058
|
}
|
|
9046
9059
|
const people = [...peopleByIdentity.values()];
|
|
@@ -9887,23 +9900,28 @@
|
|
|
9887
9900
|
.map((message) => normalizedPartyName(message.party))
|
|
9888
9901
|
.filter(Boolean),
|
|
9889
9902
|
);
|
|
9890
|
-
const participantNames = new Set(
|
|
9891
|
-
(thread.msgs || [])
|
|
9892
|
-
.filter((message) => message.direction === "in" && !message.ownedAgent)
|
|
9893
|
-
.map((message) => String(message.party || "").trim())
|
|
9894
|
-
.filter(Boolean),
|
|
9895
|
-
);
|
|
9903
|
+
const participantNames = new Set();
|
|
9896
9904
|
if (thread.isGroup) {
|
|
9897
9905
|
const group = groupsList.find((candidate) => String(candidate.id || "") === String(thread.groupId || ""))
|
|
9898
9906
|
|| groupsList.find((candidate) => normalizedPartyName(candidate.name) === normalizedPartyName(thread.groupName));
|
|
9907
|
+
// The current roster decides who can be mentioned. Historical sender
|
|
9908
|
+
// labels can be stale (or belong to somebody who has left), and must
|
|
9909
|
+
// not sit beside the viewer's saved contact name as a second person.
|
|
9899
9910
|
for (const member of group ? groupInfoRoster(group) : []) {
|
|
9900
9911
|
if (!member.currentUser && member.name) participantNames.add(String(member.name).trim());
|
|
9901
9912
|
}
|
|
9902
|
-
} else
|
|
9913
|
+
} else {
|
|
9914
|
+
for (const message of thread.msgs || []) {
|
|
9915
|
+
if (message.direction === "in" && !message.ownedAgent && message.party) {
|
|
9916
|
+
participantNames.add(String(message.party).trim());
|
|
9917
|
+
}
|
|
9918
|
+
}
|
|
9919
|
+
if (thread.party && !ownedAgentParticipantNames.has(normalizedPartyName(thread.party))) {
|
|
9903
9920
|
// buildThreads names a wire thread after its newest inbound sender.
|
|
9904
9921
|
// An owned-agent response is inbound too, but it is an execution face,
|
|
9905
9922
|
// not a second participant beside @my_codex / @my_claude.
|
|
9906
|
-
|
|
9923
|
+
participantNames.add(String(thread.party).trim());
|
|
9924
|
+
}
|
|
9907
9925
|
}
|
|
9908
9926
|
const mentionOptions = [
|
|
9909
9927
|
...(payload.features?.requests === true ? [
|
|
@@ -10050,7 +10068,7 @@
|
|
|
10050
10068
|
id:`optimistic-agent:${idempotencyKey}:${provider}`, relayId:"", threadId:sendAnchor.threadId || thread.threadId,
|
|
10051
10069
|
inReplyToRelayId:optimisticId, direction:"out", seen:false, seenAt:null, readReceipts:[],
|
|
10052
10070
|
title:"I'm on it", body:"I'm on it", party:provider === "claude" ? "My Claude" : "My Codex",
|
|
10053
|
-
partyKey
|
|
10071
|
+
partyKey:sendAnchor.partyKey || thread.partyKey || "", at:new Date(Date.now() + index + 1).toISOString(), isGroup:Boolean(sendAnchor.isGroup || thread.isGroup),
|
|
10054
10072
|
groupName:sendAnchor.groupName || thread.groupName || "", unread:false, textLike:true, request:false, pending:true,
|
|
10055
10073
|
source:{ host:"relay-agent-run", surface:provider === "claude" ? "claude_code" : "codex" }, ownedAgent:true, agentInvocation:true,
|
|
10056
10074
|
reactions:{ aggregates:[], events:[] }, attachments:[], preview:"",
|
package/package.json
CHANGED