@erdoai/cli 0.105.0 → 0.107.0
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/dist/index.js +146 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -576,6 +576,31 @@ var ErdoClient = class {
|
|
|
576
576
|
`/v1/voice/sms-conversations/${encodeURIComponent(sessionID)}${qs ? `?${qs}` : ""}`
|
|
577
577
|
);
|
|
578
578
|
}
|
|
579
|
+
// WhatsApp conversations on those same numbers — their own resource rather
|
|
580
|
+
// than a channel on the SMS reads, addressed and filtered the same way.
|
|
581
|
+
listWhatsAppConversations(params) {
|
|
582
|
+
const q = new URLSearchParams();
|
|
583
|
+
if (params?.phone_number) q.set("phone_number", params.phone_number);
|
|
584
|
+
if (params?.address) q.set("address", params.address);
|
|
585
|
+
if (params?.canonical_lead_id) q.set("canonical_lead_id", params.canonical_lead_id);
|
|
586
|
+
if (params?.limit !== void 0) q.set("limit", String(params.limit));
|
|
587
|
+
if (params?.cursor) q.set("cursor", params.cursor);
|
|
588
|
+
const qs = q.toString();
|
|
589
|
+
return this.request(
|
|
590
|
+
"GET",
|
|
591
|
+
`/v1/voice/whatsapp-conversations${qs ? `?${qs}` : ""}`
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
getWhatsAppConversation(sessionID, params) {
|
|
595
|
+
const q = new URLSearchParams();
|
|
596
|
+
if (params?.limit !== void 0) q.set("limit", String(params.limit));
|
|
597
|
+
if (params?.cursor) q.set("cursor", params.cursor);
|
|
598
|
+
const qs = q.toString();
|
|
599
|
+
return this.request(
|
|
600
|
+
"GET",
|
|
601
|
+
`/v1/voice/whatsapp-conversations/${encodeURIComponent(sessionID)}${qs ? `?${qs}` : ""}`
|
|
602
|
+
);
|
|
603
|
+
}
|
|
579
604
|
// The organization's business profile: its legal identity, which every A2P
|
|
580
605
|
// registration on the account is checked against. It follows the org
|
|
581
606
|
// convention rather than the voice one because it is the organization's, not
|
|
@@ -5968,6 +5993,127 @@ contact: ${parts.join(" \xB7 ")}`);
|
|
|
5968
5993
|
}
|
|
5969
5994
|
}
|
|
5970
5995
|
);
|
|
5996
|
+
var voiceWhatsAppCmd = voiceCmd.command("whatsapp").description("WhatsApp conversations on a voice agent's own number");
|
|
5997
|
+
voiceWhatsAppCmd.command("list").description("List the organization's WhatsApp conversations, most recently active first").option("--phone-number <number>", "only conversations on this Erdo number (any format)").option("--address <number>", "only the conversation with this person (any format)").option("--lead <lead>", LEAD_FILTER_HELP).option("--limit <n>", "page size (default 25, max 100)").option("--cursor <cursor>", "next_cursor from the preceding page (stable paging)").option("--json", "print the raw JSON result instead of a table").action(
|
|
5998
|
+
async (opts) => {
|
|
5999
|
+
try {
|
|
6000
|
+
const res = await new ErdoClient().listWhatsAppConversations({
|
|
6001
|
+
phone_number: opts.phoneNumber,
|
|
6002
|
+
address: opts.address,
|
|
6003
|
+
canonical_lead_id: opts.lead,
|
|
6004
|
+
limit: opts.limit ? Number(opts.limit) : void 0,
|
|
6005
|
+
cursor: opts.cursor
|
|
6006
|
+
});
|
|
6007
|
+
if (opts.json) {
|
|
6008
|
+
print(res);
|
|
6009
|
+
return;
|
|
6010
|
+
}
|
|
6011
|
+
const conversations = res.conversations ?? [];
|
|
6012
|
+
if (conversations.length === 0) {
|
|
6013
|
+
console.log("No WhatsApp conversations match those filters.");
|
|
6014
|
+
return;
|
|
6015
|
+
}
|
|
6016
|
+
printAlignedTable(
|
|
6017
|
+
["session id", "phone", "address", "name", "msgs", "last inbound", "last outbound", "lead ref", "summary"],
|
|
6018
|
+
conversations.map((c) => [
|
|
6019
|
+
c.session_id,
|
|
6020
|
+
c.phone_number,
|
|
6021
|
+
c.suppressed ? `${c.address} (suppressed)` : c.address,
|
|
6022
|
+
c.display_name ?? "",
|
|
6023
|
+
c.message_count,
|
|
6024
|
+
c.last_inbound_at ?? "",
|
|
6025
|
+
c.last_outbound_at ?? "",
|
|
6026
|
+
leadReferenceLabel(c.lead_reference),
|
|
6027
|
+
c.summary
|
|
6028
|
+
])
|
|
6029
|
+
);
|
|
6030
|
+
process.stderr.write(`showing ${conversations.length} conversation(s)
|
|
6031
|
+
`);
|
|
6032
|
+
if (res.next_cursor) {
|
|
6033
|
+
process.stderr.write(`more available \u2014 re-run with --cursor ${res.next_cursor}
|
|
6034
|
+
`);
|
|
6035
|
+
}
|
|
6036
|
+
} catch (e) {
|
|
6037
|
+
fail(e);
|
|
6038
|
+
}
|
|
6039
|
+
}
|
|
6040
|
+
);
|
|
6041
|
+
function whatsAppMessageText(m) {
|
|
6042
|
+
const parts = [];
|
|
6043
|
+
if (m.body) parts.push(m.body);
|
|
6044
|
+
if (m.location) {
|
|
6045
|
+
const where = [m.location.label, m.location.address].filter(Boolean).join(", ");
|
|
6046
|
+
parts.push(`[location ${m.location.latitude},${m.location.longitude}${where ? ` ${where}` : ""}]`);
|
|
6047
|
+
}
|
|
6048
|
+
if (m.context?.button_text) parts.push(`[tapped "${m.context.button_text}"]`);
|
|
6049
|
+
else if (m.context?.replied_message_id) parts.push(`[reply to ${m.context.replied_message_id}]`);
|
|
6050
|
+
if (m.referral) parts.push(`[from ad${m.referral.Headline ? ` "${m.referral.Headline}"` : ""}]`);
|
|
6051
|
+
if (parts.length === 0 && m.message_type && m.message_type !== "text") parts.push(`[${m.message_type}]`);
|
|
6052
|
+
return parts.join(" ");
|
|
6053
|
+
}
|
|
6054
|
+
voiceWhatsAppCmd.command("get <sessionID>").description("Read one WhatsApp conversation: its metadata, then every message oldest first").option("--limit <n>", "messages per page (default 50, max 200)").option("--cursor <cursor>", "next_cursor from the preceding page of messages").option("--json", "print the raw JSON result instead of a table").action(
|
|
6055
|
+
async (sessionID, opts) => {
|
|
6056
|
+
try {
|
|
6057
|
+
const res = await new ErdoClient().getWhatsAppConversation(sessionID, {
|
|
6058
|
+
limit: opts.limit ? Number(opts.limit) : void 0,
|
|
6059
|
+
cursor: opts.cursor
|
|
6060
|
+
});
|
|
6061
|
+
if (opts.json) {
|
|
6062
|
+
print(res);
|
|
6063
|
+
return;
|
|
6064
|
+
}
|
|
6065
|
+
const c = res.conversation;
|
|
6066
|
+
printAlignedTable(
|
|
6067
|
+
["session id", "phone", "address", "name", "msgs", "last inbound", "last outbound", "summary"],
|
|
6068
|
+
[
|
|
6069
|
+
[
|
|
6070
|
+
c.session_id,
|
|
6071
|
+
c.phone_number,
|
|
6072
|
+
c.suppressed ? `${c.address} (suppressed)` : c.address,
|
|
6073
|
+
c.display_name ?? "",
|
|
6074
|
+
c.message_count,
|
|
6075
|
+
c.last_inbound_at ?? "",
|
|
6076
|
+
c.last_outbound_at ?? "",
|
|
6077
|
+
c.summary
|
|
6078
|
+
]
|
|
6079
|
+
]
|
|
6080
|
+
);
|
|
6081
|
+
const contact = c.contact;
|
|
6082
|
+
if (contact && (contact.name || contact.email || contact.phone || contact.company)) {
|
|
6083
|
+
const parts = [contact.name, contact.email, contact.phone, contact.company].filter(Boolean);
|
|
6084
|
+
console.log(`
|
|
6085
|
+
contact: ${parts.join(" \xB7 ")}`);
|
|
6086
|
+
}
|
|
6087
|
+
if (c.lead_reference) {
|
|
6088
|
+
console.log(`lead: ${c.lead_reference} (${c.canonical_lead_id})`);
|
|
6089
|
+
}
|
|
6090
|
+
const messages = res.messages ?? [];
|
|
6091
|
+
if (messages.length === 0) {
|
|
6092
|
+
console.log("\nNo messages have been recorded in this conversation yet.");
|
|
6093
|
+
return;
|
|
6094
|
+
}
|
|
6095
|
+
console.log("");
|
|
6096
|
+
printAlignedTable(
|
|
6097
|
+
["at", "direction", "status", "media", "message"],
|
|
6098
|
+
messages.map((m) => [
|
|
6099
|
+
m.created_at,
|
|
6100
|
+
m.direction,
|
|
6101
|
+
m.status,
|
|
6102
|
+
m.num_media > 0 ? m.num_media : "",
|
|
6103
|
+
whatsAppMessageText(m)
|
|
6104
|
+
])
|
|
6105
|
+
);
|
|
6106
|
+
process.stderr.write(`showing ${messages.length} message(s), oldest first
|
|
6107
|
+
`);
|
|
6108
|
+
if (res.next_cursor) {
|
|
6109
|
+
process.stderr.write(`more available \u2014 re-run with --cursor ${res.next_cursor}
|
|
6110
|
+
`);
|
|
6111
|
+
}
|
|
6112
|
+
} catch (e) {
|
|
6113
|
+
fail(e);
|
|
6114
|
+
}
|
|
6115
|
+
}
|
|
6116
|
+
);
|
|
5971
6117
|
var voiceNumbersCmd = voiceCmd.command("numbers").description("The organization's phone numbers, their A2P SMS registration and their caller name");
|
|
5972
6118
|
function printRegistrationState(registration) {
|
|
5973
6119
|
if (registration === null || typeof registration !== "object") {
|