@erdoai/cli 0.75.0 → 0.76.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 +122 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -482,6 +482,32 @@ var ErdoClient = class {
482
482
  getVoiceCall(callID) {
483
483
  return this.request("GET", `/v1/voice/calls/${encodeURIComponent(callID)}`);
484
484
  }
485
+ // Website concierge widget conversations — the text/voice/video sessions
486
+ // visitors held on the customer's own pages. Covers every widget in the org
487
+ // unless narrowed by the widget handle (its name or public key, vw_...).
488
+ listWidgetConversations(params) {
489
+ const q = new URLSearchParams();
490
+ if (params?.widget) q.set("widget", params.widget);
491
+ if (params?.since) q.set("since", params.since);
492
+ if (params?.until) q.set("until", params.until);
493
+ if (params?.limit !== void 0) q.set("limit", String(params.limit));
494
+ if (params?.offset !== void 0) q.set("offset", String(params.offset));
495
+ if (params?.cursor) q.set("cursor", params.cursor);
496
+ const qs = q.toString();
497
+ return this.request(
498
+ "GET",
499
+ `/v1/voice/widget-conversations${qs ? `?${qs}` : ""}`
500
+ );
501
+ }
502
+ // The session id identifies the conversation on its own and another org's
503
+ // session is never returned, so the widget handle is optional.
504
+ getWidgetConversation(sessionID, widget) {
505
+ return this.request(
506
+ "POST",
507
+ `/v1/voice/widget-conversations/get`,
508
+ { session_id: sessionID, ...widget ? { widget } : {} }
509
+ );
510
+ }
485
511
  // Run a read-only HogQL query against the org's page-analytics events. Rows are
486
512
  // positional per columns; enabled:false means page analytics is off for the org
487
513
  // (not zero traffic). A rejected query surfaces PostHog's message as the error.
@@ -4753,7 +4779,17 @@ sentEmailsCmd.command("get <emailID>").description("Read one sent email, includi
4753
4779
  fail(e);
4754
4780
  }
4755
4781
  });
4756
- var voiceCmd = program.command("voice").description("Read voice agent phone conversations");
4782
+ var voiceCmd = program.command("voice").description("Read voice agent phone calls and website widget conversations");
4783
+ function contactLabel(contact) {
4784
+ if (!contact) return "-";
4785
+ const name = [contact.first_name, contact.last_name].filter(Boolean).join(" ");
4786
+ const reach = contact.email || contact.phone;
4787
+ if (!name && !reach) return "none";
4788
+ return [name, reach].filter(Boolean).join(" \xB7 ");
4789
+ }
4790
+ function leadStatusLabel(outcome) {
4791
+ return outcome ? outcome : "pending";
4792
+ }
4757
4793
  var voiceCallsCmd = voiceCmd.command("calls").description("Inbound and outbound phone call records");
4758
4794
  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(
4759
4795
  async (opts) => {
@@ -4775,7 +4811,19 @@ voiceCallsCmd.command("list").description("List the organization's phone calls,
4775
4811
  return;
4776
4812
  }
4777
4813
  printAlignedTable(
4778
- ["call id", "direction", "from", "to", "status", "secs", "transcript", "started", "summary"],
4814
+ [
4815
+ "call id",
4816
+ "direction",
4817
+ "from",
4818
+ "to",
4819
+ "status",
4820
+ "secs",
4821
+ "transcript",
4822
+ "contact",
4823
+ "lead",
4824
+ "started",
4825
+ "summary"
4826
+ ],
4779
4827
  calls.map((call) => [
4780
4828
  call.call_id,
4781
4829
  call.direction,
@@ -4784,6 +4832,8 @@ voiceCallsCmd.command("list").description("List the organization's phone calls,
4784
4832
  call.status,
4785
4833
  call.duration_seconds,
4786
4834
  call.has_transcript ? "yes" : "no",
4835
+ contactLabel(call.contact),
4836
+ leadStatusLabel(call.lead_status),
4787
4837
  call.created_at,
4788
4838
  call.transcript_summary
4789
4839
  ])
@@ -4799,13 +4849,82 @@ voiceCallsCmd.command("list").description("List the organization's phone calls,
4799
4849
  }
4800
4850
  }
4801
4851
  );
4802
- voiceCallsCmd.command("get <callID>").description("Read one phone call in full: transcript, summary, and per-turn LLM metrics").action(async (callID) => {
4852
+ voiceCallsCmd.command("get <callID>").description(
4853
+ "Read one phone call in full: transcript, summary, per-turn LLM metrics, and the lead it produced (contact, lead_status, lead_saved_at)"
4854
+ ).action(async (callID) => {
4803
4855
  try {
4804
4856
  print(await new ErdoClient().getVoiceCall(callID));
4805
4857
  } catch (e) {
4806
4858
  fail(e);
4807
4859
  }
4808
4860
  });
4861
+ var widgetConversationsCmd = voiceCmd.command("widget-conversations").description("Website concierge widget conversations (text, voice and video sessions)");
4862
+ 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(
4863
+ async (opts) => {
4864
+ try {
4865
+ const res = await new ErdoClient().listWidgetConversations({
4866
+ widget: opts.widget,
4867
+ since: opts.since,
4868
+ until: opts.until,
4869
+ limit: opts.limit ? Number(opts.limit) : void 0,
4870
+ offset: opts.offset ? Number(opts.offset) : void 0,
4871
+ cursor: opts.cursor
4872
+ });
4873
+ if (opts.json) {
4874
+ print(res);
4875
+ return;
4876
+ }
4877
+ const conversations = res.conversations ?? [];
4878
+ if (conversations.length === 0) {
4879
+ console.log("No conversations match those filters.");
4880
+ return;
4881
+ }
4882
+ printAlignedTable(
4883
+ [
4884
+ "session id",
4885
+ "widget",
4886
+ "modality",
4887
+ "secs",
4888
+ "transcript",
4889
+ "contact",
4890
+ "lead",
4891
+ "started",
4892
+ "summary"
4893
+ ],
4894
+ conversations.map((c) => [
4895
+ c.session_id,
4896
+ c.widget_name || c.widget,
4897
+ c.modality,
4898
+ c.duration_seconds,
4899
+ c.has_transcript ? "yes" : "no",
4900
+ contactLabel(c.contact),
4901
+ leadStatusLabel(c.lead_status),
4902
+ c.created_at,
4903
+ c.transcript_summary
4904
+ ])
4905
+ );
4906
+ process.stderr.write(
4907
+ `showing ${conversations.length} of ${res.total} conversation(s)
4908
+ `
4909
+ );
4910
+ if (res.next_cursor) {
4911
+ process.stderr.write(`more available \u2014 re-run with --cursor ${res.next_cursor}
4912
+ `);
4913
+ }
4914
+ } catch (e) {
4915
+ fail(e);
4916
+ }
4917
+ }
4918
+ );
4919
+ widgetConversationsCmd.command("get <sessionID>").description(
4920
+ "Read one widget conversation in full: transcript, summary, topics, per-turn LLM metrics, and the lead it produced (contact, lead_status, lead_saved_at)"
4921
+ ).option("--widget <handle>", "the widget it belongs to \u2014 optional, the session id identifies it").action(async (sessionID, opts) => {
4922
+ try {
4923
+ print(await new ErdoClient().getWidgetConversation(sessionID, opts.widget));
4924
+ } catch (e) {
4925
+ fail(e);
4926
+ }
4927
+ });
4809
4928
  var datasetsCmd = program.command("datasets").description("Datasets");
4810
4929
  datasetsCmd.command("list").description("List datasets").option(
4811
4930
  "--class <class>",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@erdoai/cli",
3
- "version": "0.75.0",
3
+ "version": "0.76.0",
4
4
  "description": "Erdo CLI \u2014 drive datasets, pages, and evals from the terminal or CI",
5
5
  "type": "module",
6
6
  "bin": {