@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
@@ -71,7 +71,12 @@ class PrismaRegistryStore extends stores_1.MemoryRegistryStore {
71
71
  id: p.id,
72
72
  adapter: p.adapter,
73
73
  capabilities: p.capabilities,
74
- credentialRef: p.credentialRef,
74
+ credentialRef: opt(p.credentialRef),
75
+ label: opt(p.label),
76
+ // Stored as {} when the provider names none.
77
+ endpoints: p.endpoints && Object.keys(p.endpoints).length
78
+ ? p.endpoints
79
+ : undefined,
75
80
  state: fromState(p.state),
76
81
  replacement: opt(p.replacement),
77
82
  retireOn: opt(p.retireOn)
@@ -80,6 +85,7 @@ class PrismaRegistryStore extends stores_1.MemoryRegistryStore {
80
85
  entries.set(m.id, clean({
81
86
  kind: "model",
82
87
  id: m.id,
88
+ label: opt(m.label),
83
89
  type: m.type,
84
90
  features: m.features,
85
91
  languages: m.languages,
@@ -92,6 +98,7 @@ class PrismaRegistryStore extends stores_1.MemoryRegistryStore {
92
98
  entries.set(v.id, clean({
93
99
  kind: "voice",
94
100
  id: v.id,
101
+ label: opt(v.label),
95
102
  models: v.models.map((r) => r.modelId),
96
103
  language: opt(v.language),
97
104
  gender: opt(v.gender),
@@ -111,19 +118,20 @@ class PrismaRegistryStore extends stores_1.MemoryRegistryStore {
111
118
  });
112
119
  }
113
120
  put(entry) {
114
- var _a, _b;
121
+ var _a, _b, _c;
115
122
  super.put(entry);
116
123
  const e = JSON.parse(JSON.stringify(entry));
117
124
  const common = {
125
+ label: (_a = e.label) !== null && _a !== void 0 ? _a : null,
118
126
  state: toState(e.state),
119
- replacement: (_a = e.replacement) !== null && _a !== void 0 ? _a : null,
120
- retireOn: (_b = e.retireOn) !== null && _b !== void 0 ? _b : null
127
+ replacement: (_b = e.replacement) !== null && _b !== void 0 ? _b : null,
128
+ retireOn: (_c = e.retireOn) !== null && _c !== void 0 ? _c : null
121
129
  };
122
130
  const provider = e.id.split("/")[0];
123
131
  this.writes.push(() => __awaiter(this, void 0, void 0, function* () {
124
- var _a, _b, _c;
132
+ var _a, _b, _c, _d, _e;
125
133
  if (e.kind === "provider") {
126
- const data = Object.assign({ adapter: e.adapter, capabilities: e.capabilities, credentialRef: e.credentialRef }, common);
134
+ const data = Object.assign({ adapter: e.adapter, capabilities: e.capabilities, credentialRef: (_a = e.credentialRef) !== null && _a !== void 0 ? _a : null, endpoints: (_b = e.endpoints) !== null && _b !== void 0 ? _b : {} }, common);
127
135
  yield this.prisma.registryProvider.upsert({
128
136
  where: { id: e.id },
129
137
  create: Object.assign({ id: e.id }, data),
@@ -139,7 +147,7 @@ class PrismaRegistryStore extends stores_1.MemoryRegistryStore {
139
147
  });
140
148
  }
141
149
  else {
142
- const data = Object.assign({ providerId: provider, language: (_a = e.language) !== null && _a !== void 0 ? _a : null, gender: (_b = e.gender) !== null && _b !== void 0 ? _b : null, ownerWorkspace: (_c = e.ownerWorkspace) !== null && _c !== void 0 ? _c : null }, common);
150
+ const data = Object.assign({ providerId: provider, language: (_c = e.language) !== null && _c !== void 0 ? _c : null, gender: (_d = e.gender) !== null && _d !== void 0 ? _d : null, ownerWorkspace: (_e = e.ownerWorkspace) !== null && _e !== void 0 ? _e : null }, common);
143
151
  yield this.prisma.$transaction([
144
152
  this.prisma.registryVoice.upsert({
145
153
  where: { id: e.id },
@@ -182,8 +190,8 @@ class PrismaRegistryStore extends stores_1.MemoryRegistryStore {
182
190
  }
183
191
  exports.PrismaRegistryStore = PrismaRegistryStore;
184
192
  /**
185
- * Usages of catalog ids in apps (speech defaults: voice, TTS and STT models) and assistants (the
186
- * Autopilot assistant in an app's Intelligence config: `languageModel.model`, and
193
+ * Usages of catalog ids in apps (speech defaults: voice, TTS and STT models) and agents (the
194
+ * Autopilot agent in an app's Intelligence config: `languageModel.model`, and
187
195
  * `conversationSettings.voice`). Legacy rows with raw vendor names are not usages until migrated
188
196
  * to catalog ids (task 5.1).
189
197
  */
@@ -250,10 +258,10 @@ class PrismaUsageSource {
250
258
  requires: ["streaming"]
251
259
  }, { kind: "app-stt", row });
252
260
  }
253
- const assistant = (_d = row.intelligence) === null || _d === void 0 ? void 0 : _d.config;
254
- const llm = (_e = assistant === null || assistant === void 0 ? void 0 : assistant.languageModel) === null || _e === void 0 ? void 0 : _e.model;
261
+ const agent = (_d = row.intelligence) === null || _d === void 0 ? void 0 : _d.config;
262
+ const llm = (_e = agent === null || agent === void 0 ? void 0 : agent.languageModel) === null || _e === void 0 ? void 0 : _e.model;
255
263
  const config = {
256
- kind: "assistant",
264
+ kind: "agent",
257
265
  ref: row.ref,
258
266
  name: row.name
259
267
  };
@@ -263,12 +271,12 @@ class PrismaUsageSource {
263
271
  config,
264
272
  model: llm,
265
273
  settings: [],
266
- requires: ((_g = (_f = assistant === null || assistant === void 0 ? void 0 : assistant.languageModel) === null || _f === void 0 ? void 0 : _f.tools) === null || _g === void 0 ? void 0 : _g.length)
274
+ requires: ((_g = (_f = agent === null || agent === void 0 ? void 0 : agent.languageModel) === null || _f === void 0 ? void 0 : _f.tools) === null || _g === void 0 ? void 0 : _g.length)
267
275
  ? ["streaming", "tool-calling"]
268
276
  : ["streaming"]
269
- }, { kind: "assistant-llm", row, model: llm });
277
+ }, { kind: "agent-llm", row, model: llm });
270
278
  }
271
- const voice = (_h = assistant === null || assistant === void 0 ? void 0 : assistant.conversationSettings) === null || _h === void 0 ? void 0 : _h.voice;
279
+ const voice = (_h = agent === null || agent === void 0 ? void 0 : agent.conversationSettings) === null || _h === void 0 ? void 0 : _h.voice;
272
280
  if (voice === id) {
273
281
  add({
274
282
  workspace: row.accessKeyId,
@@ -277,7 +285,7 @@ class PrismaUsageSource {
277
285
  voice,
278
286
  settings: [],
279
287
  requires: ["streaming"]
280
- }, { kind: "assistant-voice", row, voice });
288
+ }, { kind: "agent-voice", row, voice });
281
289
  }
282
290
  }
283
291
  return out;
@@ -325,7 +333,7 @@ class PrismaUsageSource {
325
333
  const config = JSON.parse(JSON.stringify((_b = (_a = row.intelligence) === null || _a === void 0 ? void 0 : _a.config) !== null && _b !== void 0 ? _b : {}));
326
334
  let path;
327
335
  let expected;
328
- if (origin.kind === "assistant-llm") {
336
+ if (origin.kind === "agent-llm") {
329
337
  path = ["languageModel", "model"];
330
338
  expected = origin.model;
331
339
  if (change.model)
@@ -343,7 +351,7 @@ class PrismaUsageSource {
343
351
  data: { config }
344
352
  });
345
353
  if (count === 0)
346
- conflict("assistant changed since it was read");
354
+ conflict("agent changed since it was read");
347
355
  else
348
356
  yield this.prisma.application.update({
349
357
  where: { ref: row.ref },
@@ -17,14 +17,22 @@
17
17
  * limitations under the License.
18
18
  */
19
19
  export type Lifecycle = "active" | "deprecated" | "retired";
20
- export type Capability = "stt" | "tts" | "llm";
20
+ /** What a provider or model serves: speech, language models, or noise cancelling (`nc`). */
21
+ export type Capability = "stt" | "tts" | "llm" | "nc";
22
+ export declare const CAPABILITIES: Capability[];
21
23
  export type ItemKind = "provider" | "model" | "voice";
24
+ /** Where a provider serves each capability; services use these unless their config overrides. */
25
+ export type ProviderEndpoints = Partial<Record<Capability, string>>;
22
26
  export type ProviderEntry = {
23
27
  kind: "provider";
24
28
  id: string;
29
+ /** A display name ("Deepgram"); the dashboard shows the id without one. */
30
+ label?: string;
25
31
  adapter: string;
26
32
  capabilities: Capability[];
27
- credentialRef: string;
33
+ /** The platform credential's name; omitted for a keyless provider (no key needed). */
34
+ credentialRef?: string;
35
+ endpoints?: ProviderEndpoints;
28
36
  state: Lifecycle;
29
37
  replacement?: string;
30
38
  retireOn?: string;
@@ -32,6 +40,8 @@ export type ProviderEntry = {
32
40
  export type ModelEntry = {
33
41
  kind: "model";
34
42
  id: string;
43
+ /** A display name ("Nova 3"); the dashboard shows the id without one. */
44
+ label?: string;
35
45
  type: Capability;
36
46
  features: string[];
37
47
  languages: string[];
@@ -44,6 +54,8 @@ export type ModelEntry = {
44
54
  export type VoiceEntry = {
45
55
  kind: "voice";
46
56
  id: string;
57
+ /** A display name ("Aura 2 Thalia"); the dashboard shows the id without one. */
58
+ label?: string;
47
59
  models: string[];
48
60
  language?: string;
49
61
  gender?: string;
@@ -61,11 +73,11 @@ export type AuditEntry = {
61
73
  target: string;
62
74
  details?: Record<string, unknown>;
63
75
  };
64
- /** One place a catalog id is used: an app's speech config or an assistant's model config. */
76
+ /** One place a catalog id is used: an app's speech config or an agent's model config. */
65
77
  export type Usage = {
66
78
  workspace: string;
67
79
  config: {
68
- kind: "app" | "assistant";
80
+ kind: "app" | "agent";
69
81
  ref: string;
70
82
  name: string;
71
83
  };
@@ -76,7 +88,7 @@ export type Usage = {
76
88
  /** Hard features the config needs (derived from its content, e.g. tools need tool-calling). */
77
89
  requires: string[];
78
90
  };
79
- /** Where usages come from (apps and assistants in the control-plane database). */
91
+ /** Where usages come from (apps and agents in the control-plane database). */
80
92
  export interface UsageSource {
81
93
  find(id: string): Usage[];
82
94
  /** Rewrites one config; returns false if it changed since it was read. */
@@ -20,3 +20,5 @@
20
20
  // The provider registry (add-provider-registry): providers, models and voices by catalog id,
21
21
  // with a manual lifecycle. The catalog never holds a secret: providers name a credentialRef.
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.CAPABILITIES = void 0;
24
+ exports.CAPABILITIES = ["stt", "tts", "llm", "nc"];
@@ -0,0 +1,9 @@
1
+ /** How long one health check may take. */
2
+ export declare const HEALTH_CHECK_TIMEOUT_MS = 2000;
3
+ /**
4
+ * Whether `address` (host:port) answers the standard gRPC health check (grpc.health.v1) with
5
+ * SERVING for the server as a whole. False on any error, a timeout or any other status (a Roomr
6
+ * node or AppBridge replica draining after SIGTERM reports NOT_SERVING). Through a Kubernetes
7
+ * Service or a Compose service name the check reaches one ready replica.
8
+ */
9
+ export declare function checkGrpcHealth(address: string, timeoutMs?: number): Promise<boolean>;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.HEALTH_CHECK_TIMEOUT_MS = void 0;
37
+ exports.checkGrpcHealth = checkGrpcHealth;
38
+ /**
39
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
40
+ * http://github.com/fonoster/fonoster
41
+ *
42
+ * This file is part of Fonoster
43
+ *
44
+ * Licensed under the MIT License (the "License");
45
+ * you may not use this file except in compliance with
46
+ * the License. You may obtain a copy of the License at
47
+ *
48
+ * https://opensource.org/licenses/MIT
49
+ *
50
+ * Unless required by applicable law or agreed to in writing, software
51
+ * distributed under the License is distributed on an "AS IS" BASIS,
52
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
53
+ * See the License for the specific language governing permissions and
54
+ * limitations under the License.
55
+ */
56
+ const grpc = __importStar(require("@grpc/grpc-js"));
57
+ const grpc_health_check_1 = require("grpc-health-check");
58
+ /** How long one health check may take. */
59
+ exports.HEALTH_CHECK_TIMEOUT_MS = 2000;
60
+ /**
61
+ * Whether `address` (host:port) answers the standard gRPC health check (grpc.health.v1) with
62
+ * SERVING for the server as a whole. False on any error, a timeout or any other status (a Roomr
63
+ * node or AppBridge replica draining after SIGTERM reports NOT_SERVING). Through a Kubernetes
64
+ * Service or a Compose service name the check reaches one ready replica.
65
+ */
66
+ function checkGrpcHealth(address, timeoutMs = exports.HEALTH_CHECK_TIMEOUT_MS) {
67
+ const Health = grpc.makeGenericClientConstructor(grpc_health_check_1.service, "Health");
68
+ const client = new Health(address, grpc.credentials.createInsecure());
69
+ return new Promise((resolve) => {
70
+ client.Check({ service: "" }, { deadline: Date.now() + timeoutMs }, (error, res) => {
71
+ client.close();
72
+ resolve(!error && ((res === null || res === void 0 ? void 0 : res.status) === "SERVING" || (res === null || res === void 0 ? void 0 : res.status) === 1));
73
+ });
74
+ });
75
+ }
@@ -0,0 +1,75 @@
1
+ import * as grpc from "@grpc/grpc-js";
2
+ /** The proto file this package loads. */
3
+ export declare const ROOMR_PROTO: string;
4
+ export type SipAuth = {
5
+ username: string;
6
+ password: string;
7
+ };
8
+ export type SipTarget = {
9
+ uri: string;
10
+ proxy?: string;
11
+ headers?: Record<string, string>;
12
+ auth?: SipAuth;
13
+ };
14
+ export type CreateCallRequest = {
15
+ callRef?: string;
16
+ to: SipTarget;
17
+ from?: string;
18
+ roomRef?: string;
19
+ session?: string;
20
+ ringTimeoutS?: number;
21
+ /** Passed through untouched in the events for this call (e.g. { app_ref }). */
22
+ metadata?: Record<string, string>;
23
+ maxDurationS?: number;
24
+ };
25
+ export type Call = {
26
+ callRef: string;
27
+ roomRef: string;
28
+ state: "RINGING" | "ANSWERED" | "ENDED";
29
+ participantRef: string;
30
+ };
31
+ export type CreateRoomRequest = {
32
+ roomRef?: string;
33
+ maxDurationS?: number;
34
+ /** Overrides the node's emptyRoomTimeout for this room (0: the node's). */
35
+ emptyTimeoutS?: number;
36
+ /** Overrides the node's maxParticipants for this room (0: the node's). */
37
+ maxParticipants?: number;
38
+ };
39
+ export type Room = {
40
+ roomRef: string;
41
+ };
42
+ /** The RPCs the control plane uses, each against one node's control address. */
43
+ export type RoomrCalls = {
44
+ createCall(addr: string, request: CreateCallRequest): Promise<Call>;
45
+ createRoom(addr: string, request: CreateRoomRequest): Promise<Room>;
46
+ endCall(addr: string, request: {
47
+ callRef: string;
48
+ }): Promise<void>;
49
+ endRoom(addr: string, request: {
50
+ roomRef: string;
51
+ }): Promise<void>;
52
+ };
53
+ /** A failed RPC, with its gRPC status code. */
54
+ export declare class RoomrError extends Error {
55
+ readonly code: grpc.status;
56
+ constructor(code: grpc.status, message: string);
57
+ }
58
+ /** The roomr.v1 package (protoLoader options as for the other Fonoster services). */
59
+ export declare function roomrPackage(): grpc.GrpcObject;
60
+ /** The Roomr service definition (fakes serve it). */
61
+ export declare function roomrService(): grpc.ServiceDefinition;
62
+ /** Each call's deadline (ms). */
63
+ export declare const ROOMR_DEADLINE_MS = 2000;
64
+ /**
65
+ * One gRPC channel per node address, reused by every call to it, with HTTP/2 keepalive and a
66
+ * deadline per call. Plaintext: the control port is reachable only inside the deployment's
67
+ * network. `close()` closes every channel.
68
+ */
69
+ export declare function createRoomrPool(options?: {
70
+ deadlineMs?: number;
71
+ }): RoomrCalls & {
72
+ close(): void;
73
+ };
74
+ export * from "./health";
75
+ export * from "./session";
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
+ };
38
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
39
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
40
+ return new (P || (P = Promise))(function (resolve, reject) {
41
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
42
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
43
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
44
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
45
+ });
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.ROOMR_DEADLINE_MS = exports.RoomrError = exports.ROOMR_PROTO = void 0;
49
+ exports.roomrPackage = roomrPackage;
50
+ exports.roomrService = roomrService;
51
+ exports.createRoomrPool = createRoomrPool;
52
+ /**
53
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
54
+ * http://github.com/fonoster/fonoster
55
+ *
56
+ * This file is part of Fonoster
57
+ *
58
+ * Licensed under the MIT License (the "License");
59
+ * you may not use this file except in compliance with
60
+ * the License. You may obtain a copy of the License at
61
+ *
62
+ * https://opensource.org/licenses/MIT
63
+ *
64
+ * Unless required by applicable law or agreed to in writing, software
65
+ * distributed under the License is distributed on an "AS IS" BASIS,
66
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67
+ * See the License for the specific language governing permissions and
68
+ * limitations under the License.
69
+ */
70
+ const path = __importStar(require("path"));
71
+ const grpc = __importStar(require("@grpc/grpc-js"));
72
+ const protoLoader = __importStar(require("@grpc/proto-loader"));
73
+ // The controller's side of Roomr (roomr.v1.Roomr, redesign-roomr "Roomr is a gRPC service
74
+ // with three nouns"). The proto is fonoster/roomr's api/roomr/v1/roomr.proto; src/protos/roomr.proto
75
+ // is the copy of the pinned release (npm run sync:roomr; the client test checks it).
76
+ /** The proto file this package loads. */
77
+ exports.ROOMR_PROTO = path.join(__dirname, "..", "protos", "roomr.proto");
78
+ /** A failed RPC, with its gRPC status code. */
79
+ class RoomrError extends Error {
80
+ constructor(code, message) {
81
+ super(message);
82
+ this.code = code;
83
+ this.name = "RoomrError";
84
+ }
85
+ }
86
+ exports.RoomrError = RoomrError;
87
+ let loaded;
88
+ /** The roomr.v1 package (protoLoader options as for the other Fonoster services). */
89
+ function roomrPackage() {
90
+ loaded !== null && loaded !== void 0 ? loaded : (loaded = grpc.loadPackageDefinition(protoLoader.loadSync(exports.ROOMR_PROTO, {
91
+ keepCase: false,
92
+ longs: String,
93
+ enums: String,
94
+ defaults: true,
95
+ oneofs: true
96
+ })));
97
+ return loaded.roomr.v1;
98
+ }
99
+ /** The Roomr service definition (fakes serve it). */
100
+ function roomrService() {
101
+ return roomrPackage().Roomr.service;
102
+ }
103
+ /** Each call's deadline (ms). */
104
+ exports.ROOMR_DEADLINE_MS = 2000;
105
+ /**
106
+ * One gRPC channel per node address, reused by every call to it, with HTTP/2 keepalive and a
107
+ * deadline per call. Plaintext: the control port is reachable only inside the deployment's
108
+ * network. `close()` closes every channel.
109
+ */
110
+ function createRoomrPool(options = {}) {
111
+ const Client = roomrPackage().Roomr;
112
+ const clients = new Map();
113
+ const client = (addr) => {
114
+ let c = clients.get(addr);
115
+ if (!c) {
116
+ c = new Client(addr, grpc.credentials.createInsecure(), {
117
+ "grpc.keepalive_time_ms": 10000,
118
+ "grpc.keepalive_timeout_ms": 5000,
119
+ "grpc.keepalive_permit_without_calls": 1
120
+ });
121
+ clients.set(addr, c);
122
+ }
123
+ return c;
124
+ };
125
+ const call = (method) => (addr, request) => new Promise((resolve, reject) => {
126
+ var _a;
127
+ const rpc = client(addr)[method].bind(client(addr));
128
+ rpc(request, { deadline: Date.now() + ((_a = options.deadlineMs) !== null && _a !== void 0 ? _a : exports.ROOMR_DEADLINE_MS) }, (err, res) => err ? reject(new RoomrError(err.code, err.details)) : resolve(res));
129
+ });
130
+ const empty = (method) => (addr, request) => __awaiter(this, void 0, void 0, function* () {
131
+ yield call(method)(addr, request);
132
+ });
133
+ return {
134
+ createCall: call("CreateCall"),
135
+ createRoom: call("CreateRoom"),
136
+ endCall: empty("EndCall"),
137
+ endRoom: empty("EndRoom"),
138
+ close() {
139
+ for (const c of clients.values())
140
+ c.close();
141
+ clients.clear();
142
+ }
143
+ };
144
+ }
145
+ __exportStar(require("./health"), exports);
146
+ __exportStar(require("./session"), exports);
@@ -0,0 +1,133 @@
1
+ import * as grpc from "@grpc/grpc-js";
2
+ /** The proto file this module loads. */
3
+ export declare const SESSION_PROTO: string;
4
+ /** The port AppBridge serves Session.Connect (and grpc.health.v1) on by default. */
5
+ export declare const SESSION_PORT = 50071;
6
+ /** The gRPC service name, as the health service reports it. */
7
+ export declare const SESSION_SERVICE_NAME = "session.v1.Session";
8
+ /** An RTP endpoint: `codec` is "L16/16000" on app legs; `srtpKey` (SDES, base64) when encrypted. */
9
+ export type MediaEndpoint = {
10
+ ip: string;
11
+ port: number;
12
+ codec?: string;
13
+ srtpKey?: string;
14
+ };
15
+ export type SessionSipTarget = {
16
+ uri: string;
17
+ proxy?: string;
18
+ headers?: Record<string, string>;
19
+ auth?: {
20
+ username: string;
21
+ password: string;
22
+ };
23
+ };
24
+ export type SessionStart = {
25
+ callRef: string;
26
+ direction: "INBOUND" | "OUTBOUND";
27
+ from: string;
28
+ to: string;
29
+ /** Every INVITE header (inbound) or CreateCall's to.headers (outbound). */
30
+ headers: Record<string, string>;
31
+ /** CreateCall's metadata, untouched (outbound calls carry `app_ref`). */
32
+ metadata: Record<string, string>;
33
+ roomRef: string;
34
+ /** The node's RTP endpoint for this call's app leg. */
35
+ media?: MediaEndpoint;
36
+ nodeRef: string;
37
+ };
38
+ export type SessionDtmf = {
39
+ digit: string;
40
+ source?: string;
41
+ };
42
+ export type SessionEvent = {
43
+ participantJoined?: {
44
+ participantRef: string;
45
+ trackId: number;
46
+ };
47
+ participantLeft?: {
48
+ participantRef: string;
49
+ cause: string;
50
+ };
51
+ transferResult?: {
52
+ status: string;
53
+ cause?: string;
54
+ sipStatus?: number;
55
+ };
56
+ ended?: {
57
+ cause: string;
58
+ sipStatus?: number;
59
+ };
60
+ /** The oneof member that is set (protoLoader `oneofs: true`). */
61
+ event?: "participantJoined" | "participantLeft" | "transferResult" | "ended";
62
+ };
63
+ /** A message from the node. */
64
+ export type NodeMessage = {
65
+ start?: SessionStart;
66
+ dtmf?: SessionDtmf;
67
+ event?: SessionEvent;
68
+ msg?: "start" | "dtmf" | "event";
69
+ };
70
+ export type ListenTrack = {
71
+ trackId: number;
72
+ rtp: MediaEndpoint;
73
+ };
74
+ /** A message to the node (exactly one member set). */
75
+ export type AppMessage = {
76
+ answer?: {
77
+ media: MediaEndpoint;
78
+ maxDurationS?: number;
79
+ };
80
+ ready?: {
81
+ media: MediaEndpoint;
82
+ };
83
+ reject?: {
84
+ sipStatus: number;
85
+ reason?: string;
86
+ };
87
+ transfer?: {
88
+ to: SessionSipTarget;
89
+ mode: "cold" | "warm" | "refer";
90
+ music?: string;
91
+ ringTimeoutS?: number;
92
+ };
93
+ transferComplete?: Record<string, never>;
94
+ /** Cuts the caller off from the app; the node loops `music` (a WAV URL) to the caller alone. */
95
+ hold?: {
96
+ music?: string;
97
+ };
98
+ resume?: Record<string, never>;
99
+ /** RFC 4733 events on the caller's leg, in order. */
100
+ sendDtmf?: {
101
+ digits: string;
102
+ };
103
+ addListener?: {
104
+ listenerRef: string;
105
+ listen: ListenTrack[];
106
+ };
107
+ removeListener?: {
108
+ listenerRef: string;
109
+ };
110
+ hangup?: {
111
+ sipStatus?: number;
112
+ reason?: string;
113
+ };
114
+ msg?: AppMessageType;
115
+ };
116
+ export type AppMessageType = "answer" | "ready" | "reject" | "transfer" | "transferComplete" | "hold" | "resume" | "sendDtmf" | "addListener" | "removeListener" | "hangup";
117
+ /** The member a message carries (the oneof's name), for logs and fakes. */
118
+ export declare function messageType<T extends Record<string, unknown>>(message: T, members: readonly string[]): string | undefined;
119
+ export declare const APP_MESSAGE_TYPES: readonly AppMessageType[];
120
+ export declare const NODE_MESSAGE_TYPES: readonly ["start", "dtmf", "event"];
121
+ export declare const SESSION_EVENT_TYPES: readonly ["participantJoined", "participantLeft", "transferResult", "ended"];
122
+ /** Ended causes the node sends (media-control "Endings carry a reason"). */
123
+ export declare const ENDED_CAUSES: readonly ["caller_hangup", "callee_hangup", "busy", "no_answer", "rejected", "media_timeout", "node_error", "max_duration", "removed", "app_gone"];
124
+ /** The session.v1 package (protoLoader options as for the other Fonoster services). */
125
+ export declare function sessionPackage(): grpc.GrpcObject;
126
+ /** The Session service definition (AppBridge serves it). */
127
+ export declare function sessionService(): grpc.ServiceDefinition;
128
+ /** The Session client constructor (the node's side; fakes use it). */
129
+ export declare function sessionClient(): grpc.ServiceClientConstructor;
130
+ /** The server side of one control stream. */
131
+ export type SessionServerStream = grpc.ServerDuplexStream<NodeMessage, AppMessage>;
132
+ /** The client side of one control stream. */
133
+ export type SessionClientStream = grpc.ClientDuplexStream<NodeMessage, AppMessage>;