@fonoster/common 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.
Files changed (88) hide show
  1. package/dist/{assistants → agents}/index.d.ts +1 -1
  2. package/dist/{assistants → agents}/index.js +1 -1
  3. package/dist/{assistants/sessionAssistantSchema.d.ts → agents/sessionAgentSchema.d.ts} +20 -6
  4. package/dist/{assistants/sessionAssistantSchema.js → agents/sessionAgentSchema.js} +16 -11
  5. package/dist/cellsecrets/index.d.ts +2 -2
  6. package/dist/cellsecrets/index.js +3 -3
  7. package/dist/config/cli/render.d.ts +1 -1
  8. package/dist/config/cli/render.js +3 -3
  9. package/dist/config/configHints.d.ts +1 -14
  10. package/dist/config/configHints.js +16 -30
  11. package/dist/config/index.d.ts +0 -1
  12. package/dist/config/index.js +0 -1
  13. package/dist/config/interpolateEnv.d.ts +1 -1
  14. package/dist/config/loadServiceConfig.d.ts +0 -5
  15. package/dist/config/loadServiceConfig.js +3 -12
  16. package/dist/constants.d.ts +1 -3
  17. package/dist/constants.js +3 -5
  18. package/dist/errors/handleZodError.js +3 -1
  19. package/dist/filters/index.d.ts +70 -0
  20. package/dist/filters/index.js +101 -0
  21. package/dist/identity/roles.js +11 -1
  22. package/dist/index.d.ts +4 -1
  23. package/dist/index.js +5 -2
  24. package/dist/protos/applications.proto +16 -2
  25. package/dist/protos/authz.proto +3 -0
  26. package/dist/protos/billing.proto +92 -0
  27. package/dist/protos/calls.proto +4 -0
  28. package/dist/protos/capabilities.proto +8 -0
  29. package/dist/protos/providers.proto +6 -2
  30. package/dist/protos/roomr.proto +146 -0
  31. package/dist/protos/session.proto +194 -0
  32. package/dist/protos/usage.proto +59 -0
  33. package/dist/registry/Registry.d.ts +13 -5
  34. package/dist/registry/Registry.js +49 -35
  35. package/dist/registry/cli.js +19 -7
  36. package/dist/registry/features.d.ts +2 -2
  37. package/dist/registry/features.js +7 -5
  38. package/dist/registry/prisma.d.ts +2 -2
  39. package/dist/registry/prisma.js +26 -18
  40. package/dist/registry/types.d.ts +17 -5
  41. package/dist/registry/types.js +2 -0
  42. package/dist/roomr/health.d.ts +9 -0
  43. package/dist/roomr/health.js +75 -0
  44. package/dist/roomr/index.d.ts +75 -0
  45. package/dist/roomr/index.js +146 -0
  46. package/dist/roomr/session.d.ts +133 -0
  47. package/dist/roomr/session.js +132 -0
  48. package/dist/session/schema.d.ts +196 -7
  49. package/dist/session/schema.js +59 -8
  50. package/dist/sessions/index.d.ts +15 -12
  51. package/dist/sessions/index.js +15 -12
  52. package/dist/telemetry.d.ts +1 -1
  53. package/dist/usage/CallUsage.d.ts +38 -0
  54. package/dist/usage/CallUsage.js +76 -0
  55. package/dist/{utils/types.d.ts → usage/index.d.ts} +4 -5
  56. package/dist/usage/index.js +38 -0
  57. package/dist/usage/meters.d.ts +113 -0
  58. package/dist/usage/meters.js +90 -0
  59. package/dist/usage/types.d.ts +159 -0
  60. package/dist/usage/types.js +84 -0
  61. package/dist/usage/usageId.d.ts +6 -0
  62. package/dist/usage/usageId.js +45 -0
  63. package/dist/utils/index.d.ts +0 -2
  64. package/dist/utils/index.js +0 -2
  65. package/dist/utils/withErrorHandling.js +1 -1
  66. package/dist/validators/calls.d.ts +5 -2
  67. package/dist/validators/calls.js +8 -1
  68. package/dist/validators/sip.d.ts +2 -2
  69. package/dist/validators/sip.js +3 -3
  70. package/dist/webhooks/bus.d.ts +29 -10
  71. package/dist/webhooks/bus.js +58 -50
  72. package/dist/webhooks/events.d.ts +1 -1
  73. package/dist/webhooks/events.js +1 -1
  74. package/package.json +9 -8
  75. package/schema/session.v1.json +82 -2
  76. package/dist/config/integrationsSchema.d.ts +0 -32
  77. package/dist/config/integrationsSchema.js +0 -56
  78. package/dist/utils/createFetchSingleCallByCallId.d.ts +0 -22
  79. package/dist/utils/createFetchSingleCallByCallId.js +0 -33
  80. package/dist/utils/types.js +0 -2
  81. /package/dist/{assistants → agents}/testCasesSchema.d.ts +0 -0
  82. /package/dist/{assistants → agents}/testCasesSchema.js +0 -0
  83. /package/dist/{assistants → agents}/tools/index.d.ts +0 -0
  84. /package/dist/{assistants → agents}/tools/index.js +0 -0
  85. /package/dist/{assistants → agents}/tools/propertySchema.d.ts +0 -0
  86. /package/dist/{assistants → agents}/tools/propertySchema.js +0 -0
  87. /package/dist/{assistants → agents}/tools/toolSchema.d.ts +0 -0
  88. /package/dist/{assistants → agents}/tools/toolSchema.js +0 -0
@@ -17,5 +17,5 @@
17
17
  * limitations under the License.
18
18
  */
19
19
  export * from "./tools";
20
- export * from "./sessionAssistantSchema";
20
+ export * from "./sessionAgentSchema";
21
21
  export * from "./testCasesSchema";
@@ -33,5 +33,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
33
33
  * limitations under the License.
34
34
  */
35
35
  __exportStar(require("./tools"), exports);
36
- __exportStar(require("./sessionAssistantSchema"), exports);
36
+ __exportStar(require("./sessionAgentSchema"), exports);
37
37
  __exportStar(require("./testCasesSchema"), exports);
@@ -214,12 +214,16 @@ export declare const sessionConversationSettingsSchema: z.ZodObject<{
214
214
  transferOptions: z.ZodOptional<z.ZodObject<{
215
215
  phoneNumber: z.ZodString;
216
216
  message: z.ZodString;
217
+ /** Said when the transfer fails, before the conversation goes on (default in Autopilot). */
218
+ failedMessage: z.ZodOptional<z.ZodString>;
217
219
  }, "strip", z.ZodTypeAny, {
218
220
  message?: string;
219
221
  phoneNumber?: string;
222
+ failedMessage?: string;
220
223
  }, {
221
224
  message?: string;
222
225
  phoneNumber?: string;
226
+ failedMessage?: string;
223
227
  }>>;
224
228
  idleOptions: z.ZodOptional<z.ZodObject<{
225
229
  message: z.ZodString;
@@ -236,7 +240,7 @@ export declare const sessionConversationSettingsSchema: z.ZodObject<{
236
240
  }>>;
237
241
  allowUserBargeIn: z.ZodDefault<z.ZodBoolean>;
238
242
  /**
239
- * The turn-taking patience knob (TT-B5): sent to the gateway with listen.update so its Pacing
243
+ * The turn-taking patience knob (TT-B5): sent to AppBridge with listen.update so its Pacing
240
244
  * policy waits less (low) or more (high) before turn.ended. Autopilot prepares a reply on
241
245
  * turn.likely_ended at low and normal, and only on turn.ended at high.
242
246
  */
@@ -266,6 +270,7 @@ export declare const sessionConversationSettingsSchema: z.ZodObject<{
266
270
  transferOptions?: {
267
271
  message?: string;
268
272
  phoneNumber?: string;
273
+ failedMessage?: string;
269
274
  };
270
275
  idleOptions?: {
271
276
  message?: string;
@@ -292,6 +297,7 @@ export declare const sessionConversationSettingsSchema: z.ZodObject<{
292
297
  transferOptions?: {
293
298
  message?: string;
294
299
  phoneNumber?: string;
300
+ failedMessage?: string;
295
301
  };
296
302
  idleOptions?: {
297
303
  message?: string;
@@ -309,7 +315,7 @@ export declare const sessionConversationSettingsSchema: z.ZodObject<{
309
315
  vad?: any;
310
316
  maxSpeechWaitTimeout?: any;
311
317
  }>;
312
- export declare const sessionAssistantSchema: z.ZodObject<{
318
+ export declare const sessionAgentSchema: z.ZodObject<{
313
319
  conversationSettings: z.ZodObject<{
314
320
  firstMessage: z.ZodOptional<z.ZodString>;
315
321
  systemPrompt: z.ZodString;
@@ -320,12 +326,16 @@ export declare const sessionAssistantSchema: z.ZodObject<{
320
326
  transferOptions: z.ZodOptional<z.ZodObject<{
321
327
  phoneNumber: z.ZodString;
322
328
  message: z.ZodString;
329
+ /** Said when the transfer fails, before the conversation goes on (default in Autopilot). */
330
+ failedMessage: z.ZodOptional<z.ZodString>;
323
331
  }, "strip", z.ZodTypeAny, {
324
332
  message?: string;
325
333
  phoneNumber?: string;
334
+ failedMessage?: string;
326
335
  }, {
327
336
  message?: string;
328
337
  phoneNumber?: string;
338
+ failedMessage?: string;
329
339
  }>>;
330
340
  idleOptions: z.ZodOptional<z.ZodObject<{
331
341
  message: z.ZodString;
@@ -342,7 +352,7 @@ export declare const sessionAssistantSchema: z.ZodObject<{
342
352
  }>>;
343
353
  allowUserBargeIn: z.ZodDefault<z.ZodBoolean>;
344
354
  /**
345
- * The turn-taking patience knob (TT-B5): sent to the gateway with listen.update so its Pacing
355
+ * The turn-taking patience knob (TT-B5): sent to AppBridge with listen.update so its Pacing
346
356
  * policy waits less (low) or more (high) before turn.ended. Autopilot prepares a reply on
347
357
  * turn.likely_ended at low and normal, and only on turn.ended at high.
348
358
  */
@@ -372,6 +382,7 @@ export declare const sessionAssistantSchema: z.ZodObject<{
372
382
  transferOptions?: {
373
383
  message?: string;
374
384
  phoneNumber?: string;
385
+ failedMessage?: string;
375
386
  };
376
387
  idleOptions?: {
377
388
  message?: string;
@@ -398,6 +409,7 @@ export declare const sessionAssistantSchema: z.ZodObject<{
398
409
  transferOptions?: {
399
410
  message?: string;
400
411
  phoneNumber?: string;
412
+ failedMessage?: string;
401
413
  };
402
414
  idleOptions?: {
403
415
  message?: string;
@@ -617,6 +629,7 @@ export declare const sessionAssistantSchema: z.ZodObject<{
617
629
  transferOptions?: {
618
630
  message?: string;
619
631
  phoneNumber?: string;
632
+ failedMessage?: string;
620
633
  };
621
634
  idleOptions?: {
622
635
  message?: string;
@@ -681,6 +694,7 @@ export declare const sessionAssistantSchema: z.ZodObject<{
681
694
  transferOptions?: {
682
695
  message?: string;
683
696
  phoneNumber?: string;
697
+ failedMessage?: string;
684
698
  };
685
699
  idleOptions?: {
686
700
  message?: string;
@@ -735,7 +749,7 @@ export declare const sessionAssistantSchema: z.ZodObject<{
735
749
  eventsHook?: any;
736
750
  audioFilters?: any;
737
751
  }>;
738
- export type SessionAssistant = z.infer<typeof sessionAssistantSchema>;
739
- export type SessionConversationSettings = SessionAssistant["conversationSettings"];
740
- export type SessionLanguageModel = SessionAssistant["languageModel"];
752
+ export type SessionAgent = z.infer<typeof sessionAgentSchema>;
753
+ export type SessionConversationSettings = SessionAgent["conversationSettings"];
754
+ export type SessionLanguageModel = SessionAgent["languageModel"];
741
755
  export type ToolDefinition = SessionLanguageModel["tools"][number];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.sessionAssistantSchema = exports.sessionConversationSettingsSchema = exports.sessionLanguageModelSchema = void 0;
3
+ exports.sessionAgentSchema = exports.sessionConversationSettingsSchema = exports.sessionLanguageModelSchema = void 0;
4
4
  /**
5
5
  * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
6
6
  * http://github.com/fonoster/fonoster
@@ -21,10 +21,10 @@ exports.sessionAssistantSchema = exports.sessionConversationSettingsSchema = exp
21
21
  */
22
22
  const zod_1 = require("zod");
23
23
  const tools_1 = require("./tools");
24
- // The assistant config for the rebuilt Autopilot (rework-autopilot A8, A11, A12; tasks 5.1, 5.2,
25
- // 5.4). Strict: vendor credentials, vendor enums, VAD settings and the assistant webhook are
26
- // rejected with messages pointing to where they moved. It is the only assistant schema: the legacy
27
- // one was deleted after the cutover job converts stored assistants (rework-autopilot 8.2).
24
+ // The agent config for the rebuilt Autopilot (rework-autopilot A8, A11, A12; tasks 5.1, 5.2,
25
+ // 5.4). Strict: vendor credentials, vendor enums, VAD settings and the agent webhook are
26
+ // rejected with messages pointing to where they moved. It is the only agent schema: the legacy
27
+ // one was deleted after the cutover job converts stored agents (rework-autopilot 8.2).
28
28
  const removed = (key, message) => zod_1.z
29
29
  .any()
30
30
  .optional()
@@ -73,7 +73,12 @@ exports.sessionConversationSettingsSchema = zod_1.z
73
73
  .positive()
74
74
  .default(30 * 60 * 1000),
75
75
  transferOptions: zod_1.z
76
- .object({ phoneNumber: zod_1.z.string(), message: zod_1.z.string() })
76
+ .object({
77
+ phoneNumber: zod_1.z.string(),
78
+ message: zod_1.z.string(),
79
+ /** Said when the transfer fails, before the conversation goes on (default in Autopilot). */
80
+ failedMessage: zod_1.z.string().optional()
81
+ })
77
82
  .optional(),
78
83
  idleOptions: zod_1.z
79
84
  .object({
@@ -84,7 +89,7 @@ exports.sessionConversationSettingsSchema = zod_1.z
84
89
  .optional(),
85
90
  allowUserBargeIn: zod_1.z.boolean().default(true),
86
91
  /**
87
- * The turn-taking patience knob (TT-B5): sent to the gateway with listen.update so its Pacing
92
+ * The turn-taking patience knob (TT-B5): sent to AppBridge with listen.update so its Pacing
88
93
  * policy waits less (low) or more (high) before turn.ended. Autopilot prepares a reply on
89
94
  * turn.likely_ended at low and normal, and only on turn.ended at high.
90
95
  */
@@ -96,17 +101,17 @@ exports.sessionConversationSettingsSchema = zod_1.z
96
101
  /** Catalog ids overriding the app's speech defaults on every speak. */
97
102
  voice: zod_1.z.string().optional(),
98
103
  language: zod_1.z.string().optional(),
99
- vad: removed("vad", "turn detection moved to the gateway (turn-taking configuration)"),
100
- maxSpeechWaitTimeout: removed("maxSpeechWaitTimeout", "turn detection moved to the gateway")
104
+ vad: removed("vad", "turn detection moved to AppBridge (turn-taking configuration)"),
105
+ maxSpeechWaitTimeout: removed("maxSpeechWaitTimeout", "turn detection moved to AppBridge")
101
106
  })
102
107
  .strict();
103
- exports.sessionAssistantSchema = zod_1.z
108
+ exports.sessionAgentSchema = zod_1.z
104
109
  .object({
105
110
  conversationSettings: exports.sessionConversationSettingsSchema,
106
111
  languageModel: exports.sessionLanguageModelSchema,
107
112
  /** Conversation eval cases, kept as they were (evaluated outside calls). */
108
113
  testCases: zod_1.z.any().optional(),
109
- eventsHook: removed("eventsHook", "assistant webhooks were retired; use workspace webhooks (conversation.ended → call.ended or call_record.sealed)"),
114
+ eventsHook: removed("eventsHook", "agent webhooks were retired; use workspace webhooks (conversation.ended → call.ended or call_record.sealed)"),
110
115
  audioFilters: removed("audioFilters", "audio filters are part of the app's configuration")
111
116
  })
112
117
  .strict();
@@ -52,7 +52,7 @@ export declare class DirectorySecretStore implements CellSecretStore {
52
52
  /** The store a config names (dir wins over file). */
53
53
  export declare function openCellSecrets(config: CellSecretsConfig, env?: Record<string, string | undefined>): CellSecretStore;
54
54
  /**
55
- * The cell's secrets as a workspace key source (gateway Catalog, Autopilot): a private region
55
+ * The cell's secrets as a workspace key source (appbridge Catalog, Autopilot): a private region
56
56
  * serves one workspace, so the provider name alone picks the key. Read errors count as unset.
57
57
  */
58
58
  export declare class CellSecretKeys {
@@ -84,7 +84,7 @@ export declare const CELL_WORKSPACE_KEYS_SUBJECT = "cell.workspacekeys.get";
84
84
  export declare class NatsWorkspaceKeys {
85
85
  private readonly requester;
86
86
  private readonly timeoutMs;
87
- /** Never cached: the gateway keeps no adapter built with these keys past the call's lookup. */
87
+ /** Never cached: AppBridge keeps no adapter built with these keys past the call's lookup. */
88
88
  readonly cacheable = false;
89
89
  constructor(requester: () => Promise<KeyRequester>, timeoutMs?: number);
90
90
  get(workspaceRef: string, providerId: string): Promise<string | undefined>;
@@ -72,7 +72,7 @@ const path = __importStar(require("path"));
72
72
  // - an encrypted file (Compose, bare metal): AES-256-GCM, key derived with scrypt from a
73
73
  // passphrase in the environment (default FONOSTER_REGION_SECRETS_KEY);
74
74
  // - a directory with one file per secret: a mounted Kubernetes Secret.
75
- // The gateway and the hosted Autopilot read it; `fonoster-region secrets` writes it. Values are
75
+ // AppBridge and the hosted Autopilot read it; `fonoster-region secrets` writes it. Values are
76
76
  // never logged; `names()` is what the region agent reports in heartbeats.
77
77
  /** Secret names: provider ids and credential refs (`deepgram`, `groq`, `openai`, `s3.secret`). */
78
78
  exports.SECRET_NAME = /^[a-z0-9][a-z0-9._-]{0,63}$/;
@@ -224,7 +224,7 @@ function openCellSecrets(config, env = process.env) {
224
224
  return new EncryptedFileSecretStore(config.file, key);
225
225
  }
226
226
  /**
227
- * The cell's secrets as a workspace key source (gateway Catalog, Autopilot): a private region
227
+ * The cell's secrets as a workspace key source (appbridge Catalog, Autopilot): a private region
228
228
  * serves one workspace, so the provider name alone picks the key. Read errors count as unset.
229
229
  */
230
230
  class CellSecretKeys {
@@ -275,7 +275,7 @@ class NatsWorkspaceKeys {
275
275
  constructor(requester, timeoutMs = 2000) {
276
276
  this.requester = requester;
277
277
  this.timeoutMs = timeoutMs;
278
- /** Never cached: the gateway keeps no adapter built with these keys past the call's lookup. */
278
+ /** Never cached: AppBridge keeps no adapter built with these keys past the call's lookup. */
279
279
  this.cacheable = false;
280
280
  }
281
281
  get(workspaceRef, providerId) {
@@ -27,7 +27,7 @@ export declare const FONOSTER_SERVICE_FILES: string[];
27
27
  export declare function renderTemplate(text: string, env: Env, file?: string, substitute?: boolean): string;
28
28
  export declare function deepMerge(base: unknown, overlay: unknown): unknown;
29
29
  export declare const EXAMPLE: RegExp;
30
- /** The rendered name of an example (`gateway.example.yaml` → `gateway.yaml`). */
30
+ /** The rendered name of an example (`appbridge.example.yaml` → `appbridge.yaml`). */
31
31
  export declare function renderedName(example: string): string | undefined;
32
32
  export declare function listExamples(configDir: string): string[];
33
33
  export type RenderOptions = {
@@ -40,9 +40,9 @@ exports.RenderError = RenderError;
40
40
  exports.FONOSTER_SERVICE_FILES = [
41
41
  "fonoster",
42
42
  "identity",
43
- "gateway",
43
+ "appbridge",
44
44
  "autopilot",
45
- "medianode"
45
+ "roomr"
46
46
  ];
47
47
  /**
48
48
  * Checks one template's placeholders and returns it with them kept (`substitute` false) or
@@ -82,7 +82,7 @@ function deepMerge(base, overlay) {
82
82
  return out;
83
83
  }
84
84
  exports.EXAMPLE = /^(.+)\.example\.([A-Za-z0-9]+)$/;
85
- /** The rendered name of an example (`gateway.example.yaml` → `gateway.yaml`). */
85
+ /** The rendered name of an example (`appbridge.example.yaml` → `appbridge.yaml`). */
86
86
  function renderedName(example) {
87
87
  const m = exports.EXAMPLE.exec(example);
88
88
  return m ? `${m[1]}.${m[2]}` : undefined;
@@ -16,19 +16,6 @@
16
16
  * See the License for the specific language governing permissions and
17
17
  * limitations under the License.
18
18
  */
19
- type Env = Record<string, string | undefined>;
20
- /** Old key path → new key path, e.g. `{ encryptionKey: "encryption.key" }`. */
21
- type MovedKeys = Record<string, string>;
22
- /**
23
- * Lists the moved keys present in a raw config, as readable hints. The new
24
- * location may itself be valid, so this only reports what was found.
25
- */
26
- declare function findMovedKeys(raw: unknown, movedKeys: MovedKeys): string[];
27
- /**
28
- * Names of environment variables that look like the old env-based config for
29
- * this service. Values are never returned, so they can be logged safely.
30
- */
31
- declare function findLegacyEnv(prefixes: string[], env?: Env): string[];
32
19
  /** Edit distance between two strings (insertions, deletions, substitutions). */
33
20
  declare function levenshtein(a: string, b: string): number;
34
21
  /**
@@ -36,4 +23,4 @@ declare function levenshtein(a: string, b: string): number;
36
23
  * to be a typo: at most a third of the key's length (at least 1) edits away, ignoring case.
37
24
  */
38
25
  declare function suggestKey(unknown: string, known: string[]): string | undefined;
39
- export { findMovedKeys, findLegacyEnv, levenshtein, suggestKey, MovedKeys };
26
+ export { levenshtein, suggestKey };
@@ -1,39 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.findMovedKeys = findMovedKeys;
4
- exports.findLegacyEnv = findLegacyEnv;
5
3
  exports.levenshtein = levenshtein;
6
4
  exports.suggestKey = suggestKey;
7
- function hasPath(input, path) {
8
- let current = input;
9
- for (const segment of path.split(".")) {
10
- if (current === null ||
11
- typeof current !== "object" ||
12
- !(segment in current)) {
13
- return false;
14
- }
15
- current = current[segment];
16
- }
17
- return true;
18
- }
19
- /**
20
- * Lists the moved keys present in a raw config, as readable hints. The new
21
- * location may itself be valid, so this only reports what was found.
22
- */
23
- function findMovedKeys(raw, movedKeys) {
24
- return Object.entries(movedKeys)
25
- .filter(([from]) => hasPath(raw, from))
26
- .map(([from, to]) => `"${from}" moved to "${to}"`);
27
- }
28
5
  /**
29
- * Names of environment variables that look like the old env-based config for
30
- * this service. Values are never returned, so they can be logged safely.
6
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
7
+ * http://github.com/fonoster/fonoster
8
+ *
9
+ * This file is part of Fonoster
10
+ *
11
+ * Licensed under the MIT License (the "License");
12
+ * you may not use this file except in compliance with
13
+ * the License. You may obtain a copy of the License at
14
+ *
15
+ * https://opensource.org/licenses/MIT
16
+ *
17
+ * Unless required by applicable law or agreed to in writing, software
18
+ * distributed under the License is distributed on an "AS IS" BASIS,
19
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
+ * See the License for the specific language governing permissions and
21
+ * limitations under the License.
31
22
  */
32
- function findLegacyEnv(prefixes, env = process.env) {
33
- return Object.keys(env)
34
- .filter((name) => prefixes.some((prefix) => name.startsWith(prefix)))
35
- .sort();
36
- }
37
23
  /** Edit distance between two strings (insertions, deletions, substitutions). */
38
24
  function levenshtein(a, b) {
39
25
  let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
@@ -17,7 +17,6 @@
17
17
  * limitations under the License.
18
18
  */
19
19
  export * from "./configHints";
20
- export * from "./integrationsSchema";
21
20
  export * from "./interpolateEnv";
22
21
  export * from "./loadServiceConfig";
23
22
  export * from "./logsSchema";
@@ -33,7 +33,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
33
33
  * limitations under the License.
34
34
  */
35
35
  __exportStar(require("./configHints"), exports);
36
- __exportStar(require("./integrationsSchema"), exports);
37
36
  __exportStar(require("./interpolateEnv"), exports);
38
37
  __exportStar(require("./loadServiceConfig"), exports);
39
38
  __exportStar(require("./logsSchema"), exports);
@@ -19,7 +19,7 @@
19
19
  type Env = Record<string, string | undefined>;
20
20
  type InterpolateOptions = {
21
21
  /**
22
- * Key paths where `${VAR}` may appear, e.g. `database.url` or `influxdb.*`
22
+ * Key paths where `${VAR}` may appear, e.g. `database.url` or `nats.*`
23
23
  * (`*` matches the key and everything below it; `*` alone matches every key). When given,
24
24
  * `${...}` at any other path is an error. When omitted, every string is interpolated.
25
25
  */
@@ -1,5 +1,4 @@
1
1
  import { z, ZodTypeAny } from "zod";
2
- import { MovedKeys } from "./configHints";
3
2
  type Env = Record<string, string | undefined>;
4
3
  type LoadServiceConfigOptions<S extends ZodTypeAny> = {
5
4
  /** Service name, used in messages. */
@@ -20,10 +19,6 @@ type LoadServiceConfigOptions<S extends ZodTypeAny> = {
20
19
  * else is an error.
21
20
  */
22
21
  interpolatePaths?: string[];
23
- /** Old key path → new key path, reported as hints. */
24
- movedKeys?: MovedKeys;
25
- /** Env var prefixes of the old env-based config, reported as a warning. */
26
- legacyEnvPrefixes?: string[];
27
22
  };
28
23
  /**
29
24
  * Loads, interpolates and strictly validates a service's config file.
@@ -21,7 +21,6 @@ exports.loadServiceConfig = loadServiceConfig;
21
21
  */
22
22
  const fs_1 = require("fs");
23
23
  const logger_1 = require("@fonoster/logger");
24
- const configHints_1 = require("./configHints");
25
24
  const interpolateEnv_1 = require("./interpolateEnv");
26
25
  const parseConfigFile_1 = require("./parseConfigFile");
27
26
  const resolveConfigFile_1 = require("./resolveConfigFile");
@@ -56,17 +55,13 @@ function formatIssues(error) {
56
55
  * Throws with the file path and the offending key path on any problem.
57
56
  */
58
57
  function loadServiceConfig(options) {
59
- var _a, _b, _c, _d, _e, _f, _g;
58
+ var _a, _b, _c, _d, _e;
60
59
  const { service, schema } = options;
61
60
  const fileBase = (_a = options.fileBase) !== null && _a !== void 0 ? _a : service;
62
61
  const argv = (_b = options.argv) !== null && _b !== void 0 ? _b : process.argv;
63
62
  const env = (_c = options.env) !== null && _c !== void 0 ? _c : process.env;
64
- const legacy = (0, configHints_1.findLegacyEnv)((_d = options.legacyEnvPrefixes) !== null && _d !== void 0 ? _d : [], env);
65
- if (legacy.length > 0) {
66
- logger.warn(`ignoring ${legacy.length} legacy environment variable(s); ${service} now reads its config file only: ${legacy.join(", ")}`);
67
- }
68
63
  const resolved = (0, resolveConfigFile_1.resolveConfigFile)(fileBase, argv, options.searchDirs);
69
- const where = (_e = resolved.path) !== null && _e !== void 0 ? _e : "(built-in defaults)";
64
+ const where = (_d = resolved.path) !== null && _d !== void 0 ? _d : "(built-in defaults)";
70
65
  let raw = {};
71
66
  if ("searched" in resolved) {
72
67
  logger.warn(`no ${service} config file found (looked for ${resolved.searched.join(", ")}); using built-in defaults`);
@@ -88,14 +83,10 @@ function loadServiceConfig(options) {
88
83
  delete rest.$schema;
89
84
  raw = rest;
90
85
  }
91
- const moved = (0, configHints_1.findMovedKeys)(raw, (_f = options.movedKeys) !== null && _f !== void 0 ? _f : {});
92
- if (moved.length > 0) {
93
- throw new Error(`invalid ${service} config at ${where}: ${moved.join("; ")}`);
94
- }
95
86
  let interpolated;
96
87
  try {
97
88
  interpolated = (0, interpolateEnv_1.interpolateEnv)(raw, env, {
98
- allowedPaths: (_g = options.interpolatePaths) !== null && _g !== void 0 ? _g : []
89
+ allowedPaths: (_e = options.interpolatePaths) !== null && _e !== void 0 ? _e : []
99
90
  });
100
91
  }
101
92
  catch (e) {
@@ -19,10 +19,8 @@
19
19
  import { ServingStatus } from "grpc-health-check";
20
20
  export declare const GRPC_NOT_SERVING_STATUS: ServingStatus;
21
21
  export declare const GRPC_SERVING_STATUS: ServingStatus;
22
- export declare const CALL_DETAIL_RECORD_MEASUREMENT = "cdr";
23
- export declare const INFLUXDB_CALLS_BUCKET = "calls";
24
22
  export declare const APP_REF_HEADER = "x-app-ref";
25
- export declare const ROUTR_DEFAULT_PEER_AOR = "sip:medianode@default";
23
+ export declare const ROUTR_DEFAULT_PEER_AOR = "sip:roomr@default";
26
24
  export declare const AUTOPILOT_SPECIAL_LOCAL_ADDRESS = "autopilot.fonoster.local";
27
25
  export declare const AUTOPILOT_INTERNAL_ADDRESS = "autopilot:50061";
28
26
  export declare const WELCOME_DEMO_SPECIAL_LOCAL_ADDRESS = "welcome.demo.fonoster.local";
package/dist/constants.js CHANGED
@@ -1,14 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WELCOME_DEMO_SPECIAL_LOCAL_ADDRESS = exports.AUTOPILOT_INTERNAL_ADDRESS = exports.AUTOPILOT_SPECIAL_LOCAL_ADDRESS = exports.ROUTR_DEFAULT_PEER_AOR = exports.APP_REF_HEADER = exports.INFLUXDB_CALLS_BUCKET = exports.CALL_DETAIL_RECORD_MEASUREMENT = exports.GRPC_SERVING_STATUS = exports.GRPC_NOT_SERVING_STATUS = void 0;
3
+ exports.WELCOME_DEMO_SPECIAL_LOCAL_ADDRESS = exports.AUTOPILOT_INTERNAL_ADDRESS = exports.AUTOPILOT_SPECIAL_LOCAL_ADDRESS = exports.ROUTR_DEFAULT_PEER_AOR = exports.APP_REF_HEADER = exports.GRPC_SERVING_STATUS = exports.GRPC_NOT_SERVING_STATUS = void 0;
4
4
  exports.GRPC_NOT_SERVING_STATUS = "NOT_SERVING";
5
5
  exports.GRPC_SERVING_STATUS = "SERVING";
6
- exports.CALL_DETAIL_RECORD_MEASUREMENT = "cdr";
7
- exports.INFLUXDB_CALLS_BUCKET = "calls";
8
6
  exports.APP_REF_HEADER = "x-app-ref";
9
- // The peer app-linked numbers point at: the Go media nodes (least-sessions). Asterisk's
7
+ // The peer app-linked numbers point at: the Go Roomr nodes (least-sessions). Asterisk's
10
8
  // sip:voice@default is gone (cleanbreak CB-B3).
11
- exports.ROUTR_DEFAULT_PEER_AOR = "sip:medianode@default";
9
+ exports.ROUTR_DEFAULT_PEER_AOR = "sip:roomr@default";
12
10
  exports.AUTOPILOT_SPECIAL_LOCAL_ADDRESS = "autopilot.fonoster.local";
13
11
  exports.AUTOPILOT_INTERNAL_ADDRESS = "autopilot:50061";
14
12
  exports.WELCOME_DEMO_SPECIAL_LOCAL_ADDRESS = "welcome.demo.fonoster.local";
@@ -25,7 +25,9 @@ const zod_validation_error_1 = require("zod-validation-error");
25
25
  const logger = (0, logger_1.getLogger)({ service: "apiserver", filePath: __filename });
26
26
  function handleZodError(error, callback) {
27
27
  if ((error === null || error === void 0 ? void 0 : error.issues[0].code) === "custom") {
28
- const message = error === null || error === void 0 ? void 0 : error.issues[0].message;
28
+ // Named like the other validation errors, so the caller knows which field is at fault.
29
+ const { message: text, path } = error.issues[0];
30
+ const message = path.length ? `${text} at "${path.join(".")}"` : text;
29
31
  logger.error("custom validation error", { message });
30
32
  callback({ code: grpc_js_1.status.INVALID_ARGUMENT, message });
31
33
  }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
3
+ * http://github.com/fonoster/fonoster
4
+ *
5
+ * This file is part of Fonoster
6
+ *
7
+ * Licensed under the MIT License (the "License");
8
+ * you may not use this file except in compliance with
9
+ * the License. You may obtain a copy of the License at
10
+ *
11
+ * https://opensource.org/licenses/MIT
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ import { z } from "zod";
20
+ /**
21
+ * The audio filters an app may configure (voice-session, "An app's audio filters are set through
22
+ * the Applications API"). Apps are untrusted input, so each filter exposes a public option schema
23
+ * here, shared by the apiserver (validation on write) and the appbridge (the filter factory).
24
+ * Anything that touches the media server's filesystem, environment or credentials stays out.
25
+ */
26
+ export declare const AI_COUSTICS_FILTER = "aiCoustics";
27
+ /** The ai-coustics filter's public options. */
28
+ export declare const aiCousticsPublicOptionsSchema: z.ZodObject<{
29
+ model: z.ZodDefault<z.ZodString>;
30
+ enhancementLevel: z.ZodDefault<z.ZodNumber>;
31
+ bypass: z.ZodDefault<z.ZodBoolean>;
32
+ }, "strict", z.ZodTypeAny, {
33
+ model?: string;
34
+ enhancementLevel?: number;
35
+ bypass?: boolean;
36
+ }, {
37
+ model?: string;
38
+ enhancementLevel?: number;
39
+ bypass?: boolean;
40
+ }>;
41
+ /** Public option schemas by filter name. */
42
+ export declare const FILTER_SCHEMAS: Record<string, z.ZodObject<z.ZodRawShape>>;
43
+ /** The filter a noise-cancelling (`nc`) provider runs, by provider id. */
44
+ export declare const FILTER_BY_PROVIDER: Record<string, string>;
45
+ export declare const FILTER_NAMES: string[];
46
+ /** The `nc` provider whose credential a filter runs with, or undefined for a filter without one. */
47
+ export declare function providerOfFilter(name: string): string | undefined;
48
+ export type AudioFilterConfig = {
49
+ name: string;
50
+ options?: Record<string, unknown>;
51
+ };
52
+ export declare const audioFilterConfigSchema: z.ZodObject<{
53
+ name: z.ZodString;
54
+ options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
55
+ }, "strict", z.ZodTypeAny, {
56
+ options?: Record<string, unknown>;
57
+ name?: string;
58
+ }, {
59
+ options?: Record<string, unknown>;
60
+ name?: string;
61
+ }>;
62
+ export declare class AudioFilterConfigError extends Error {
63
+ constructor(message: string);
64
+ }
65
+ /**
66
+ * Validates an app's `filters` list: known names and public options only. Returns the list with
67
+ * each filter's options as given (defaults are applied by the filter itself). Throws
68
+ * AudioFilterConfigError naming the first offending filter or option.
69
+ */
70
+ export declare function parseFilters(input: unknown): AudioFilterConfig[];