relay-companion 0.1.2 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relay-companion",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Relay companion: connects local coding agents to Relay tasks, approvals, and connector tools.",
5
5
  "type": "module",
6
6
  "bin": {
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)}`, { name, email, emails });
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":