@getdial/cli 0.43.0 → 0.44.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/cli.js CHANGED
@@ -18,6 +18,7 @@ import { runNumberPurchase } from "./commands/number/purchase.js";
18
18
  import { runNumberSet } from "./commands/number/set.js";
19
19
  import { runNumberWhatsapp } from "./commands/number/whatsapp.js";
20
20
  import { runGroupList } from "./commands/group/list.js";
21
+ import { runLookup } from "./commands/lookup/lookup.js";
21
22
  import { runContactsList } from "./commands/contacts/list.js";
22
23
  import { runMessageSend } from "./commands/message/send.js";
23
24
  import { runMessageReply } from "./commands/message/reply.js";
@@ -337,6 +338,13 @@ program
337
338
  startingAfter: opts.startingAfter,
338
339
  json: !!opts.json,
339
340
  })));
341
+ program
342
+ .command("lookup")
343
+ .argument("<number>", "the phone number to look up, in E.164 (e.g. +14155550123)")
344
+ .description("What channels a phone number can receive on, so you can pick one before sending. Works on " +
345
+ "any number, not just yours. GET /api/v1/lookup.")
346
+ .option("--json", "machine-readable output")
347
+ .action(async (number, opts) => process.exit(await runLookup(number, { json: !!opts.json })));
340
348
  const group = program
341
349
  .command("group")
342
350
  .description("Group conversations your lines are in (WhatsApp).");
@@ -0,0 +1,31 @@
1
+ import { lookupNumber } from "../../lib/ops/lookup.js";
2
+ import { isDialError } from "../../lib/ops/errors.js";
3
+ import { printDialError } from "../../lib/cli-error.js";
4
+ /** Channels in the order they are printed, with the label each one shows as. */
5
+ const CHANNEL_LABELS = {
6
+ imessage: "iMessage",
7
+ };
8
+ export async function runLookup(number, opts) {
9
+ try {
10
+ const result = await lookupNumber(number);
11
+ if (opts.json) {
12
+ console.log(JSON.stringify({ ok: true, ...result }));
13
+ return 0;
14
+ }
15
+ console.log(result.number);
16
+ for (const [channel, supported] of Object.entries(result.supports)) {
17
+ // A channel added to the API after this CLI shipped still prints, under its
18
+ // raw key — reporting an unknown channel is better than hiding it.
19
+ const label = CHANNEL_LABELS[channel] ?? channel;
20
+ console.log(` ${label.padEnd(9)} ${supported ? "yes" : "no"}`);
21
+ }
22
+ return 0;
23
+ }
24
+ catch (e) {
25
+ // A lookup that could not be completed exits non-zero rather than printing
26
+ // "no": the two mean different things, and only one is worth retrying.
27
+ if (isDialError(e))
28
+ return printDialError(opts.json, e);
29
+ throw e;
30
+ }
31
+ }
@@ -0,0 +1,20 @@
1
+ import { apiGet } from "../api.js";
2
+ import { maybeAuth } from "./auth.js";
3
+ import { DialError } from "./errors.js";
4
+ /**
5
+ * Look a number up.
6
+ *
7
+ * Shared by `dial lookup` and the local MCP `lookup_number` tool, so both speak to
8
+ * the API through one place and inherit the saved key the same way.
9
+ *
10
+ * A lookup Dial could not complete comes back as an error (502), never as a
11
+ * negative verdict — so a `false` here always means the number genuinely is not
12
+ * reachable on that channel, and callers can treat the two differently.
13
+ */
14
+ export async function lookupNumber(number) {
15
+ const auth = maybeAuth();
16
+ const res = await apiGet(`/api/v1/lookup?number=${encodeURIComponent(number)}`, auth?.apiKey);
17
+ if (!res.ok)
18
+ throw new DialError("lookup_failed", res.error, res.status);
19
+ return res.data;
20
+ }
@@ -8,6 +8,7 @@ import { stopTypingTool } from "./stop-typing.js";
8
8
  import { listMessagesTool } from "./list-messages.js";
9
9
  import { listGroupsTool } from "./list-groups.js";
10
10
  import { listContactsTool } from "./list-contacts.js";
11
+ import { lookupNumberTool } from "./lookup-number.js";
11
12
  import { placeCallTool } from "./place-call.js";
12
13
  import { listCallsTool } from "./list-calls.js";
13
14
  import { getCallTool } from "./get-call.js";
@@ -35,6 +36,7 @@ export const tools = [
35
36
  listMessagesTool,
36
37
  listGroupsTool,
37
38
  listContactsTool,
39
+ lookupNumberTool,
38
40
  placeCallTool,
39
41
  listCallsTool,
40
42
  getCallTool,
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ import { jsonResult } from "../result.js";
3
+ import { lookupNumber } from "../../lib/ops/lookup.js";
4
+ const inputSchema = {
5
+ number: z
6
+ .string()
7
+ .describe("The phone number to look up, in E.164 — e.g. +14155550123. Any number, not just your own."),
8
+ };
9
+ export const lookupNumberTool = {
10
+ name: "lookup_number",
11
+ config: {
12
+ title: "Look Up A Number",
13
+ description: "Check what channels a phone number can receive on, before sending to it. Works on ANY number in the " +
14
+ "world — it doesn't have to be one of your numbers, and you don't have to have messaged it before. " +
15
+ "`supports` describes the number you asked about, not your own line: each key is a channel and the " +
16
+ "boolean says whether that number can be reached there. Read the channels you need by name, since more " +
17
+ "are added over time. The answer is point-in-time, not a property of the number — someone who changes " +
18
+ "device or turns the service off stops being reachable — so treat `true` as a strong signal for picking " +
19
+ "a channel rather than a promise that the send will land. A lookup that fails is an error, never a " +
20
+ "`false`, so a `false` always means the number genuinely isn't reachable there.",
21
+ inputSchema,
22
+ outputSchema: {
23
+ number: z.string().describe("The number you asked about, normalized to E.164"),
24
+ supports: z
25
+ .object({
26
+ imessage: z.boolean().describe("Whether the number can currently receive iMessage"),
27
+ })
28
+ .describe("One key per channel, true when the number can be reached there"),
29
+ },
30
+ annotations: { readOnlyHint: true, openWorldHint: true },
31
+ },
32
+ run: async (args) => jsonResult(await lookupNumber(args.number)),
33
+ };
@@ -31,6 +31,7 @@ export const OPERATIONAL_TOOL_NAMES = [
31
31
  "list_messages",
32
32
  "list_groups",
33
33
  "list_contacts",
34
+ "lookup_number",
34
35
  "place_call",
35
36
  "list_calls",
36
37
  "get_call",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getdial/cli",
3
- "version": "0.43.0",
3
+ "version": "0.44.0",
4
4
  "description": "Dial CLI — install, sign up, and run the local listen service.",
5
5
  "license": "MIT",
6
6
  "repository": {
package/skills.tar.gz CHANGED
Binary file