@getdial/cli 0.45.0 → 0.46.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
|
@@ -65,6 +65,20 @@ function parseCalling(value) {
|
|
|
65
65
|
return false;
|
|
66
66
|
throw new InvalidArgumentError(`must be "on" or "off", got: ${value}`);
|
|
67
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* `--forward-to <e164|off>` → the number as typed, or null to stop forwarding.
|
|
70
|
+
*
|
|
71
|
+
* `off` (any case) or an empty string means "stop forwarding", sent as null.
|
|
72
|
+
* Anything else is sent as-is: the CLI never validates phone numbers locally,
|
|
73
|
+
* so the server's own 400 (invalid E.164, or the number's own number) is the
|
|
74
|
+
* one message the user sees.
|
|
75
|
+
*/
|
|
76
|
+
function parseForwardTo(value) {
|
|
77
|
+
const trimmed = value.trim();
|
|
78
|
+
if (trimmed === "" || trimmed.toLowerCase() === "off")
|
|
79
|
+
return null;
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
68
82
|
program
|
|
69
83
|
.name("dial")
|
|
70
84
|
.description("Dial CLI — set up your account and run the listen service.")
|
|
@@ -226,6 +240,7 @@ number
|
|
|
226
240
|
.option("--whatsapp-name <text>", "WhatsApp display name shown to recipients (WhatsApp-ready numbers only): 1-25 chars, no reserved marks. The call blocks until WhatsApp applies it")
|
|
227
241
|
.option("--whatsapp-avatar <path-or-url>", "WhatsApp avatar photo (WhatsApp-ready numbers only): a local image file or public URL. Square jpeg/png between 192x192 and 640x640 (not resized)")
|
|
228
242
|
.option("--calling <on|off>", "switch calling on or off for this number, both directions: off means inbound calls aren't connected and none can be placed from it (messaging is unaffected)", parseCalling)
|
|
243
|
+
.option("--forward-to <e164|off>", "forward inbound calls to this phone number instead of answering them with the AI voice agent. `off` stops forwarding", parseForwardTo)
|
|
229
244
|
.option("--json", "machine-readable output")
|
|
230
245
|
.action(async (numberArg, opts) => {
|
|
231
246
|
let maxCallDurationSeconds;
|
|
@@ -250,6 +265,7 @@ number
|
|
|
250
265
|
whatsappName: opts.whatsappName,
|
|
251
266
|
whatsappAvatar: opts.whatsappAvatar,
|
|
252
267
|
callingEnabled: opts.calling,
|
|
268
|
+
forwardTo: opts.forwardTo,
|
|
253
269
|
json: !!opts.json,
|
|
254
270
|
}));
|
|
255
271
|
});
|
|
@@ -19,7 +19,9 @@ export async function runNumberList(opts) {
|
|
|
19
19
|
// this line is hand-built, so without this the switch would be invisible
|
|
20
20
|
// in the CLI's default output.
|
|
21
21
|
const calling = n.callingEnabled === false ? " calling:off" : "";
|
|
22
|
-
|
|
22
|
+
// Same reasoning: marked only when set, since the default is the AI agent answering.
|
|
23
|
+
const forward = n.forwardTo ? ` forward:${n.forwardTo}` : "";
|
|
24
|
+
console.log(`${n.number} id=${n.id} ${n.country}${nickname}${calling}${forward}${tag}`);
|
|
23
25
|
}
|
|
24
26
|
return 0;
|
|
25
27
|
}
|
|
@@ -20,6 +20,7 @@ export async function runNumberSet(opts) {
|
|
|
20
20
|
...(opts.lastName !== undefined ? { lastName: opts.lastName } : {}),
|
|
21
21
|
...(opts.avatar !== undefined ? { avatar: opts.avatar } : {}),
|
|
22
22
|
...(opts.callingEnabled !== undefined ? { callingEnabled: opts.callingEnabled } : {}),
|
|
23
|
+
...(opts.forwardTo !== undefined ? { forwardTo: opts.forwardTo } : {}),
|
|
23
24
|
...(opts.whatsappName !== undefined ? { whatsappName: opts.whatsappName } : {}),
|
|
24
25
|
...(opts.whatsappAvatar !== undefined ? { whatsappAvatar: opts.whatsappAvatar } : {}),
|
|
25
26
|
});
|
|
@@ -37,6 +38,9 @@ export async function runNumberSet(opts) {
|
|
|
37
38
|
// Always printed, not only when it changed: "is calling on?" is the
|
|
38
39
|
// question someone runs this command to settle.
|
|
39
40
|
console.log(` calling: ${n.callingEnabled === false ? "off" : "on"}`);
|
|
41
|
+
// Printed alongside calling for the same reason: "who picks up?" is the
|
|
42
|
+
// other half of that question.
|
|
43
|
+
console.log(` forward to: ${n.forwardTo ?? "off (AI voice agent answers)"}`);
|
|
40
44
|
const hasIdentity = n.firstName != null || n.lastName != null || n.avatarUrl != null;
|
|
41
45
|
if (hasIdentity) {
|
|
42
46
|
console.log(` display name: ${[n.firstName, n.lastName].filter(Boolean).join(" ")}`);
|
package/dist/lib/ops/numbers.js
CHANGED
|
@@ -127,6 +127,9 @@ export async function setNumberProperties(opts) {
|
|
|
127
127
|
body.lastName = opts.lastName;
|
|
128
128
|
if (opts.callingEnabled !== undefined)
|
|
129
129
|
body.callingEnabled = opts.callingEnabled;
|
|
130
|
+
// Empty string stops forwarding → send null, the one "off" spelling on the wire.
|
|
131
|
+
if (opts.forwardTo !== undefined)
|
|
132
|
+
body.forwardTo = opts.forwardTo || null;
|
|
130
133
|
if (opts.whatsappName !== undefined)
|
|
131
134
|
body.whatsappName = opts.whatsappName;
|
|
132
135
|
// A URL avatar goes in the JSON body; a local file forces multipart (below).
|
|
@@ -141,7 +144,7 @@ export async function setNumberProperties(opts) {
|
|
|
141
144
|
if (opts.whatsappAvatar !== undefined && !whatsappAvatarFile)
|
|
142
145
|
body.whatsappAvatarUrl = opts.whatsappAvatar;
|
|
143
146
|
if (Object.keys(body).length === 0 && !avatarFile && !whatsappAvatarFile) {
|
|
144
|
-
throw new DialError("bad_request", "Provide at least one property to update (inboundInstruction, inboundVoiceGender, inboundLanguage, nickname, maxCallDurationSeconds, calling, channel with name/avatar, firstName, lastName, avatar, whatsappName, or whatsappAvatar).");
|
|
147
|
+
throw new DialError("bad_request", "Provide at least one property to update (inboundInstruction, inboundVoiceGender, inboundLanguage, nickname, maxCallDurationSeconds, calling, forwardTo, channel with name/avatar, firstName, lastName, avatar, whatsappName, or whatsappAvatar).");
|
|
145
148
|
}
|
|
146
149
|
const auth = maybeAuth();
|
|
147
150
|
// The REST API keys numbers by id; the CLI/tool takes the E.164 number for ergonomics,
|
|
@@ -160,8 +163,10 @@ export async function setNumberProperties(opts) {
|
|
|
160
163
|
let res;
|
|
161
164
|
if (avatarFile || whatsappAvatarFile) {
|
|
162
165
|
const form = new ApiFormData();
|
|
166
|
+
// A null (a clear, e.g. `--forward-to off`) goes as an empty text part —
|
|
167
|
+
// multipart has no null, and String(null) would send the word "null".
|
|
163
168
|
for (const [field, value] of Object.entries(body))
|
|
164
|
-
form.set(field, String(value));
|
|
169
|
+
form.set(field, value === null ? "" : String(value));
|
|
165
170
|
if (avatarFile) {
|
|
166
171
|
form.append("avatar", new Blob([new Uint8Array(avatarFile.data)], { type: avatarFile.contentType }), avatarFile.name);
|
|
167
172
|
}
|
package/dist/mcp/schemas.js
CHANGED
|
@@ -42,6 +42,11 @@ export const phoneNumberSchema = z
|
|
|
42
42
|
.boolean()
|
|
43
43
|
.optional()
|
|
44
44
|
.describe("Whether calling is switched on for this number, both directions. false → inbound calls are not connected and place_call from it fails with calling_disabled; messaging is unaffected"),
|
|
45
|
+
forwardTo: z
|
|
46
|
+
.string()
|
|
47
|
+
.nullable()
|
|
48
|
+
.optional()
|
|
49
|
+
.describe("E.164 number inbound calls are forwarded to instead of the AI voice agent answering, or null when the agent answers."),
|
|
45
50
|
firstName: z
|
|
46
51
|
.string()
|
|
47
52
|
.nullable()
|
|
@@ -66,12 +66,17 @@ const inputSchema = {
|
|
|
66
66
|
.boolean()
|
|
67
67
|
.optional()
|
|
68
68
|
.describe("Switch calling on or off for this number, in both directions. false stops inbound calls from being connected (the caller is never answered) and makes place_call from this number fail with calling_disabled (409); messaging on the number is unaffected. Takes effect on the next call — a call already in progress is not ended. Omit to leave it unchanged."),
|
|
69
|
+
forwardTo: z
|
|
70
|
+
.string()
|
|
71
|
+
.nullable()
|
|
72
|
+
.optional()
|
|
73
|
+
.describe("Forward inbound calls to this phone number (E.164) instead of having the AI voice agent answer; the caller is connected when that phone answers, and the call ends if it is busy or doesn't answer. null stops forwarding. Ignored while calling is off. Omitted leaves it unchanged."),
|
|
69
74
|
};
|
|
70
75
|
export const setNumberPropertiesTool = {
|
|
71
76
|
name: "set_number_properties",
|
|
72
77
|
config: {
|
|
73
78
|
title: "Set Number Properties",
|
|
74
|
-
description: 'Update a phone number\'s properties: its inbound instruction (the system prompt for inbound calls), inbound voice gender, inbound language, nickname, whether calling is switched on at all (callingEnabled), and its display identity. For the display identity prefer `channel` ("imessage", "whatsapp", or "both") with `name`/`avatarUrl` — one call that keeps every channel\'s profile identical. The per-channel fields remain for when the profiles differ: firstName/lastName/avatarUrl for iMessage, whatsappName/whatsappAvatarUrl for WhatsApp-ready numbers. Provide at least one property, and don\'t mix `channel` with the per-channel fields.',
|
|
79
|
+
description: 'Update a phone number\'s properties: its inbound instruction (the system prompt for inbound calls), inbound voice gender, inbound language, nickname, whether calling is switched on at all (callingEnabled), a phone to forward inbound calls to instead of the AI voice agent (forwardTo), and its display identity. For the display identity prefer `channel` ("imessage", "whatsapp", or "both") with `name`/`avatarUrl` — one call that keeps every channel\'s profile identical. The per-channel fields remain for when the profiles differ: firstName/lastName/avatarUrl for iMessage, whatsappName/whatsappAvatarUrl for WhatsApp-ready numbers. Provide at least one property, and don\'t mix `channel` with the per-channel fields.',
|
|
75
80
|
inputSchema,
|
|
76
81
|
outputSchema: { number: phoneNumberSchema },
|
|
77
82
|
annotations: { openWorldHint: true },
|
|
@@ -97,6 +102,7 @@ export const setNumberPropertiesTool = {
|
|
|
97
102
|
...(args.callingEnabled !== undefined
|
|
98
103
|
? { callingEnabled: args.callingEnabled }
|
|
99
104
|
: {}),
|
|
105
|
+
...(args.forwardTo !== undefined ? { forwardTo: args.forwardTo } : {}),
|
|
100
106
|
...(args.whatsappAvatarUrl !== undefined
|
|
101
107
|
? { whatsappAvatar: args.whatsappAvatarUrl }
|
|
102
108
|
: {}),
|
package/package.json
CHANGED
package/skills.tar.gz
CHANGED
|
Binary file
|