@getdial/cli 0.42.0 → 0.43.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/commands/call/get.js +46 -1
- package/dist/mcp/schemas.js +18 -0
- package/dist/mcp/tools/get-call.js +3 -1
- package/package.json +1 -1
- package/skills.tar.gz +0 -0
|
@@ -1,6 +1,48 @@
|
|
|
1
1
|
import { getCall } from "../../lib/ops/calls.js";
|
|
2
2
|
import { isDialError } from "../../lib/ops/errors.js";
|
|
3
3
|
import { printDialError } from "../../lib/cli-error.js";
|
|
4
|
+
/**
|
|
5
|
+
* A silence long enough to call out. Three seconds is past a natural beat between
|
|
6
|
+
* speakers but short enough to catch an agent thinking too long, which is what
|
|
7
|
+
* anyone reading a transcript for pacing is looking for.
|
|
8
|
+
*/
|
|
9
|
+
const NOTABLE_PAUSE_MS = 3000;
|
|
10
|
+
/**
|
|
11
|
+
* Plain words for who spoke. "person" rather than "caller" because on an outbound
|
|
12
|
+
* call the human is the callee; "transferred" for the third party a call was
|
|
13
|
+
* handed off to, who is a different human from the one who was on the line first.
|
|
14
|
+
*/
|
|
15
|
+
function speakerLabel(speaker) {
|
|
16
|
+
if (speaker === "agent")
|
|
17
|
+
return "agent";
|
|
18
|
+
return speaker === "transfer_target" ? "transferred" : "person";
|
|
19
|
+
}
|
|
20
|
+
/** ms into the call's audio → "m:ss.t", the stamp each transcript line carries. */
|
|
21
|
+
function formatOffset(ms) {
|
|
22
|
+
const minutes = Math.floor(ms / 60000);
|
|
23
|
+
const seconds = Math.floor((ms % 60000) / 1000);
|
|
24
|
+
const tenths = Math.floor((ms % 1000) / 100);
|
|
25
|
+
return `${minutes}:${String(seconds).padStart(2, "0")}.${tenths}`;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Print the transcript with each turn stamped, and call out the long silences
|
|
29
|
+
* between them. The flat string cannot show a pause, which is the whole reason
|
|
30
|
+
* the timed turns exist.
|
|
31
|
+
*/
|
|
32
|
+
function printTimedTranscript(turns) {
|
|
33
|
+
console.log(`transcript:`);
|
|
34
|
+
turns.forEach((turn, i) => {
|
|
35
|
+
const previous = turns[i - 1];
|
|
36
|
+
if (previous) {
|
|
37
|
+
const pauseMs = turn.startMs - previous.endMs;
|
|
38
|
+
if (pauseMs >= NOTABLE_PAUSE_MS) {
|
|
39
|
+
console.log(` ... ${(pauseMs / 1000).toFixed(1)}s pause`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const speaker = speakerLabel(turn.speaker).padEnd(12);
|
|
43
|
+
console.log(` ${formatOffset(turn.startMs).padStart(7)} ${speaker}${turn.text}`);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
4
46
|
export async function runCallGet(opts) {
|
|
5
47
|
try {
|
|
6
48
|
const c = await getCall(opts.callId);
|
|
@@ -19,7 +61,10 @@ export async function runCallGet(opts) {
|
|
|
19
61
|
console.log(`instruction:`);
|
|
20
62
|
console.log(c.instruction);
|
|
21
63
|
}
|
|
22
|
-
if (c.
|
|
64
|
+
if (c.transcriptTurns?.length) {
|
|
65
|
+
printTimedTranscript(c.transcriptTurns);
|
|
66
|
+
}
|
|
67
|
+
else if (c.transcript) {
|
|
23
68
|
console.log(`transcript:`);
|
|
24
69
|
console.log(c.transcript);
|
|
25
70
|
}
|
package/dist/mcp/schemas.js
CHANGED
|
@@ -147,6 +147,17 @@ export const messageSchema = z
|
|
|
147
147
|
createdAt: z.string().optional(),
|
|
148
148
|
})
|
|
149
149
|
.passthrough();
|
|
150
|
+
export const transcriptTurnSchema = z
|
|
151
|
+
.object({
|
|
152
|
+
speaker: z
|
|
153
|
+
.enum(["agent", "user", "transfer_target"])
|
|
154
|
+
.describe("`agent` is Dial's AI voice agent, `user` the human on the other end, and " +
|
|
155
|
+
"`transfer_target` the human the call was cold-transferred to"),
|
|
156
|
+
text: z.string().describe("What was said during the turn"),
|
|
157
|
+
startMs: z.number().describe("Approximate ms into the call's audio at which the turn began"),
|
|
158
|
+
endMs: z.number().describe("Approximate ms into the call's audio at which the turn ended"),
|
|
159
|
+
})
|
|
160
|
+
.describe("One uninterrupted stretch of speech by one party, placed in time");
|
|
150
161
|
export const callSchema = z
|
|
151
162
|
.object({
|
|
152
163
|
id: z.string(),
|
|
@@ -156,6 +167,13 @@ export const callSchema = z
|
|
|
156
167
|
status: statusSchema,
|
|
157
168
|
duration: z.number().nullish(),
|
|
158
169
|
transcript: z.string().nullish(),
|
|
170
|
+
transcriptTurns: transcriptTurnSchema
|
|
171
|
+
.array()
|
|
172
|
+
.nullish()
|
|
173
|
+
.describe("The same conversation as `transcript`, split into timed turns and ordered by " +
|
|
174
|
+
"startMs. Use it to measure pacing: the pause before a turn is its startMs minus " +
|
|
175
|
+
"the previous turn's endMs. Null when the call has no transcript, or when the " +
|
|
176
|
+
"call's turn timing was not recorded."),
|
|
159
177
|
instruction: z.string().nullable().optional(),
|
|
160
178
|
createdAt: z.string().optional(),
|
|
161
179
|
})
|
|
@@ -9,7 +9,9 @@ export const getCallTool = {
|
|
|
9
9
|
name: "get_call",
|
|
10
10
|
config: {
|
|
11
11
|
title: "Get Call",
|
|
12
|
-
description: "Fetch a single call by id — status, duration, and transcript when available."
|
|
12
|
+
description: "Fetch a single call by id — status, duration, and transcript when available. " +
|
|
13
|
+
"The transcript comes back twice: `transcript` as flat text, and `transcriptTurns` " +
|
|
14
|
+
"as timed turns for analysing pacing and spotting long pauses.",
|
|
13
15
|
inputSchema,
|
|
14
16
|
outputSchema: { call: callSchema },
|
|
15
17
|
annotations: { readOnlyHint: true, openWorldHint: true },
|
package/package.json
CHANGED
package/skills.tar.gz
CHANGED
|
Binary file
|