convoai 1.0.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/LICENSE +21 -0
- package/README.md +862 -0
- package/bin/convoai.ts +3 -0
- package/dist/bin/convoai.d.ts +2 -0
- package/dist/bin/convoai.js +4 -0
- package/dist/bin/convoai.js.map +1 -0
- package/dist/src/api/agents.d.ts +24 -0
- package/dist/src/api/agents.js +51 -0
- package/dist/src/api/agents.js.map +1 -0
- package/dist/src/api/calls.d.ts +53 -0
- package/dist/src/api/calls.js +22 -0
- package/dist/src/api/calls.js.map +1 -0
- package/dist/src/api/client.d.ts +10 -0
- package/dist/src/api/client.js +63 -0
- package/dist/src/api/client.js.map +1 -0
- package/dist/src/api/types.d.ts +207 -0
- package/dist/src/api/types.js +20 -0
- package/dist/src/api/types.js.map +1 -0
- package/dist/src/commands/agent/_helpers.d.ts +7 -0
- package/dist/src/commands/agent/_helpers.js +32 -0
- package/dist/src/commands/agent/_helpers.js.map +1 -0
- package/dist/src/commands/agent/history.d.ts +2 -0
- package/dist/src/commands/agent/history.js +78 -0
- package/dist/src/commands/agent/history.js.map +1 -0
- package/dist/src/commands/agent/interrupt.d.ts +2 -0
- package/dist/src/commands/agent/interrupt.js +32 -0
- package/dist/src/commands/agent/interrupt.js.map +1 -0
- package/dist/src/commands/agent/join.d.ts +2 -0
- package/dist/src/commands/agent/join.js +168 -0
- package/dist/src/commands/agent/join.js.map +1 -0
- package/dist/src/commands/agent/list.d.ts +2 -0
- package/dist/src/commands/agent/list.js +67 -0
- package/dist/src/commands/agent/list.js.map +1 -0
- package/dist/src/commands/agent/speak.d.ts +2 -0
- package/dist/src/commands/agent/speak.js +48 -0
- package/dist/src/commands/agent/speak.js.map +1 -0
- package/dist/src/commands/agent/start.d.ts +2 -0
- package/dist/src/commands/agent/start.js +212 -0
- package/dist/src/commands/agent/start.js.map +1 -0
- package/dist/src/commands/agent/status.d.ts +2 -0
- package/dist/src/commands/agent/status.js +42 -0
- package/dist/src/commands/agent/status.js.map +1 -0
- package/dist/src/commands/agent/stop.d.ts +2 -0
- package/dist/src/commands/agent/stop.js +107 -0
- package/dist/src/commands/agent/stop.js.map +1 -0
- package/dist/src/commands/agent/turns.d.ts +2 -0
- package/dist/src/commands/agent/turns.js +99 -0
- package/dist/src/commands/agent/turns.js.map +1 -0
- package/dist/src/commands/agent/update.d.ts +2 -0
- package/dist/src/commands/agent/update.js +74 -0
- package/dist/src/commands/agent/update.js.map +1 -0
- package/dist/src/commands/agent/watch.d.ts +2 -0
- package/dist/src/commands/agent/watch.js +291 -0
- package/dist/src/commands/agent/watch.js.map +1 -0
- package/dist/src/commands/auth/login.d.ts +2 -0
- package/dist/src/commands/auth/login.js +118 -0
- package/dist/src/commands/auth/login.js.map +1 -0
- package/dist/src/commands/auth/logout.d.ts +2 -0
- package/dist/src/commands/auth/logout.js +84 -0
- package/dist/src/commands/auth/logout.js.map +1 -0
- package/dist/src/commands/auth/status.d.ts +2 -0
- package/dist/src/commands/auth/status.js +114 -0
- package/dist/src/commands/auth/status.js.map +1 -0
- package/dist/src/commands/call/_helpers.d.ts +7 -0
- package/dist/src/commands/call/_helpers.js +32 -0
- package/dist/src/commands/call/_helpers.js.map +1 -0
- package/dist/src/commands/call/hangup.d.ts +2 -0
- package/dist/src/commands/call/hangup.js +29 -0
- package/dist/src/commands/call/hangup.js.map +1 -0
- package/dist/src/commands/call/initiate.d.ts +2 -0
- package/dist/src/commands/call/initiate.js +137 -0
- package/dist/src/commands/call/initiate.js.map +1 -0
- package/dist/src/commands/call/status.d.ts +2 -0
- package/dist/src/commands/call/status.js +50 -0
- package/dist/src/commands/call/status.js.map +1 -0
- package/dist/src/commands/completion.d.ts +2 -0
- package/dist/src/commands/completion.js +542 -0
- package/dist/src/commands/completion.js.map +1 -0
- package/dist/src/commands/config/get.d.ts +2 -0
- package/dist/src/commands/config/get.js +79 -0
- package/dist/src/commands/config/get.js.map +1 -0
- package/dist/src/commands/config/init.d.ts +2 -0
- package/dist/src/commands/config/init.js +176 -0
- package/dist/src/commands/config/init.js.map +1 -0
- package/dist/src/commands/config/path.d.ts +2 -0
- package/dist/src/commands/config/path.js +22 -0
- package/dist/src/commands/config/path.js.map +1 -0
- package/dist/src/commands/config/set.d.ts +2 -0
- package/dist/src/commands/config/set.js +115 -0
- package/dist/src/commands/config/set.js.map +1 -0
- package/dist/src/commands/config/show.d.ts +2 -0
- package/dist/src/commands/config/show.js +147 -0
- package/dist/src/commands/config/show.js.map +1 -0
- package/dist/src/commands/preset/list.d.ts +2 -0
- package/dist/src/commands/preset/list.js +39 -0
- package/dist/src/commands/preset/list.js.map +1 -0
- package/dist/src/commands/preset/use.d.ts +2 -0
- package/dist/src/commands/preset/use.js +89 -0
- package/dist/src/commands/preset/use.js.map +1 -0
- package/dist/src/commands/quickstart.d.ts +2 -0
- package/dist/src/commands/quickstart.js +595 -0
- package/dist/src/commands/quickstart.js.map +1 -0
- package/dist/src/commands/repl.d.ts +2 -0
- package/dist/src/commands/repl.js +391 -0
- package/dist/src/commands/repl.js.map +1 -0
- package/dist/src/commands/template/delete.d.ts +2 -0
- package/dist/src/commands/template/delete.js +54 -0
- package/dist/src/commands/template/delete.js.map +1 -0
- package/dist/src/commands/template/list.d.ts +2 -0
- package/dist/src/commands/template/list.js +48 -0
- package/dist/src/commands/template/list.js.map +1 -0
- package/dist/src/commands/template/save.d.ts +2 -0
- package/dist/src/commands/template/save.js +86 -0
- package/dist/src/commands/template/save.js.map +1 -0
- package/dist/src/commands/template/show.d.ts +2 -0
- package/dist/src/commands/template/show.js +98 -0
- package/dist/src/commands/template/show.js.map +1 -0
- package/dist/src/commands/template/use.d.ts +2 -0
- package/dist/src/commands/template/use.js +109 -0
- package/dist/src/commands/template/use.js.map +1 -0
- package/dist/src/commands/token.d.ts +2 -0
- package/dist/src/commands/token.js +75 -0
- package/dist/src/commands/token.js.map +1 -0
- package/dist/src/config/manager.d.ts +22 -0
- package/dist/src/config/manager.js +130 -0
- package/dist/src/config/manager.js.map +1 -0
- package/dist/src/config/paths.d.ts +9 -0
- package/dist/src/config/paths.js +28 -0
- package/dist/src/config/paths.js.map +1 -0
- package/dist/src/config/schema.d.ts +396 -0
- package/dist/src/config/schema.js +57 -0
- package/dist/src/config/schema.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +157 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/presets/defaults.d.ts +20 -0
- package/dist/src/presets/defaults.js +195 -0
- package/dist/src/presets/defaults.js.map +1 -0
- package/dist/src/providers/catalog.d.ts +103 -0
- package/dist/src/providers/catalog.js +247 -0
- package/dist/src/providers/catalog.js.map +1 -0
- package/dist/src/templates/manager.d.ts +24 -0
- package/dist/src/templates/manager.js +77 -0
- package/dist/src/templates/manager.js.map +1 -0
- package/dist/src/ui/colors.d.ts +9 -0
- package/dist/src/ui/colors.js +36 -0
- package/dist/src/ui/colors.js.map +1 -0
- package/dist/src/ui/output.d.ts +17 -0
- package/dist/src/ui/output.js +27 -0
- package/dist/src/ui/output.js.map +1 -0
- package/dist/src/ui/spinner.d.ts +5 -0
- package/dist/src/ui/spinner.js +23 -0
- package/dist/src/ui/spinner.js.map +1 -0
- package/dist/src/ui/table.d.ts +8 -0
- package/dist/src/ui/table.js +38 -0
- package/dist/src/ui/table.js.map +1 -0
- package/dist/src/utils/errors.d.ts +11 -0
- package/dist/src/utils/errors.js +38 -0
- package/dist/src/utils/errors.js.map +1 -0
- package/dist/src/utils/format.d.ts +16 -0
- package/dist/src/utils/format.js +87 -0
- package/dist/src/utils/format.js.map +1 -0
- package/dist/src/utils/hints.d.ts +7 -0
- package/dist/src/utils/hints.js +22 -0
- package/dist/src/utils/hints.js.map +1 -0
- package/dist/src/utils/token.d.ts +6 -0
- package/dist/src/utils/token.js +26 -0
- package/dist/src/utils/token.js.map +1 -0
- package/package.json +65 -0
- package/src/web/client.html +136 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
// ─── Status Colors ──────────────────────────────────────────────────────────
|
|
3
|
+
const STATUS_COLORS = {
|
|
4
|
+
RUNNING: chalk.green,
|
|
5
|
+
STARTING: chalk.yellow,
|
|
6
|
+
RECOVERING: chalk.yellow,
|
|
7
|
+
FAILED: chalk.red,
|
|
8
|
+
STOPPED: chalk.red,
|
|
9
|
+
IDLE: chalk.gray,
|
|
10
|
+
STOPPING: chalk.gray,
|
|
11
|
+
};
|
|
12
|
+
/** Colorize an agent status string for terminal display. */
|
|
13
|
+
export function colorStatus(status) {
|
|
14
|
+
const colorize = STATUS_COLORS[status] ?? chalk.white;
|
|
15
|
+
return colorize(status);
|
|
16
|
+
}
|
|
17
|
+
// ─── General-Purpose Helpers ────────────────────────────────────────────────
|
|
18
|
+
export function dim(text) {
|
|
19
|
+
return chalk.dim(text);
|
|
20
|
+
}
|
|
21
|
+
export function bold(text) {
|
|
22
|
+
return chalk.bold(text);
|
|
23
|
+
}
|
|
24
|
+
export function success(text) {
|
|
25
|
+
return chalk.green(text);
|
|
26
|
+
}
|
|
27
|
+
export function error(text) {
|
|
28
|
+
return chalk.red(text);
|
|
29
|
+
}
|
|
30
|
+
export function warn(text) {
|
|
31
|
+
return chalk.yellow(text);
|
|
32
|
+
}
|
|
33
|
+
export function info(text) {
|
|
34
|
+
return chalk.cyan(text);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=colors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.js","sourceRoot":"","sources":["../../../src/ui/colors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,+EAA+E;AAE/E,MAAM,aAAa,GAAkD;IACnE,OAAO,EAAE,KAAK,CAAC,KAAK;IACpB,QAAQ,EAAE,KAAK,CAAC,MAAM;IACtB,UAAU,EAAE,KAAK,CAAC,MAAM;IACxB,MAAM,EAAE,KAAK,CAAC,GAAG;IACjB,OAAO,EAAE,KAAK,CAAC,GAAG;IAClB,IAAI,EAAE,KAAK,CAAC,IAAI;IAChB,QAAQ,EAAE,KAAK,CAAC,IAAI;CACrB,CAAC;AAEF,4DAA4D;AAC5D,MAAM,UAAU,WAAW,CAAC,MAAmB;IAC7C,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC;IACtD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC1B,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,GAAG,CAAC,IAAY;IAC9B,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAY;IAC/B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,IAAY;IAChC,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAY;IAC/B,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAY;IAC/B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output data as JSON (if --json flag is set) or do nothing and let
|
|
3
|
+
* the calling command handle human-friendly rendering.
|
|
4
|
+
*/
|
|
5
|
+
export declare function output(data: unknown, opts: {
|
|
6
|
+
json?: boolean;
|
|
7
|
+
}): void;
|
|
8
|
+
/** Check whether JSON output mode is active. */
|
|
9
|
+
export declare function isJsonMode(options: {
|
|
10
|
+
json?: boolean;
|
|
11
|
+
}): boolean;
|
|
12
|
+
/** Print a success message with a green checkmark. */
|
|
13
|
+
export declare function printSuccess(message: string): void;
|
|
14
|
+
/** Print an error message with a red X. */
|
|
15
|
+
export declare function printError(message: string): void;
|
|
16
|
+
/** Print a next-step hint with a dim prefix. */
|
|
17
|
+
export declare function printHint(message: string): void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
/**
|
|
3
|
+
* Output data as JSON (if --json flag is set) or do nothing and let
|
|
4
|
+
* the calling command handle human-friendly rendering.
|
|
5
|
+
*/
|
|
6
|
+
export function output(data, opts) {
|
|
7
|
+
if (opts.json) {
|
|
8
|
+
console.log(JSON.stringify(data, null, 2));
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** Check whether JSON output mode is active. */
|
|
12
|
+
export function isJsonMode(options) {
|
|
13
|
+
return options.json === true;
|
|
14
|
+
}
|
|
15
|
+
/** Print a success message with a green checkmark. */
|
|
16
|
+
export function printSuccess(message) {
|
|
17
|
+
console.log(`${chalk.green('\u2714')} ${message}`);
|
|
18
|
+
}
|
|
19
|
+
/** Print an error message with a red X. */
|
|
20
|
+
export function printError(message) {
|
|
21
|
+
console.error(`${chalk.red('\u2716')} ${message}`);
|
|
22
|
+
}
|
|
23
|
+
/** Print a next-step hint with a dim prefix. */
|
|
24
|
+
export function printHint(message) {
|
|
25
|
+
console.log(`${chalk.dim('Next:')} ${message}`);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/ui/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,IAAa,EAAE,IAAwB;IAC5D,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,UAAU,CAAC,OAA2B;IACpD,OAAO,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC;AAC/B,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import ora from 'ora';
|
|
2
|
+
/**
|
|
3
|
+
* Run an async function with a terminal spinner.
|
|
4
|
+
* Gracefully degrades in non-TTY environments (e.g. piped output).
|
|
5
|
+
*/
|
|
6
|
+
export async function withSpinner(message, fn) {
|
|
7
|
+
// Skip spinner entirely if stdout is not a TTY
|
|
8
|
+
if (!process.stdout.isTTY) {
|
|
9
|
+
return fn();
|
|
10
|
+
}
|
|
11
|
+
const spinner = ora(message).start();
|
|
12
|
+
try {
|
|
13
|
+
const result = await fn();
|
|
14
|
+
spinner.succeed();
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
const failMessage = err instanceof Error ? err.message : String(err);
|
|
19
|
+
spinner.fail(failMessage);
|
|
20
|
+
throw err;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=spinner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AAEtB;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAe,EACf,EAAoB;IAEpB,+CAA+C;IAC/C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC1B,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC;IAErC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC;QAC1B,OAAO,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,WAAW,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACrE,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC1B,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Print a formatted table to stdout.
|
|
3
|
+
*/
|
|
4
|
+
export declare function printTable(headers: string[], rows: string[][]): void;
|
|
5
|
+
/**
|
|
6
|
+
* Print a list of key-value pairs, formatted for single-item detail views.
|
|
7
|
+
*/
|
|
8
|
+
export declare function printKeyValue(pairs: [string, string][]): void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Table from 'cli-table3';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
/**
|
|
4
|
+
* Print a formatted table to stdout.
|
|
5
|
+
*/
|
|
6
|
+
export function printTable(headers, rows) {
|
|
7
|
+
const table = new Table({
|
|
8
|
+
head: headers.map((h) => chalk.bold(h)),
|
|
9
|
+
style: {
|
|
10
|
+
head: [], // disable default color — we apply our own via chalk
|
|
11
|
+
border: [],
|
|
12
|
+
compact: true,
|
|
13
|
+
},
|
|
14
|
+
chars: {
|
|
15
|
+
top: '', 'top-mid': '', 'top-left': '', 'top-right': '',
|
|
16
|
+
bottom: '', 'bottom-mid': '', 'bottom-left': '', 'bottom-right': '',
|
|
17
|
+
left: '', 'left-mid': '',
|
|
18
|
+
mid: '', 'mid-mid': '',
|
|
19
|
+
right: '', 'right-mid': '',
|
|
20
|
+
middle: ' ',
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
for (const row of rows) {
|
|
24
|
+
table.push(row);
|
|
25
|
+
}
|
|
26
|
+
console.log(table.toString());
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Print a list of key-value pairs, formatted for single-item detail views.
|
|
30
|
+
*/
|
|
31
|
+
export function printKeyValue(pairs) {
|
|
32
|
+
const maxKeyLen = Math.max(...pairs.map(([k]) => k.length));
|
|
33
|
+
for (const [key, value] of pairs) {
|
|
34
|
+
const paddedKey = key.padEnd(maxKeyLen);
|
|
35
|
+
console.log(` ${chalk.dim(paddedKey)} ${value}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.js","sourceRoot":"","sources":["../../../src/ui/table.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,OAAiB,EAAE,IAAgB;IAC5D,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACtB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACvC,KAAK,EAAE;YACL,IAAI,EAAE,EAAE,EAAQ,qDAAqD;YACrE,MAAM,EAAE,EAAE;YACV,OAAO,EAAE,IAAI;SACd;QACD,KAAK,EAAE;YACL,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE;YACvD,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE;YACnE,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE;YACxB,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE;YACtB,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE;YAC1B,MAAM,EAAE,IAAI;SACb;KACF,CAAC,CAAC;IAEH,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAE5D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract a human-readable message from an API error.
|
|
3
|
+
*/
|
|
4
|
+
export declare function formatApiError(error: unknown): string;
|
|
5
|
+
/**
|
|
6
|
+
* Format an error, print to stderr, and exit with code 1.
|
|
7
|
+
* In JSON mode, outputs a structured error object instead.
|
|
8
|
+
*/
|
|
9
|
+
export declare function handleError(error: unknown, options?: {
|
|
10
|
+
json?: boolean;
|
|
11
|
+
}): never;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { AxiosError } from 'axios';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
/**
|
|
4
|
+
* Extract a human-readable message from an API error.
|
|
5
|
+
*/
|
|
6
|
+
export function formatApiError(error) {
|
|
7
|
+
if (error instanceof AxiosError) {
|
|
8
|
+
const status = error.response?.status;
|
|
9
|
+
const data = error.response?.data;
|
|
10
|
+
const detail = data?.detail || data?.reason || error.message;
|
|
11
|
+
if (status) {
|
|
12
|
+
return `API Error ${status}: ${detail}`;
|
|
13
|
+
}
|
|
14
|
+
if (error.code === 'ECONNREFUSED' || error.code === 'ENOTFOUND') {
|
|
15
|
+
return `Network error: could not reach the API (${error.code})`;
|
|
16
|
+
}
|
|
17
|
+
return `Request failed: ${error.message}`;
|
|
18
|
+
}
|
|
19
|
+
if (error instanceof Error) {
|
|
20
|
+
return error.message;
|
|
21
|
+
}
|
|
22
|
+
return String(error);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Format an error, print to stderr, and exit with code 1.
|
|
26
|
+
* In JSON mode, outputs a structured error object instead.
|
|
27
|
+
*/
|
|
28
|
+
export function handleError(error, options) {
|
|
29
|
+
const message = formatApiError(error);
|
|
30
|
+
if (options?.json) {
|
|
31
|
+
console.error(JSON.stringify({ error: message }, null, 2));
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
console.error(`${chalk.red('\u2716')} ${message}`);
|
|
35
|
+
}
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/utils/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAoC,CAAC;QAClE,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,IAAI,IAAI,EAAE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC;QAE7D,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,aAAa,MAAM,KAAK,MAAM,EAAE,CAAC;QAC1C,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAChE,OAAO,2CAA2C,KAAK,CAAC,IAAI,GAAG,CAAC;QAClE,CAAC;QACD,OAAO,mBAAmB,KAAK,CAAC,OAAO,EAAE,CAAC;IAC5C,CAAC;IAED,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CACzB,KAAc,EACd,OAA4B;IAE5B,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAEtC,IAAI,OAAO,EAAE,IAAI,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Generate a unique agent name. */
|
|
2
|
+
export declare function generateAgentName(): string;
|
|
3
|
+
/** Mask a secret: show first 4 chars, then ****. */
|
|
4
|
+
export declare function maskSecret(value: string | undefined): string;
|
|
5
|
+
/** Format a Unix timestamp (seconds) to readable date. Returns "—" for falsy values. */
|
|
6
|
+
export declare function formatTimestamp(ts: number | undefined): string;
|
|
7
|
+
/** Convert a Unix timestamp to a relative time string. */
|
|
8
|
+
export declare function relativeTime(ts: number | undefined): string;
|
|
9
|
+
/** Format a duration in seconds to human-readable string. */
|
|
10
|
+
export declare function formatDuration(seconds: number): string;
|
|
11
|
+
/** Color-code a latency value: green < 1000ms, yellow 1000-2000ms, red > 2000ms. */
|
|
12
|
+
export declare function colorLatency(ms: number | undefined): string;
|
|
13
|
+
/** Format a role for conversation display. */
|
|
14
|
+
export declare function formatRole(role: string): string;
|
|
15
|
+
/** Calculate average of an array of numbers, ignoring undefined. */
|
|
16
|
+
export declare function averageOf(values: (number | undefined)[]): number;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
/** Generate a unique agent name. */
|
|
3
|
+
export function generateAgentName() {
|
|
4
|
+
const ts = Math.floor(Date.now() / 1000);
|
|
5
|
+
const rand = Math.random().toString(36).slice(2, 6);
|
|
6
|
+
return `agent-${ts}-${rand}`;
|
|
7
|
+
}
|
|
8
|
+
/** Mask a secret: show first 4 chars, then ****. */
|
|
9
|
+
export function maskSecret(value) {
|
|
10
|
+
if (!value)
|
|
11
|
+
return '(not set)';
|
|
12
|
+
if (value.length <= 4)
|
|
13
|
+
return '****';
|
|
14
|
+
return value.slice(0, 4) + '****';
|
|
15
|
+
}
|
|
16
|
+
/** Format a Unix timestamp (seconds) to readable date. Returns "—" for falsy values. */
|
|
17
|
+
export function formatTimestamp(ts) {
|
|
18
|
+
if (!ts)
|
|
19
|
+
return '—';
|
|
20
|
+
const date = new Date(ts * 1000);
|
|
21
|
+
return date.toLocaleString('en-US', {
|
|
22
|
+
year: 'numeric',
|
|
23
|
+
month: 'short',
|
|
24
|
+
day: 'numeric',
|
|
25
|
+
hour: '2-digit',
|
|
26
|
+
minute: '2-digit',
|
|
27
|
+
second: '2-digit',
|
|
28
|
+
hour12: false,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** Convert a Unix timestamp to a relative time string. */
|
|
32
|
+
export function relativeTime(ts) {
|
|
33
|
+
if (!ts)
|
|
34
|
+
return '—';
|
|
35
|
+
const nowSec = Math.floor(Date.now() / 1000);
|
|
36
|
+
const diffSec = nowSec - ts;
|
|
37
|
+
if (diffSec < 0)
|
|
38
|
+
return 'just now';
|
|
39
|
+
if (diffSec < 60)
|
|
40
|
+
return `${diffSec}s ago`;
|
|
41
|
+
const diffMin = Math.floor(diffSec / 60);
|
|
42
|
+
if (diffMin < 60)
|
|
43
|
+
return `${diffMin}m ago`;
|
|
44
|
+
const diffHr = Math.floor(diffMin / 60);
|
|
45
|
+
if (diffHr < 24)
|
|
46
|
+
return `${diffHr}h ago`;
|
|
47
|
+
const diffDay = Math.floor(diffHr / 24);
|
|
48
|
+
return `${diffDay}d ago`;
|
|
49
|
+
}
|
|
50
|
+
/** Format a duration in seconds to human-readable string. */
|
|
51
|
+
export function formatDuration(seconds) {
|
|
52
|
+
if (seconds < 60)
|
|
53
|
+
return `${seconds}s`;
|
|
54
|
+
const min = Math.floor(seconds / 60);
|
|
55
|
+
const sec = seconds % 60;
|
|
56
|
+
if (min < 60)
|
|
57
|
+
return `${min}m ${sec}s`;
|
|
58
|
+
const hr = Math.floor(min / 60);
|
|
59
|
+
return `${hr}h ${min % 60}m`;
|
|
60
|
+
}
|
|
61
|
+
/** Color-code a latency value: green < 1000ms, yellow 1000-2000ms, red > 2000ms. */
|
|
62
|
+
export function colorLatency(ms) {
|
|
63
|
+
if (ms === undefined || ms === null)
|
|
64
|
+
return '—';
|
|
65
|
+
const str = `${ms}ms`;
|
|
66
|
+
if (ms < 1000)
|
|
67
|
+
return chalk.green(str);
|
|
68
|
+
if (ms < 2000)
|
|
69
|
+
return chalk.yellow(str);
|
|
70
|
+
return chalk.red(str);
|
|
71
|
+
}
|
|
72
|
+
/** Format a role for conversation display. */
|
|
73
|
+
export function formatRole(role) {
|
|
74
|
+
if (role === 'user')
|
|
75
|
+
return chalk.cyan(`[${role}]`.padEnd(12));
|
|
76
|
+
if (role === 'assistant')
|
|
77
|
+
return chalk.green(`[${role}]`.padEnd(12));
|
|
78
|
+
return chalk.dim(`[${role}]`.padEnd(12));
|
|
79
|
+
}
|
|
80
|
+
/** Calculate average of an array of numbers, ignoring undefined. */
|
|
81
|
+
export function averageOf(values) {
|
|
82
|
+
const valid = values.filter((v) => v !== undefined && v !== null);
|
|
83
|
+
if (valid.length === 0)
|
|
84
|
+
return 0;
|
|
85
|
+
return Math.round(valid.reduce((sum, v) => sum + v, 0) / valid.length);
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/utils/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Display a truncated agent ID (first 12 characters). */
|
|
2
|
+
export declare function shortId(id: string): string;
|
|
3
|
+
export declare function hintAfterStart(agentId: string): string;
|
|
4
|
+
export declare function hintAfterStop(): string;
|
|
5
|
+
export declare function hintAfterLogin(): string;
|
|
6
|
+
export declare function hintAfterList(): string;
|
|
7
|
+
export declare function hintAfterHistory(agentId: string): string;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// ─── Short ID ───────────────────────────────────────────────────────────────
|
|
2
|
+
/** Display a truncated agent ID (first 12 characters). */
|
|
3
|
+
export function shortId(id) {
|
|
4
|
+
return id.slice(0, 12);
|
|
5
|
+
}
|
|
6
|
+
// ─── Next-Step Hints ────────────────────────────────────────────────────────
|
|
7
|
+
export function hintAfterStart(agentId) {
|
|
8
|
+
return `Run \`convoai agent status ${shortId(agentId)}\` to check status.`;
|
|
9
|
+
}
|
|
10
|
+
export function hintAfterStop() {
|
|
11
|
+
return 'Run `convoai agent list` to see remaining agents.';
|
|
12
|
+
}
|
|
13
|
+
export function hintAfterLogin() {
|
|
14
|
+
return 'Run `convoai agent start --channel <name>` to start your first agent.';
|
|
15
|
+
}
|
|
16
|
+
export function hintAfterList() {
|
|
17
|
+
return 'Run `convoai agent status <id>` to inspect an agent.';
|
|
18
|
+
}
|
|
19
|
+
export function hintAfterHistory(agentId) {
|
|
20
|
+
return `Run \`convoai agent turns ${shortId(agentId)}\` to view turn-level latency.`;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=hints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hints.js","sourceRoot":"","sources":["../../../src/utils/hints.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAE/E,0DAA0D;AAC1D,MAAM,UAAU,OAAO,CAAC,EAAU;IAChC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACzB,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,OAAO,8BAA8B,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,mDAAmD,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,uEAAuE,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,sDAAsD,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,6BAA6B,OAAO,CAAC,OAAO,CAAC,gCAAgC,CAAC;AACvF,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate an RTC token for agent authentication.
|
|
3
|
+
* Uses app_certificate from config or AGORA_APP_CERTIFICATE env var.
|
|
4
|
+
* Returns undefined if no certificate is available (app may not require tokens).
|
|
5
|
+
*/
|
|
6
|
+
export declare function generateRtcToken(channelName: string, uid?: number, expireSeconds?: number): Promise<string | undefined>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { loadConfig } from '../config/manager.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generate an RTC token for agent authentication.
|
|
4
|
+
* Uses app_certificate from config or AGORA_APP_CERTIFICATE env var.
|
|
5
|
+
* Returns undefined if no certificate is available (app may not require tokens).
|
|
6
|
+
*/
|
|
7
|
+
export async function generateRtcToken(channelName, uid = 0, expireSeconds = 86400) {
|
|
8
|
+
const config = loadConfig();
|
|
9
|
+
const appId = config.app_id;
|
|
10
|
+
const certificate = process.env.AGORA_APP_CERTIFICATE ?? config.app_certificate;
|
|
11
|
+
if (!appId || !certificate) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
const pkg = await import('agora-token');
|
|
16
|
+
const mod = pkg.default ?? pkg;
|
|
17
|
+
const { RtcTokenBuilder, RtcRole } = mod;
|
|
18
|
+
const expireTs = Math.floor(Date.now() / 1000) + expireSeconds;
|
|
19
|
+
return RtcTokenBuilder.buildTokenWithUid(appId, certificate, channelName, uid, RtcRole.PUBLISHER, expireTs, expireTs);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// agora-token not installed or token generation failed
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../../src/utils/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,WAAmB,EACnB,MAAc,CAAC,EACf,gBAAwB,KAAK;IAE7B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;IAC5B,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,MAAM,CAAC,eAAe,CAAC;IAEhF,IAAI,CAAC,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC;QAC/B,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC;QAEzC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,aAAa,CAAC;QAC/D,OAAO,eAAe,CAAC,iBAAiB,CACtC,KAAK,EACL,WAAW,EACX,WAAW,EACX,GAAG,EACH,OAAO,CAAC,SAAS,EACjB,QAAQ,EACR,QAAQ,CACT,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,uDAAuD;QACvD,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "convoai",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI for Agora ConvoAI Engine — start, manage, and monitor conversational AI agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"convoai": "./dist/bin/convoai.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "tsx bin/convoai.ts",
|
|
12
|
+
"start": "node dist/bin/convoai.js",
|
|
13
|
+
"lint": "tsc --noEmit",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"test:watch": "vitest",
|
|
16
|
+
"test:coverage": "vitest run --coverage",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"agora",
|
|
21
|
+
"convoai",
|
|
22
|
+
"conversational-ai",
|
|
23
|
+
"cli",
|
|
24
|
+
"voice-ai",
|
|
25
|
+
"realtime"
|
|
26
|
+
],
|
|
27
|
+
"author": "Agora ConvoAI CLI Contributors",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/AgoraIO-Community/convoai-cli"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/AgoraIO-Community/convoai-cli#readme",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/AgoraIO-Community/convoai-cli/issues"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"bin",
|
|
39
|
+
"src/web",
|
|
40
|
+
"README.md",
|
|
41
|
+
"LICENSE"
|
|
42
|
+
],
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"agora-token": "^2.0.5",
|
|
46
|
+
"axios": "^1.7.0",
|
|
47
|
+
"chalk": "^5.3.0",
|
|
48
|
+
"cli-table3": "^0.6.5",
|
|
49
|
+
"commander": "^12.1.0",
|
|
50
|
+
"inquirer": "^9.3.0",
|
|
51
|
+
"ora": "^8.1.0",
|
|
52
|
+
"zod": "^3.23.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/inquirer": "^9.0.7",
|
|
56
|
+
"@types/node": "^20.14.0",
|
|
57
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
58
|
+
"tsx": "^4.16.0",
|
|
59
|
+
"typescript": "^5.5.0",
|
|
60
|
+
"vitest": "^4.1.2"
|
|
61
|
+
},
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=18.0.0"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>ConvoAI Voice Chat</title>
|
|
7
|
+
<style>
|
|
8
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
9
|
+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0a0a0a; color: #e0e0e0; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 20px; }
|
|
10
|
+
.card { background: #1a1a1a; border: 1px solid #333; border-radius: 16px; padding: 32px; width: 100%; max-width: 420px; text-align: center; }
|
|
11
|
+
h1 { font-size: 22px; margin-bottom: 4px; color: #00c8ff; }
|
|
12
|
+
.channel-name { color: #00ff88; font-size: 18px; font-weight: 600; margin: 8px 0 24px; }
|
|
13
|
+
.status { font-size: 14px; margin-bottom: 16px; }
|
|
14
|
+
.status.connected { color: #00ff88; }
|
|
15
|
+
.status.disconnected { color: #666; }
|
|
16
|
+
.status.connecting { color: #ffaa00; }
|
|
17
|
+
.status.error { color: #ff4444; }
|
|
18
|
+
.pulse { width: 120px; height: 120px; border-radius: 50%; background: radial-gradient(circle, #00c8ff22, transparent); display: flex; align-items: center; justify-content: center; margin: 0 auto 24px; position: relative; }
|
|
19
|
+
.pulse.active { animation: pulse 1.5s ease-in-out infinite; }
|
|
20
|
+
.pulse-inner { width: 80px; height: 80px; border-radius: 50%; background: #1a1a1a; border: 3px solid #333; display: flex; align-items: center; justify-content: center; font-size: 32px; }
|
|
21
|
+
.pulse.active .pulse-inner { border-color: #00c8ff; }
|
|
22
|
+
@keyframes pulse { 0%, 100% { transform: scale(1); opacity: 0.5; } 50% { transform: scale(1.15); opacity: 1; } }
|
|
23
|
+
.volume-bar { height: 6px; background: #222; border-radius: 3px; margin: 0 auto 20px; width: 80%; overflow: hidden; }
|
|
24
|
+
.volume-fill { height: 100%; background: linear-gradient(90deg, #00c8ff, #00ff88); width: 0%; transition: width 0.1s; border-radius: 3px; }
|
|
25
|
+
.log { background: #0a0a0a; border: 1px solid #222; border-radius: 8px; padding: 12px; margin-top: 16px; max-height: 160px; overflow-y: auto; font-family: 'SF Mono', Monaco, monospace; font-size: 11px; line-height: 1.6; text-align: left; }
|
|
26
|
+
.log-entry { color: #555; }
|
|
27
|
+
.log-entry.info { color: #00c8ff; }
|
|
28
|
+
.log-entry.ok { color: #00ff88; }
|
|
29
|
+
.log-entry.err { color: #ff4444; }
|
|
30
|
+
.log-entry.audio { color: #ffaa00; }
|
|
31
|
+
.hint { color: #444; font-size: 11px; margin-top: 20px; }
|
|
32
|
+
</style>
|
|
33
|
+
</head>
|
|
34
|
+
<body>
|
|
35
|
+
<div class="card">
|
|
36
|
+
<h1>ConvoAI Voice Chat</h1>
|
|
37
|
+
<div class="channel-name" id="channelDisplay">—</div>
|
|
38
|
+
<div class="pulse" id="pulse"><div class="pulse-inner" id="icon">🎙</div></div>
|
|
39
|
+
<div class="volume-bar"><div id="vol" class="volume-fill"></div></div>
|
|
40
|
+
<div class="status connecting" id="status">Connecting...</div>
|
|
41
|
+
<div class="log" id="log"></div>
|
|
42
|
+
<p class="hint">Press Ctrl+C in the terminal to stop</p>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<script src="https://download.agora.io/sdk/release/AgoraRTC_N-4.22.0.js"></script>
|
|
46
|
+
<script>
|
|
47
|
+
const P = new URLSearchParams(location.search);
|
|
48
|
+
const appId = P.get('appId');
|
|
49
|
+
const channel = P.get('channel');
|
|
50
|
+
const token = P.get('token') || null;
|
|
51
|
+
const uid = Number(P.get('uid')) || 0;
|
|
52
|
+
|
|
53
|
+
document.getElementById('channelDisplay').textContent = channel || '—';
|
|
54
|
+
|
|
55
|
+
let client, localTrack, volTimer;
|
|
56
|
+
|
|
57
|
+
function log(m, t='') {
|
|
58
|
+
const el = document.getElementById('log');
|
|
59
|
+
const d = document.createElement('div');
|
|
60
|
+
d.className = 'log-entry ' + t;
|
|
61
|
+
d.textContent = `${new Date().toLocaleTimeString()} ${m}`;
|
|
62
|
+
el.appendChild(d);
|
|
63
|
+
el.scrollTop = el.scrollHeight;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function setStatus(t, c) {
|
|
67
|
+
const el = document.getElementById('status');
|
|
68
|
+
el.textContent = t;
|
|
69
|
+
el.className = 'status ' + c;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function start() {
|
|
73
|
+
if (!appId || !channel) {
|
|
74
|
+
setStatus('Missing appId or channel', 'error');
|
|
75
|
+
log('Error: appId and channel are required in URL params', 'err');
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
client = AgoraRTC.createClient({ mode: 'rtc', codec: 'vp8' });
|
|
81
|
+
|
|
82
|
+
client.on('user-published', async (user, mediaType) => {
|
|
83
|
+
await client.subscribe(user, mediaType);
|
|
84
|
+
if (mediaType === 'audio') {
|
|
85
|
+
user.audioTrack.play();
|
|
86
|
+
log('Agent speaking...', 'audio');
|
|
87
|
+
document.getElementById('pulse').classList.add('active');
|
|
88
|
+
document.getElementById('icon').textContent = '🔊';
|
|
89
|
+
if (volTimer) clearInterval(volTimer);
|
|
90
|
+
volTimer = setInterval(() => {
|
|
91
|
+
const v = user.audioTrack.getVolumeLevel();
|
|
92
|
+
document.getElementById('vol').style.width = (v * 100) + '%';
|
|
93
|
+
}, 100);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
client.on('user-unpublished', (user, mediaType) => {
|
|
98
|
+
if (mediaType === 'audio') {
|
|
99
|
+
document.getElementById('pulse').classList.remove('active');
|
|
100
|
+
document.getElementById('icon').textContent = '🎙';
|
|
101
|
+
document.getElementById('vol').style.width = '0%';
|
|
102
|
+
log('Agent stopped speaking', 'info');
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
client.on('user-left', (user) => {
|
|
107
|
+
log('Agent left the channel', 'info');
|
|
108
|
+
document.getElementById('pulse').classList.remove('active');
|
|
109
|
+
document.getElementById('icon').textContent = '👋';
|
|
110
|
+
setStatus('Agent disconnected', 'disconnected');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
log('Joining channel: ' + channel, 'info');
|
|
114
|
+
await client.join(appId, channel, token, uid || null);
|
|
115
|
+
log('Joined (uid: ' + (uid || 'auto') + ')', 'ok');
|
|
116
|
+
|
|
117
|
+
localTrack = await AgoraRTC.createMicrophoneAudioTrack();
|
|
118
|
+
await client.publish([localTrack]);
|
|
119
|
+
log('Microphone live — speak now!', 'ok');
|
|
120
|
+
setStatus('Connected — speak to the agent!', 'connected');
|
|
121
|
+
|
|
122
|
+
} catch (err) {
|
|
123
|
+
log('Error: ' + err.message, 'err');
|
|
124
|
+
setStatus('Failed: ' + err.message, 'error');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
window.addEventListener('beforeunload', async () => {
|
|
129
|
+
if (localTrack) { localTrack.stop(); localTrack.close(); }
|
|
130
|
+
if (client) await client.leave();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
start();
|
|
134
|
+
</script>
|
|
135
|
+
</body>
|
|
136
|
+
</html>
|