@getdial/cli 0.22.0 → 0.23.1

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
@@ -110,14 +110,33 @@ number
110
110
  .option("--inbound-instruction <text>", "new system prompt for inbound calls to this number")
111
111
  .option("--inbound-voice-gender <male|female>", 'voice gender for inbound calls; pass "" to clear (reverts to the default, female)')
112
112
  .option("--nickname <text>", 'human-readable label for the number, e.g. "Support line"; pass "" to clear')
113
+ .option("--max-call-duration <seconds>", "call duration cap for this number, in seconds, applied as a hard ceiling to both inbound and outbound calls (the smallest of the per-number, account, and per-call caps wins)", (v) => {
114
+ const n = parseInt(v, 10);
115
+ if (!Number.isInteger(n) || n <= 0 || String(n) !== v.trim()) {
116
+ console.error(`error: --max-call-duration must be a positive integer (seconds), got: ${v}`);
117
+ process.exit(2);
118
+ }
119
+ return n;
120
+ })
121
+ .option("--clear-max-call-duration", "remove the per-number call duration cap")
113
122
  .option("--json", "machine-readable output")
114
- .action(async (numberArg, opts) => process.exit(await runNumberSet({
115
- number: numberArg,
116
- inboundInstruction: opts.inboundInstruction,
117
- inboundVoiceGender: opts.inboundVoiceGender,
118
- nickname: opts.nickname,
119
- json: !!opts.json,
120
- })));
123
+ .action(async (numberArg, opts) => {
124
+ let maxCallDurationSeconds;
125
+ if (opts.clearMaxCallDuration) {
126
+ maxCallDurationSeconds = null;
127
+ }
128
+ else if (opts.maxCallDuration !== undefined) {
129
+ maxCallDurationSeconds = opts.maxCallDuration;
130
+ }
131
+ process.exit(await runNumberSet({
132
+ number: numberArg,
133
+ inboundInstruction: opts.inboundInstruction,
134
+ inboundVoiceGender: opts.inboundVoiceGender,
135
+ nickname: opts.nickname,
136
+ maxCallDurationSeconds,
137
+ json: !!opts.json,
138
+ }));
139
+ });
121
140
  const message = program
122
141
  .command("message")
123
142
  .description("Send an SMS. POST /api/v1/messages.")
@@ -160,6 +179,14 @@ const call = program
160
179
  .option("--transfer-to <e164>", "forward-to number, E.164: the agent waits for a real human (riding out hold/IVR) then cold-transfers the call here")
161
180
  .option("--idempotency-key <key>", "unique key (e.g. a UUID) making the placement idempotent: re-running with the same key returns the already-placed call instead of dialing again")
162
181
  .option("--from-number-id <id>", "phoneNumberId to call from (defaults to onboard's number)")
182
+ .option("--max-call-duration <seconds>", "maximum call duration cap (seconds); call is terminated when this limit is reached", (v) => {
183
+ const n = parseInt(v, 10);
184
+ if (!Number.isInteger(n) || n <= 0 || String(n) !== v.trim()) {
185
+ console.error(`error: --max-call-duration must be a positive integer (seconds), got: ${v}`);
186
+ process.exit(2);
187
+ }
188
+ return n;
189
+ })
163
190
  .option("--json", "machine-readable output")
164
191
  .action(async (opts) => {
165
192
  if (!opts.to || !opts.outboundInstruction) {
@@ -174,6 +201,7 @@ const call = program
174
201
  transferTo: opts.transferTo,
175
202
  idempotencyKey: opts.idempotencyKey,
176
203
  fromNumberId: opts.fromNumberId,
204
+ maxCallDurationSeconds: opts.maxCallDuration,
177
205
  json: !!opts.json,
178
206
  }));
179
207
  });
@@ -11,6 +11,7 @@ export async function runCallSend(opts) {
11
11
  transferTo: opts.transferTo,
12
12
  idempotencyKey: opts.idempotencyKey,
13
13
  fromNumberId: opts.fromNumberId,
14
+ maxCallDurationSeconds: opts.maxCallDurationSeconds,
14
15
  });
15
16
  const waitCmd = `dial wait-for call.ended -f callId=${c.id} --json`;
16
17
  const followUpQuestion = "Want me to wait for the call to finish and report back (duration, final status, transcript)?";
@@ -8,6 +8,7 @@ export async function runNumberSet(opts) {
8
8
  inboundInstruction: opts.inboundInstruction,
9
9
  ...(opts.inboundVoiceGender !== undefined ? { inboundVoiceGender: opts.inboundVoiceGender } : {}),
10
10
  ...(opts.nickname !== undefined ? { nickname: opts.nickname } : {}),
11
+ ...(opts.maxCallDurationSeconds !== undefined ? { maxCallDurationSeconds: opts.maxCallDurationSeconds } : {}),
11
12
  });
12
13
  if (opts.json) {
13
14
  console.log(JSON.stringify({ ok: true, number: n }));
@@ -12,6 +12,7 @@ export async function placeCall(opts) {
12
12
  // Omitted → the server uses the default voice gender (female).
13
13
  ...(opts.voiceGender ? { voiceGender: opts.voiceGender } : {}),
14
14
  ...(opts.transferTo ? { transferTo: opts.transferTo } : {}),
15
+ ...(opts.maxCallDurationSeconds !== undefined ? { maxCallDurationSeconds: opts.maxCallDurationSeconds } : {}),
15
16
  }, auth.apiKey, opts.idempotencyKey ? { "idempotency-key": opts.idempotencyKey } : undefined);
16
17
  if (!res.ok)
17
18
  throw new DialError("call_failed", res.error, res.status);
@@ -31,8 +31,10 @@ export async function setNumberProperties(opts) {
31
31
  body.inboundVoiceGender = opts.inboundVoiceGender || null;
32
32
  if (opts.nickname !== undefined)
33
33
  body.nickname = opts.nickname;
34
+ if (opts.maxCallDurationSeconds !== undefined)
35
+ body.maxCallDurationSeconds = opts.maxCallDurationSeconds;
34
36
  if (Object.keys(body).length === 0) {
35
- throw new DialError("bad_request", "Provide at least one property to update (inboundInstruction, inboundVoiceGender, or nickname).");
37
+ throw new DialError("bad_request", "Provide at least one property to update (inboundInstruction, inboundVoiceGender, nickname, or maxCallDurationSeconds).");
36
38
  }
37
39
  const auth = requireAuth();
38
40
  // The REST API keys numbers by id; the CLI/tool takes the E.164 number for ergonomics,
@@ -10,6 +10,7 @@ const inputSchema = {
10
10
  transferTo: z.string().optional().describe("Forward-to number, E.164: the agent waits for a real human (riding out hold/IVR) then cold-transfers the call here. Must differ from `to` and the from number."),
11
11
  idempotencyKey: z.string().optional().describe("Unique key (e.g. a UUID) making the placement idempotent: retrying with the same key returns the already-placed call instead of dialing again"),
12
12
  fromNumberId: z.string().optional().describe("Number id to call from; defaults to your primary number"),
13
+ maxCallDurationSeconds: z.number().int().positive().optional().describe("Maximum call duration cap (seconds); the call is terminated when this limit is reached"),
13
14
  };
14
15
  export const placeCallTool = {
15
16
  name: "place_call",
@@ -30,6 +31,7 @@ export const placeCallTool = {
30
31
  transferTo: args.transferTo,
31
32
  idempotencyKey: args.idempotencyKey,
32
33
  fromNumberId: args.fromNumberId,
34
+ maxCallDurationSeconds: args.maxCallDurationSeconds,
33
35
  });
34
36
  return jsonResult({
35
37
  call,
@@ -7,6 +7,7 @@ const inputSchema = {
7
7
  inboundInstruction: z.string().min(1).optional().describe("New system prompt for inbound calls to this number"),
8
8
  inboundVoiceGender: z.enum(["male", "female"]).optional().describe("Voice gender for inbound calls to this number; the default is female"),
9
9
  nickname: z.string().max(100).optional().describe('Human-readable label for the number, e.g. "Support line". Pass an empty string to clear it.'),
10
+ maxCallDurationSeconds: z.number().int().positive().nullable().optional().describe("Call duration cap for this number, in seconds, applied as a hard ceiling to both inbound and outbound calls (the smallest of the per-number, account, and per-call caps wins). Pass null to clear the cap; omit to leave it unchanged."),
10
11
  };
11
12
  export const setNumberPropertiesTool = {
12
13
  name: "set_number_properties",
@@ -23,6 +24,7 @@ export const setNumberPropertiesTool = {
23
24
  inboundInstruction: args.inboundInstruction,
24
25
  ...(args.inboundVoiceGender !== undefined ? { inboundVoiceGender: args.inboundVoiceGender } : {}),
25
26
  ...(args.nickname !== undefined ? { nickname: args.nickname } : {}),
27
+ ...(args.maxCallDurationSeconds !== undefined ? { maxCallDurationSeconds: args.maxCallDurationSeconds } : {}),
26
28
  }),
27
29
  }),
28
30
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getdial/cli",
3
- "version": "0.22.0",
3
+ "version": "0.23.1",
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