@erdoai/cli 0.89.0 → 0.91.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.
Files changed (2) hide show
  1. package/dist/index.js +61 -11
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -489,10 +489,15 @@ var ErdoClient = class {
489
489
  // Phone conversation records: inbound calls to a voice agent's own number and
490
490
  // the outbound calls Erdo placed. Website chat widget conversations are a
491
491
  // different resource — they live under /v1/voice/widget-conversations.
492
+ // canonical_lead_id narrows to one lead's calls, by its UUID or its lead
493
+ // reference — the same filter every conversation list takes.
492
494
  listVoiceCalls(params) {
493
495
  const q = new URLSearchParams();
494
496
  if (params?.agent) q.set("agent", params.agent);
495
497
  if (params?.direction) q.set("direction", params.direction);
498
+ if (params?.since) q.set("since", params.since);
499
+ if (params?.until) q.set("until", params.until);
500
+ if (params?.canonical_lead_id) q.set("canonical_lead_id", params.canonical_lead_id);
496
501
  if (params?.limit !== void 0) q.set("limit", String(params.limit));
497
502
  if (params?.offset !== void 0) q.set("offset", String(params.offset));
498
503
  if (params?.cursor) q.set("cursor", params.cursor);
@@ -510,6 +515,7 @@ var ErdoClient = class {
510
515
  if (params?.widget) q.set("widget", params.widget);
511
516
  if (params?.since) q.set("since", params.since);
512
517
  if (params?.until) q.set("until", params.until);
518
+ if (params?.canonical_lead_id) q.set("canonical_lead_id", params.canonical_lead_id);
513
519
  if (params?.limit !== void 0) q.set("limit", String(params.limit));
514
520
  if (params?.offset !== void 0) q.set("offset", String(params.offset));
515
521
  if (params?.cursor) q.set("cursor", params.cursor);
@@ -536,6 +542,7 @@ var ErdoClient = class {
536
542
  const q = new URLSearchParams();
537
543
  if (params?.phone_number) q.set("phone_number", params.phone_number);
538
544
  if (params?.address) q.set("address", params.address);
545
+ if (params?.canonical_lead_id) q.set("canonical_lead_id", params.canonical_lead_id);
539
546
  if (params?.limit !== void 0) q.set("limit", String(params.limit));
540
547
  if (params?.cursor) q.set("cursor", params.cursor);
541
548
  const qs = q.toString();
@@ -5215,13 +5222,20 @@ function contactLabel(contact) {
5215
5222
  function leadStatusLabel(outcome) {
5216
5223
  return outcome ? outcome : "pending";
5217
5224
  }
5225
+ function leadReferenceLabel(reference) {
5226
+ return reference ? reference : "-";
5227
+ }
5228
+ var LEAD_FILTER_HELP = "only this lead's conversations \u2014 its canonical lead id (UUID) or its 22-character lead reference";
5218
5229
  var voiceCallsCmd = voiceCmd.command("calls").description("Inbound and outbound phone call records");
5219
- voiceCallsCmd.command("list").description("List the organization's phone calls, newest first").option("--agent <slug>", "only calls held by this voice agent, by slug").option("--direction <direction>", "only 'inbound' (calls to the agent's number) or 'outbound'").option("--limit <n>", "page size (default 25, max 100)").option("--offset <n>", "rows to skip").option("--cursor <cursor>", "next_cursor from the preceding page (stable paging)").option("--json", "print the raw JSON result instead of a table").action(
5230
+ voiceCallsCmd.command("list").description("List the organization's phone calls, newest first").option("--agent <slug>", "only calls held by this voice agent, by slug").option("--direction <direction>", "only 'inbound' (calls to the agent's number) or 'outbound'").option("--since <rfc3339>", "only calls that started at or after this time (inclusive)").option("--until <rfc3339>", "only calls that started before this time (exclusive)").option("--lead <lead>", LEAD_FILTER_HELP).option("--limit <n>", "page size (default 25, max 100)").option("--offset <n>", "rows to skip").option("--cursor <cursor>", "next_cursor from the preceding page (stable paging)").option("--json", "print the raw JSON result instead of a table").action(
5220
5231
  async (opts) => {
5221
5232
  try {
5222
5233
  const res = await new ErdoClient().listVoiceCalls({
5223
5234
  agent: opts.agent,
5224
5235
  direction: opts.direction,
5236
+ since: opts.since,
5237
+ until: opts.until,
5238
+ canonical_lead_id: opts.lead,
5225
5239
  limit: opts.limit ? Number(opts.limit) : void 0,
5226
5240
  offset: opts.offset ? Number(opts.offset) : void 0,
5227
5241
  cursor: opts.cursor
@@ -5232,7 +5246,14 @@ voiceCallsCmd.command("list").description("List the organization's phone calls,
5232
5246
  }
5233
5247
  const calls = res.conversations ?? [];
5234
5248
  if (calls.length === 0) {
5235
- console.log("No calls match those filters.");
5249
+ if (res.total > 0) {
5250
+ process.stderr.write(
5251
+ `showing 0 of ${res.total} call(s) \u2014 offset/cursor is past the last one
5252
+ `
5253
+ );
5254
+ } else {
5255
+ console.log("No calls match those filters.");
5256
+ }
5236
5257
  return;
5237
5258
  }
5238
5259
  printAlignedTable(
@@ -5246,6 +5267,7 @@ voiceCallsCmd.command("list").description("List the organization's phone calls,
5246
5267
  "transcript",
5247
5268
  "contact",
5248
5269
  "lead",
5270
+ "lead ref",
5249
5271
  "started",
5250
5272
  "summary"
5251
5273
  ],
@@ -5259,11 +5281,12 @@ voiceCallsCmd.command("list").description("List the organization's phone calls,
5259
5281
  call.has_transcript ? "yes" : "no",
5260
5282
  contactLabel(call.contact),
5261
5283
  leadStatusLabel(call.lead_status),
5284
+ leadReferenceLabel(call.lead_reference),
5262
5285
  call.created_at,
5263
5286
  call.transcript_summary
5264
5287
  ])
5265
5288
  );
5266
- process.stderr.write(`showing ${calls.length} call(s)
5289
+ process.stderr.write(`showing ${calls.length} of ${res.total} call(s)
5267
5290
  `);
5268
5291
  if (res.next_cursor) {
5269
5292
  process.stderr.write(`more available \u2014 re-run with --cursor ${res.next_cursor}
@@ -5275,7 +5298,7 @@ voiceCallsCmd.command("list").description("List the organization's phone calls,
5275
5298
  }
5276
5299
  );
5277
5300
  voiceCallsCmd.command("get <callID>").description(
5278
- "Read one phone call in full: transcript, summary, per-turn LLM metrics, and the lead it produced (contact, lead_status, lead_saved_at)"
5301
+ "Read one phone call in full: transcript, summary, per-turn LLM metrics, and the lead it produced (contact, lead_status, lead_saved_at, canonical_lead_id, lead_reference)"
5279
5302
  ).action(async (callID) => {
5280
5303
  try {
5281
5304
  print(await new ErdoClient().getVoiceCall(callID));
@@ -5284,13 +5307,14 @@ voiceCallsCmd.command("get <callID>").description(
5284
5307
  }
5285
5308
  });
5286
5309
  var widgetConversationsCmd = voiceCmd.command("widget-conversations").description("Website concierge widget conversations (text, voice and video sessions)");
5287
- widgetConversationsCmd.command("list").description("List the organization's widget conversations, newest first").option("--widget <handle>", "only this widget's conversations \u2014 its name or public key (vw_...)").option("--since <rfc3339>", "only conversations that started at or after this time (inclusive)").option("--until <rfc3339>", "only conversations that started before this time (exclusive)").option("--limit <n>", "page size (default 25, max 100)").option("--offset <n>", "rows to skip").option("--cursor <cursor>", "next_cursor from the preceding page (stable paging)").option("--json", "print the raw JSON result instead of a table").action(
5310
+ widgetConversationsCmd.command("list").description("List the organization's widget conversations, newest first").option("--widget <handle>", "only this widget's conversations \u2014 its name or public key (vw_...)").option("--since <rfc3339>", "only conversations that started at or after this time (inclusive)").option("--until <rfc3339>", "only conversations that started before this time (exclusive)").option("--lead <lead>", LEAD_FILTER_HELP).option("--limit <n>", "page size (default 25, max 100)").option("--offset <n>", "rows to skip").option("--cursor <cursor>", "next_cursor from the preceding page (stable paging)").option("--json", "print the raw JSON result instead of a table").action(
5288
5311
  async (opts) => {
5289
5312
  try {
5290
5313
  const res = await new ErdoClient().listWidgetConversations({
5291
5314
  widget: opts.widget,
5292
5315
  since: opts.since,
5293
5316
  until: opts.until,
5317
+ canonical_lead_id: opts.lead,
5294
5318
  limit: opts.limit ? Number(opts.limit) : void 0,
5295
5319
  offset: opts.offset ? Number(opts.offset) : void 0,
5296
5320
  cursor: opts.cursor
@@ -5301,7 +5325,14 @@ widgetConversationsCmd.command("list").description("List the organization's widg
5301
5325
  }
5302
5326
  const conversations = res.conversations ?? [];
5303
5327
  if (conversations.length === 0) {
5304
- console.log("No conversations match those filters.");
5328
+ if (res.total > 0) {
5329
+ process.stderr.write(
5330
+ `showing 0 of ${res.total} conversation(s) \u2014 offset/cursor is past the last one
5331
+ `
5332
+ );
5333
+ } else {
5334
+ console.log("No conversations match those filters.");
5335
+ }
5305
5336
  return;
5306
5337
  }
5307
5338
  printAlignedTable(
@@ -5313,6 +5344,7 @@ widgetConversationsCmd.command("list").description("List the organization's widg
5313
5344
  "transcript",
5314
5345
  "contact",
5315
5346
  "lead",
5347
+ "lead ref",
5316
5348
  "started",
5317
5349
  "summary"
5318
5350
  ],
@@ -5324,6 +5356,7 @@ widgetConversationsCmd.command("list").description("List the organization's widg
5324
5356
  c.has_transcript ? "yes" : "no",
5325
5357
  contactLabel(c.contact),
5326
5358
  leadStatusLabel(c.lead_status),
5359
+ leadReferenceLabel(c.lead_reference),
5327
5360
  c.created_at,
5328
5361
  c.transcript_summary
5329
5362
  ])
@@ -5342,7 +5375,7 @@ widgetConversationsCmd.command("list").description("List the organization's widg
5342
5375
  }
5343
5376
  );
5344
5377
  widgetConversationsCmd.command("get <sessionID>").description(
5345
- "Read one widget conversation in full: transcript, summary, topics, per-turn LLM metrics, and the lead it produced (contact, lead_status, lead_saved_at)"
5378
+ "Read one widget conversation in full: transcript, summary, topics, per-turn LLM metrics, and the lead it produced (contact, lead_status, lead_saved_at, canonical_lead_id, lead_reference)"
5346
5379
  ).option("--widget <handle>", "the widget it belongs to \u2014 optional, the session id identifies it").action(async (sessionID, opts) => {
5347
5380
  try {
5348
5381
  print(await new ErdoClient().getWidgetConversation(sessionID, opts.widget));
@@ -5351,12 +5384,13 @@ widgetConversationsCmd.command("get <sessionID>").description(
5351
5384
  }
5352
5385
  });
5353
5386
  var voiceSMSCmd = voiceCmd.command("sms").description("Text conversations on a voice agent's own number");
5354
- voiceSMSCmd.command("list").description("List the organization's SMS 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("--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(
5387
+ voiceSMSCmd.command("list").description("List the organization's SMS 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(
5355
5388
  async (opts) => {
5356
5389
  try {
5357
5390
  const res = await new ErdoClient().listSMSConversations({
5358
5391
  phone_number: opts.phoneNumber,
5359
5392
  address: opts.address,
5393
+ canonical_lead_id: opts.lead,
5360
5394
  limit: opts.limit ? Number(opts.limit) : void 0,
5361
5395
  cursor: opts.cursor
5362
5396
  });
@@ -5370,7 +5404,7 @@ voiceSMSCmd.command("list").description("List the organization's SMS conversatio
5370
5404
  return;
5371
5405
  }
5372
5406
  printAlignedTable(
5373
- ["session id", "phone", "address", "msgs", "last inbound", "last outbound", "summary"],
5407
+ ["session id", "phone", "address", "msgs", "last inbound", "last outbound", "lead ref", "summary"],
5374
5408
  conversations.map((c) => [
5375
5409
  c.session_id,
5376
5410
  c.phone_number,
@@ -5380,6 +5414,7 @@ voiceSMSCmd.command("list").description("List the organization's SMS conversatio
5380
5414
  c.message_count,
5381
5415
  c.last_inbound_at ?? "",
5382
5416
  c.last_outbound_at ?? "",
5417
+ leadReferenceLabel(c.lead_reference),
5383
5418
  c.summary
5384
5419
  ])
5385
5420
  );
@@ -5426,6 +5461,9 @@ voiceSMSCmd.command("get <sessionID>").description("Read one SMS conversation: i
5426
5461
  console.log(`
5427
5462
  contact: ${parts.join(" \xB7 ")}`);
5428
5463
  }
5464
+ if (c.lead_reference) {
5465
+ console.log(`lead: ${c.lead_reference} (${c.canonical_lead_id})`);
5466
+ }
5429
5467
  const messages = res.messages ?? [];
5430
5468
  if (messages.length === 0) {
5431
5469
  console.log("\nNo texts have been recorded in this conversation yet.");
@@ -6290,8 +6328,20 @@ function printLead(lead) {
6290
6328
  if (lead.captures?.length) {
6291
6329
  console.log("\ncaptures");
6292
6330
  printAlignedTable(
6293
- ["when", "producer", "resolution", "conversion"],
6294
- lead.captures.map((c) => [c.created_at, c.producer, c.resolution, c.conversion_status])
6331
+ ["when", "producer", "pipeline", "resolution", "conversion"],
6332
+ lead.captures.map((c) => [c.created_at, c.producer, c.pipeline_id ?? "", c.resolution, c.conversion_status])
6333
+ );
6334
+ }
6335
+ if (lead.refused_captures?.length) {
6336
+ console.log("\nrefused captures (this lead was one of the candidates)");
6337
+ printAlignedTable(
6338
+ ["when", "pipeline", "resolution", "candidates"],
6339
+ lead.refused_captures.map((c) => [
6340
+ c.created_at,
6341
+ c.pipeline_id ?? "",
6342
+ c.resolution,
6343
+ (c.candidate_lead_ids ?? []).join(", ")
6344
+ ])
6295
6345
  );
6296
6346
  }
6297
6347
  if (lead.row) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@erdoai/cli",
3
- "version": "0.89.0",
3
+ "version": "0.91.0",
4
4
  "description": "Erdo CLI — drive datasets, pages, and evals from the terminal or CI",
5
5
  "type": "module",
6
6
  "bin": {