@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 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 `assistant` key makes it an Autopilot
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 `assistant` key makes it an Autopilot
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> [default: pstn.fonoster.com] the uri to point twilio to for outbound calls (use if
1380
- running your Fonoster instance)
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 assistant (its catalog id names the provider; keys come from the workspace or
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.sessionAssistantSchema.parse(rawAutopilotApplication.intelligence.config);
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 assistant = (_c = app.intelligence) === null || _c === void 0 ? void 0 : _c.config;
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 = assistant === null || assistant === void 0 ? void 0 : assistant.languageModel) === null || _d === void 0 ? void 0 : _d.model)}`]
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 = {
@@ -122,7 +122,7 @@ Catalog.flags = {
122
122
  type: core_1.Flags.string({
123
123
  char: "t",
124
124
  description: "only this capability",
125
- options: ["stt", "tts", "llm"]
125
+ options: ["stt", "tts", "llm", "nc"]
126
126
  })
127
127
  };
128
128
  exports.default = Catalog;
@@ -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
- originationUriBase: flags["outbound-uri-base"],
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 uri to point twilio to for outbound calls (use if running your Fonoster instance)",
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.com",
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.com"
90
+ default: "api.fonoster.ai"
91
91
  }),
92
92
  accessKeyId: yield (0, prompts_1.input)({
93
93
  message: "Access Key Id",
@@ -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.com";
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.FONOSTER_ORIGINATION_URI_BASE = exports.FONOSTER_ACCESS_CONTROL_LIST = exports.CONFIG_FILE = exports.BASE_DIR = void 0;
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.com";
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 `assistant` key makes it an Autopilot agent)"
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; `assistant` (inline) makes it an Autopilot agent. */
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 assistant under (`llm.<provider>`). */
77
- function intelligenceFor(assistant) {
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 = assistant.languageModel) === null || _a === void 0 ? void 0 : _a.model;
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: assistant
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 = (_e = app.intelligence) === null || _e === void 0 ? void 0 : _e.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; `assistant` (inline) makes it an Autopilot agent. */
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
- if (raw.flavor !== undefined)
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 (assistant) {
120
+ if (agent) {
123
121
  request.type = "AUTOPILOT";
124
- request.intelligence = intelligenceFor(assistant);
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 assistant = readConfigFile(flags.agent);
139
+ const agent = readConfigFile(flags.agent);
146
140
  request.type = "AUTOPILOT";
147
- request.intelligence = fileToRequest({ assistant }).intelligence;
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.30.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": "b59b06a3ef325abe3f188c0fb87cc22d50ed5471",
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.30.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",