@fonoster/ctl 0.30.0 → 0.31.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/README.md +4 -4
- package/dist/commands/applications/create.d.ts +1 -2
- package/dist/commands/applications/eval.js +2 -2
- package/dist/commands/applications/get.js +14 -2
- package/dist/commands/applications/update.d.ts +1 -2
- package/dist/commands/applications/update.js +1 -0
- package/dist/commands/providers/catalog.js +1 -1
- package/dist/commands/sipnet/numbers/linkTwilioNumber.js +4 -3
- package/dist/commands/workspaces/login.js +2 -2
- package/dist/constants.d.ts +1 -2
- package/dist/constants.js +2 -3
- package/dist/utils/applicationFlags.d.ts +1 -2
- package/dist/utils/applicationFlags.js +4 -4
- package/dist/utils/applicationRequest.d.ts +3 -4
- package/dist/utils/applicationRequest.js +27 -21
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -210,7 +210,7 @@ USAGE
|
|
|
210
210
|
|
|
211
211
|
FLAGS
|
|
212
212
|
-a, --agent=<value> a YAML or JSON agent file; makes it an Autopilot agent (hosted by Fonoster)
|
|
213
|
-
-f, --from-file=<value> a YAML or JSON file with the Application (an `
|
|
213
|
+
-f, --from-file=<value> a YAML or JSON file with the Application (an `agent` key makes it an Autopilot
|
|
214
214
|
agent)
|
|
215
215
|
-i, --insecure allow connections to a server with no TLS
|
|
216
216
|
-l, --listener=<value>... a listen-only socket: <wss-url>[,inbound|outbound|both] (repeatable, at most 4)
|
|
@@ -387,7 +387,7 @@ ARGUMENTS
|
|
|
387
387
|
|
|
388
388
|
FLAGS
|
|
389
389
|
-a, --agent=<value> a YAML or JSON agent file; makes it an Autopilot agent (hosted by Fonoster)
|
|
390
|
-
-f, --from-file=<value> a YAML or JSON file with the Application (an `
|
|
390
|
+
-f, --from-file=<value> a YAML or JSON file with the Application (an `agent` key makes it an Autopilot
|
|
391
391
|
agent)
|
|
392
392
|
-i, --insecure allow connections to a server with no TLS
|
|
393
393
|
-l, --listener=<value>... a listen-only socket: <wss-url>[,inbound|outbound|both] (repeatable, at most 4)
|
|
@@ -1376,8 +1376,8 @@ USAGE
|
|
|
1376
1376
|
FLAGS
|
|
1377
1377
|
-a, --access-control-list=<value> [default: 165.22.7.155/32] the access control list to allow (use if running your
|
|
1378
1378
|
Fonoster instance)
|
|
1379
|
-
-b, --outbound-uri-base=<value>
|
|
1380
|
-
|
|
1379
|
+
-b, --outbound-uri-base=<value> the host Twilio sends calls to, under which the trunk's inbound URI is made
|
|
1380
|
+
(default: pstn.<the server's domain>)
|
|
1381
1381
|
-i, --insecure allow connections to a server with no TLS
|
|
1382
1382
|
|
|
1383
1383
|
DESCRIPTION
|
|
@@ -8,8 +8,6 @@ export default class Create extends AuthenticatedCommand<typeof Create> {
|
|
|
8
8
|
url: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
9
|
protocol: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
10
|
agent: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
-
flavor: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
-
assistant: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
11
|
voice: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
12
|
language: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
13
|
"stt-model": import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -25,6 +23,7 @@ export default class Create extends AuthenticatedCommand<typeof Create> {
|
|
|
25
23
|
recording: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
26
24
|
amd: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
27
25
|
"amd-window": import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
26
|
+
"noise-cancelling": import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
28
27
|
};
|
|
29
28
|
run(): Promise<void>;
|
|
30
29
|
private printCreated;
|
|
@@ -112,9 +112,9 @@ class EvalIntelligence extends AuthenticatedCommand_1.AuthenticatedCommand {
|
|
|
112
112
|
});
|
|
113
113
|
rawAutopilotApplication.intelligence.config.testCases.scenarios =
|
|
114
114
|
mappedScenarios;
|
|
115
|
-
// A session
|
|
115
|
+
// A session agent (its catalog id names the provider; keys come from the workspace or
|
|
116
116
|
// the platform, never from the file).
|
|
117
|
-
const parsedAutopilotApplication = common_1.
|
|
117
|
+
const parsedAutopilotApplication = common_1.sessionAgentSchema.parse(rawAutopilotApplication.intelligence.config);
|
|
118
118
|
const autopilotApplication = {
|
|
119
119
|
intelligence: {
|
|
120
120
|
productRef: `llm.${parsedAutopilotApplication.languageModel.model.split("/")[0]}`,
|
|
@@ -64,6 +64,7 @@ exports.formatApplication = formatApplication;
|
|
|
64
64
|
* See the License for the specific language governing permissions and
|
|
65
65
|
* limitations under the License.
|
|
66
66
|
*/
|
|
67
|
+
const common_1 = require("@fonoster/common");
|
|
67
68
|
const SDK = __importStar(require("@fonoster/sdk"));
|
|
68
69
|
const core_1 = require("@oclif/core");
|
|
69
70
|
const cliui_1 = __importDefault(require("cliui"));
|
|
@@ -73,13 +74,23 @@ const errorHandler_1 = __importDefault(require("../../errorHandler"));
|
|
|
73
74
|
const or = (value, fallback = "-") => value === undefined || value === null || value === "" || value === 0
|
|
74
75
|
? fallback
|
|
75
76
|
: String(value);
|
|
77
|
+
/** The nc provider behind the app's filter, or the filter names for anything else. */
|
|
78
|
+
function noiseCancelling(app) {
|
|
79
|
+
var _a;
|
|
80
|
+
const filters = (_a = app.filters) !== null && _a !== void 0 ? _a : [];
|
|
81
|
+
if (!filters.length)
|
|
82
|
+
return "off";
|
|
83
|
+
return filters
|
|
84
|
+
.map((f) => { var _a; return (_a = common_1.AudioFilters.providerOfFilter(f.name)) !== null && _a !== void 0 ? _a : f.name; })
|
|
85
|
+
.join(", ");
|
|
86
|
+
}
|
|
76
87
|
function formatApplication(app) {
|
|
77
88
|
var _a, _b, _c, _d, _e, _f;
|
|
78
89
|
const speech = (_a = app.speech) !== null && _a !== void 0 ? _a : {};
|
|
79
90
|
const listeners = ((_b = app.listeners) !== null && _b !== void 0 ? _b : [])
|
|
80
91
|
.map((l) => { var _a; return `${l.url} (${(_a = l.tracks) !== null && _a !== void 0 ? _a : "both"})`; })
|
|
81
92
|
.join(", ");
|
|
82
|
-
const
|
|
93
|
+
const agent = (_c = app.intelligence) === null || _c === void 0 ? void 0 : _c.config;
|
|
83
94
|
const lines = [
|
|
84
95
|
"APPLICATION DETAILS",
|
|
85
96
|
"------------------",
|
|
@@ -89,7 +100,7 @@ function formatApplication(app) {
|
|
|
89
100
|
`URL: \t${or(app.url || app.endpoint)}`,
|
|
90
101
|
`PROTOCOL: \t${or(app.protocol, "fonoster")}`,
|
|
91
102
|
...(app.type === "AUTOPILOT"
|
|
92
|
-
? [`MODEL: \t${or((_d =
|
|
103
|
+
? [`MODEL: \t${or((_d = agent === null || agent === void 0 ? void 0 : agent.languageModel) === null || _d === void 0 ? void 0 : _d.model)}`]
|
|
93
104
|
: []),
|
|
94
105
|
`VOICE: \t${or(speech.voice)}`,
|
|
95
106
|
`LANGUAGE: \t${or(speech.language)}`,
|
|
@@ -100,6 +111,7 @@ function formatApplication(app) {
|
|
|
100
111
|
`AUDIO: \t${((_e = app.audio) === null || _e === void 0 ? void 0 : _e.codec) ? `${app.audio.codec} ${app.audio.rate} Hz` : "default"}`,
|
|
101
112
|
`RECORDING: \t${or(app.recording, "off")}`,
|
|
102
113
|
`AMD: \t${((_f = app.amd) === null || _f === void 0 ? void 0 : _f.enabled) ? `on (${app.amd.windowMs || 4000} ms)` : "off"}`,
|
|
114
|
+
`NOISE CANCELLING: \t${noiseCancelling(app)}`,
|
|
103
115
|
`FALLBACK APP: \t${or(app.fallbackAppRef)}`,
|
|
104
116
|
`FALLBACK MESSAGE: \t${or(app.fallbackMessage)}`,
|
|
105
117
|
`LISTENERS: \t${or(listeners)}`,
|
|
@@ -11,8 +11,6 @@ export default class Update extends AuthenticatedCommand<typeof Update> {
|
|
|
11
11
|
url: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
12
|
protocol: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
13
|
agent: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
|
-
flavor: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
|
-
assistant: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
16
14
|
voice: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
17
15
|
language: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
16
|
"stt-model": import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -28,6 +26,7 @@ export default class Update extends AuthenticatedCommand<typeof Update> {
|
|
|
28
26
|
recording: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
29
27
|
amd: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
30
28
|
"amd-window": import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
29
|
+
"noise-cancelling": import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
31
30
|
};
|
|
32
31
|
run(): Promise<void>;
|
|
33
32
|
}
|
|
@@ -62,6 +62,7 @@ Update.examples = [
|
|
|
62
62
|
"<%= config.bin %> <%= command.id %> <ref> --voice elevenlabs/rachel --patience high",
|
|
63
63
|
"<%= config.bin %> <%= command.id %> <ref> --agent agent.yaml",
|
|
64
64
|
"<%= config.bin %> <%= command.id %> <ref> --clear-listeners --listener wss://rec.example.com/ws,inbound",
|
|
65
|
+
"<%= config.bin %> <%= command.id %> <ref> --noise-cancelling aicoustics",
|
|
65
66
|
"<%= config.bin %> <%= command.id %> --from-file app.yaml # with `ref` in the file"
|
|
66
67
|
];
|
|
67
68
|
Update.args = {
|
|
@@ -71,6 +71,7 @@ const utils_1 = require("../../../utils");
|
|
|
71
71
|
class LinkTwilioNumber extends AuthenticatedCommand_1.AuthenticatedCommand {
|
|
72
72
|
run() {
|
|
73
73
|
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
var _a;
|
|
74
75
|
const { flags } = yield this.parse(LinkTwilioNumber);
|
|
75
76
|
const fonosterClient = yield this.createSdkClient();
|
|
76
77
|
const applications = new Fonoster.Applications(fonosterClient);
|
|
@@ -115,7 +116,8 @@ class LinkTwilioNumber extends AuthenticatedCommand_1.AuthenticatedCommand {
|
|
|
115
116
|
phoneNumber: answers.number,
|
|
116
117
|
accessKeyId,
|
|
117
118
|
aclEntries: flags["access-control-list"].split(","),
|
|
118
|
-
|
|
119
|
+
// Trunk inbound URIs live under pstn.<domain> (features.sip.names).
|
|
120
|
+
originationUriBase: (_a = flags["outbound-uri-base"]) !== null && _a !== void 0 ? _a : `pstn.${(yield fonosterClient.getCapabilities()).domain}`,
|
|
119
121
|
applicationRef: answers.applicationRef,
|
|
120
122
|
friendlyName: answers.friendlyName
|
|
121
123
|
});
|
|
@@ -131,8 +133,7 @@ LinkTwilioNumber.examples = ["<%= config.bin %> <%= command.id %>"];
|
|
|
131
133
|
LinkTwilioNumber.flags = {
|
|
132
134
|
"outbound-uri-base": core_1.Flags.string({
|
|
133
135
|
char: "b",
|
|
134
|
-
description: "the
|
|
135
|
-
default: constants_1.FONOSTER_ORIGINATION_URI_BASE,
|
|
136
|
+
description: "the host Twilio sends calls to, under which the trunk's inbound URI is made (default: pstn.<the server's domain>)",
|
|
136
137
|
required: false
|
|
137
138
|
}),
|
|
138
139
|
"access-control-list": core_1.Flags.string({
|
|
@@ -74,7 +74,7 @@ class Login extends BaseCommand_1.BaseCommand {
|
|
|
74
74
|
const { flags } = yield this.parse(Login);
|
|
75
75
|
if (flags["access-key-id"] && flags["access-key-secret"]) {
|
|
76
76
|
const answers = {
|
|
77
|
-
endpoint: (_a = flags.endpoint) !== null && _a !== void 0 ? _a : "api.fonoster.
|
|
77
|
+
endpoint: (_a = flags.endpoint) !== null && _a !== void 0 ? _a : "api.fonoster.ai",
|
|
78
78
|
accessKeyId: flags["access-key-id"],
|
|
79
79
|
accessKeySecret: flags["access-key-secret"]
|
|
80
80
|
};
|
|
@@ -87,7 +87,7 @@ class Login extends BaseCommand_1.BaseCommand {
|
|
|
87
87
|
const answers = {
|
|
88
88
|
endpoint: yield (0, prompts_1.input)({
|
|
89
89
|
message: "Endpoint",
|
|
90
|
-
default: "api.fonoster.
|
|
90
|
+
default: "api.fonoster.ai"
|
|
91
91
|
}),
|
|
92
92
|
accessKeyId: yield (0, prompts_1.input)({
|
|
93
93
|
message: "Access Key Id",
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export declare const BASE_DIR: string;
|
|
2
2
|
export declare const CONFIG_FILE: string;
|
|
3
3
|
export declare const FONOSTER_ACCESS_CONTROL_LIST: string[];
|
|
4
|
-
export declare const FONOSTER_ORIGINATION_URI_BASE = "pstn.fonoster.com";
|
|
5
4
|
export declare const TWILIO_PSTN_URI_BASE = "pstn.twilio.com";
|
|
6
|
-
export declare const WORKSPACE_ENDPOINT = "api.fonoster.
|
|
5
|
+
export declare const WORKSPACE_ENDPOINT = "api.fonoster.ai";
|
package/dist/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.WORKSPACE_ENDPOINT = exports.TWILIO_PSTN_URI_BASE = exports.
|
|
3
|
+
exports.WORKSPACE_ENDPOINT = exports.TWILIO_PSTN_URI_BASE = exports.FONOSTER_ACCESS_CONTROL_LIST = exports.CONFIG_FILE = exports.BASE_DIR = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
|
|
6
6
|
* http://github.com/fonoster/fonoster
|
|
@@ -24,6 +24,5 @@ const path_1 = require("path");
|
|
|
24
24
|
exports.BASE_DIR = (0, path_1.join)((0, os_1.homedir)(), ".fonoster");
|
|
25
25
|
exports.CONFIG_FILE = (0, path_1.join)((0, os_1.homedir)(), ".fonoster", "config.json");
|
|
26
26
|
exports.FONOSTER_ACCESS_CONTROL_LIST = ["165.22.7.155/32"]; // TODO: We will need to allow passing this as a parameter
|
|
27
|
-
exports.FONOSTER_ORIGINATION_URI_BASE = "pstn.fonoster.com";
|
|
28
27
|
exports.TWILIO_PSTN_URI_BASE = "pstn.twilio.com";
|
|
29
|
-
exports.WORKSPACE_ENDPOINT = "api.fonoster.
|
|
28
|
+
exports.WORKSPACE_ENDPOINT = "api.fonoster.ai";
|
|
@@ -5,8 +5,6 @@ export declare const applicationFlags: {
|
|
|
5
5
|
url: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
6
6
|
protocol: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
7
7
|
agent: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
8
|
-
flavor: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
|
-
assistant: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
8
|
voice: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
9
|
language: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
10
|
"stt-model": import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -22,4 +20,5 @@ export declare const applicationFlags: {
|
|
|
22
20
|
recording: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
23
21
|
amd: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
24
22
|
"amd-window": import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
23
|
+
"noise-cancelling": import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
25
24
|
};
|
|
@@ -24,7 +24,7 @@ const core_1 = require("@oclif/core");
|
|
|
24
24
|
exports.applicationFlags = {
|
|
25
25
|
"from-file": core_1.Flags.string({
|
|
26
26
|
char: "f",
|
|
27
|
-
description: "a YAML or JSON file with the Application (an `
|
|
27
|
+
description: "a YAML or JSON file with the Application (an `agent` key makes it an Autopilot agent)"
|
|
28
28
|
}),
|
|
29
29
|
name: core_1.Flags.string({ char: "n", description: "the Application name" }),
|
|
30
30
|
url: core_1.Flags.string({
|
|
@@ -39,9 +39,6 @@ exports.applicationFlags = {
|
|
|
39
39
|
char: "a",
|
|
40
40
|
description: "a YAML or JSON agent file; makes it an Autopilot agent (hosted by Fonoster)"
|
|
41
41
|
}),
|
|
42
|
-
// Renamed in 0.30; kept hidden so old scripts get a clear error.
|
|
43
|
-
flavor: core_1.Flags.string({ hidden: true }),
|
|
44
|
-
assistant: core_1.Flags.string({ hidden: true }),
|
|
45
42
|
voice: core_1.Flags.string({
|
|
46
43
|
description: "TTS voice as a catalog id (e.g. deepgram/aura-2-thalia-en)"
|
|
47
44
|
}),
|
|
@@ -91,5 +88,8 @@ exports.applicationFlags = {
|
|
|
91
88
|
}),
|
|
92
89
|
"amd-window": core_1.Flags.integer({
|
|
93
90
|
description: "milliseconds of caller audio AMD classifies (500 to 15000, default 4000); implies --amd"
|
|
91
|
+
}),
|
|
92
|
+
"noise-cancelling": core_1.Flags.string({
|
|
93
|
+
description: "noise cancelling on the caller's audio: none, or a noise-cancelling provider (aicoustics)"
|
|
94
94
|
})
|
|
95
95
|
};
|
|
@@ -4,9 +4,6 @@ type ApplicationFlags = {
|
|
|
4
4
|
url?: string;
|
|
5
5
|
protocol?: string;
|
|
6
6
|
agent?: string;
|
|
7
|
-
/** Renamed flags (0.30): rejected with a clear error. */
|
|
8
|
-
flavor?: string;
|
|
9
|
-
assistant?: string;
|
|
10
7
|
voice?: string;
|
|
11
8
|
language?: string;
|
|
12
9
|
"stt-model"?: string;
|
|
@@ -22,6 +19,8 @@ type ApplicationFlags = {
|
|
|
22
19
|
recording?: string;
|
|
23
20
|
amd?: boolean;
|
|
24
21
|
"amd-window"?: number;
|
|
22
|
+
/** none, or an nc provider id (aicoustics). */
|
|
23
|
+
"noise-cancelling"?: string;
|
|
25
24
|
};
|
|
26
25
|
type AppRequest = CreateApplicationRequest & {
|
|
27
26
|
ref?: string;
|
|
@@ -32,7 +31,7 @@ declare function readConfigFile<T = Record<string, unknown>>(filePath: string):
|
|
|
32
31
|
declare function parseListener(value: string): AppListener;
|
|
33
32
|
/** An existing app as a create/update request (blank fields dropped). */
|
|
34
33
|
declare function applicationToRequest(app: Application): AppRequest;
|
|
35
|
-
/** A file in the new app model; `
|
|
34
|
+
/** A file in the new app model; `agent` (inline) makes it an Autopilot agent. */
|
|
36
35
|
declare function fileToRequest(raw: Record<string, unknown>): AppRequest;
|
|
37
36
|
/**
|
|
38
37
|
* Applies command flags on top of `base` (the current app on update, `{}` on create).
|
|
@@ -40,6 +40,7 @@ exports.readConfigFile = readConfigFile;
|
|
|
40
40
|
*/
|
|
41
41
|
const fs_1 = require("fs");
|
|
42
42
|
const path_1 = __importDefault(require("path"));
|
|
43
|
+
const common_1 = require("@fonoster/common");
|
|
43
44
|
const js_yaml_1 = require("js-yaml");
|
|
44
45
|
const TRACKS = ["inbound", "outbound", "both"];
|
|
45
46
|
/** Reads a YAML or JSON file into an object. */
|
|
@@ -73,18 +74,18 @@ function blank(value) {
|
|
|
73
74
|
function compact(obj) {
|
|
74
75
|
return Object.fromEntries(Object.entries(obj).filter(([, v]) => !blank(v)));
|
|
75
76
|
}
|
|
76
|
-
/** The LLM product the control plane files the
|
|
77
|
-
function intelligenceFor(
|
|
77
|
+
/** The LLM product the control plane files the agent under (`llm.<provider>`). */
|
|
78
|
+
function intelligenceFor(agent) {
|
|
78
79
|
var _a;
|
|
79
|
-
const model = (_a =
|
|
80
|
+
const model = (_a = agent.languageModel) === null || _a === void 0 ? void 0 : _a.model;
|
|
80
81
|
return {
|
|
81
82
|
productRef: (model === null || model === void 0 ? void 0 : model.includes("/")) ? `llm.${model.split("/")[0]}` : "",
|
|
82
|
-
config:
|
|
83
|
+
config: agent
|
|
83
84
|
};
|
|
84
85
|
}
|
|
85
86
|
/** An existing app as a create/update request (blank fields dropped). */
|
|
86
87
|
function applicationToRequest(app) {
|
|
87
|
-
var _a, _b, _c, _d, _e;
|
|
88
|
+
var _a, _b, _c, _d, _e, _f;
|
|
88
89
|
const request = {
|
|
89
90
|
name: app.name,
|
|
90
91
|
type: app.type,
|
|
@@ -97,31 +98,28 @@ function applicationToRequest(app) {
|
|
|
97
98
|
recording: (app.recording || undefined),
|
|
98
99
|
amd: ((_d = app.amd) === null || _d === void 0 ? void 0 : _d.enabled)
|
|
99
100
|
? compact({ enabled: true, windowMs: app.amd.windowMs })
|
|
100
|
-
: undefined
|
|
101
|
+
: undefined,
|
|
102
|
+
filters: (_e = app.filters) !== null && _e !== void 0 ? _e : []
|
|
101
103
|
};
|
|
102
104
|
// Autopilot apps follow the operator's hosted Autopilot URL; only streams carry theirs.
|
|
103
105
|
if (app.type !== "AUTOPILOT")
|
|
104
106
|
request.url = app.url || app.endpoint;
|
|
105
|
-
const config = (
|
|
107
|
+
const config = (_f = app.intelligence) === null || _f === void 0 ? void 0 : _f.config;
|
|
106
108
|
if (app.type === "AUTOPILOT" && config && Object.keys(config).length) {
|
|
107
109
|
request.intelligence = intelligenceFor(config);
|
|
108
110
|
}
|
|
109
111
|
return compact(request);
|
|
110
112
|
}
|
|
111
|
-
/** A file in the new app model; `
|
|
113
|
+
/** A file in the new app model; `agent` (inline) makes it an Autopilot agent. */
|
|
112
114
|
function fileToRequest(raw) {
|
|
113
115
|
var _a, _b;
|
|
114
|
-
|
|
115
|
-
throw new Error("`flavor` was renamed to `protocol` (fonoster or twilio; native is now fonoster)");
|
|
116
|
-
if (raw.type === "EXTERNAL")
|
|
117
|
-
throw new Error("type EXTERNAL was renamed to STREAM");
|
|
118
|
-
const _c = raw, { assistant } = _c, rest = __rest(_c, ["assistant"]);
|
|
116
|
+
const _c = raw, { agent } = _c, rest = __rest(_c, ["agent"]);
|
|
119
117
|
const request = Object.assign({}, rest);
|
|
120
118
|
// Test cases belong to applications:eval, not to the app.
|
|
121
119
|
delete request.testCases;
|
|
122
|
-
if (
|
|
120
|
+
if (agent) {
|
|
123
121
|
request.type = "AUTOPILOT";
|
|
124
|
-
request.intelligence = intelligenceFor(
|
|
122
|
+
request.intelligence = intelligenceFor(agent);
|
|
125
123
|
}
|
|
126
124
|
// Never send a model key that sits in an agent file; keys live in the vendor keys.
|
|
127
125
|
const lm = (_b = (_a = request.intelligence) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.languageModel;
|
|
@@ -135,16 +133,12 @@ function fileToRequest(raw) {
|
|
|
135
133
|
function applyFlags(base, flags) {
|
|
136
134
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
137
135
|
const request = Object.assign(Object.assign({}, base), { speech: Object.assign({}, ((_a = base.speech) !== null && _a !== void 0 ? _a : {})), listeners: [...((_b = base.listeners) !== null && _b !== void 0 ? _b : [])] });
|
|
138
|
-
if (flags.assistant !== undefined)
|
|
139
|
-
throw new Error("--assistant was renamed to --agent");
|
|
140
|
-
if (flags.flavor !== undefined)
|
|
141
|
-
throw new Error("--flavor was renamed to --protocol (fonoster or twilio; native is now fonoster)");
|
|
142
136
|
if (flags.name !== undefined)
|
|
143
137
|
request.name = flags.name;
|
|
144
138
|
if (flags.agent) {
|
|
145
|
-
const
|
|
139
|
+
const agent = readConfigFile(flags.agent);
|
|
146
140
|
request.type = "AUTOPILOT";
|
|
147
|
-
request.intelligence = fileToRequest({
|
|
141
|
+
request.intelligence = fileToRequest({ agent }).intelligence;
|
|
148
142
|
}
|
|
149
143
|
if (flags.url !== undefined)
|
|
150
144
|
request.url = flags.url;
|
|
@@ -188,10 +182,22 @@ function applyFlags(base, flags) {
|
|
|
188
182
|
const windowMs = (_l = flags["amd-window"]) !== null && _l !== void 0 ? _l : (_m = request.amd) === null || _m === void 0 ? void 0 : _m.windowMs;
|
|
189
183
|
request.amd = windowMs ? { enabled: true, windowMs } : { enabled: true };
|
|
190
184
|
}
|
|
185
|
+
if (flags["noise-cancelling"] !== undefined)
|
|
186
|
+
request.filters = noiseCancellingFilters(flags["noise-cancelling"]);
|
|
191
187
|
if (!request.type)
|
|
192
188
|
request.type = "STREAM";
|
|
193
189
|
return request;
|
|
194
190
|
}
|
|
191
|
+
/** `--noise-cancelling none|<nc provider>` as the app's filters (one filter per provider). */
|
|
192
|
+
function noiseCancellingFilters(value) {
|
|
193
|
+
const provider = value.trim().toLowerCase();
|
|
194
|
+
if (!provider || provider === "none" || provider === "off")
|
|
195
|
+
return [];
|
|
196
|
+
const name = common_1.AudioFilters.FILTER_BY_PROVIDER[provider];
|
|
197
|
+
if (!name)
|
|
198
|
+
throw new Error(`unknown noise-cancelling provider "${value}" (use none or ${Object.keys(common_1.AudioFilters.FILTER_BY_PROVIDER).join(", ")})`);
|
|
199
|
+
return [{ name }];
|
|
200
|
+
}
|
|
195
201
|
/** Throws the errors the control plane would, before a round trip. */
|
|
196
202
|
function checkRequest(request) {
|
|
197
203
|
var _a;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fonoster/ctl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"description": "Fonoster Control Tool",
|
|
5
5
|
"author": "Pedro Sanders <psanders@fonoster.com>",
|
|
6
6
|
"homepage": "https://github.com/fonoster/fonoster#readme",
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
"scripts": {
|
|
15
15
|
"prebuild": "rimraf ./dist tsconfig.tsbuildinfo",
|
|
16
16
|
"build": "tsc -b tsconfig.json",
|
|
17
|
-
"clean": "rimraf ./dist node_modules tsconfig.tsbuildinfo",
|
|
18
17
|
"generate:readme": "oclif readme"
|
|
19
18
|
},
|
|
20
19
|
"files": [
|
|
@@ -30,7 +29,7 @@
|
|
|
30
29
|
"bugs": {
|
|
31
30
|
"url": "https://github.com/fonoster/fonoster/issues"
|
|
32
31
|
},
|
|
33
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "f0a5102dddeea0f70f659234108805bc10690f2e",
|
|
34
33
|
"bin": {
|
|
35
34
|
"fonoster": "./bin/run.js"
|
|
36
35
|
},
|
|
@@ -51,7 +50,7 @@
|
|
|
51
50
|
}
|
|
52
51
|
},
|
|
53
52
|
"dependencies": {
|
|
54
|
-
"@fonoster/sdk": "^0.
|
|
53
|
+
"@fonoster/sdk": "^0.31.0",
|
|
55
54
|
"@inquirer/prompts": "^7.1.0",
|
|
56
55
|
"@oclif/core": "^4.0.34",
|
|
57
56
|
"@oclif/plugin-warn-if-update-available": "^3.1.28",
|