relay-companion 0.1.1 → 0.1.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/overlay/inbox.html +16 -0
- package/package.json +1 -1
- package/src/client.js +15 -6
- package/src/mcp.js +48 -2
package/overlay/inbox.html
CHANGED
|
@@ -66,6 +66,21 @@
|
|
|
66
66
|
.card.has-unread .sq0 { fill:var(--accent); }
|
|
67
67
|
.word { font-family:var(--serif); font-size:19px; font-weight:500; letter-spacing:-.01em; color:var(--ink); line-height:1; }
|
|
68
68
|
.spacer { flex:1 1 auto; }
|
|
69
|
+
.minimize-hint {
|
|
70
|
+
margin-right:10px;
|
|
71
|
+
font-size:11px;
|
|
72
|
+
font-weight:500;
|
|
73
|
+
color:var(--muted-3);
|
|
74
|
+
line-height:1;
|
|
75
|
+
transition:color .18s var(--settle), opacity .18s var(--settle), width .18s var(--settle), margin .18s var(--settle);
|
|
76
|
+
}
|
|
77
|
+
.lockup:hover .minimize-hint { color:var(--muted-2); }
|
|
78
|
+
.card.collapsed .minimize-hint {
|
|
79
|
+
width:0;
|
|
80
|
+
margin-right:0;
|
|
81
|
+
overflow:hidden;
|
|
82
|
+
opacity:0;
|
|
83
|
+
}
|
|
69
84
|
.count {
|
|
70
85
|
font-family:var(--mono); font-size:13px; font-weight:500; font-variant-numeric:tabular-nums;
|
|
71
86
|
color:var(--accent); line-height:1; transition:color .3s var(--settle);
|
|
@@ -381,6 +396,7 @@
|
|
|
381
396
|
</svg>
|
|
382
397
|
<span class="word">relay</span>
|
|
383
398
|
<span class="spacer"></span>
|
|
399
|
+
<span class="minimize-hint">Minimize</span>
|
|
384
400
|
<span class="count zero" id="count">0</span>
|
|
385
401
|
</div>
|
|
386
402
|
|
package/package.json
CHANGED
package/src/client.js
CHANGED
|
@@ -182,12 +182,21 @@ export class RelayClient {
|
|
|
182
182
|
return this.#req("GET", "/v1/contacts");
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
upsertContact({ name, email, emails }) {
|
|
186
|
-
return this.#req("POST", "/v1/contacts", { name, email, emails });
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
updateContact(contactId, { name, email, emails } = {}) {
|
|
190
|
-
return this.#req("PATCH", `/v1/contacts/${encodeURIComponent(contactId)}`, {
|
|
185
|
+
upsertContact({ name, firstName, surname, lastName, email, emails, notes, idempotencyKey }) {
|
|
186
|
+
return this.#req("POST", "/v1/contacts", { name, firstName, surname, lastName, email, emails, notes, idempotencyKey });
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
updateContact(contactId, { name, firstName, surname, lastName, email, emails, notes, idempotencyKey } = {}) {
|
|
190
|
+
return this.#req("PATCH", `/v1/contacts/${encodeURIComponent(contactId)}`, {
|
|
191
|
+
name,
|
|
192
|
+
firstName,
|
|
193
|
+
surname,
|
|
194
|
+
lastName,
|
|
195
|
+
email,
|
|
196
|
+
emails,
|
|
197
|
+
notes,
|
|
198
|
+
idempotencyKey,
|
|
199
|
+
});
|
|
191
200
|
}
|
|
192
201
|
|
|
193
202
|
importContacts(contacts, source = "imported") {
|
package/src/mcp.js
CHANGED
|
@@ -45,6 +45,25 @@ export const TOOLS = [
|
|
|
45
45
|
required: ["query"],
|
|
46
46
|
},
|
|
47
47
|
},
|
|
48
|
+
{
|
|
49
|
+
name: "relay_contact_update",
|
|
50
|
+
description:
|
|
51
|
+
"Correct a Relay contact in this human's contact book. Use this after relay_send auto-creates an email-only contact, or when the human asks you to fix a saved contact. Prefer firstName and surname over a single name string. If you are not sure of the person's first name and surname, ask the human for clarification before editing the contact.",
|
|
52
|
+
inputSchema: {
|
|
53
|
+
type: "object",
|
|
54
|
+
properties: {
|
|
55
|
+
contactId: { type: "string", description: "The contactId returned by relay_contacts_search or relay_send.contact.contactId." },
|
|
56
|
+
firstName: { type: "string" },
|
|
57
|
+
surname: { type: "string" },
|
|
58
|
+
name: { type: "string", description: "Fallback display name; prefer firstName + surname when possible." },
|
|
59
|
+
email: { type: "string" },
|
|
60
|
+
emails: { type: "array", items: { type: "string" } },
|
|
61
|
+
notes: { type: "string" },
|
|
62
|
+
idempotencyKey: { type: "string" },
|
|
63
|
+
},
|
|
64
|
+
required: ["contactId", "idempotencyKey"],
|
|
65
|
+
},
|
|
66
|
+
},
|
|
48
67
|
{
|
|
49
68
|
name: "relay_inbox_list",
|
|
50
69
|
description:
|
|
@@ -318,11 +337,26 @@ function text(obj) {
|
|
|
318
337
|
return { content: [{ type: "text", text: typeof obj === "string" ? obj : JSON.stringify(obj, null, 2) }] };
|
|
319
338
|
}
|
|
320
339
|
|
|
340
|
+
function relaySendResultForAgent(result) {
|
|
341
|
+
if (!result?.contact?.autoCreated) return result;
|
|
342
|
+
return {
|
|
343
|
+
...result,
|
|
344
|
+
agentInstruction:
|
|
345
|
+
result.agentInstruction ||
|
|
346
|
+
[
|
|
347
|
+
`Relay auto-added ${result.contact.email} to this human's contact book because there was no saved contact for this recipient.`,
|
|
348
|
+
"You are responsible for correcting the contact's firstName and surname with relay_contact_update if you know them from reliable context.",
|
|
349
|
+
"If you are not sure of the person's first name and surname, ask the human for clarification before editing the contact.",
|
|
350
|
+
].join(" "),
|
|
351
|
+
nextRecommendedTool: "relay_contact_update",
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
|
|
321
355
|
export async function handleCall(client, name, args) {
|
|
322
356
|
switch (name) {
|
|
323
357
|
case "relay_send":
|
|
324
358
|
return text(
|
|
325
|
-
await client.sendRelay({
|
|
359
|
+
relaySendResultForAgent(await client.sendRelay({
|
|
326
360
|
recipient: args.recipient,
|
|
327
361
|
kind: args.kind || "message",
|
|
328
362
|
title: args.title,
|
|
@@ -332,10 +366,22 @@ export async function handleCall(client, name, args) {
|
|
|
332
366
|
targetSurfaces: args.targetSurfaces || [],
|
|
333
367
|
attachments: args.attachments || [],
|
|
334
368
|
idempotencyKey: args.idempotencyKey,
|
|
335
|
-
}),
|
|
369
|
+
})),
|
|
336
370
|
);
|
|
337
371
|
case "relay_contacts_search":
|
|
338
372
|
return text(await client.searchContacts(args.query));
|
|
373
|
+
case "relay_contact_update":
|
|
374
|
+
return text(
|
|
375
|
+
await client.updateContact(args.contactId, {
|
|
376
|
+
firstName: args.firstName,
|
|
377
|
+
surname: args.surname,
|
|
378
|
+
name: args.name,
|
|
379
|
+
email: args.email,
|
|
380
|
+
emails: args.emails,
|
|
381
|
+
notes: args.notes,
|
|
382
|
+
idempotencyKey: args.idempotencyKey,
|
|
383
|
+
}),
|
|
384
|
+
);
|
|
339
385
|
case "relay_inbox_list":
|
|
340
386
|
return text(await client.inbox());
|
|
341
387
|
case "relay_acknowledge":
|