convoai 1.6.2 → 1.7.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/src/api/calls.d.ts +33 -36
- package/dist/src/api/calls.js +12 -7
- package/dist/src/api/calls.js.map +1 -1
- package/dist/src/api/numbers.d.ts +63 -0
- package/dist/src/api/numbers.js +27 -0
- package/dist/src/api/numbers.js.map +1 -0
- package/dist/src/commands/call/hangup.js +9 -16
- package/dist/src/commands/call/hangup.js.map +1 -1
- package/dist/src/commands/call/initiate.js +69 -112
- package/dist/src/commands/call/initiate.js.map +1 -1
- package/dist/src/commands/call/status.js +14 -32
- package/dist/src/commands/call/status.js.map +1 -1
- package/dist/src/commands/completion.js +2 -1
- package/dist/src/commands/completion.js.map +1 -1
- package/dist/src/commands/go.js +64 -0
- package/dist/src/commands/go.js.map +1 -1
- package/dist/src/commands/phone/_helpers.d.ts +12 -0
- package/dist/src/commands/phone/_helpers.js +98 -0
- package/dist/src/commands/phone/_helpers.js.map +1 -0
- package/dist/src/commands/phone/get.d.ts +2 -0
- package/dist/src/commands/phone/get.js +34 -0
- package/dist/src/commands/phone/get.js.map +1 -0
- package/dist/src/commands/phone/hangup.d.ts +2 -0
- package/dist/src/commands/phone/hangup.js +20 -0
- package/dist/src/commands/phone/hangup.js.map +1 -0
- package/dist/src/commands/phone/history.d.ts +2 -0
- package/dist/src/commands/phone/history.js +56 -0
- package/dist/src/commands/phone/history.js.map +1 -0
- package/dist/src/commands/phone/import.d.ts +2 -0
- package/dist/src/commands/phone/import.js +88 -0
- package/dist/src/commands/phone/import.js.map +1 -0
- package/dist/src/commands/phone/numbers.d.ts +2 -0
- package/dist/src/commands/phone/numbers.js +34 -0
- package/dist/src/commands/phone/numbers.js.map +1 -0
- package/dist/src/commands/phone/remove.d.ts +2 -0
- package/dist/src/commands/phone/remove.js +31 -0
- package/dist/src/commands/phone/remove.js.map +1 -0
- package/dist/src/commands/phone/send.d.ts +2 -0
- package/dist/src/commands/phone/send.js +236 -0
- package/dist/src/commands/phone/send.js.map +1 -0
- package/dist/src/commands/phone/status.d.ts +2 -0
- package/dist/src/commands/phone/status.js +34 -0
- package/dist/src/commands/phone/status.js.map +1 -0
- package/dist/src/commands/phone/update.d.ts +2 -0
- package/dist/src/commands/phone/update.js +41 -0
- package/dist/src/commands/phone/update.js.map +1 -0
- package/dist/src/commands/quickstart.js +85 -19
- package/dist/src/commands/quickstart.js.map +1 -1
- package/dist/src/index.js +40 -3
- package/dist/src/index.js.map +1 -1
- package/package.json +1 -1
package/dist/src/api/calls.d.ts
CHANGED
|
@@ -1,53 +1,50 @@
|
|
|
1
1
|
import type { AxiosInstance } from 'axios';
|
|
2
|
-
export interface
|
|
2
|
+
export interface SendCallRequest {
|
|
3
3
|
name: string;
|
|
4
|
+
sip: {
|
|
5
|
+
to_number: string;
|
|
6
|
+
from_number: string;
|
|
7
|
+
rtc_uid: string;
|
|
8
|
+
rtc_token: string;
|
|
9
|
+
};
|
|
4
10
|
properties: {
|
|
5
11
|
channel: string;
|
|
6
|
-
|
|
7
|
-
agent_rtc_uid
|
|
12
|
+
token: string;
|
|
13
|
+
agent_rtc_uid: string;
|
|
14
|
+
remote_rtc_uids: string[];
|
|
8
15
|
idle_timeout?: number;
|
|
9
|
-
llm?:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
system_messages?: Array<{
|
|
13
|
-
role: string;
|
|
14
|
-
content: string;
|
|
15
|
-
}>;
|
|
16
|
-
greeting_message?: string;
|
|
17
|
-
params?: {
|
|
18
|
-
model?: string;
|
|
19
|
-
max_tokens?: number;
|
|
20
|
-
temperature?: number;
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
tts?: {
|
|
24
|
-
vendor?: string;
|
|
25
|
-
params?: Record<string, unknown>;
|
|
26
|
-
};
|
|
27
|
-
asr?: {
|
|
28
|
-
language?: string;
|
|
29
|
-
vendor?: string;
|
|
30
|
-
};
|
|
16
|
+
llm?: Record<string, unknown>;
|
|
17
|
+
tts?: Record<string, unknown>;
|
|
18
|
+
asr?: Record<string, unknown>;
|
|
31
19
|
};
|
|
32
20
|
}
|
|
21
|
+
export interface SendCallResponse {
|
|
22
|
+
agent_id: string;
|
|
23
|
+
}
|
|
33
24
|
export interface CallStatusResponse {
|
|
34
25
|
agent_id: string;
|
|
35
26
|
status: string;
|
|
36
|
-
direction: 'inbound' | 'outbound';
|
|
37
|
-
phone_number?: string;
|
|
38
27
|
start_ts: number;
|
|
39
|
-
|
|
28
|
+
stop_ts?: number;
|
|
29
|
+
channel?: string;
|
|
30
|
+
message?: string;
|
|
40
31
|
}
|
|
41
32
|
export declare class CallAPI {
|
|
42
33
|
private readonly client;
|
|
43
34
|
constructor(client: AxiosInstance);
|
|
44
|
-
/** Initiate an outbound phone call. */
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
status: string;
|
|
48
|
-
}>;
|
|
49
|
-
/** Hang up an active call. */
|
|
50
|
-
hangup(agentId: string): Promise<void>;
|
|
51
|
-
/** Get the current status of a call. */
|
|
35
|
+
/** Initiate an outbound phone call via SIP. */
|
|
36
|
+
send(req: SendCallRequest): Promise<SendCallResponse>;
|
|
37
|
+
/** Get the current status of a call (reuses agent status endpoint). */
|
|
52
38
|
status(agentId: string): Promise<CallStatusResponse>;
|
|
39
|
+
/** Hang up an active call (reuses agent leave endpoint). */
|
|
40
|
+
hangup(agentId: string): Promise<void>;
|
|
41
|
+
/** List calls (reuses agent list, caller can filter). */
|
|
42
|
+
list(params?: {
|
|
43
|
+
limit?: number;
|
|
44
|
+
state?: number;
|
|
45
|
+
}): Promise<{
|
|
46
|
+
data: {
|
|
47
|
+
list: CallStatusResponse[];
|
|
48
|
+
};
|
|
49
|
+
}>;
|
|
53
50
|
}
|
package/dist/src/api/calls.js
CHANGED
|
@@ -4,18 +4,23 @@ export class CallAPI {
|
|
|
4
4
|
constructor(client) {
|
|
5
5
|
this.client = client;
|
|
6
6
|
}
|
|
7
|
-
/** Initiate an outbound phone call. */
|
|
8
|
-
async
|
|
7
|
+
/** Initiate an outbound phone call via SIP. */
|
|
8
|
+
async send(req) {
|
|
9
9
|
const { data } = await this.client.post('/call', req);
|
|
10
10
|
return data;
|
|
11
11
|
}
|
|
12
|
-
/**
|
|
12
|
+
/** Get the current status of a call (reuses agent status endpoint). */
|
|
13
|
+
async status(agentId) {
|
|
14
|
+
const { data } = await this.client.get(`/agents/${agentId}`);
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
/** Hang up an active call (reuses agent leave endpoint). */
|
|
13
18
|
async hangup(agentId) {
|
|
14
|
-
await this.client.post(`/
|
|
19
|
+
await this.client.post(`/agents/${agentId}/leave`);
|
|
15
20
|
}
|
|
16
|
-
/**
|
|
17
|
-
async
|
|
18
|
-
const { data } = await this.client.get(
|
|
21
|
+
/** List calls (reuses agent list, caller can filter). */
|
|
22
|
+
async list(params) {
|
|
23
|
+
const { data } = await this.client.get('/agents', { params });
|
|
19
24
|
return data;
|
|
20
25
|
}
|
|
21
26
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calls.js","sourceRoot":"","sources":["../../../src/api/calls.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"calls.js","sourceRoot":"","sources":["../../../src/api/calls.ts"],"names":[],"mappings":"AAsCA,+EAA+E;AAE/E,MAAM,OAAO,OAAO;IACW;IAA7B,YAA6B,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;IAAG,CAAC;IAEtD,+CAA+C;IAC/C,KAAK,CAAC,IAAI,CAAC,GAAoB;QAC7B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAmB,OAAO,EAAE,GAAG,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uEAAuE;IACvE,KAAK,CAAC,MAAM,CAAC,OAAe;QAC1B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAqB,WAAW,OAAO,EAAE,CAAC,CAAC;QACjF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,4DAA4D;IAC5D,KAAK,CAAC,MAAM,CAAC,OAAe;QAC1B,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,OAAO,QAAQ,CAAC,CAAC;IACrD,CAAC;IAED,yDAAyD;IACzD,KAAK,CAAC,IAAI,CAAC,MAA2C;QACpD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { AxiosInstance } from 'axios';
|
|
2
|
+
export interface PhoneNumber {
|
|
3
|
+
phone_number: string;
|
|
4
|
+
label: string;
|
|
5
|
+
provider: 'byo' | 'twilio';
|
|
6
|
+
inbound: boolean;
|
|
7
|
+
outbound: boolean;
|
|
8
|
+
associated_pipeline: {
|
|
9
|
+
pipeline_id: string;
|
|
10
|
+
pipeline_name: string;
|
|
11
|
+
} | null;
|
|
12
|
+
inbound_config: {
|
|
13
|
+
allowed_addresses?: string[];
|
|
14
|
+
} | null;
|
|
15
|
+
outbound_config: {
|
|
16
|
+
address?: string;
|
|
17
|
+
transport?: 'tls' | 'tcp' | 'udp';
|
|
18
|
+
prefix?: string;
|
|
19
|
+
user?: string;
|
|
20
|
+
password?: string;
|
|
21
|
+
} | null;
|
|
22
|
+
}
|
|
23
|
+
export interface ImportNumberRequest {
|
|
24
|
+
provider: 'byo' | 'twilio';
|
|
25
|
+
phone_number: string;
|
|
26
|
+
label: string;
|
|
27
|
+
inbound?: boolean;
|
|
28
|
+
outbound?: boolean;
|
|
29
|
+
inbound_config?: {
|
|
30
|
+
allowed_addresses?: string[];
|
|
31
|
+
};
|
|
32
|
+
outbound_config: {
|
|
33
|
+
address: string;
|
|
34
|
+
transport: 'tls' | 'tcp' | 'udp';
|
|
35
|
+
prefix?: string;
|
|
36
|
+
user?: string;
|
|
37
|
+
password?: string;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export interface UpdateNumberRequest {
|
|
41
|
+
label?: string;
|
|
42
|
+
inbound?: boolean;
|
|
43
|
+
outbound?: boolean;
|
|
44
|
+
inbound_config?: {
|
|
45
|
+
allowed_addresses?: string[];
|
|
46
|
+
};
|
|
47
|
+
outbound_config?: {
|
|
48
|
+
address?: string;
|
|
49
|
+
transport?: 'tls' | 'tcp' | 'udp';
|
|
50
|
+
prefix?: string;
|
|
51
|
+
user?: string;
|
|
52
|
+
password?: string;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export declare class NumberAPI {
|
|
56
|
+
private readonly client;
|
|
57
|
+
constructor(client: AxiosInstance);
|
|
58
|
+
list(): Promise<PhoneNumber[]>;
|
|
59
|
+
import(req: ImportNumberRequest): Promise<PhoneNumber>;
|
|
60
|
+
get(phoneNumber: string): Promise<PhoneNumber>;
|
|
61
|
+
update(phoneNumber: string, req: UpdateNumberRequest): Promise<PhoneNumber>;
|
|
62
|
+
delete(phoneNumber: string): Promise<void>;
|
|
63
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// ─── Number API ─────────────────────────────────────────────────────────────
|
|
2
|
+
export class NumberAPI {
|
|
3
|
+
client;
|
|
4
|
+
constructor(client) {
|
|
5
|
+
this.client = client;
|
|
6
|
+
}
|
|
7
|
+
async list() {
|
|
8
|
+
const { data } = await this.client.get('/phone-numbers');
|
|
9
|
+
return data;
|
|
10
|
+
}
|
|
11
|
+
async import(req) {
|
|
12
|
+
const { data } = await this.client.post('/phone-numbers', req);
|
|
13
|
+
return data;
|
|
14
|
+
}
|
|
15
|
+
async get(phoneNumber) {
|
|
16
|
+
const { data } = await this.client.get(`/phone-numbers/${encodeURIComponent(phoneNumber)}`);
|
|
17
|
+
return data;
|
|
18
|
+
}
|
|
19
|
+
async update(phoneNumber, req) {
|
|
20
|
+
const { data } = await this.client.patch(`/phone-numbers/${encodeURIComponent(phoneNumber)}`, req);
|
|
21
|
+
return data;
|
|
22
|
+
}
|
|
23
|
+
async delete(phoneNumber) {
|
|
24
|
+
await this.client.delete(`/phone-numbers/${encodeURIComponent(phoneNumber)}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=numbers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"numbers.js","sourceRoot":"","sources":["../../../src/api/numbers.ts"],"names":[],"mappings":"AAoDA,+EAA+E;AAE/E,MAAM,OAAO,SAAS;IACS;IAA7B,YAA6B,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;IAAG,CAAC;IAEtD,KAAK,CAAC,IAAI;QACR,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAgB,gBAAgB,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAwB;QACnC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAc,gBAAgB,EAAE,GAAG,CAAC,CAAC;QAC5E,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,WAAmB;QAC3B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAc,kBAAkB,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACzG,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,WAAmB,EAAE,GAAwB;QACxD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAc,kBAAkB,kBAAkB,CAAC,WAAW,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAChH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,WAAmB;QAC9B,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IAChF,CAAC;CACF"}
|
|
@@ -1,28 +1,21 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { printSuccess
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { getCallAPI } from '../phone/_helpers.js';
|
|
3
|
+
import { printSuccess } from '../../ui/output.js';
|
|
4
4
|
import { handleError } from '../../utils/errors.js';
|
|
5
|
-
import { shortId } from '../../utils/hints.js';
|
|
6
|
-
// ─── Command Registration ──────────────────────────────────────────────────
|
|
7
5
|
export function registerCallHangup(program) {
|
|
8
6
|
program
|
|
9
7
|
.command('hangup <agent-id>')
|
|
10
|
-
.description('
|
|
11
|
-
.option('--profile <name>', 'Config profile
|
|
12
|
-
.option('--json', 'Output result as JSON')
|
|
8
|
+
.description('(deprecated) Use "phone hangup" instead')
|
|
9
|
+
.option('--profile <name>', 'Config profile')
|
|
13
10
|
.action(async (agentId, opts) => {
|
|
11
|
+
console.log(chalk.yellow(' ⚠ "call hangup" is deprecated. Use "convoai phone hangup" instead.'));
|
|
14
12
|
try {
|
|
15
13
|
const api = getCallAPI(opts.profile);
|
|
16
|
-
await
|
|
17
|
-
|
|
18
|
-
console.log(JSON.stringify({ agent_id: agentId, status: 'HUNG_UP' }, null, 2));
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
printSuccess(`Call ${shortId(agentId)} hung up.`);
|
|
22
|
-
printHint('Run `convoai call initiate --phone <number>` to start a new call.');
|
|
14
|
+
await api.hangup(agentId);
|
|
15
|
+
printSuccess('Call ended');
|
|
23
16
|
}
|
|
24
17
|
catch (error) {
|
|
25
|
-
handleError(error
|
|
18
|
+
handleError(error);
|
|
26
19
|
}
|
|
27
20
|
});
|
|
28
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hangup.js","sourceRoot":"","sources":["../../../../src/commands/call/hangup.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"hangup.js","sourceRoot":"","sources":["../../../../src/commands/call/hangup.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IACjD,OAAO;SACJ,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,yCAAyC,CAAC;SACtD,MAAM,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;SAC5C,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,IAAI,EAAE,EAAE;QACtC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,sEAAsE,CAAC,CAAC,CAAC;QAClG,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrC,MAAM,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC1B,YAAY,CAAC,YAAY,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,WAAW,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -1,133 +1,90 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { getCallAPI } from '
|
|
3
|
-
import {
|
|
4
|
-
import { printKeyValue } from '../../ui/table.js';
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { getCallAPI, getNumberAPI, getConfig, validateE164, pickOutboundNumber } from '../phone/_helpers.js';
|
|
3
|
+
import { generateRtcToken } from '../../utils/token.js';
|
|
5
4
|
import { printSuccess, printError, printHint } from '../../ui/output.js';
|
|
5
|
+
import { withSpinner } from '../../ui/spinner.js';
|
|
6
6
|
import { handleError } from '../../utils/errors.js';
|
|
7
|
-
import {
|
|
8
|
-
// ─── Name Generation ───────────────────────────────────────────────────────
|
|
9
|
-
function generateCallName() {
|
|
10
|
-
const timestamp = Date.now();
|
|
11
|
-
const random = Math.random().toString(36).substring(2, 6);
|
|
12
|
-
return `call-${timestamp}-${random}`;
|
|
13
|
-
}
|
|
14
|
-
function generateChannelName() {
|
|
15
|
-
const timestamp = Date.now();
|
|
16
|
-
const random = Math.random().toString(36).substring(2, 6);
|
|
17
|
-
return `call-ch-${timestamp}-${random}`;
|
|
18
|
-
}
|
|
19
|
-
// ─── Interactive Prompts ───────────────────────────────────────────────────
|
|
20
|
-
async function promptForPhone() {
|
|
21
|
-
const { default: inquirer } = await import('inquirer');
|
|
22
|
-
const { phone } = await inquirer.prompt([
|
|
23
|
-
{
|
|
24
|
-
type: 'input',
|
|
25
|
-
name: 'phone',
|
|
26
|
-
message: 'Phone number (E.164 format, e.g. +15551234567):',
|
|
27
|
-
},
|
|
28
|
-
]);
|
|
29
|
-
return phone;
|
|
30
|
-
}
|
|
31
|
-
// ─── Request Builder ───────────────────────────────────────────────────────
|
|
32
|
-
function buildRequest(opts) {
|
|
33
|
-
const config = resolveConfig(opts.profile);
|
|
34
|
-
const properties = {
|
|
35
|
-
channel: opts.channel ?? generateChannelName(),
|
|
36
|
-
phone_number: opts.phone,
|
|
37
|
-
};
|
|
38
|
-
// Build LLM config from CLI flags and config defaults
|
|
39
|
-
const llm = {};
|
|
40
|
-
let hasLlm = false;
|
|
41
|
-
if (opts.model) {
|
|
42
|
-
llm.params = { model: opts.model };
|
|
43
|
-
hasLlm = true;
|
|
44
|
-
}
|
|
45
|
-
if (opts.systemMessage) {
|
|
46
|
-
llm.system_messages = [{ role: 'system', content: opts.systemMessage }];
|
|
47
|
-
hasLlm = true;
|
|
48
|
-
}
|
|
49
|
-
if (opts.greeting) {
|
|
50
|
-
llm.greeting_message = opts.greeting;
|
|
51
|
-
hasLlm = true;
|
|
52
|
-
}
|
|
53
|
-
// Apply config-level LLM defaults if present
|
|
54
|
-
if (config.llm) {
|
|
55
|
-
if (config.llm.url && !llm.params) {
|
|
56
|
-
llm.url = config.llm.url;
|
|
57
|
-
hasLlm = true;
|
|
58
|
-
}
|
|
59
|
-
if (config.llm.api_key) {
|
|
60
|
-
llm.api_key = config.llm.api_key;
|
|
61
|
-
hasLlm = true;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
if (hasLlm) {
|
|
65
|
-
properties.llm = llm;
|
|
66
|
-
}
|
|
67
|
-
// Apply TTS from config
|
|
68
|
-
if (config.tts) {
|
|
69
|
-
properties.tts = config.tts;
|
|
70
|
-
}
|
|
71
|
-
// Apply ASR from config
|
|
72
|
-
if (config.asr) {
|
|
73
|
-
properties.asr = config.asr;
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
name: generateCallName(),
|
|
77
|
-
properties,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
// ─── Command Registration ──────────────────────────────────────────────────
|
|
7
|
+
import { loadConfig } from '../../config/manager.js';
|
|
81
8
|
export function registerCallInitiate(program) {
|
|
82
9
|
program
|
|
83
10
|
.command('initiate')
|
|
84
|
-
.description('
|
|
85
|
-
.option('--phone <number>', 'Phone number
|
|
86
|
-
.option('
|
|
87
|
-
.option('--model <model>', 'LLM model
|
|
88
|
-
.option('--system-message <msg>', 'System prompt
|
|
89
|
-
.option('--greeting <msg>', 'Greeting message
|
|
90
|
-
.option('--profile <name>', 'Config profile
|
|
91
|
-
.option('--json', '
|
|
92
|
-
.option('--dry-run', '
|
|
11
|
+
.description('(deprecated) Use "phone send" instead')
|
|
12
|
+
.option('--phone <number>', 'Phone number (maps to --to)')
|
|
13
|
+
.option('--channel <name>', 'Channel name (ignored)')
|
|
14
|
+
.option('--model <model>', 'LLM model')
|
|
15
|
+
.option('--system-message <msg>', 'System prompt (maps to --task)')
|
|
16
|
+
.option('--greeting <msg>', 'Greeting message')
|
|
17
|
+
.option('--profile <name>', 'Config profile')
|
|
18
|
+
.option('--json', 'JSON output')
|
|
19
|
+
.option('--dry-run', 'Dry run')
|
|
93
20
|
.action(async (opts) => {
|
|
21
|
+
console.log(chalk.yellow(' ⚠ "call initiate" is deprecated. Use "convoai phone send" instead.'));
|
|
94
22
|
try {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
23
|
+
const config = getConfig(opts.profile);
|
|
24
|
+
const numberApi = getNumberAPI(opts.profile);
|
|
25
|
+
const callApi = getCallAPI(opts.profile);
|
|
26
|
+
// Map old flags to new
|
|
27
|
+
let toNumber = opts.phone;
|
|
28
|
+
const task = opts.systemMessage;
|
|
29
|
+
// If no phone flag, try interactive
|
|
30
|
+
if (!toNumber && process.stdin.isTTY) {
|
|
31
|
+
const { default: inquirer } = await import('inquirer');
|
|
32
|
+
const ans = await inquirer.prompt([{
|
|
33
|
+
type: 'input', name: 'to', message: 'To number (E.164):',
|
|
34
|
+
validate: (v) => /^\+[1-9]\d{1,14}$/.test(v.trim()) || 'Invalid E.164',
|
|
35
|
+
}]);
|
|
36
|
+
toNumber = ans.to;
|
|
37
|
+
}
|
|
38
|
+
if (!toNumber) {
|
|
39
|
+
printError('--phone is required.');
|
|
40
|
+
process.exit(1);
|
|
99
41
|
}
|
|
100
|
-
|
|
101
|
-
|
|
42
|
+
toNumber = validateE164(toNumber);
|
|
43
|
+
// Pick from number
|
|
44
|
+
const numbers = await numberApi.list();
|
|
45
|
+
if (numbers.length === 0) {
|
|
46
|
+
printError('No phone numbers. Run: convoai phone import');
|
|
102
47
|
process.exit(1);
|
|
103
48
|
}
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
49
|
+
const picked = await pickOutboundNumber(numbers);
|
|
50
|
+
const channelName = `call-${Date.now().toString(36)}`;
|
|
51
|
+
const configObj = loadConfig();
|
|
52
|
+
const appCert = process.env.AGORA_APP_CERTIFICATE ?? configObj.app_certificate;
|
|
53
|
+
const agentToken = await generateRtcToken(channelName, 0, 86400, config.app_id, appCert);
|
|
54
|
+
const sipToken = await generateRtcToken(channelName, 1, 86400, config.app_id, appCert);
|
|
55
|
+
if (!agentToken || !sipToken) {
|
|
56
|
+
printError('Token generation failed.');
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
const llm = { ...(config.llm ?? {}) };
|
|
60
|
+
if (task)
|
|
61
|
+
llm.system_messages = [{ role: 'system', content: task }];
|
|
62
|
+
if (opts.greeting)
|
|
63
|
+
llm.greeting_message = opts.greeting;
|
|
64
|
+
if (opts.model) {
|
|
65
|
+
if (!llm.params)
|
|
66
|
+
llm.params = {};
|
|
67
|
+
llm.params.model = opts.model;
|
|
68
|
+
}
|
|
69
|
+
const request = {
|
|
70
|
+
name: `call-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
|
|
71
|
+
sip: { to_number: toNumber, from_number: picked.phone_number, rtc_uid: '1', rtc_token: sipToken },
|
|
72
|
+
properties: {
|
|
73
|
+
channel: channelName, token: agentToken, agent_rtc_uid: '0', remote_rtc_uids: ['1'],
|
|
74
|
+
idle_timeout: 600, llm, tts: config.tts ?? {}, asr: config.asr ?? {},
|
|
75
|
+
},
|
|
76
|
+
};
|
|
113
77
|
if (opts.dryRun) {
|
|
114
78
|
console.log(JSON.stringify(request, null, 2));
|
|
115
79
|
return;
|
|
116
80
|
}
|
|
117
|
-
const
|
|
118
|
-
const result = await withSpinner('Initiating call...', () => api.initiate(request));
|
|
81
|
+
const result = await withSpinner('Initiating call...', () => callApi.send(request));
|
|
119
82
|
if (opts.json) {
|
|
120
83
|
console.log(JSON.stringify(result, null, 2));
|
|
121
84
|
return;
|
|
122
85
|
}
|
|
123
|
-
printSuccess(
|
|
124
|
-
|
|
125
|
-
['Agent ID', result.agent_id],
|
|
126
|
-
['Status', result.status],
|
|
127
|
-
['Phone', phone],
|
|
128
|
-
['Channel', request.properties.channel],
|
|
129
|
-
]);
|
|
130
|
-
printHint(`Run \`convoai call status ${shortId(result.agent_id)}\` to check call status.`);
|
|
86
|
+
printSuccess(`Call initiated (${result.agent_id})`);
|
|
87
|
+
printHint(`convoai phone status ${result.agent_id}`);
|
|
131
88
|
}
|
|
132
89
|
catch (error) {
|
|
133
90
|
handleError(error, { json: opts.json });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initiate.js","sourceRoot":"","sources":["../../../../src/commands/call/initiate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"initiate.js","sourceRoot":"","sources":["../../../../src/commands/call/initiate.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,46 +1,28 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { getCallAPI } from '../phone/_helpers.js';
|
|
3
3
|
import { printKeyValue } from '../../ui/table.js';
|
|
4
4
|
import { handleError } from '../../utils/errors.js';
|
|
5
|
-
// ─── Command Registration ──────────────────────────────────────────────────
|
|
6
5
|
export function registerCallStatus(program) {
|
|
7
6
|
program
|
|
8
7
|
.command('status <agent-id>')
|
|
9
|
-
.description('
|
|
10
|
-
.option('--profile <name>', 'Config profile
|
|
11
|
-
.option('--json', '
|
|
8
|
+
.description('(deprecated) Use "phone status" instead')
|
|
9
|
+
.option('--profile <name>', 'Config profile')
|
|
10
|
+
.option('--json', 'JSON output')
|
|
12
11
|
.action(async (agentId, opts) => {
|
|
12
|
+
console.log(chalk.yellow(' ⚠ "call status" is deprecated. Use "convoai phone status" instead.'));
|
|
13
13
|
try {
|
|
14
14
|
const api = getCallAPI(opts.profile);
|
|
15
|
-
const
|
|
15
|
+
const status = await api.status(agentId);
|
|
16
16
|
if (opts.json) {
|
|
17
|
-
console.log(JSON.stringify(
|
|
17
|
+
console.log(JSON.stringify(status, null, 2));
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
['
|
|
23
|
-
['
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
pairs.push(['Phone', result.phone_number]);
|
|
27
|
-
}
|
|
28
|
-
pairs.push(['Started', formatTimestamp(result.start_ts)]);
|
|
29
|
-
if (result.end_ts) {
|
|
30
|
-
pairs.push(['Ended', formatTimestamp(result.end_ts)]);
|
|
31
|
-
const duration = result.end_ts - result.start_ts;
|
|
32
|
-
if (duration >= 0) {
|
|
33
|
-
pairs.push(['Duration', formatDuration(duration)]);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
// Call is still active — show elapsed time
|
|
38
|
-
const elapsed = Math.floor(Date.now() / 1000) - result.start_ts;
|
|
39
|
-
if (elapsed >= 0) {
|
|
40
|
-
pairs.push(['Elapsed', formatDuration(elapsed)]);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
printKeyValue(pairs);
|
|
20
|
+
console.log('');
|
|
21
|
+
printKeyValue([
|
|
22
|
+
['Agent ID', status.agent_id],
|
|
23
|
+
['Status', status.status],
|
|
24
|
+
['Channel', status.channel ?? '-'],
|
|
25
|
+
]);
|
|
44
26
|
}
|
|
45
27
|
catch (error) {
|
|
46
28
|
handleError(error, { json: opts.json });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../../src/commands/call/status.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../../src/commands/call/status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IACjD,OAAO;SACJ,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,yCAAyC,CAAC;SACtD,MAAM,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;SAC5C,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC;SAC/B,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,IAAI,EAAE,EAAE;QACtC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,sEAAsE,CAAC,CAAC,CAAC;QAClG,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACzC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;gBAAC,OAAO;YAAC,CAAC;YACxE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,aAAa,CAAC;gBACZ,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC;gBAC7B,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC;gBACzB,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,IAAI,GAAG,CAAC;aACnC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,WAAW,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -4,8 +4,9 @@ import { join } from 'node:path';
|
|
|
4
4
|
import { printSuccess, printError, printHint } from '../ui/output.js';
|
|
5
5
|
import { handleError } from '../utils/errors.js';
|
|
6
6
|
// ─── Completion Data ──────────────────────────────────────────────────────
|
|
7
|
-
const TOP_LEVEL_COMMANDS = ['go', 'init', 'dev', 'quickstart', 'openclaw', 'auth', 'agent', 'call', 'config', 'preset', 'template', 'token', 'completion'];
|
|
7
|
+
const TOP_LEVEL_COMMANDS = ['go', 'init', 'dev', 'quickstart', 'openclaw', 'phone', 'auth', 'agent', 'call', 'config', 'preset', 'template', 'token', 'completion'];
|
|
8
8
|
const SUBCOMMANDS = {
|
|
9
|
+
phone: ['send', 'numbers', 'import', 'number', 'update', 'remove', 'hangup', 'status', 'history'],
|
|
9
10
|
agent: ['start', 'stop', 'status', 'list', 'update', 'speak', 'interrupt', 'history', 'turns', 'join', 'chat', 'panel'],
|
|
10
11
|
auth: ['login', 'logout', 'status'],
|
|
11
12
|
call: ['initiate', 'hangup', 'status'],
|