@fonoster/common 0.27.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 (209) hide show
  1. package/dist/{voice/PlayDtmf.d.ts → agents/index.d.ts} +3 -5
  2. package/dist/{assistants → agents}/index.js +2 -6
  3. package/dist/agents/sessionAgentSchema.d.ts +755 -0
  4. package/dist/agents/sessionAgentSchema.js +117 -0
  5. package/dist/{voice/Dial.d.ts → calls/index.d.ts} +16 -13
  6. package/dist/calls/index.js +44 -0
  7. package/dist/cellsecrets/index.d.ts +91 -0
  8. package/dist/cellsecrets/index.js +299 -0
  9. package/dist/config/cli/check.d.ts +6 -0
  10. package/dist/config/cli/check.js +202 -0
  11. package/dist/config/cli/envFile.d.ts +23 -0
  12. package/dist/config/cli/envFile.js +81 -0
  13. package/dist/config/cli/exposure.d.ts +10 -0
  14. package/dist/config/cli/exposure.js +93 -0
  15. package/dist/config/cli/index.d.ts +2 -0
  16. package/dist/{identity/tokenHasAccessKeyId.js → config/cli/index.js} +7 -8
  17. package/dist/config/cli/info.d.ts +6 -0
  18. package/dist/config/cli/info.js +62 -0
  19. package/dist/config/cli/init.d.ts +9 -0
  20. package/dist/config/cli/init.js +152 -0
  21. package/dist/config/cli/main.d.ts +11 -0
  22. package/dist/config/cli/main.js +155 -0
  23. package/dist/config/cli/render.d.ts +44 -0
  24. package/dist/config/cli/render.js +129 -0
  25. package/dist/config/cli/secrets.d.ts +21 -0
  26. package/dist/config/cli/secrets.js +117 -0
  27. package/dist/config/cli/types.d.ts +24 -0
  28. package/dist/config/cli/types.js +7 -0
  29. package/dist/{assistants/index.d.ts → config/configHints.d.ts} +8 -7
  30. package/dist/config/configHints.js +47 -0
  31. package/dist/{voice → config}/index.d.ts +11 -13
  32. package/dist/{voice → config}/index.js +11 -13
  33. package/dist/config/interpolateEnv.d.ts +34 -0
  34. package/dist/config/interpolateEnv.js +70 -0
  35. package/dist/config/loadServiceConfig.d.ts +28 -0
  36. package/dist/config/loadServiceConfig.js +112 -0
  37. package/dist/config/logsSchema.d.ts +76 -0
  38. package/dist/config/logsSchema.js +49 -0
  39. package/dist/config/natsConnection.d.ts +53 -0
  40. package/dist/config/natsConnection.js +58 -0
  41. package/dist/config/parseConfigFile.d.ts +7 -0
  42. package/dist/config/parseConfigFile.js +60 -0
  43. package/dist/config/resolveConfigFile.d.ts +17 -0
  44. package/dist/config/resolveConfigFile.js +54 -0
  45. package/dist/config/resolveSecretRefs.d.ts +35 -0
  46. package/dist/config/resolveSecretRefs.js +129 -0
  47. package/dist/{assistants/audioFiltersSchema.d.ts → config/strictDeep.d.ts} +9 -12
  48. package/dist/config/strictDeep.js +58 -0
  49. package/dist/config/telemetrySchema.d.ts +39 -0
  50. package/dist/config/telemetrySchema.js +44 -0
  51. package/dist/config/toJsonSchema.d.ts +30 -0
  52. package/dist/config/toJsonSchema.js +161 -0
  53. package/dist/constants.d.ts +1 -6
  54. package/dist/constants.js +4 -7
  55. package/dist/envs.d.ts +2 -1
  56. package/dist/envs.js +13 -11
  57. package/dist/errors/handleZodError.js +3 -1
  58. package/dist/filters/index.d.ts +70 -0
  59. package/dist/filters/index.js +101 -0
  60. package/dist/identity/createAuthInterceptor.d.ts +9 -2
  61. package/dist/identity/createAuthInterceptor.js +36 -30
  62. package/dist/identity/hasAccess.d.ts +9 -3
  63. package/dist/identity/hasAccess.js +32 -8
  64. package/dist/identity/index.d.ts +1 -0
  65. package/dist/identity/index.js +1 -0
  66. package/dist/identity/isValidToken.d.ts +12 -2
  67. package/dist/identity/isValidToken.js +25 -9
  68. package/dist/identity/roles.js +33 -7
  69. package/dist/identity/types.d.ts +6 -1
  70. package/dist/identity/types.js +1 -0
  71. package/dist/{assistants/LanguageModelProvider.js → identity/verifyAccessToken.d.ts} +10 -11
  72. package/dist/identity/verifyAccessToken.js +44 -0
  73. package/dist/index.d.ts +15 -2
  74. package/dist/index.js +18 -3
  75. package/dist/net/assertPublicDestination.d.ts +52 -0
  76. package/dist/net/assertPublicDestination.js +342 -0
  77. package/dist/{voice/StopSay.d.ts → net/index.d.ts} +1 -6
  78. package/dist/net/index.js +35 -0
  79. package/dist/notifications/createSendEmail.js +3 -1
  80. package/dist/protos/applications.proto +138 -3
  81. package/dist/protos/authz.proto +26 -4
  82. package/dist/protos/billing.proto +92 -0
  83. package/dist/protos/calls.proto +4 -0
  84. package/dist/protos/capabilities.proto +102 -0
  85. package/dist/protos/identity.proto +26 -1
  86. package/dist/protos/providers.proto +139 -0
  87. package/dist/protos/roomr.proto +146 -0
  88. package/dist/protos/session.proto +194 -0
  89. package/dist/protos/usage.proto +59 -0
  90. package/dist/protos/webhooks.proto +140 -0
  91. package/dist/{utils/types.d.ts → regions/hub/index.d.ts} +1 -5
  92. package/dist/regions/hub/index.js +35 -0
  93. package/dist/regions/hub/natsJwt.d.ts +63 -0
  94. package/dist/regions/hub/natsJwt.js +195 -0
  95. package/dist/registry/Registry.d.ts +87 -0
  96. package/dist/registry/Registry.js +432 -0
  97. package/dist/registry/cli.d.ts +20 -0
  98. package/dist/registry/cli.js +436 -0
  99. package/dist/registry/features.d.ts +31 -0
  100. package/dist/registry/features.js +38 -0
  101. package/dist/registry/index.d.ts +24 -0
  102. package/dist/registry/index.js +40 -0
  103. package/dist/registry/prisma.d.ts +67 -0
  104. package/dist/registry/prisma.js +399 -0
  105. package/dist/registry/stores.d.ts +21 -0
  106. package/dist/{assistants/languageModelConfigSchema.js → registry/stores.js} +55 -38
  107. package/dist/registry/types.d.ts +110 -0
  108. package/dist/{assistants/LanguageModelProvider.d.ts → registry/types.js} +6 -8
  109. package/dist/registry/workspaceKeys.d.ts +41 -0
  110. package/dist/registry/workspaceKeys.js +64 -0
  111. package/dist/roomr/health.d.ts +9 -0
  112. package/dist/{assistants/eventsHookSchema.js → roomr/health.js} +22 -18
  113. package/dist/roomr/index.d.ts +75 -0
  114. package/dist/roomr/index.js +146 -0
  115. package/dist/roomr/session.d.ts +133 -0
  116. package/dist/roomr/session.js +132 -0
  117. package/dist/session/index.d.ts +19 -0
  118. package/dist/session/index.js +35 -0
  119. package/dist/session/schema.d.ts +2140 -0
  120. package/dist/session/schema.js +448 -0
  121. package/dist/sessions/index.d.ts +96 -0
  122. package/dist/sessions/index.js +197 -0
  123. package/dist/telemetry.d.ts +76 -0
  124. package/dist/telemetry.js +360 -0
  125. package/dist/types.d.ts +3 -5
  126. package/dist/{voice/Gather.d.ts → usage/CallUsage.d.ts} +19 -18
  127. package/dist/usage/CallUsage.js +76 -0
  128. package/dist/usage/index.d.ts +22 -0
  129. package/dist/usage/index.js +38 -0
  130. package/dist/usage/meters.d.ts +113 -0
  131. package/dist/usage/meters.js +90 -0
  132. package/dist/usage/types.d.ts +159 -0
  133. package/dist/usage/types.js +84 -0
  134. package/dist/usage/usageId.d.ts +6 -0
  135. package/dist/usage/usageId.js +45 -0
  136. package/dist/utils/{findIntegrationsCredentials.js → WriteBehind.d.ts} +13 -10
  137. package/dist/utils/WriteBehind.js +64 -0
  138. package/dist/utils/index.d.ts +1 -3
  139. package/dist/utils/index.js +1 -3
  140. package/dist/utils/{createFetchSingleCallByCallId.d.ts → logUnhandledRejections.d.ts} +8 -4
  141. package/dist/{assistants/audioFiltersSchema.js → utils/logUnhandledRejections.js} +17 -12
  142. package/dist/utils/withErrorHandling.js +1 -1
  143. package/dist/validators/calls.d.ts +3 -0
  144. package/dist/validators/calls.js +12 -2
  145. package/dist/validators/identity.d.ts +37 -8
  146. package/dist/validators/identity.js +22 -3
  147. package/dist/validators/index.d.ts +1 -0
  148. package/dist/validators/index.js +1 -0
  149. package/dist/validators/sip.d.ts +40 -0
  150. package/dist/validators/sip.js +99 -0
  151. package/dist/validators/sipnet/credentials.d.ts +2 -2
  152. package/dist/validators/sipnet/domains.js +7 -7
  153. package/dist/validators/sipnet/trunks.d.ts +14 -14
  154. package/dist/validators/sipnet/trunks.js +4 -2
  155. package/dist/webhooks/Dispatcher.d.ts +87 -0
  156. package/dist/webhooks/Dispatcher.js +225 -0
  157. package/dist/webhooks/bus.d.ts +68 -0
  158. package/dist/webhooks/bus.js +178 -0
  159. package/dist/webhooks/events.d.ts +66 -0
  160. package/dist/webhooks/events.js +62 -0
  161. package/dist/webhooks/index.d.ts +23 -0
  162. package/dist/webhooks/index.js +39 -0
  163. package/dist/webhooks/prisma.d.ts +55 -0
  164. package/dist/webhooks/prisma.js +242 -0
  165. package/dist/webhooks/signing.d.ts +8 -0
  166. package/dist/webhooks/signing.js +53 -0
  167. package/package.json +25 -11
  168. package/schema/session.v1.json +871 -0
  169. package/dist/assistants/assistantSchema.d.ts +0 -739
  170. package/dist/assistants/assistantSchema.js +0 -37
  171. package/dist/assistants/conversationSettingsSchema.d.ts +0 -122
  172. package/dist/assistants/conversationSettingsSchema.js +0 -133
  173. package/dist/assistants/eventsHookSchema.d.ts +0 -38
  174. package/dist/assistants/languageModelConfigSchema.d.ts +0 -206
  175. package/dist/identity/tokenHasAccessKeyId.d.ts +0 -2
  176. package/dist/protos/voice.proto +0 -557
  177. package/dist/utils/createFetchSingleCallByCallId.js +0 -33
  178. package/dist/utils/findIntegrationsCredentials.d.ts +0 -23
  179. package/dist/utils/types.js +0 -2
  180. package/dist/voice/Dial.js +0 -20
  181. package/dist/voice/Gather.js +0 -9
  182. package/dist/voice/Mute.d.ts +0 -31
  183. package/dist/voice/Mute.js +0 -9
  184. package/dist/voice/Play.d.ts +0 -30
  185. package/dist/voice/Play.js +0 -2
  186. package/dist/voice/PlayDtmf.js +0 -2
  187. package/dist/voice/PlaybackControl.d.ts +0 -31
  188. package/dist/voice/PlaybackControl.js +0 -11
  189. package/dist/voice/Record.d.ts +0 -36
  190. package/dist/voice/Record.js +0 -7
  191. package/dist/voice/Say.d.ts +0 -28
  192. package/dist/voice/Say.js +0 -2
  193. package/dist/voice/StopSay.js +0 -2
  194. package/dist/voice/Stream.d.ts +0 -53
  195. package/dist/voice/Stream.js +0 -19
  196. package/dist/voice/StreamGather.d.ts +0 -34
  197. package/dist/voice/StreamGather.js +0 -9
  198. package/dist/voice/Verb.d.ts +0 -27
  199. package/dist/voice/Verb.js +0 -2
  200. package/dist/voice/voice.d.ts +0 -171
  201. package/dist/voice/voice.js +0 -65
  202. package/dist/{assistants → agents}/testCasesSchema.d.ts +4 -4
  203. /package/dist/{assistants → agents}/testCasesSchema.js +0 -0
  204. /package/dist/{assistants → agents}/tools/index.d.ts +0 -0
  205. /package/dist/{assistants → agents}/tools/index.js +0 -0
  206. /package/dist/{assistants → agents}/tools/propertySchema.d.ts +0 -0
  207. /package/dist/{assistants → agents}/tools/propertySchema.js +0 -0
  208. /package/dist/{assistants → agents}/tools/toolSchema.d.ts +0 -0
  209. /package/dist/{assistants → agents}/tools/toolSchema.js +0 -0
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_SECRETS_DIR = exports.SECRET_PREFIX = void 0;
4
+ exports.isSecretRef = isSecretRef;
5
+ exports.resolveSecretRef = resolveSecretRef;
6
+ exports.resolveSecretRefs = resolveSecretRefs;
7
+ /**
8
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
9
+ * http://github.com/fonoster/fonoster
10
+ *
11
+ * This file is part of Fonoster
12
+ *
13
+ * Licensed under the MIT License (the "License");
14
+ * you may not use this file except in compliance with
15
+ * the License. You may obtain a copy of the License at
16
+ *
17
+ * https://opensource.org/licenses/MIT
18
+ *
19
+ * Unless required by applicable law or agreed to in writing, software
20
+ * distributed under the License is distributed on an "AS IS" BASIS,
21
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
+ * See the License for the specific language governing permissions and
23
+ * limitations under the License.
24
+ */
25
+ const fs_1 = require("fs");
26
+ const path_1 = require("path");
27
+ /**
28
+ * `secret://` references in config values (add-platform, decision D8). A string value that is
29
+ * exactly a reference is replaced at startup by the secret it names, so YAML never holds the raw
30
+ * secret:
31
+ *
32
+ * secret://env/NAME the environment variable NAME
33
+ * secret://file/<absolute path> a file's contents (e.g. secret://file/run/secrets/db-url)
34
+ * secret://k8s/<secret>#<key> a Kubernetes Secret mounted as a volume, read from
35
+ * secret://k8s/<ns>/<secret>#<key> <FONOSTER_SECRETS_DIR>/<secret>/<key>
36
+ * (default /var/run/fonoster/secrets; the Helm chart mounts
37
+ * every referenced Secret there). The namespace, when given,
38
+ * must be the pod's (POD_NAMESPACE) if that is known.
39
+ *
40
+ * File contents lose one trailing newline. Errors name the key path and the reference, never a
41
+ * value. Values that only contain `secret://` somewhere else are left alone.
42
+ */
43
+ exports.SECRET_PREFIX = "secret://";
44
+ exports.DEFAULT_SECRETS_DIR = "/var/run/fonoster/secrets";
45
+ const NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
46
+ const K8S_NAME = /^[a-z0-9]([-a-z0-9.]*[a-z0-9])?$/;
47
+ const K8S_KEY = /^[-._a-zA-Z0-9]+$/;
48
+ function isSecretRef(value) {
49
+ return typeof value === "string" && value.startsWith(exports.SECRET_PREFIX);
50
+ }
51
+ function readSecretFile(ref, path, options) {
52
+ var _a;
53
+ const read = (_a = options.readFile) !== null && _a !== void 0 ? _a : ((p) => (0, fs_1.readFileSync)(p, { encoding: "utf8" }));
54
+ try {
55
+ return read(path).replace(/\r?\n$/, "");
56
+ }
57
+ catch (e) {
58
+ const code = e.code;
59
+ throw new Error(`${ref}: cannot read ${path}${code ? ` (${code})` : ""}`);
60
+ }
61
+ }
62
+ /** Resolves one `secret://` reference. Throws with a message that never contains the secret. */
63
+ function resolveSecretRef(ref, options = {}) {
64
+ var _a, _b, _c;
65
+ const env = (_a = options.env) !== null && _a !== void 0 ? _a : process.env;
66
+ const rest = ref.slice(exports.SECRET_PREFIX.length);
67
+ const slash = rest.indexOf("/");
68
+ const kind = slash < 0 ? rest : rest.slice(0, slash);
69
+ const target = slash < 0 ? "" : rest.slice(slash + 1);
70
+ if (kind === "env") {
71
+ if (!NAME.test(target))
72
+ throw new Error(`invalid variable name in ${ref}`);
73
+ const value = env[target];
74
+ if (value === undefined || value === "")
75
+ throw new Error(`${ref}: environment variable ${target} is not set`);
76
+ return value;
77
+ }
78
+ if (kind === "file") {
79
+ if (!target)
80
+ throw new Error(`${ref}: missing file path`);
81
+ const path = (0, path_1.resolve)("/", target);
82
+ return readSecretFile(ref, path, options);
83
+ }
84
+ if (kind === "k8s") {
85
+ const hash = target.indexOf("#");
86
+ if (hash < 0)
87
+ throw new Error(`${ref}: missing #<key>`);
88
+ const parts = target.slice(0, hash).split("/");
89
+ const key = target.slice(hash + 1);
90
+ if (parts.length > 2 || !parts.every((p) => K8S_NAME.test(p)))
91
+ throw new Error(`${ref}: expected secret://k8s/[<namespace>/]<secret>#<key>`);
92
+ if (!K8S_KEY.test(key))
93
+ throw new Error(`${ref}: invalid key`);
94
+ const [namespace, name] = parts.length === 2 ? parts : [undefined, parts[0]];
95
+ const podNamespace = env.POD_NAMESPACE;
96
+ if (namespace && podNamespace && namespace !== podNamespace)
97
+ throw new Error(`${ref}: Secrets of namespace ${namespace} are not mounted here (${podNamespace})`);
98
+ const dir = (_c = (_b = options.secretsDir) !== null && _b !== void 0 ? _b : env.FONOSTER_SECRETS_DIR) !== null && _c !== void 0 ? _c : exports.DEFAULT_SECRETS_DIR;
99
+ const base = (0, path_1.isAbsolute)(dir) ? dir : (0, path_1.resolve)(dir);
100
+ return readSecretFile(ref, (0, path_1.join)(base, name, key), options);
101
+ }
102
+ throw new Error(`unsupported reference ${ref} (use secret://env/NAME, secret://file/<path> or secret://k8s/<secret>#<key>)`);
103
+ }
104
+ function walk(input, options, path) {
105
+ if (isSecretRef(input)) {
106
+ try {
107
+ return resolveSecretRef(input, options);
108
+ }
109
+ catch (e) {
110
+ throw new Error(`${path || "(root)"}: ${e.message}`);
111
+ }
112
+ }
113
+ if (Array.isArray(input))
114
+ return input.map((item, i) => walk(item, options, `${path}[${i}]`));
115
+ if (input !== null && typeof input === "object") {
116
+ return Object.fromEntries(Object.entries(input).map(([k, v]) => [
117
+ k,
118
+ walk(v, options, path ? `${path}.${k}` : k)
119
+ ]));
120
+ }
121
+ return input;
122
+ }
123
+ /**
124
+ * Returns a copy of a parsed config with every `secret://` value resolved. Errors name the key
125
+ * path (`providers.deepgram.credential.value: secret://env/DG: environment variable DG is not set`).
126
+ */
127
+ function resolveSecretRefs(input, options = {}) {
128
+ return walk(input, options, "");
129
+ }
@@ -16,15 +16,12 @@
16
16
  * See the License for the specific language governing permissions and
17
17
  * limitations under the License.
18
18
  */
19
- import { z } from "zod";
20
- declare const audioFiltersSchema: z.ZodDefault<z.ZodArray<z.ZodObject<{
21
- name: z.ZodString;
22
- options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
23
- }, "strip", z.ZodTypeAny, {
24
- options?: Record<string, unknown>;
25
- name?: string;
26
- }, {
27
- options?: Record<string, unknown>;
28
- name?: string;
29
- }>, "many">>;
30
- export { audioFiltersSchema };
19
+ import { ZodTypeAny } from "zod";
20
+ /**
21
+ * Returns a copy of `schema` in which every object rejects unknown keys, so a
22
+ * misspelled config key fails validation instead of being silently dropped.
23
+ * Objects declared with `.passthrough()` (free-form blocks such as provider
24
+ * credentials) are left as they are.
25
+ */
26
+ declare function strictDeep<T extends ZodTypeAny>(schema: T): T;
27
+ export { strictDeep };
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.strictDeep = strictDeep;
4
+ /**
5
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
6
+ * http://github.com/fonoster/fonoster
7
+ *
8
+ * This file is part of Fonoster
9
+ *
10
+ * Licensed under the MIT License (the "License");
11
+ * you may not use this file except in compliance with
12
+ * the License. You may obtain a copy of the License at
13
+ *
14
+ * https://opensource.org/licenses/MIT
15
+ *
16
+ * Unless required by applicable law or agreed to in writing, software
17
+ * distributed under the License is distributed on an "AS IS" BASIS,
18
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ * See the License for the specific language governing permissions and
20
+ * limitations under the License.
21
+ */
22
+ const zod_1 = require("zod");
23
+ /**
24
+ * Returns a copy of `schema` in which every object rejects unknown keys, so a
25
+ * misspelled config key fails validation instead of being silently dropped.
26
+ * Objects declared with `.passthrough()` (free-form blocks such as provider
27
+ * credentials) are left as they are.
28
+ */
29
+ function strictDeep(schema) {
30
+ if (schema instanceof zod_1.ZodObject) {
31
+ const shape = schema.shape;
32
+ const strictShape = Object.fromEntries(Object.entries(shape).map(([key, value]) => [key, strictDeep(value)]));
33
+ const unknownKeys = schema._def.unknownKeys === "passthrough" ? "passthrough" : "strict";
34
+ return new zod_1.ZodObject(Object.assign(Object.assign({}, schema._def), { shape: () => strictShape, unknownKeys }));
35
+ }
36
+ if (schema instanceof zod_1.ZodOptional) {
37
+ return new zod_1.ZodOptional(Object.assign(Object.assign({}, schema._def), { innerType: strictDeep(schema._def.innerType) }));
38
+ }
39
+ if (schema instanceof zod_1.ZodNullable) {
40
+ return new zod_1.ZodNullable(Object.assign(Object.assign({}, schema._def), { innerType: strictDeep(schema._def.innerType) }));
41
+ }
42
+ if (schema instanceof zod_1.ZodDefault) {
43
+ return new zod_1.ZodDefault(Object.assign(Object.assign({}, schema._def), { innerType: strictDeep(schema._def.innerType) }));
44
+ }
45
+ if (schema instanceof zod_1.ZodArray) {
46
+ return new zod_1.ZodArray(Object.assign(Object.assign({}, schema._def), { type: strictDeep(schema._def.type) }));
47
+ }
48
+ if (schema instanceof zod_1.ZodEffects) {
49
+ return new zod_1.ZodEffects(Object.assign(Object.assign({}, schema._def), { schema: strictDeep(schema._def.schema) }));
50
+ }
51
+ if (schema instanceof zod_1.ZodUnion) {
52
+ return new zod_1.ZodUnion(Object.assign(Object.assign({}, schema._def), { options: schema._def.options.map((option) => strictDeep(option)) }));
53
+ }
54
+ if (schema instanceof zod_1.ZodRecord) {
55
+ return new zod_1.ZodRecord(Object.assign(Object.assign({}, schema._def), { valueType: strictDeep(schema._def.valueType) }));
56
+ }
57
+ return schema;
58
+ }
@@ -0,0 +1,39 @@
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 `telemetry` section shared by every Fonoster service's config file
22
+ * (unify-config-placeholders): the OTLP/HTTP endpoint telemetry goes to. Empty or absent means
23
+ * off, unless the container environment sets `OTEL_EXPORTER_OTLP_ENDPOINT`.
24
+ */
25
+ declare const telemetrySchema: z.ZodOptional<z.ZodObject<{
26
+ /** Usually `"${OTEL_EXPORTER_OTLP_ENDPOINT:-}"`, e.g. http://otel-collector:4318. */
27
+ otlpEndpoint: z.ZodOptional<z.ZodString>;
28
+ }, "strip", z.ZodTypeAny, {
29
+ otlpEndpoint?: string;
30
+ }, {
31
+ otlpEndpoint?: string;
32
+ }>>;
33
+ type TelemetryConfig = z.infer<typeof telemetrySchema>;
34
+ /**
35
+ * The environment `initTelemetry` reads, with the config's endpoint (when set) in
36
+ * `OTEL_EXPORTER_OTLP_ENDPOINT`.
37
+ */
38
+ declare function telemetryEnv(config: TelemetryConfig, env?: Record<string, string | undefined>): Record<string, string | undefined>;
39
+ export { telemetrySchema, telemetryEnv, TelemetryConfig };
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.telemetrySchema = void 0;
4
+ exports.telemetryEnv = telemetryEnv;
5
+ /**
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.
22
+ */
23
+ const zod_1 = require("zod");
24
+ /**
25
+ * The `telemetry` section shared by every Fonoster service's config file
26
+ * (unify-config-placeholders): the OTLP/HTTP endpoint telemetry goes to. Empty or absent means
27
+ * off, unless the container environment sets `OTEL_EXPORTER_OTLP_ENDPOINT`.
28
+ */
29
+ const telemetrySchema = zod_1.z
30
+ .object({
31
+ /** Usually `"${OTEL_EXPORTER_OTLP_ENDPOINT:-}"`, e.g. http://otel-collector:4318. */
32
+ otlpEndpoint: zod_1.z.string().optional()
33
+ })
34
+ .optional();
35
+ exports.telemetrySchema = telemetrySchema;
36
+ /**
37
+ * The environment `initTelemetry` reads, with the config's endpoint (when set) in
38
+ * `OTEL_EXPORTER_OTLP_ENDPOINT`.
39
+ */
40
+ function telemetryEnv(config, env = process.env) {
41
+ var _a;
42
+ const endpoint = (_a = config === null || config === void 0 ? void 0 : config.otlpEndpoint) === null || _a === void 0 ? void 0 : _a.trim();
43
+ return endpoint ? Object.assign(Object.assign({}, env), { OTEL_EXPORTER_OTLP_ENDPOINT: endpoint }) : env;
44
+ }
@@ -0,0 +1,30 @@
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 { ZodTypeAny } from "zod";
20
+ export type JsonSchema = Record<string, unknown>;
21
+ /**
22
+ * The JSON Schema (draft 2020-12) of a service config schema. Unknown keys are rejected
23
+ * (`additionalProperties: false`) wherever the service rejects them: every object, as
24
+ * `strictDeep` makes them, except `.passthrough()` blocks.
25
+ */
26
+ declare function toJsonSchema(schema: ZodTypeAny, options?: {
27
+ id?: string;
28
+ title?: string;
29
+ }): JsonSchema;
30
+ export { toJsonSchema };
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toJsonSchema = toJsonSchema;
4
+ /**
5
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
6
+ * http://github.com/fonoster/fonoster
7
+ *
8
+ * This file is part of Fonoster
9
+ *
10
+ * Licensed under the MIT License (the "License");
11
+ * you may not use this file except in compliance with
12
+ * the License. You may obtain a copy of the License at
13
+ *
14
+ * https://opensource.org/licenses/MIT
15
+ *
16
+ * Unless required by applicable law or agreed to in writing, software
17
+ * distributed under the License is distributed on an "AS IS" BASIS,
18
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ * See the License for the specific language governing permissions and
20
+ * limitations under the License.
21
+ */
22
+ const zod_1 = require("zod");
23
+ const strictDeep_1 = require("./strictDeep");
24
+ function stringSchema(checks) {
25
+ const out = { type: "string" };
26
+ for (const c of checks) {
27
+ if (c.kind === "min")
28
+ out.minLength = c.value;
29
+ else if (c.kind === "max")
30
+ out.maxLength = c.value;
31
+ else if (c.kind === "length")
32
+ out.minLength = out.maxLength = c.value;
33
+ else if (c.kind === "regex")
34
+ out.pattern = c.regex.source;
35
+ else if (c.kind === "url")
36
+ out.format = "uri";
37
+ else if (c.kind === "email")
38
+ out.format = "email";
39
+ }
40
+ return out;
41
+ }
42
+ function numberSchema(checks) {
43
+ const out = { type: "number" };
44
+ for (const c of checks) {
45
+ if (c.kind === "int")
46
+ out.type = "integer";
47
+ else if (c.kind === "min")
48
+ out[c.inclusive ? "minimum" : "exclusiveMinimum"] = c.value;
49
+ else if (c.kind === "max")
50
+ out[c.inclusive ? "maximum" : "exclusiveMaximum"] = c.value;
51
+ else if (c.kind === "multipleOf")
52
+ out.multipleOf = c.value;
53
+ }
54
+ return out;
55
+ }
56
+ /** Whether an object key may be left out of the input (optional, or has a default). */
57
+ function isOptionalInput(schema) {
58
+ const kind = schema._def.typeName;
59
+ if (kind === zod_1.ZodFirstPartyTypeKind.ZodOptional ||
60
+ kind === zod_1.ZodFirstPartyTypeKind.ZodDefault)
61
+ return true;
62
+ if (kind === zod_1.ZodFirstPartyTypeKind.ZodEffects)
63
+ return isOptionalInput(schema._def.schema);
64
+ if (kind === zod_1.ZodFirstPartyTypeKind.ZodNullable)
65
+ return isOptionalInput(schema._def.innerType);
66
+ if (kind === zod_1.ZodFirstPartyTypeKind.ZodAny ||
67
+ kind === zod_1.ZodFirstPartyTypeKind.ZodUnknown)
68
+ return true;
69
+ return false;
70
+ }
71
+ function convert(schema, path) {
72
+ const def = schema._def;
73
+ const description = schema.description
74
+ ? { description: schema.description }
75
+ : {};
76
+ switch (def.typeName) {
77
+ case zod_1.ZodFirstPartyTypeKind.ZodString:
78
+ return Object.assign(Object.assign({}, stringSchema(def.checks)), description);
79
+ case zod_1.ZodFirstPartyTypeKind.ZodNumber:
80
+ return Object.assign(Object.assign({}, numberSchema(def.checks)), description);
81
+ case zod_1.ZodFirstPartyTypeKind.ZodBoolean:
82
+ return Object.assign({ type: "boolean" }, description);
83
+ case zod_1.ZodFirstPartyTypeKind.ZodLiteral:
84
+ return Object.assign({ const: def.value }, description);
85
+ case zod_1.ZodFirstPartyTypeKind.ZodEnum:
86
+ return Object.assign({ type: "string", enum: [...def.values] }, description);
87
+ case zod_1.ZodFirstPartyTypeKind.ZodAny:
88
+ case zod_1.ZodFirstPartyTypeKind.ZodUnknown:
89
+ return Object.assign({}, description);
90
+ case zod_1.ZodFirstPartyTypeKind.ZodNull:
91
+ return { type: "null" };
92
+ case zod_1.ZodFirstPartyTypeKind.ZodObject: {
93
+ const shape = def.shape();
94
+ const properties = {};
95
+ const required = [];
96
+ for (const [key, value] of Object.entries(shape)) {
97
+ properties[key] = convert(value, path ? `${path}.${key}` : key);
98
+ if (!isOptionalInput(value))
99
+ required.push(key);
100
+ }
101
+ const catchall = def.catchall;
102
+ const hasCatchall = catchall && catchall._def.typeName !== zod_1.ZodFirstPartyTypeKind.ZodNever;
103
+ return Object.assign(Object.assign(Object.assign({ type: "object", properties }, (required.length ? { required } : {})), { additionalProperties: hasCatchall
104
+ ? convert(catchall, `${path}.*`)
105
+ : def.unknownKeys !== "strict" }), description);
106
+ }
107
+ case zod_1.ZodFirstPartyTypeKind.ZodArray: {
108
+ const out = Object.assign({ type: "array", items: convert(def.type, `${path}[]`) }, description);
109
+ if (def.minLength)
110
+ out.minItems = def.minLength.value;
111
+ if (def.maxLength)
112
+ out.maxItems = def.maxLength.value;
113
+ if (def.exactLength)
114
+ out.minItems = out.maxItems = def.exactLength.value;
115
+ return out;
116
+ }
117
+ case zod_1.ZodFirstPartyTypeKind.ZodRecord:
118
+ return Object.assign({ type: "object", additionalProperties: convert(def.valueType, `${path}.*`) }, description);
119
+ case zod_1.ZodFirstPartyTypeKind.ZodUnion:
120
+ case zod_1.ZodFirstPartyTypeKind.ZodDiscriminatedUnion: {
121
+ const options = Array.isArray(def.options)
122
+ ? def.options
123
+ : [...def.options.values()];
124
+ return Object.assign({ anyOf: options.map((o, i) => convert(o, `${path}|${i}`)) }, description);
125
+ }
126
+ case zod_1.ZodFirstPartyTypeKind.ZodOptional:
127
+ return Object.assign(Object.assign({}, convert(def.innerType, path)), description);
128
+ case zod_1.ZodFirstPartyTypeKind.ZodNullable:
129
+ return Object.assign({ anyOf: [convert(def.innerType, path), { type: "null" }] }, description);
130
+ case zod_1.ZodFirstPartyTypeKind.ZodDefault: {
131
+ const inner = convert(def.innerType, path);
132
+ // Object defaults such as `{}` are filled in by the inner schema; only scalars are shown.
133
+ const value = def.defaultValue();
134
+ return Object.assign(Object.assign(Object.assign({}, inner), (value === null || typeof value !== "object"
135
+ ? { default: value }
136
+ : {})), description);
137
+ }
138
+ case zod_1.ZodFirstPartyTypeKind.ZodEffects:
139
+ return Object.assign(Object.assign({}, convert(def.schema, path)), description);
140
+ case zod_1.ZodFirstPartyTypeKind.ZodBranded:
141
+ return convert(def.type, path);
142
+ case zod_1.ZodFirstPartyTypeKind.ZodCatch:
143
+ return convert(def.innerType, path);
144
+ case zod_1.ZodFirstPartyTypeKind.ZodReadonly:
145
+ return convert(def.innerType, path);
146
+ case zod_1.ZodFirstPartyTypeKind.ZodPipeline:
147
+ return convert(def.in, path);
148
+ case zod_1.ZodFirstPartyTypeKind.ZodLazy:
149
+ return convert(def.getter(), path);
150
+ default:
151
+ throw new Error(`toJsonSchema: unsupported Zod type ${def.typeName} at ${path || "(root)"}`);
152
+ }
153
+ }
154
+ /**
155
+ * The JSON Schema (draft 2020-12) of a service config schema. Unknown keys are rejected
156
+ * (`additionalProperties: false`) wherever the service rejects them: every object, as
157
+ * `strictDeep` makes them, except `.passthrough()` blocks.
158
+ */
159
+ function toJsonSchema(schema, options = {}) {
160
+ return Object.assign(Object.assign(Object.assign({ $schema: "https://json-schema.org/draft/2020-12/schema" }, (options.id ? { $id: options.id } : {})), (options.title ? { title: options.title } : {})), convert((0, strictDeep_1.strictDeep)(schema), ""));
161
+ }
@@ -19,13 +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 STASIS_APP_NAME = "mediacontroller";
23
- export declare const CALL_CONTEXT = "local-ctx-common";
24
- export declare const CALL_EXTENSION = "start";
25
- export declare const CALL_DETAIL_RECORD_MEASUREMENT = "cdr";
26
- export declare const INFLUXDB_CALLS_BUCKET = "calls";
27
22
  export declare const APP_REF_HEADER = "x-app-ref";
28
- export declare const ROUTR_DEFAULT_PEER_AOR = "sip:voice@default";
23
+ export declare const ROUTR_DEFAULT_PEER_AOR = "sip:roomr@default";
29
24
  export declare const AUTOPILOT_SPECIAL_LOCAL_ADDRESS = "autopilot.fonoster.local";
30
25
  export declare const AUTOPILOT_INTERNAL_ADDRESS = "autopilot:50061";
31
26
  export declare const WELCOME_DEMO_SPECIAL_LOCAL_ADDRESS = "welcome.demo.fonoster.local";
package/dist/constants.js CHANGED
@@ -1,15 +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.CALL_EXTENSION = exports.CALL_CONTEXT = exports.STASIS_APP_NAME = 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.STASIS_APP_NAME = "mediacontroller";
7
- exports.CALL_CONTEXT = "local-ctx-common";
8
- exports.CALL_EXTENSION = "start";
9
- exports.CALL_DETAIL_RECORD_MEASUREMENT = "cdr";
10
- exports.INFLUXDB_CALLS_BUCKET = "calls";
11
6
  exports.APP_REF_HEADER = "x-app-ref";
12
- exports.ROUTR_DEFAULT_PEER_AOR = "sip:voice@default";
7
+ // The peer app-linked numbers point at: the Go Roomr nodes (least-sessions). Asterisk's
8
+ // sip:voice@default is gone (cleanbreak CB-B3).
9
+ exports.ROUTR_DEFAULT_PEER_AOR = "sip:roomr@default";
13
10
  exports.AUTOPILOT_SPECIAL_LOCAL_ADDRESS = "autopilot.fonoster.local";
14
11
  exports.AUTOPILOT_INTERNAL_ADDRESS = "autopilot:50061";
15
12
  exports.WELCOME_DEMO_SPECIAL_LOCAL_ADDRESS = "welcome.demo.fonoster.local";
package/dist/envs.d.ts CHANGED
@@ -1 +1,2 @@
1
- export declare const ROOT_DOMAIN: string;
1
+ export declare const setRootDomain: (domain: string) => void;
2
+ export declare const getRootDomain: () => string;
package/dist/envs.js CHANGED
@@ -1,9 +1,6 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ROOT_DOMAIN = void 0;
3
+ exports.getRootDomain = exports.setRootDomain = void 0;
7
4
  /**
8
5
  * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
9
6
  * http://github.com/fonoster/fonoster
@@ -22,10 +19,15 @@ exports.ROOT_DOMAIN = void 0;
22
19
  * See the License for the specific language governing permissions and
23
20
  * limitations under the License.
24
21
  */
25
- const path_1 = require("path");
26
- const dotenv_1 = __importDefault(require("dotenv"));
27
- if (process.env.NODE_ENV === "development") {
28
- dotenv_1.default.config({ path: (0, path_1.join)(__dirname, "..", "..", "..", ".env") });
29
- }
30
- const e = process.env;
31
- exports.ROOT_DOMAIN = e.APISERVER_ROOT_DOMAIN || e.ROOT_DOMAIN || "fonoster.local";
22
+ /**
23
+ * Root SIP domain that workspace domains must end with. The API server sets it
24
+ * from fonoster.yaml's `domain` at boot (setRootDomain); nothing reads it from
25
+ * the environment or a .env file (fix-config-and-placement-gaps).
26
+ */
27
+ let rootDomain = "fonoster.local";
28
+ const setRootDomain = (domain) => {
29
+ rootDomain = domain;
30
+ };
31
+ exports.setRootDomain = setRootDomain;
32
+ const getRootDomain = () => rootDomain;
33
+ exports.getRootDomain = getRootDomain;
@@ -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[];