convoai 1.6.2 → 1.8.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.
Files changed (72) hide show
  1. package/README.md +38 -2
  2. package/dist/src/api/calls.d.ts +33 -36
  3. package/dist/src/api/calls.js +12 -7
  4. package/dist/src/api/calls.js.map +1 -1
  5. package/dist/src/api/numbers.d.ts +63 -0
  6. package/dist/src/api/numbers.js +27 -0
  7. package/dist/src/api/numbers.js.map +1 -0
  8. package/dist/src/api/types.d.ts +6 -0
  9. package/dist/src/commands/call/hangup.js +9 -16
  10. package/dist/src/commands/call/hangup.js.map +1 -1
  11. package/dist/src/commands/call/initiate.js +69 -112
  12. package/dist/src/commands/call/initiate.js.map +1 -1
  13. package/dist/src/commands/call/status.js +14 -32
  14. package/dist/src/commands/call/status.js.map +1 -1
  15. package/dist/src/commands/completion.js +2 -1
  16. package/dist/src/commands/completion.js.map +1 -1
  17. package/dist/src/commands/go.js +64 -0
  18. package/dist/src/commands/go.js.map +1 -1
  19. package/dist/src/commands/phone/_dashboard.d.ts +31 -0
  20. package/dist/src/commands/phone/_dashboard.js +127 -0
  21. package/dist/src/commands/phone/_dashboard.js.map +1 -0
  22. package/dist/src/commands/phone/_helpers.d.ts +30 -0
  23. package/dist/src/commands/phone/_helpers.js +133 -0
  24. package/dist/src/commands/phone/_helpers.js.map +1 -0
  25. package/dist/src/commands/phone/_modes/agent.d.ts +22 -0
  26. package/dist/src/commands/phone/_modes/agent.js +59 -0
  27. package/dist/src/commands/phone/_modes/agent.js.map +1 -0
  28. package/dist/src/commands/phone/_modes/free.d.ts +29 -0
  29. package/dist/src/commands/phone/_modes/free.js +44 -0
  30. package/dist/src/commands/phone/_modes/free.js.map +1 -0
  31. package/dist/src/commands/phone/_modes/translate.d.ts +30 -0
  32. package/dist/src/commands/phone/_modes/translate.js +89 -0
  33. package/dist/src/commands/phone/_modes/translate.js.map +1 -0
  34. package/dist/src/commands/phone/get.d.ts +2 -0
  35. package/dist/src/commands/phone/get.js +34 -0
  36. package/dist/src/commands/phone/get.js.map +1 -0
  37. package/dist/src/commands/phone/go.d.ts +2 -0
  38. package/dist/src/commands/phone/go.js +235 -0
  39. package/dist/src/commands/phone/go.js.map +1 -0
  40. package/dist/src/commands/phone/hangup.d.ts +2 -0
  41. package/dist/src/commands/phone/hangup.js +20 -0
  42. package/dist/src/commands/phone/hangup.js.map +1 -0
  43. package/dist/src/commands/phone/history.d.ts +2 -0
  44. package/dist/src/commands/phone/history.js +56 -0
  45. package/dist/src/commands/phone/history.js.map +1 -0
  46. package/dist/src/commands/phone/import.d.ts +2 -0
  47. package/dist/src/commands/phone/import.js +88 -0
  48. package/dist/src/commands/phone/import.js.map +1 -0
  49. package/dist/src/commands/phone/numbers.d.ts +2 -0
  50. package/dist/src/commands/phone/numbers.js +34 -0
  51. package/dist/src/commands/phone/numbers.js.map +1 -0
  52. package/dist/src/commands/phone/remove.d.ts +2 -0
  53. package/dist/src/commands/phone/remove.js +31 -0
  54. package/dist/src/commands/phone/remove.js.map +1 -0
  55. package/dist/src/commands/phone/send.d.ts +2 -0
  56. package/dist/src/commands/phone/send.js +228 -0
  57. package/dist/src/commands/phone/send.js.map +1 -0
  58. package/dist/src/commands/phone/status.d.ts +2 -0
  59. package/dist/src/commands/phone/status.js +34 -0
  60. package/dist/src/commands/phone/status.js.map +1 -0
  61. package/dist/src/commands/phone/update.d.ts +2 -0
  62. package/dist/src/commands/phone/update.js +41 -0
  63. package/dist/src/commands/phone/update.js.map +1 -0
  64. package/dist/src/commands/quickstart.js +85 -19
  65. package/dist/src/commands/quickstart.js.map +1 -1
  66. package/dist/src/config/schema.d.ts +23 -0
  67. package/dist/src/config/schema.js +6 -0
  68. package/dist/src/config/schema.js.map +1 -1
  69. package/dist/src/index.js +42 -3
  70. package/dist/src/index.js.map +1 -1
  71. package/package.json +1 -1
  72. package/src/web/phone-dashboard.html +180 -0
package/README.md CHANGED
@@ -28,8 +28,9 @@ Start, manage, and monitor conversational AI agents from your terminal. One comm
28
28
  - **Real-time agent monitoring** -- live status, latency, and conversation turns in the runtime panel
29
29
  - **Built-in presets** -- start with OpenAI, Anthropic, Gemini, or Realtime in one flag
30
30
  - **Profile management** -- switch between dev, staging, and prod with a single option
31
+ - **Phone calls** -- `convoai phone send` makes outbound calls with SIP, `--wait` shows live status
32
+ - **Number management** -- import, list, update, remove phone numbers (Twilio or BYO SIP)
31
33
  - **Shell completions** -- tab-complete commands in bash, zsh, and fish
32
- - **Telephony support (beta)** -- initiate and manage phone calls through ConvoAI
33
34
 
34
35
  ---
35
36
 
@@ -47,6 +48,9 @@ convoai dev
47
48
  # Or instant voice chat — zero setup
48
49
  convoai go
49
50
 
51
+ # Or make a phone call
52
+ convoai phone send
53
+
50
54
  # Override the model on the fly
51
55
  convoai go --model gpt-4o
52
56
 
@@ -93,6 +97,37 @@ my-app/
93
97
 
94
98
  ---
95
99
 
100
+ ## Phone Go (v1.8.0)
101
+
102
+ One-command phone experience — translate calls, agent outbound, or free calls with a live dashboard:
103
+
104
+ ```bash
105
+ # Interactive — choose mode, fill in details
106
+ convoai phone go
107
+
108
+ # Translate call — each side speaks their own language
109
+ convoai phone go --mode translate --lang zh:ja --to +81312345678
110
+
111
+ # Agent outbound — AI completes a task autonomously
112
+ convoai phone go --mode agent --task "Book dinner for 2 at 7pm" --task-lang ja --to +81312345678
113
+
114
+ # Free call — quick dial with optional AI assistance
115
+ convoai phone go --mode free --to +15559876543
116
+ ```
117
+
118
+ Live browser dashboard shows call status, translation text, and a hang-up button.
119
+
120
+ **Phone calls & number management:**
121
+
122
+ ```bash
123
+ convoai phone send # Make an outbound call (flag mode)
124
+ convoai phone import # Import a number (Twilio or BYO SIP)
125
+ convoai phone numbers # List your numbers
126
+ convoai phone remove <num> # Remove a number
127
+ ```
128
+
129
+ ---
130
+
96
131
  ## Installation
97
132
 
98
133
  ### npm (recommended)
@@ -187,8 +222,9 @@ Commands are organized into scenario groups:
187
222
  |---|---|
188
223
  | **Start** | `go`, `quickstart` |
189
224
  | **Agent** | `agent start`, `agent stop`, `agent status`, `agent list`, `agent update`, `agent speak`, `agent interrupt`, `agent history`, `agent turns`, `agent join` |
225
+ | **Phone** | `phone go`, `phone send`, `phone numbers`, `phone import`, `phone number`, `phone update`, `phone remove`, `phone hangup`, `phone status`, `phone history` |
190
226
  | **Config** | `config init`, `config set`, `config get`, `config show`, `config path`, `auth login`, `auth logout`, `auth status` |
191
- | **More** | `preset list`, `preset use`, `template save/list/show/delete/use`, `call initiate/hangup/status`, `token`, `completion` |
227
+ | **More** | `preset list`, `preset use`, `template save/list/show/delete/use`, `token`, `completion` |
192
228
 
193
229
  ---
194
230
 
@@ -1,53 +1,50 @@
1
1
  import type { AxiosInstance } from 'axios';
2
- export interface InitiateCallRequest {
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
- phone_number: string;
7
- agent_rtc_uid?: string;
12
+ token: string;
13
+ agent_rtc_uid: string;
14
+ remote_rtc_uids: string[];
8
15
  idle_timeout?: number;
9
- llm?: {
10
- url?: string;
11
- api_key?: string;
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
- end_ts?: number;
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
- initiate(req: InitiateCallRequest): Promise<{
46
- agent_id: string;
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
  }
@@ -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 initiate(req) {
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
- /** Hang up an active call. */
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(`/calls/${agentId}/hangup`);
19
+ await this.client.post(`/agents/${agentId}/leave`);
15
20
  }
16
- /** Get the current status of a call. */
17
- async status(agentId) {
18
- const { data } = await this.client.get(`/calls/${agentId}`);
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":"AAgCA,+EAA+E;AAE/E,MAAM,OAAO,OAAO;IACW;IAA7B,YAA6B,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;IAAG,CAAC;IAEtD,uCAAuC;IACvC,KAAK,CAAC,QAAQ,CAAC,GAAwB;QACrC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAuC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC5F,OAAO,IAAI,CAAC;IACd,CAAC;IAED,8BAA8B;IAC9B,KAAK,CAAC,MAAM,CAAC,OAAe;QAC1B,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,OAAO,SAAS,CAAC,CAAC;IACrD,CAAC;IAED,wCAAwC;IACxC,KAAK,CAAC,MAAM,CAAC,OAAe;QAC1B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAqB,UAAU,OAAO,EAAE,CAAC,CAAC;QAChF,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
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"}
@@ -191,6 +191,11 @@ export interface ApiErrorResponse {
191
191
  detail: string;
192
192
  reason: string;
193
193
  }
194
+ export interface VoiceProfile {
195
+ id?: string;
196
+ provider?: string;
197
+ voice_id?: string;
198
+ }
194
199
  export interface ConvoAIConfig {
195
200
  app_id?: string;
196
201
  app_certificate?: string;
@@ -200,6 +205,7 @@ export interface ConvoAIConfig {
200
205
  region?: 'global' | 'cn';
201
206
  default_profile?: string;
202
207
  profiles?: Record<string, ProfileConfig>;
208
+ voice_profile?: VoiceProfile;
203
209
  }
204
210
  export interface ProfileConfig {
205
211
  app_id?: string;
@@ -1,28 +1,21 @@
1
- import { getCallAPI } from './_helpers.js';
2
- import { withSpinner } from '../../ui/spinner.js';
3
- import { printSuccess, printHint } from '../../ui/output.js';
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('Hang up an active call')
11
- .option('--profile <name>', 'Config profile to use')
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 withSpinner(`Hanging up call ${shortId(agentId)}...`, () => api.hangup(agentId));
17
- if (opts.json) {
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, { json: opts.json });
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,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAc,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,8EAA8E;AAE9E,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IACjD,OAAO;SACJ,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,wBAAwB,CAAC;SACrC,MAAM,CAAC,kBAAkB,EAAE,uBAAuB,CAAC;SACnD,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAAC;SACzC,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,IAAI,EAAE,EAAE;QACtC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrC,MAAM,WAAW,CAAC,mBAAmB,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,CAC/D,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CACpB,CAAC;YAEF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC/E,OAAO;YACT,CAAC;YAED,YAAY,CAAC,QAAQ,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;YAClD,SAAS,CAAC,mEAAmE,CAAC,CAAC;QACjF,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"}
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 { resolveConfig } from '../../config/manager.js';
2
- import { getCallAPI } from './_helpers.js';
3
- import { withSpinner } from '../../ui/spinner.js';
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 { shortId } from '../../utils/hints.js';
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('Initiate an outbound phone call')
85
- .option('--phone <number>', 'Phone number in E.164 format (required)')
86
- .option('-c, --channel <name>', 'Channel name (auto-generated if omitted)')
87
- .option('--model <model>', 'LLM model name (e.g. gpt-4o-mini)')
88
- .option('--system-message <msg>', 'System prompt for the LLM')
89
- .option('--greeting <msg>', 'Greeting message spoken on connect')
90
- .option('--profile <name>', 'Config profile to use')
91
- .option('--json', 'Output result as JSON')
92
- .option('--dry-run', 'Show the request payload without sending it')
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
- let phone = opts.phone;
96
- // Interactive prompt if running in a TTY and phone is missing
97
- if (!phone && process.stdin.isTTY) {
98
- phone = await promptForPhone();
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
- if (!phone) {
101
- printError('--phone is required. Provide it as a flag or run interactively in a TTY.');
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 request = buildRequest({
105
- phone,
106
- channel: opts.channel,
107
- model: opts.model,
108
- systemMessage: opts.systemMessage,
109
- greeting: opts.greeting,
110
- profile: opts.profile,
111
- });
112
- // Dry-run mode: print request and exit
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 api = getCallAPI(opts.profile);
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('Call initiated successfully.');
124
- printKeyValue([
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":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAmB,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,8EAA8E;AAE9E,SAAS,gBAAgB;IACvB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1D,OAAO,QAAQ,SAAS,IAAI,MAAM,EAAE,CAAC;AACvC,CAAC;AAED,SAAS,mBAAmB;IAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1D,OAAO,WAAW,SAAS,IAAI,MAAM,EAAE,CAAC;AAC1C,CAAC;AAED,8EAA8E;AAE9E,KAAK,UAAU,cAAc;IAC3B,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IACvD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QACtC;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,iDAAiD;SAC3D;KACF,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,8EAA8E;AAE9E,SAAS,YAAY,CAAC,IAOrB;IACC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE3C,MAAM,UAAU,GAAsC;QACpD,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,mBAAmB,EAAE;QAC9C,YAAY,EAAE,IAAI,CAAC,KAAK;KACzB,CAAC;IAEF,sDAAsD;IACtD,MAAM,GAAG,GAA0D,EAAE,CAAC;IACtE,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,MAAM,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QACnC,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,GAAG,CAAC,eAAe,GAAG,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;QACxE,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,gBAAgB,GAAG,IAAI,CAAC,QAAQ,CAAC;QACrC,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IAED,6CAA6C;IAC7C,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;QACf,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;YAClC,GAAG,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;YACzB,MAAM,GAAG,IAAI,CAAC;QAChB,CAAC;QACD,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;YACvB,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;YACjC,MAAM,GAAG,IAAI,CAAC;QAChB,CAAC;IACH,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC;IACvB,CAAC;IAED,wBAAwB;IACxB,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;QACf,UAAU,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;IAC9B,CAAC;IAED,wBAAwB;IACxB,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;QACf,UAAU,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;IAC9B,CAAC;IAED,OAAO;QACL,IAAI,EAAE,gBAAgB,EAAE;QACxB,UAAU;KACX,CAAC;AACJ,CAAC;AAED,8EAA8E;AAE9E,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,iCAAiC,CAAC;SAC9C,MAAM,CAAC,kBAAkB,EAAE,yCAAyC,CAAC;SACrE,MAAM,CAAC,sBAAsB,EAAE,0CAA0C,CAAC;SAC1E,MAAM,CAAC,iBAAiB,EAAE,mCAAmC,CAAC;SAC9D,MAAM,CAAC,wBAAwB,EAAE,2BAA2B,CAAC;SAC7D,MAAM,CAAC,kBAAkB,EAAE,oCAAoC,CAAC;SAChE,MAAM,CAAC,kBAAkB,EAAE,uBAAuB,CAAC;SACnD,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAAC;SACzC,MAAM,CAAC,WAAW,EAAE,6CAA6C,CAAC;SAClE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,IAAI,CAAC;YACH,IAAI,KAAK,GAAuB,IAAI,CAAC,KAAK,CAAC;YAE3C,8DAA8D;YAC9D,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;gBAClC,KAAK,GAAG,MAAM,cAAc,EAAE,CAAC;YACjC,CAAC;YAED,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,UAAU,CAAC,0EAA0E,CAAC,CAAC;gBACvF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,MAAM,OAAO,GAAG,YAAY,CAAC;gBAC3B,KAAK;gBACL,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,aAAa,EAAE,IAAI,CAAC,aAAa;gBACjC,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,OAAO,EAAE,IAAI,CAAC,OAAO;aACtB,CAAC,CAAC;YAEH,uCAAuC;YACvC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC9C,OAAO;YACT,CAAC;YAED,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrC,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YAEpF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC7C,OAAO;YACT,CAAC;YAED,YAAY,CAAC,8BAA8B,CAAC,CAAC;YAC7C,aAAa,CAAC;gBACZ,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC;gBAC7B,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC;gBACzB,CAAC,OAAO,EAAE,KAAK,CAAC;gBAChB,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;aACxC,CAAC,CAAC;YACH,SAAS,CAAC,6BAA6B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,0BAA0B,CAAC,CAAC;QAC7F,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"}
1
+ {"version":3,"file":"initiate.js","sourceRoot":"","sources":["../../../../src/commands/call/initiate.ts"],"names":[],"mappings":"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"}