@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
@@ -0,0 +1,132 @@
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.ENDED_CAUSES = exports.SESSION_EVENT_TYPES = exports.NODE_MESSAGE_TYPES = exports.APP_MESSAGE_TYPES = exports.SESSION_SERVICE_NAME = exports.SESSION_PORT = exports.SESSION_PROTO = void 0;
37
+ exports.messageType = messageType;
38
+ exports.sessionPackage = sessionPackage;
39
+ exports.sessionService = sessionService;
40
+ exports.sessionClient = sessionClient;
41
+ /**
42
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
43
+ * http://github.com/fonoster/fonoster
44
+ *
45
+ * This file is part of Fonoster
46
+ *
47
+ * Licensed under the MIT License (the "License");
48
+ * you may not use this file except in compliance with
49
+ * the License. You may obtain a copy of the License at
50
+ *
51
+ * https://opensource.org/licenses/MIT
52
+ *
53
+ * Unless required by applicable law or agreed to in writing, software
54
+ * distributed under the License is distributed on an "AS IS" BASIS,
55
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
56
+ * See the License for the specific language governing permissions and
57
+ * limitations under the License.
58
+ */
59
+ const path = __importStar(require("path"));
60
+ const grpc = __importStar(require("@grpc/grpc-js"));
61
+ const protoLoader = __importStar(require("@grpc/proto-loader"));
62
+ // The per-call control stream (session.v1.Session, redesign-roomr media-control "Each call opens
63
+ // one control stream to the session endpoint"). The Roomr node is the client: it opens one
64
+ // connection per call and sends Start first; the session endpoint (AppBridge) answers with
65
+ // Answer, Ready or Reject and sends the app's commands. Audio never travels here. The proto is
66
+ // fonoster/roomr's api/session/v1/session.proto; src/protos/session.proto is the copy of the
67
+ // pinned release (npm run sync:roomr; the client test checks it).
68
+ /** The proto file this module loads. */
69
+ exports.SESSION_PROTO = path.join(__dirname, "..", "protos", "session.proto");
70
+ /** The port AppBridge serves Session.Connect (and grpc.health.v1) on by default. */
71
+ exports.SESSION_PORT = 50071;
72
+ /** The gRPC service name, as the health service reports it. */
73
+ exports.SESSION_SERVICE_NAME = "session.v1.Session";
74
+ /** The member a message carries (the oneof's name), for logs and fakes. */
75
+ function messageType(message, members) {
76
+ if (typeof message.msg === "string")
77
+ return message.msg;
78
+ return members.find((m) => message[m] !== undefined && message[m] !== null);
79
+ }
80
+ exports.APP_MESSAGE_TYPES = [
81
+ "answer",
82
+ "ready",
83
+ "reject",
84
+ "transfer",
85
+ "transferComplete",
86
+ "hold",
87
+ "resume",
88
+ "sendDtmf",
89
+ "addListener",
90
+ "removeListener",
91
+ "hangup"
92
+ ];
93
+ exports.NODE_MESSAGE_TYPES = ["start", "dtmf", "event"];
94
+ exports.SESSION_EVENT_TYPES = [
95
+ "participantJoined",
96
+ "participantLeft",
97
+ "transferResult",
98
+ "ended"
99
+ ];
100
+ /** Ended causes the node sends (media-control "Endings carry a reason"). */
101
+ exports.ENDED_CAUSES = [
102
+ "caller_hangup",
103
+ "callee_hangup",
104
+ "busy",
105
+ "no_answer",
106
+ "rejected",
107
+ "media_timeout",
108
+ "node_error",
109
+ "max_duration",
110
+ "removed",
111
+ "app_gone"
112
+ ];
113
+ let loaded;
114
+ /** The session.v1 package (protoLoader options as for the other Fonoster services). */
115
+ function sessionPackage() {
116
+ loaded !== null && loaded !== void 0 ? loaded : (loaded = grpc.loadPackageDefinition(protoLoader.loadSync(exports.SESSION_PROTO, {
117
+ keepCase: false,
118
+ longs: Number,
119
+ enums: String,
120
+ defaults: true,
121
+ oneofs: true
122
+ })));
123
+ return loaded.session.v1;
124
+ }
125
+ /** The Session service definition (AppBridge serves it). */
126
+ function sessionService() {
127
+ return sessionPackage().Session.service;
128
+ }
129
+ /** The Session client constructor (the node's side; fakes use it). */
130
+ function sessionClient() {
131
+ return sessionPackage().Session;
132
+ }
@@ -56,6 +56,9 @@ export declare const sessionStartSchema: {
56
56
  readonly type: "object";
57
57
  }];
58
58
  };
59
+ readonly traceparent: {
60
+ readonly type: "string";
61
+ };
59
62
  readonly audio: {
60
63
  readonly type: "object";
61
64
  readonly required: readonly ["codec", "rate"];
@@ -118,7 +121,7 @@ export declare const sessionEndSchema: {
118
121
  };
119
122
  };
120
123
  };
121
- export declare const ERROR_CODES: readonly ["bad_message", "unknown_command", "read_only", "not_supported_by_protocol", "provider_unavailable", "provider_timeout", "invalid_catalog_id", "feature_not_supported", "transfer_failed", "on_hold", "queue_full", "play_fetch_failed", "internal"];
124
+ export declare const ERROR_CODES: readonly ["bad_message", "unknown_command", "read_only", "not_supported_by_protocol", "provider_unavailable", "provider_timeout", "invalid_catalog_id", "feature_not_supported", "transfer_failed", "transfer_not_answered", "on_hold", "queue_full", "play_fetch_failed", "key_unavailable", "internal"];
122
125
  export declare const errorSchema: {
123
126
  readonly type: "object";
124
127
  readonly required: readonly ["type", "code", "message", "fatal"];
@@ -328,7 +331,22 @@ export declare const dtmfEventSchema: {
328
331
  };
329
332
  };
330
333
  };
331
- /** Answering-machine detection, once per call, for apps with `amd` (add-media-node 4.3). */
334
+ /** A warm transfer's new party answered; the app may now send transfer.complete. */
335
+ export declare const transferAnsweredSchema: {
336
+ readonly type: "object";
337
+ readonly required: readonly ["type", "relatesTo"];
338
+ readonly properties: {
339
+ readonly type: {
340
+ readonly const: "transfer.answered";
341
+ };
342
+ readonly relatesTo: {
343
+ readonly type: "string";
344
+ readonly minLength: 1;
345
+ readonly maxLength: 128;
346
+ };
347
+ };
348
+ };
349
+ /** Answering-machine detection, once per call, for apps with `amd` (add-roomr 4.3). */
332
350
  export declare const amdResultSchema: {
333
351
  readonly type: "object";
334
352
  readonly required: readonly ["type", "status", "confidence", "detector", "audioMs"];
@@ -630,6 +648,54 @@ export declare const handoffSchema: {
630
648
  };
631
649
  };
632
650
  };
651
+ /**
652
+ * Model token usage from Fonoster's own Autopilot (add-usage-metering D4). Reserved like
653
+ * record.note: accepted only from Autopilot agents and left out of the public docs.
654
+ */
655
+ export declare const usageReportSchema: {
656
+ readonly type: "object";
657
+ readonly required: readonly ["type", "lines"];
658
+ readonly properties: {
659
+ readonly type: {
660
+ readonly const: "usage.report";
661
+ };
662
+ readonly id: {
663
+ readonly type: "string";
664
+ readonly minLength: 1;
665
+ readonly maxLength: 128;
666
+ };
667
+ readonly lines: {
668
+ readonly type: "array";
669
+ readonly minItems: 1;
670
+ readonly maxItems: 64;
671
+ readonly items: {
672
+ readonly type: "object";
673
+ readonly required: readonly ["meter", "quantity", "provider", "keySource"];
674
+ readonly additionalProperties: false;
675
+ readonly properties: {
676
+ readonly meter: {
677
+ readonly enum: readonly ["llm.tokens.in", "llm.tokens.out", "llm.tokens.cached", "embedding.tokens"];
678
+ };
679
+ readonly quantity: {
680
+ readonly type: "integer";
681
+ readonly minimum: 0;
682
+ };
683
+ readonly provider: {
684
+ readonly type: "string";
685
+ readonly minLength: 1;
686
+ };
687
+ readonly model: {
688
+ readonly type: "string";
689
+ readonly minLength: 1;
690
+ };
691
+ readonly keySource: {
692
+ readonly enum: readonly ["platform", "workspace"];
693
+ };
694
+ };
695
+ };
696
+ };
697
+ };
698
+ };
633
699
  export declare const recordNoteSchema: {
634
700
  readonly type: "object";
635
701
  readonly required: readonly ["type", "data"];
@@ -665,6 +731,7 @@ export type OutputInterrupted = FromSchema<typeof outputInterruptedSchema>;
665
731
  export type MarkEvent = FromSchema<typeof markEventSchema>;
666
732
  export type DtmfEvent = FromSchema<typeof dtmfEventSchema>;
667
733
  export type AmdResult = FromSchema<typeof amdResultSchema>;
734
+ export type TransferAnswered = FromSchema<typeof transferAnsweredSchema>;
668
735
  export type Speak = FromSchema<typeof speakSchema>;
669
736
  export type Play = FromSchema<typeof playSchema>;
670
737
  export type ListenUpdate = FromSchema<typeof listenUpdateSchema>;
@@ -680,10 +747,10 @@ export type Hold = FromSchema<typeof holdSchema>;
680
747
  export type Resume = FromSchema<typeof resumeSchema>;
681
748
  export type Handoff = FromSchema<typeof handoffSchema>;
682
749
  export type RecordNote = FromSchema<typeof recordNoteSchema>;
683
- export type GatewayMessage = SessionStart | SessionEnd | SessionError | TurnUserStarted | TurnLikelyEnded | TurnEnded | TurnResumed | TurnBackchannel | TurnEstimate | TranscriptPartial | OutputStarted | OutputDone | OutputInterrupted | MarkEvent | DtmfEvent | AmdResult;
750
+ export type AppBridgeMessage = SessionStart | SessionEnd | SessionError | TurnUserStarted | TurnLikelyEnded | TurnEnded | TurnResumed | TurnBackchannel | TurnEstimate | TranscriptPartial | OutputStarted | OutputDone | OutputInterrupted | MarkEvent | DtmfEvent | TransferAnswered | AmdResult;
684
751
  export type AppCommand = Speak | Play | ListenUpdate | Subscribe | MarkCommand | Clear | Hangup | DtmfSend | Transfer | TransferComplete | Hold | Resume | Handoff | RecordNote;
685
752
  /** Schemas by message type, per direction. "mark" exists in both directions. */
686
- export declare const GATEWAY_MESSAGE_SCHEMAS: {
753
+ export declare const APPBRIDGE_MESSAGE_SCHEMAS: {
687
754
  readonly "session.start": {
688
755
  readonly type: "object";
689
756
  readonly required: readonly ["type", "protocol", "sessionRef", "callRef", "appRef", "direction", "from", "to", "metadata", "handoff", "audio", "tracks", "speech"];
@@ -722,6 +789,9 @@ export declare const GATEWAY_MESSAGE_SCHEMAS: {
722
789
  readonly type: "object";
723
790
  }];
724
791
  };
792
+ readonly traceparent: {
793
+ readonly type: "string";
794
+ };
725
795
  readonly audio: {
726
796
  readonly type: "object";
727
797
  readonly required: readonly ["codec", "rate"];
@@ -992,6 +1062,20 @@ export declare const GATEWAY_MESSAGE_SCHEMAS: {
992
1062
  };
993
1063
  };
994
1064
  };
1065
+ readonly "transfer.answered": {
1066
+ readonly type: "object";
1067
+ readonly required: readonly ["type", "relatesTo"];
1068
+ readonly properties: {
1069
+ readonly type: {
1070
+ readonly const: "transfer.answered";
1071
+ };
1072
+ readonly relatesTo: {
1073
+ readonly type: "string";
1074
+ readonly minLength: 1;
1075
+ readonly maxLength: 128;
1076
+ };
1077
+ };
1078
+ };
995
1079
  readonly "amd.result": {
996
1080
  readonly type: "object";
997
1081
  readonly required: readonly ["type", "status", "confidence", "detector", "audioMs"];
@@ -1310,9 +1394,53 @@ export declare const APP_COMMAND_SCHEMAS: {
1310
1394
  };
1311
1395
  };
1312
1396
  };
1397
+ readonly "usage.report": {
1398
+ readonly type: "object";
1399
+ readonly required: readonly ["type", "lines"];
1400
+ readonly properties: {
1401
+ readonly type: {
1402
+ readonly const: "usage.report";
1403
+ };
1404
+ readonly id: {
1405
+ readonly type: "string";
1406
+ readonly minLength: 1;
1407
+ readonly maxLength: 128;
1408
+ };
1409
+ readonly lines: {
1410
+ readonly type: "array";
1411
+ readonly minItems: 1;
1412
+ readonly maxItems: 64;
1413
+ readonly items: {
1414
+ readonly type: "object";
1415
+ readonly required: readonly ["meter", "quantity", "provider", "keySource"];
1416
+ readonly additionalProperties: false;
1417
+ readonly properties: {
1418
+ readonly meter: {
1419
+ readonly enum: readonly ["llm.tokens.in", "llm.tokens.out", "llm.tokens.cached", "embedding.tokens"];
1420
+ };
1421
+ readonly quantity: {
1422
+ readonly type: "integer";
1423
+ readonly minimum: 0;
1424
+ };
1425
+ readonly provider: {
1426
+ readonly type: "string";
1427
+ readonly minLength: 1;
1428
+ };
1429
+ readonly model: {
1430
+ readonly type: "string";
1431
+ readonly minLength: 1;
1432
+ };
1433
+ readonly keySource: {
1434
+ readonly enum: readonly ["platform", "workspace"];
1435
+ };
1436
+ };
1437
+ };
1438
+ };
1439
+ };
1440
+ };
1313
1441
  };
1314
1442
  export type AppCommandType = keyof typeof APP_COMMAND_SCHEMAS;
1315
- export type GatewayMessageType = keyof typeof GATEWAY_MESSAGE_SCHEMAS;
1443
+ export type AppBridgeMessageType = keyof typeof APPBRIDGE_MESSAGE_SCHEMAS;
1316
1444
  /** The whole protocol as one JSON Schema document, as exported to schema/session.v1.json. */
1317
1445
  export declare function sessionProtocolDocument(): {
1318
1446
  $schema: string;
@@ -1320,7 +1448,7 @@ export declare function sessionProtocolDocument(): {
1320
1448
  title: string;
1321
1449
  description: string;
1322
1450
  protocol: string;
1323
- gatewayToApp: {
1451
+ appBridgeToApp: {
1324
1452
  readonly "session.start": {
1325
1453
  readonly type: "object";
1326
1454
  readonly required: readonly ["type", "protocol", "sessionRef", "callRef", "appRef", "direction", "from", "to", "metadata", "handoff", "audio", "tracks", "speech"];
@@ -1359,6 +1487,9 @@ export declare function sessionProtocolDocument(): {
1359
1487
  readonly type: "object";
1360
1488
  }];
1361
1489
  };
1490
+ readonly traceparent: {
1491
+ readonly type: "string";
1492
+ };
1362
1493
  readonly audio: {
1363
1494
  readonly type: "object";
1364
1495
  readonly required: readonly ["codec", "rate"];
@@ -1629,6 +1760,20 @@ export declare function sessionProtocolDocument(): {
1629
1760
  };
1630
1761
  };
1631
1762
  };
1763
+ readonly "transfer.answered": {
1764
+ readonly type: "object";
1765
+ readonly required: readonly ["type", "relatesTo"];
1766
+ readonly properties: {
1767
+ readonly type: {
1768
+ readonly const: "transfer.answered";
1769
+ };
1770
+ readonly relatesTo: {
1771
+ readonly type: "string";
1772
+ readonly minLength: 1;
1773
+ readonly maxLength: 128;
1774
+ };
1775
+ };
1776
+ };
1632
1777
  readonly "amd.result": {
1633
1778
  readonly type: "object";
1634
1779
  readonly required: readonly ["type", "status", "confidence", "detector", "audioMs"];
@@ -1664,7 +1809,7 @@ export declare function sessionProtocolDocument(): {
1664
1809
  };
1665
1810
  };
1666
1811
  };
1667
- appToGateway: {
1812
+ appToAppBridge: {
1668
1813
  readonly speak: {
1669
1814
  readonly type: "object";
1670
1815
  readonly required: readonly ["type", "text"];
@@ -1947,5 +2092,49 @@ export declare function sessionProtocolDocument(): {
1947
2092
  };
1948
2093
  };
1949
2094
  };
2095
+ readonly "usage.report": {
2096
+ readonly type: "object";
2097
+ readonly required: readonly ["type", "lines"];
2098
+ readonly properties: {
2099
+ readonly type: {
2100
+ readonly const: "usage.report";
2101
+ };
2102
+ readonly id: {
2103
+ readonly type: "string";
2104
+ readonly minLength: 1;
2105
+ readonly maxLength: 128;
2106
+ };
2107
+ readonly lines: {
2108
+ readonly type: "array";
2109
+ readonly minItems: 1;
2110
+ readonly maxItems: 64;
2111
+ readonly items: {
2112
+ readonly type: "object";
2113
+ readonly required: readonly ["meter", "quantity", "provider", "keySource"];
2114
+ readonly additionalProperties: false;
2115
+ readonly properties: {
2116
+ readonly meter: {
2117
+ readonly enum: readonly ["llm.tokens.in", "llm.tokens.out", "llm.tokens.cached", "embedding.tokens"];
2118
+ };
2119
+ readonly quantity: {
2120
+ readonly type: "integer";
2121
+ readonly minimum: 0;
2122
+ };
2123
+ readonly provider: {
2124
+ readonly type: "string";
2125
+ readonly minLength: 1;
2126
+ };
2127
+ readonly model: {
2128
+ readonly type: "string";
2129
+ readonly minLength: 1;
2130
+ };
2131
+ readonly keySource: {
2132
+ readonly enum: readonly ["platform", "workspace"];
2133
+ };
2134
+ };
2135
+ };
2136
+ };
2137
+ };
2138
+ };
1950
2139
  };
1951
2140
  };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.APP_COMMAND_SCHEMAS = exports.GATEWAY_MESSAGE_SCHEMAS = exports.recordNoteSchema = exports.handoffSchema = exports.resumeSchema = exports.holdSchema = exports.transferCompleteSchema = exports.transferSchema = exports.TRANSFER_MODES = exports.dtmfSendSchema = exports.hangupSchema = exports.clearSchema = exports.markCommandSchema = exports.subscribeSchema = exports.SUBSCRIBABLE_EVENTS = exports.listenUpdateSchema = exports.playSchema = exports.speakSchema = exports.amdResultSchema = exports.dtmfEventSchema = exports.markEventSchema = exports.outputInterruptedSchema = exports.outputDoneSchema = exports.outputStartedSchema = exports.transcriptPartialSchema = exports.turnEstimateSchema = exports.turnBackchannelSchema = exports.turnResumedSchema = exports.turnEndedSchema = exports.turnLikelyEndedSchema = exports.turnUserStartedSchema = exports.errorSchema = exports.ERROR_CODES = exports.sessionEndSchema = exports.SESSION_END_REASONS = exports.sessionStartSchema = exports.SESSION_PROTOCOL = void 0;
3
+ exports.APP_COMMAND_SCHEMAS = exports.APPBRIDGE_MESSAGE_SCHEMAS = exports.recordNoteSchema = exports.usageReportSchema = exports.handoffSchema = exports.resumeSchema = exports.holdSchema = exports.transferCompleteSchema = exports.transferSchema = exports.TRANSFER_MODES = exports.dtmfSendSchema = exports.hangupSchema = exports.clearSchema = exports.markCommandSchema = exports.subscribeSchema = exports.SUBSCRIBABLE_EVENTS = exports.listenUpdateSchema = exports.playSchema = exports.speakSchema = exports.amdResultSchema = exports.transferAnsweredSchema = exports.dtmfEventSchema = exports.markEventSchema = exports.outputInterruptedSchema = exports.outputDoneSchema = exports.outputStartedSchema = exports.transcriptPartialSchema = exports.turnEstimateSchema = exports.turnBackchannelSchema = exports.turnResumedSchema = exports.turnEndedSchema = exports.turnLikelyEndedSchema = exports.turnUserStartedSchema = exports.errorSchema = exports.ERROR_CODES = exports.sessionEndSchema = exports.SESSION_END_REASONS = exports.sessionStartSchema = exports.SESSION_PROTOCOL = void 0;
4
4
  exports.sessionProtocolDocument = sessionProtocolDocument;
5
5
  // The fonoster.session.v1 messages (fonoster protocol), as JSON Schema. These schemas are the source
6
6
  // of truth: TypeScript types are derived from them below, and schema/session.v1.json is exported
@@ -11,7 +11,7 @@ exports.sessionProtocolDocument = sessionProtocolDocument;
11
11
  exports.SESSION_PROTOCOL = "fonoster.session.v1";
12
12
  const id = { type: "string", minLength: 1, maxLength: 128 };
13
13
  const catalogId = { type: "string", minLength: 1 };
14
- // ---- gateway → app ---------------------------------------------------------------------
14
+ // ---- appbridge → app ---------------------------------------------------------------------
15
15
  exports.sessionStartSchema = {
16
16
  type: "object",
17
17
  required: [
@@ -40,6 +40,8 @@ exports.sessionStartSchema = {
40
40
  to: { type: "string" },
41
41
  metadata: { type: "object" },
42
42
  handoff: { oneOf: [{ type: "null" }, { type: "object" }] },
43
+ // W3C traceparent of the call's span, so the app's spans join the call's trace (optional).
44
+ traceparent: { type: "string" },
43
45
  audio: {
44
46
  type: "object",
45
47
  required: ["codec", "rate"],
@@ -95,9 +97,11 @@ exports.ERROR_CODES = [
95
97
  "invalid_catalog_id",
96
98
  "feature_not_supported",
97
99
  "transfer_failed",
100
+ "transfer_not_answered",
98
101
  "on_hold",
99
102
  "queue_full",
100
103
  "play_fetch_failed",
104
+ "key_unavailable",
101
105
  "internal"
102
106
  ];
103
107
  exports.errorSchema = {
@@ -204,7 +208,16 @@ exports.dtmfEventSchema = {
204
208
  digit: { type: "string", pattern: "^[0-9A-D*#]$" }
205
209
  }
206
210
  };
207
- /** Answering-machine detection, once per call, for apps with `amd` (add-media-node 4.3). */
211
+ /** A warm transfer's new party answered; the app may now send transfer.complete. */
212
+ exports.transferAnsweredSchema = {
213
+ type: "object",
214
+ required: ["type", "relatesTo"],
215
+ properties: {
216
+ type: { const: "transfer.answered" },
217
+ relatesTo: id
218
+ }
219
+ };
220
+ /** Answering-machine detection, once per call, for apps with `amd` (add-roomr 4.3). */
208
221
  exports.amdResultSchema = {
209
222
  type: "object",
210
223
  required: ["type", "status", "confidence", "detector", "audioMs"],
@@ -221,7 +234,7 @@ exports.amdResultSchema = {
221
234
  reason: { type: "string" }
222
235
  }
223
236
  };
224
- // ---- app → gateway ---------------------------------------------------------------------
237
+ // ---- app → appbridge ---------------------------------------------------------------------
225
238
  exports.speakSchema = {
226
239
  type: "object",
227
240
  required: ["type", "text"],
@@ -339,6 +352,42 @@ exports.handoffSchema = {
339
352
  payload: { type: "object" }
340
353
  }
341
354
  };
355
+ /**
356
+ * Model token usage from Fonoster's own Autopilot (add-usage-metering D4). Reserved like
357
+ * record.note: accepted only from Autopilot agents and left out of the public docs.
358
+ */
359
+ exports.usageReportSchema = {
360
+ type: "object",
361
+ required: ["type", "lines"],
362
+ properties: {
363
+ type: { const: "usage.report" },
364
+ id,
365
+ lines: {
366
+ type: "array",
367
+ minItems: 1,
368
+ maxItems: 64,
369
+ items: {
370
+ type: "object",
371
+ required: ["meter", "quantity", "provider", "keySource"],
372
+ additionalProperties: false,
373
+ properties: {
374
+ meter: {
375
+ enum: [
376
+ "llm.tokens.in",
377
+ "llm.tokens.out",
378
+ "llm.tokens.cached",
379
+ "embedding.tokens"
380
+ ]
381
+ },
382
+ quantity: { type: "integer", minimum: 0 },
383
+ provider: { type: "string", minLength: 1 },
384
+ model: { type: "string", minLength: 1 },
385
+ keySource: { enum: ["platform", "workspace"] }
386
+ }
387
+ }
388
+ }
389
+ }
390
+ };
342
391
  exports.recordNoteSchema = {
343
392
  type: "object",
344
393
  required: ["type", "data"],
@@ -349,7 +398,7 @@ exports.recordNoteSchema = {
349
398
  }
350
399
  };
351
400
  /** Schemas by message type, per direction. "mark" exists in both directions. */
352
- exports.GATEWAY_MESSAGE_SCHEMAS = {
401
+ exports.APPBRIDGE_MESSAGE_SCHEMAS = {
353
402
  "session.start": exports.sessionStartSchema,
354
403
  "session.end": exports.sessionEndSchema,
355
404
  error: exports.errorSchema,
@@ -365,6 +414,7 @@ exports.GATEWAY_MESSAGE_SCHEMAS = {
365
414
  "output.interrupted": exports.outputInterruptedSchema,
366
415
  mark: exports.markEventSchema,
367
416
  dtmf: exports.dtmfEventSchema,
417
+ "transfer.answered": exports.transferAnsweredSchema,
368
418
  "amd.result": exports.amdResultSchema
369
419
  };
370
420
  exports.APP_COMMAND_SCHEMAS = {
@@ -381,7 +431,8 @@ exports.APP_COMMAND_SCHEMAS = {
381
431
  hold: exports.holdSchema,
382
432
  resume: exports.resumeSchema,
383
433
  handoff: exports.handoffSchema,
384
- "record.note": exports.recordNoteSchema
434
+ "record.note": exports.recordNoteSchema,
435
+ "usage.report": exports.usageReportSchema
385
436
  };
386
437
  /** The whole protocol as one JSON Schema document, as exported to schema/session.v1.json. */
387
438
  function sessionProtocolDocument() {
@@ -391,7 +442,7 @@ function sessionProtocolDocument() {
391
442
  title: exports.SESSION_PROTOCOL,
392
443
  description: "Messages of the Fonoster session protocol (a stream with protocol fonoster). Unknown types and fields must be ignored.",
393
444
  protocol: exports.SESSION_PROTOCOL,
394
- gatewayToApp: exports.GATEWAY_MESSAGE_SCHEMAS,
395
- appToGateway: exports.APP_COMMAND_SCHEMAS
445
+ appBridgeToApp: exports.APPBRIDGE_MESSAGE_SCHEMAS,
446
+ appToAppBridge: exports.APP_COMMAND_SCHEMAS
396
447
  };
397
448
  }
@@ -18,26 +18,29 @@
18
18
  */
19
19
  import type { KV, NatsConnection } from "nats";
20
20
  /**
21
- * The session registry (add-platform 2.3, add-media-node 3.2, decision D3): one NATS JetStream KV
21
+ * The session registry (add-platform 2.3, add-roomr 3.2, decision D3): one NATS JetStream KV
22
22
  * bucket shared by every service. Keys are `<kind>.<id>`:
23
23
  *
24
- * nodes.<nodeId> media node: { nodeId, rooms, draining, at } (written by the node)
25
- * rooms.<roomRef> media node: { roomRef, nodeId, at } (written by the node)
26
- * calls.<callRef> gateway: { callRef, gatewayRef, nodeId, roomRef, direction, at }
27
- * + once answered: { appRef, from, to, startedAt }
28
- * gateways.<gatewayRef> gateway: { gatewayRef, calls, at }
24
+ * calls.<callRef> appbridge: { callRef, bridgeRef, nodeId, roomRef, direction, at }
25
+ * + once answered: { appRef, workspaceRef, from, to, startedAt }
26
+ * appbridges.<bridgeRef> retired: AppBridge no longer writes it (redesign-roomr 15.3)
27
+ * placements.<callRef> apiserver: { callRef, nodeRef, controlAddr, roomRef?, at }
28
+ * while an outbound call is being placed (CreateCall)
29
29
  *
30
- * The control plane reads `calls` and `gateways`: a call whose entry and whose gateway's entry
31
- * both stop being rewritten lost its gateway mid-call, and gets `call.ended` (`appbridge-lost`).
30
+ * Roomr nodes write nothing here (core NATS only: heartbeat and events); the control plane learns
31
+ * nodes from their heartbeats.
32
+ *
33
+ * The control plane reads `calls` (billing counts active calls from them). A call that loses its
34
+ * AppBridge mid-call is reported by its node's `call.ended` with cause `app_gone` (redesign-roomr
35
+ * 15.4), not by expired `appbridges` entries.
32
36
  *
33
37
  * Entries are leases: the bucket keeps a value for SESSIONS_TTL_MS after its last write, owners
34
- * rewrite theirs every SESSIONS_REFRESH_MS, and a crashed owner's entries expire on their own. The
35
- * Go node uses the same bucket, TTL and key rules (go/medianode/internal/registry).
38
+ * rewrite theirs every SESSIONS_REFRESH_MS, and a crashed owner's entries expire on their own.
36
39
  */
37
40
  export declare const SESSIONS_BUCKET = "fonoster_sessions";
38
41
  export declare const SESSIONS_TTL_MS = 15000;
39
42
  export declare const SESSIONS_REFRESH_MS = 5000;
40
- export type SessionKind = "nodes" | "rooms" | "calls" | "gateways";
43
+ export type SessionKind = "nodes" | "rooms" | "calls" | "appbridges" | "placements";
41
44
  /** `<kind>.<id>` with characters KV keys do not allow replaced by `_`. */
42
45
  export declare const sessionKey: (kind: SessionKind, id: string) => string;
43
46
  /** Opens the bucket, creating it when it does not exist yet. */
@@ -49,7 +52,7 @@ type Logger = {
49
52
  warn(message: string): void;
50
53
  };
51
54
  /**
52
- * An owner's entries, kept alive until deleted (the gateway's calls and its own gateway entry).
55
+ * An owner's entries, kept alive until deleted (AppBridge's calls and its own appbridge entry).
53
56
  * Writes never throw: the registry is best effort and entries are rewritten on the next refresh.
54
57
  */
55
58
  export declare class SessionLeases {