qca-sdk 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +239 -0
- package/dist/core/client.d.ts +12 -0
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +24 -7
- package/dist/core/client.js.map +1 -1
- package/dist/esm/core/client.d.ts +12 -0
- package/dist/esm/core/client.d.ts.map +1 -1
- package/dist/esm/core/client.js +24 -7
- package/dist/esm/core/client.js.map +1 -1
- package/dist/esm/forward/drive.d.ts +20 -0
- package/dist/esm/forward/drive.d.ts.map +1 -0
- package/dist/esm/forward/drive.js +45 -0
- package/dist/esm/forward/drive.js.map +1 -0
- package/dist/esm/forward/forwardClient.d.ts +6 -0
- package/dist/esm/forward/forwardClient.d.ts.map +1 -1
- package/dist/esm/forward/forwardClient.js +6 -0
- package/dist/esm/forward/forwardClient.js.map +1 -1
- package/dist/esm/forward/identity-service-account-token.d.ts +11 -0
- package/dist/esm/forward/identity-service-account-token.d.ts.map +1 -0
- package/dist/esm/forward/identity-service-account-token.js +18 -0
- package/dist/esm/forward/identity-service-account-token.js.map +1 -0
- package/dist/esm/forward/identity.d.ts +2 -0
- package/dist/esm/forward/identity.d.ts.map +1 -1
- package/dist/esm/forward/identity.js +2 -0
- package/dist/esm/forward/identity.js.map +1 -1
- package/dist/esm/forward/index.d.ts +8 -0
- package/dist/esm/forward/index.d.ts.map +1 -1
- package/dist/esm/forward/index.js +7 -0
- package/dist/esm/forward/index.js.map +1 -1
- package/dist/esm/forward/realtime/connection.d.ts +106 -0
- package/dist/esm/forward/realtime/connection.d.ts.map +1 -0
- package/dist/esm/forward/realtime/connection.js +465 -0
- package/dist/esm/forward/realtime/connection.js.map +1 -0
- package/dist/esm/forward/realtime/conversation.d.ts +31 -0
- package/dist/esm/forward/realtime/conversation.d.ts.map +1 -0
- package/dist/esm/forward/realtime/conversation.js +92 -0
- package/dist/esm/forward/realtime/conversation.js.map +1 -0
- package/dist/esm/forward/realtime/realtime.d.ts +9 -0
- package/dist/esm/forward/realtime/realtime.d.ts.map +1 -0
- package/dist/esm/forward/realtime/realtime.js +9 -0
- package/dist/esm/forward/realtime/realtime.js.map +1 -0
- package/dist/esm/forward/realtime/types.d.ts +204 -0
- package/dist/esm/forward/realtime/types.d.ts.map +1 -0
- package/dist/esm/forward/realtime/types.js +7 -0
- package/dist/esm/forward/realtime/types.js.map +1 -0
- package/dist/esm/forward/service-account-token.d.ts +15 -0
- package/dist/esm/forward/service-account-token.d.ts.map +1 -0
- package/dist/esm/forward/service-account-token.js +38 -0
- package/dist/esm/forward/service-account-token.js.map +1 -0
- package/dist/esm/forward/types.d.ts +119 -0
- package/dist/esm/forward/types.d.ts.map +1 -1
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/forward/drive.d.ts +20 -0
- package/dist/forward/drive.d.ts.map +1 -0
- package/dist/forward/drive.js +49 -0
- package/dist/forward/drive.js.map +1 -0
- package/dist/forward/forwardClient.d.ts +6 -0
- package/dist/forward/forwardClient.d.ts.map +1 -1
- package/dist/forward/forwardClient.js +6 -0
- package/dist/forward/forwardClient.js.map +1 -1
- package/dist/forward/identity-service-account-token.d.ts +11 -0
- package/dist/forward/identity-service-account-token.d.ts.map +1 -0
- package/dist/forward/identity-service-account-token.js +22 -0
- package/dist/forward/identity-service-account-token.js.map +1 -0
- package/dist/forward/identity.d.ts +2 -0
- package/dist/forward/identity.d.ts.map +1 -1
- package/dist/forward/identity.js +2 -0
- package/dist/forward/identity.js.map +1 -1
- package/dist/forward/index.d.ts +8 -0
- package/dist/forward/index.d.ts.map +1 -1
- package/dist/forward/index.js +19 -1
- package/dist/forward/index.js.map +1 -1
- package/dist/forward/realtime/connection.d.ts +106 -0
- package/dist/forward/realtime/connection.d.ts.map +1 -0
- package/dist/forward/realtime/connection.js +473 -0
- package/dist/forward/realtime/connection.js.map +1 -0
- package/dist/forward/realtime/conversation.d.ts +31 -0
- package/dist/forward/realtime/conversation.d.ts.map +1 -0
- package/dist/forward/realtime/conversation.js +97 -0
- package/dist/forward/realtime/conversation.js.map +1 -0
- package/dist/forward/realtime/realtime.d.ts +9 -0
- package/dist/forward/realtime/realtime.d.ts.map +1 -0
- package/dist/forward/realtime/realtime.js +13 -0
- package/dist/forward/realtime/realtime.js.map +1 -0
- package/dist/forward/realtime/types.d.ts +204 -0
- package/dist/forward/realtime/types.d.ts.map +1 -0
- package/dist/forward/realtime/types.js +11 -0
- package/dist/forward/realtime/types.js.map +1 -0
- package/dist/forward/service-account-token.d.ts +15 -0
- package/dist/forward/service-account-token.d.ts.map +1 -0
- package/dist/forward/service-account-token.js +43 -0
- package/dist/forward/service-account-token.js.map +1 -0
- package/dist/forward/types.d.ts +119 -0
- package/dist/forward/types.d.ts.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +9 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/forward/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7E,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AACxF,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AACjF,YAAY,EAAE,QAAQ,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC;AACxF,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/forward/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7E,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AACxF,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AACjF,YAAY,EAAE,QAAQ,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC;AACxF,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,6BAA6B,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC9J,YAAY,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAClH,cAAc,qBAAqB,CAAC;AAEpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AAEnF,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/forward/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.Usage = exports.ServiceAccountCredential = exports.PATCredential = exports.toFile = exports.ResumableSessionEventStream = exports.Stream = exports.PagePromise = exports.Page = exports.APIPromise = exports.Models = exports.MemoryStoreMemoryVersions = exports.MemoryStoreMemories = exports.MemoryStores = exports.VaultCredentials = exports.Vaults = exports.SkillVersions = exports.Skills = exports.Files = exports.Environments = exports.ChannelPairings = exports.ChannelQRSessions = exports.Channels = exports.BatchTasks = exports.Batches = exports.ScheduleRuns = exports.Schedules = exports.SessionThreadEvents = exports.SessionThreads = exports.SessionResources = exports.SessionEvents = exports.Sessions = exports.IdentityMemoryStores = exports.IdentityConfigs = exports.Identities = exports.Templates = exports.default = exports.ForwardClient = void 0;
|
|
17
|
+
exports.Drives = exports.IdentityServiceAccountTokens = exports.ServiceAccountTokens = exports.decodeRealtimeAudio = exports.RealtimeServerError = exports.RealtimeConnectionClosedError = exports.RealtimeProtocolError = exports.RealtimeConnection = exports.RealtimeHistoryPage = exports.RealtimeConversations = exports.Realtime = exports.Usage = exports.ServiceAccountCredential = exports.PATCredential = exports.toFile = exports.ResumableSessionEventStream = exports.Stream = exports.PagePromise = exports.Page = exports.APIPromise = exports.Models = exports.MemoryStoreMemoryVersions = exports.MemoryStoreMemories = exports.MemoryStores = exports.VaultCredentials = exports.Vaults = exports.SkillVersions = exports.Skills = exports.Files = exports.Environments = exports.ChannelPairings = exports.ChannelQRSessions = exports.Channels = exports.BatchTasks = exports.Batches = exports.ScheduleRuns = exports.Schedules = exports.SessionThreadEvents = exports.SessionThreads = exports.SessionResources = exports.SessionEvents = exports.Sessions = exports.IdentityMemoryStores = exports.IdentityConfigs = exports.Identities = exports.Templates = exports.default = exports.ForwardClient = void 0;
|
|
18
18
|
var forwardClient_js_1 = require("./forwardClient.js");
|
|
19
19
|
Object.defineProperty(exports, "ForwardClient", { enumerable: true, get: function () { return forwardClient_js_1.ForwardClient; } });
|
|
20
20
|
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return forwardClient_js_1.ForwardClient; } });
|
|
@@ -88,4 +88,22 @@ Object.defineProperty(exports, "ServiceAccountCredential", { enumerable: true, g
|
|
|
88
88
|
__exportStar(require("../core/error.js"), exports);
|
|
89
89
|
var usage_js_1 = require("./usage.js");
|
|
90
90
|
Object.defineProperty(exports, "Usage", { enumerable: true, get: function () { return usage_js_1.Usage; } });
|
|
91
|
+
var realtime_js_1 = require("./realtime/realtime.js");
|
|
92
|
+
Object.defineProperty(exports, "Realtime", { enumerable: true, get: function () { return realtime_js_1.Realtime; } });
|
|
93
|
+
var conversation_js_1 = require("./realtime/conversation.js");
|
|
94
|
+
Object.defineProperty(exports, "RealtimeConversations", { enumerable: true, get: function () { return conversation_js_1.RealtimeConversations; } });
|
|
95
|
+
Object.defineProperty(exports, "RealtimeHistoryPage", { enumerable: true, get: function () { return conversation_js_1.RealtimeHistoryPage; } });
|
|
96
|
+
var connection_js_1 = require("./realtime/connection.js");
|
|
97
|
+
Object.defineProperty(exports, "RealtimeConnection", { enumerable: true, get: function () { return connection_js_1.RealtimeConnection; } });
|
|
98
|
+
Object.defineProperty(exports, "RealtimeProtocolError", { enumerable: true, get: function () { return connection_js_1.RealtimeProtocolError; } });
|
|
99
|
+
Object.defineProperty(exports, "RealtimeConnectionClosedError", { enumerable: true, get: function () { return connection_js_1.RealtimeConnectionClosedError; } });
|
|
100
|
+
Object.defineProperty(exports, "RealtimeServerError", { enumerable: true, get: function () { return connection_js_1.RealtimeServerError; } });
|
|
101
|
+
Object.defineProperty(exports, "decodeRealtimeAudio", { enumerable: true, get: function () { return connection_js_1.decodeRealtimeAudio; } });
|
|
102
|
+
__exportStar(require("./realtime/types.js"), exports);
|
|
103
|
+
var service_account_token_js_1 = require("./service-account-token.js");
|
|
104
|
+
Object.defineProperty(exports, "ServiceAccountTokens", { enumerable: true, get: function () { return service_account_token_js_1.ServiceAccountTokens; } });
|
|
105
|
+
var identity_service_account_token_js_1 = require("./identity-service-account-token.js");
|
|
106
|
+
Object.defineProperty(exports, "IdentityServiceAccountTokens", { enumerable: true, get: function () { return identity_service_account_token_js_1.IdentityServiceAccountTokens; } });
|
|
107
|
+
var drive_js_1 = require("./drive.js");
|
|
108
|
+
Object.defineProperty(exports, "Drives", { enumerable: true, get: function () { return drive_js_1.Drives; } });
|
|
91
109
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/forward/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,uDAA6E;AAApE,iHAAA,aAAa,OAAA;AAAE,2GAAA,aAAa,OAAW;AAEhD,6CAA2B;AAC3B,6CAA0C;AAAjC,wGAAA,SAAS,OAAA;AAClB,6CAA2C;AAAlC,yGAAA,UAAU,OAAA;AACnB,2DAAuD;AAA9C,qHAAA,eAAe,OAAA;AACxB,uEAAkE;AAAzD,gIAAA,oBAAoB,OAAA;AAC7B,2CAAwC;AAA/B,sGAAA,QAAQ,OAAA;AACjB,uDAAmD;AAA1C,iHAAA,aAAa,OAAA;AACtB,6DAAyD;AAAhD,uHAAA,gBAAgB,OAAA;AACzB,yDAAqD;AAA5C,mHAAA,cAAc,OAAA;AACvB,qEAAgE;AAAvD,8HAAA,mBAAmB,OAAA;AAC5B,6CAA0C;AAAjC,wGAAA,SAAS,OAAA;AAClB,qDAAiD;AAAxC,+GAAA,YAAY,OAAA;AACrB,uCAAqC;AAA5B,mGAAA,OAAO,OAAA;AAChB,iDAA6C;AAApC,2GAAA,UAAU,OAAA;AACnB,2CAAwC;AAA/B,sGAAA,QAAQ,OAAA;AACjB,iEAA4D;AAAnD,0HAAA,iBAAiB,OAAA;AAC1B,2DAAuD;AAA9C,qHAAA,eAAe,OAAA;AACxB,mDAAgD;AAAvC,8GAAA,YAAY,OAAA;AACrB,qCAAkC;AAAzB,gGAAA,KAAK,OAAA;AACd,uCAAoC;AAA3B,kGAAA,MAAM,OAAA;AACf,uDAAmD;AAA1C,iHAAA,aAAa,OAAA;AACtB,uCAAoC;AAA3B,kGAAA,MAAM,OAAA;AACf,6DAAyD;AAAhD,uHAAA,gBAAgB,OAAA;AACzB,qDAAiD;AAAxC,+GAAA,YAAY,OAAA;AACrB,mEAA+D;AAAtD,6HAAA,mBAAmB,OAAA;AAC5B,mFAA6E;AAApE,2IAAA,yBAAyB,OAAA;AAClC,uCAAoC;AAA3B,kGAAA,MAAM,OAAA;AAEf,yDAAoD;AAA3C,4GAAA,UAAU,OAAA;AACnB,uDAA0D;AAAjD,qGAAA,IAAI,OAAA;AAAE,4GAAA,WAAW,OAAA;AAC1B,qDAA8C;AAArC,sGAAA,MAAM,OAAA;AACf,+FAAwF;AAA/E,gJAAA,2BAA2B,OAAA;AACpC,iDAA4C;AAAnC,oGAAA,MAAM,OAAA;AAEf,yDAAiF;AAAxE,+GAAA,aAAa,OAAA;AAAE,0HAAA,wBAAwB,OAAA;AAGhD,mDAAiC;AACjC,uCAAmC;AAA1B,iGAAA,KAAK,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/forward/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,uDAA6E;AAApE,iHAAA,aAAa,OAAA;AAAE,2GAAA,aAAa,OAAW;AAEhD,6CAA2B;AAC3B,6CAA0C;AAAjC,wGAAA,SAAS,OAAA;AAClB,6CAA2C;AAAlC,yGAAA,UAAU,OAAA;AACnB,2DAAuD;AAA9C,qHAAA,eAAe,OAAA;AACxB,uEAAkE;AAAzD,gIAAA,oBAAoB,OAAA;AAC7B,2CAAwC;AAA/B,sGAAA,QAAQ,OAAA;AACjB,uDAAmD;AAA1C,iHAAA,aAAa,OAAA;AACtB,6DAAyD;AAAhD,uHAAA,gBAAgB,OAAA;AACzB,yDAAqD;AAA5C,mHAAA,cAAc,OAAA;AACvB,qEAAgE;AAAvD,8HAAA,mBAAmB,OAAA;AAC5B,6CAA0C;AAAjC,wGAAA,SAAS,OAAA;AAClB,qDAAiD;AAAxC,+GAAA,YAAY,OAAA;AACrB,uCAAqC;AAA5B,mGAAA,OAAO,OAAA;AAChB,iDAA6C;AAApC,2GAAA,UAAU,OAAA;AACnB,2CAAwC;AAA/B,sGAAA,QAAQ,OAAA;AACjB,iEAA4D;AAAnD,0HAAA,iBAAiB,OAAA;AAC1B,2DAAuD;AAA9C,qHAAA,eAAe,OAAA;AACxB,mDAAgD;AAAvC,8GAAA,YAAY,OAAA;AACrB,qCAAkC;AAAzB,gGAAA,KAAK,OAAA;AACd,uCAAoC;AAA3B,kGAAA,MAAM,OAAA;AACf,uDAAmD;AAA1C,iHAAA,aAAa,OAAA;AACtB,uCAAoC;AAA3B,kGAAA,MAAM,OAAA;AACf,6DAAyD;AAAhD,uHAAA,gBAAgB,OAAA;AACzB,qDAAiD;AAAxC,+GAAA,YAAY,OAAA;AACrB,mEAA+D;AAAtD,6HAAA,mBAAmB,OAAA;AAC5B,mFAA6E;AAApE,2IAAA,yBAAyB,OAAA;AAClC,uCAAoC;AAA3B,kGAAA,MAAM,OAAA;AAEf,yDAAoD;AAA3C,4GAAA,UAAU,OAAA;AACnB,uDAA0D;AAAjD,qGAAA,IAAI,OAAA;AAAE,4GAAA,WAAW,OAAA;AAC1B,qDAA8C;AAArC,sGAAA,MAAM,OAAA;AACf,+FAAwF;AAA/E,gJAAA,2BAA2B,OAAA;AACpC,iDAA4C;AAAnC,oGAAA,MAAM,OAAA;AAEf,yDAAiF;AAAxE,+GAAA,aAAa,OAAA;AAAE,0HAAA,wBAAwB,OAAA;AAGhD,mDAAiC;AACjC,uCAAmC;AAA1B,iGAAA,KAAK,OAAA;AAEd,sDAAkD;AAAzC,uGAAA,QAAQ,OAAA;AACjB,8DAAwF;AAA/E,wHAAA,qBAAqB,OAAA;AAAE,sHAAA,mBAAmB,OAAA;AACnD,0DAA8J;AAArJ,mHAAA,kBAAkB,OAAA;AAAE,sHAAA,qBAAqB,OAAA;AAAE,8HAAA,6BAA6B,OAAA;AAAE,oHAAA,mBAAmB,OAAA;AAAE,oHAAA,mBAAmB,OAAA;AAE3H,sDAAoC;AAEpC,uEAAkE;AAAzD,gIAAA,oBAAoB,OAAA;AAC7B,yFAAmF;AAA1E,iJAAA,4BAA4B,OAAA;AAErC,uCAAoC;AAA3B,kGAAA,MAAM,OAAA"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { APIClient, HeadersLike } from '../../core/client.js';
|
|
2
|
+
import { APIConnectionError } from '../../core/error.js';
|
|
3
|
+
import { type RealtimeClientEvent, type RealtimeClosed, type RealtimePlaybackReceipt, type RealtimeReady, type RealtimeServerEvent } from './types.js';
|
|
4
|
+
export interface RealtimeConnectOptions {
|
|
5
|
+
conversationId: string;
|
|
6
|
+
headers?: HeadersLike;
|
|
7
|
+
/** Cancelling this signal releases the entire connection, including ready waits. */
|
|
8
|
+
signal?: AbortSignal | null;
|
|
9
|
+
handshakeTimeout?: number;
|
|
10
|
+
readyTimeout?: number;
|
|
11
|
+
sendTimeout?: number;
|
|
12
|
+
closeTimeout?: number;
|
|
13
|
+
maxQueuedEvents?: number;
|
|
14
|
+
maxQueueBytes?: number;
|
|
15
|
+
maxReceiveBytes?: number;
|
|
16
|
+
/** Node agent (including proxy agents) and TLS settings; fetch/middleware do not apply to WS. */
|
|
17
|
+
transport?: {
|
|
18
|
+
agent?: object;
|
|
19
|
+
ca?: string | Uint8Array | Array<string | Uint8Array>;
|
|
20
|
+
cert?: string | Uint8Array;
|
|
21
|
+
key?: string | Uint8Array;
|
|
22
|
+
servername?: string;
|
|
23
|
+
rejectUnauthorized?: boolean;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface RealtimeWaitOptions {
|
|
27
|
+
signal?: AbortSignal | null;
|
|
28
|
+
timeout?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface RealtimeCloseOptions extends RealtimeWaitOptions {
|
|
31
|
+
requestId?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare class RealtimeProtocolError extends APIConnectionError {
|
|
34
|
+
readonly conversationId: string;
|
|
35
|
+
readonly code: string;
|
|
36
|
+
constructor(message: string, conversationId: string, code?: string);
|
|
37
|
+
}
|
|
38
|
+
export declare class RealtimeConnectionClosedError extends APIConnectionError {
|
|
39
|
+
readonly conversationId: string;
|
|
40
|
+
readonly closeCode: number;
|
|
41
|
+
readonly closeReason: string;
|
|
42
|
+
constructor(conversationId: string, closeCode: number, closeReason: string);
|
|
43
|
+
}
|
|
44
|
+
export declare class RealtimeServerError extends APIConnectionError {
|
|
45
|
+
readonly event: RealtimeServerEvent;
|
|
46
|
+
readonly code: string;
|
|
47
|
+
readonly retryable?: boolean;
|
|
48
|
+
readonly retry_after_ms?: number;
|
|
49
|
+
constructor(event: RealtimeServerEvent);
|
|
50
|
+
}
|
|
51
|
+
/** Decode an audio.delta payload into raw 24 kHz PCM16 bytes; this does not play it. */
|
|
52
|
+
export declare function decodeRealtimeAudio(event: RealtimeServerEvent): Uint8Array;
|
|
53
|
+
/** A Node-only connection with one receiver and bounded input/output queues. No reconnect or replay. */
|
|
54
|
+
export declare class RealtimeConnection implements AsyncIterable<RealtimeServerEvent> {
|
|
55
|
+
private readonly socket;
|
|
56
|
+
private readonly options;
|
|
57
|
+
readonly conversationId: string;
|
|
58
|
+
ready: RealtimeReady;
|
|
59
|
+
request_id: string | null;
|
|
60
|
+
private readonly queue;
|
|
61
|
+
private queueBytes;
|
|
62
|
+
private lastSequence;
|
|
63
|
+
private readonly maxQueuedEvents;
|
|
64
|
+
private readonly maxQueueBytes;
|
|
65
|
+
private readonly sendTimeout;
|
|
66
|
+
private readonly closeTimeout;
|
|
67
|
+
private readonly readyPromise;
|
|
68
|
+
private readyResolve;
|
|
69
|
+
private readyReject;
|
|
70
|
+
private receiver?;
|
|
71
|
+
private terminal?;
|
|
72
|
+
private ended;
|
|
73
|
+
private closing;
|
|
74
|
+
private sendTail;
|
|
75
|
+
private sendCount;
|
|
76
|
+
private sendBytes;
|
|
77
|
+
private graceful?;
|
|
78
|
+
private closeAck?;
|
|
79
|
+
private handshakeTimer?;
|
|
80
|
+
private readyTimer?;
|
|
81
|
+
private readonly abort;
|
|
82
|
+
private constructor();
|
|
83
|
+
/** @internal */
|
|
84
|
+
static connect(client: APIClient, options: RealtimeConnectOptions): Promise<RealtimeConnection>;
|
|
85
|
+
private onMessage;
|
|
86
|
+
private finish;
|
|
87
|
+
private fail;
|
|
88
|
+
/** Read one event. Concurrent consumers are rejected instead of stealing each other's events. */
|
|
89
|
+
receive(options?: RealtimeWaitOptions): Promise<IteratorResult<RealtimeServerEvent>>;
|
|
90
|
+
[Symbol.asyncIterator](): AsyncGenerator<RealtimeServerEvent>;
|
|
91
|
+
/** Serialize sends in call order; no input is automatically replayed. */
|
|
92
|
+
sendEvent(event: RealtimeClientEvent, options?: RealtimeWaitOptions): Promise<void>;
|
|
93
|
+
sendText(text: string, options?: RealtimeWaitOptions): Promise<void>;
|
|
94
|
+
appendAudio(pcm: Uint8Array, options?: RealtimeWaitOptions): Promise<void>;
|
|
95
|
+
interrupt(options?: RealtimeWaitOptions): Promise<void>;
|
|
96
|
+
ping(options?: RealtimeWaitOptions): Promise<void>;
|
|
97
|
+
playbackStarted(receipt?: RealtimePlaybackReceipt, options?: RealtimeWaitOptions): Promise<void>;
|
|
98
|
+
playbackEnded(receipt?: RealtimePlaybackReceipt, options?: RealtimeWaitOptions): Promise<void>;
|
|
99
|
+
playbackCancelled(receipt?: RealtimePlaybackReceipt, options?: RealtimeWaitOptions): Promise<void>;
|
|
100
|
+
private playback;
|
|
101
|
+
/** Send connection.close, require its matching persistence acknowledgement, then release transport. */
|
|
102
|
+
closeGracefully(options?: RealtimeCloseOptions): Promise<RealtimeClosed>;
|
|
103
|
+
/** Transport close does not promise history persistence or cancel background Work. */
|
|
104
|
+
close(): void;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../src/forward/realtime/connection.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAsE,MAAM,qBAAqB,CAAC;AAC7H,OAAO,EAAoB,KAAK,mBAAmB,EAAE,KAAK,cAAc,EAAE,KAAK,uBAAuB,EAAE,KAAK,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEzK,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,oFAAoF;IACpF,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iGAAiG;IACjG,SAAS,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACjM;AACD,MAAM,WAAW,mBAAmB;IAAG,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;AACtF,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAAG,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;AACxF,qBAAa,qBAAsB,SAAQ,kBAAkB;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM;IAAE,QAAQ,CAAC,IAAI;gBAA/D,OAAO,EAAE,MAAM,EAAW,cAAc,EAAE,MAAM,EAAW,IAAI,SAAkB;CAC9F;AACD,qBAAa,6BAA8B,SAAQ,kBAAkB;IACvD,QAAQ,CAAC,cAAc,EAAE,MAAM;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM;IAAE,QAAQ,CAAC,WAAW,EAAE,MAAM;gBAAhF,cAAc,EAAE,MAAM,EAAW,SAAS,EAAE,MAAM,EAAW,WAAW,EAAE,MAAM;CACtG;AACD,qBAAa,mBAAoB,SAAQ,kBAAkB;IAI7C,QAAQ,CAAC,KAAK,EAAE,mBAAmB;IAH/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;gBACZ,KAAK,EAAE,mBAAmB;CAOhD;AAqED,wFAAwF;AACxF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,GAAG,UAAU,CAK1E;AAED,wGAAwG;AACxG,qBAAa,kBAAmB,YAAW,aAAa,CAAC,mBAAmB,CAAC;IA2BvD,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAa,OAAO,CAAC,QAAQ,CAAC,OAAO;IA1BhF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,KAAK,EAAG,aAAa,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4D;IAClF,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgB;IAC7C,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,WAAW,CAA0B;IAC7C,OAAO,CAAC,QAAQ,CAAC,CAAqG;IACtH,OAAO,CAAC,QAAQ,CAAC,CAAQ;IACzB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAoC;IACpD,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,CAA0B;IAC3C,OAAO,CAAC,QAAQ,CAAC,CAAkG;IACnH,OAAO,CAAC,cAAc,CAAC,CAAgC;IACvD,OAAO,CAAC,UAAU,CAAC,CAAgC;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IAEnC,OAAO;IAwCP,gBAAgB;WACH,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA+BrG,OAAO,CAAC,SAAS;IAyBjB,OAAO,CAAC,MAAM;IAUd,OAAO,CAAC,IAAI;IAEZ,iGAAiG;IAC3F,OAAO,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC;IAWvF,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,cAAc,CAAC,mBAAmB,CAAC;IAGpE,yEAAyE;IACzE,SAAS,CAAC,KAAK,EAAE,mBAAmB,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BvF,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE,WAAW,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1E,SAAS,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IACvD,IAAI,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAClD,eAAe,CAAC,OAAO,GAAE,uBAA4B,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IACpG,aAAa,CAAC,OAAO,GAAE,uBAA4B,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAClG,iBAAiB,CAAC,OAAO,GAAE,uBAA4B,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IACtG,OAAO,CAAC,QAAQ;IAIhB,uGAAuG;IACvG,eAAe,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC;IAqB5E,sFAAsF;IACtF,KAAK,IAAI,IAAI;CASd"}
|
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RealtimeConnection = exports.RealtimeServerError = exports.RealtimeConnectionClosedError = exports.RealtimeProtocolError = void 0;
|
|
4
|
+
exports.decodeRealtimeAudio = decodeRealtimeAudio;
|
|
5
|
+
const error_js_1 = require("../../core/error.js");
|
|
6
|
+
const types_js_1 = require("./types.js");
|
|
7
|
+
class RealtimeProtocolError extends error_js_1.APIConnectionError {
|
|
8
|
+
conversationId;
|
|
9
|
+
code;
|
|
10
|
+
constructor(message, conversationId, code = 'invalid_event') {
|
|
11
|
+
super(message);
|
|
12
|
+
this.conversationId = conversationId;
|
|
13
|
+
this.code = code;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.RealtimeProtocolError = RealtimeProtocolError;
|
|
17
|
+
class RealtimeConnectionClosedError extends error_js_1.APIConnectionError {
|
|
18
|
+
conversationId;
|
|
19
|
+
closeCode;
|
|
20
|
+
closeReason;
|
|
21
|
+
constructor(conversationId, closeCode, closeReason) {
|
|
22
|
+
super(`Realtime connection closed (${closeCode})`);
|
|
23
|
+
this.conversationId = conversationId;
|
|
24
|
+
this.closeCode = closeCode;
|
|
25
|
+
this.closeReason = closeReason;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.RealtimeConnectionClosedError = RealtimeConnectionClosedError;
|
|
29
|
+
class RealtimeServerError extends error_js_1.APIConnectionError {
|
|
30
|
+
event;
|
|
31
|
+
code;
|
|
32
|
+
retryable;
|
|
33
|
+
retry_after_ms;
|
|
34
|
+
constructor(event) {
|
|
35
|
+
const payload = event.payload;
|
|
36
|
+
super(typeof payload.message === 'string' ? payload.message : 'Realtime server error');
|
|
37
|
+
this.event = event;
|
|
38
|
+
this.code = String(payload.code);
|
|
39
|
+
this.retryable = typeof payload.retryable === 'boolean' ? payload.retryable : undefined;
|
|
40
|
+
this.retry_after_ms = typeof payload.retry_after_ms === 'number' ? payload.retry_after_ms : undefined;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.RealtimeServerError = RealtimeServerError;
|
|
44
|
+
const importWS = () => import('ws');
|
|
45
|
+
const CLIENT_MESSAGE_BYTES = 256 * 1024;
|
|
46
|
+
const terminalErrors = new Set(['provider_initialization_failed', 'context_restore_failed', 'provider_unavailable', 'service_restarting', 'event_persistence_failed']);
|
|
47
|
+
const base64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
48
|
+
function validTimestamp(value) {
|
|
49
|
+
if (typeof value !== 'string' || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/.test(value) || !Number.isFinite(Date.parse(value)))
|
|
50
|
+
return false;
|
|
51
|
+
const year = Number(value.slice(0, 4)), month = Number(value.slice(5, 7)), day = Number(value.slice(8, 10));
|
|
52
|
+
const leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
53
|
+
return day > 0 && day <= [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1];
|
|
54
|
+
}
|
|
55
|
+
const isObject = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
56
|
+
function positive(value, fallback, name) {
|
|
57
|
+
const result = value ?? fallback;
|
|
58
|
+
if (!Number.isSafeInteger(result) || result <= 0 || result > 2 ** 31 - 1)
|
|
59
|
+
throw new error_js_1.QoderError(`${name} must be a positive integer within the timer/size limit`);
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
function wait(value, timeout, signal, label) {
|
|
63
|
+
return new Promise((resolve, reject) => {
|
|
64
|
+
const abort = () => finish(new error_js_1.APIUserAbortError(`${label} was aborted`));
|
|
65
|
+
const timer = setTimeout(() => finish(new error_js_1.APIConnectionTimeoutError(`${label} timed out`)), timeout);
|
|
66
|
+
let settled = false;
|
|
67
|
+
function finish(error, result) {
|
|
68
|
+
if (settled)
|
|
69
|
+
return;
|
|
70
|
+
settled = true;
|
|
71
|
+
clearTimeout(timer);
|
|
72
|
+
signal?.removeEventListener('abort', abort);
|
|
73
|
+
if (error)
|
|
74
|
+
reject(error);
|
|
75
|
+
else
|
|
76
|
+
resolve(result);
|
|
77
|
+
}
|
|
78
|
+
if (signal?.aborted)
|
|
79
|
+
abort();
|
|
80
|
+
else
|
|
81
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
82
|
+
value.then(result => finish(undefined, result), error => finish(error instanceof Error ? error : new error_js_1.APIConnectionError(label)));
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
function validateEvent(value, conversationId) {
|
|
86
|
+
const invalid = () => new RealtimeProtocolError('Invalid Realtime event envelope or payload', conversationId);
|
|
87
|
+
if (!isObject(value) || value.version !== types_js_1.REALTIME_VERSION || typeof value.type !== 'string' || !value.type
|
|
88
|
+
|| !isObject(value.payload) || typeof value.event_id !== 'string' || !value.event_id
|
|
89
|
+
|| !Number.isSafeInteger(value.sequence) || value.sequence < 0 || value.conversation_id !== conversationId
|
|
90
|
+
|| !validTimestamp(value.timestamp)
|
|
91
|
+
|| (value.work_id !== undefined && typeof value.work_id !== 'string')
|
|
92
|
+
|| (value.announcement_id !== undefined && typeof value.announcement_id !== 'string'))
|
|
93
|
+
throw invalid();
|
|
94
|
+
const p = value.payload;
|
|
95
|
+
const required = {
|
|
96
|
+
'voice.state': ['state'], 'voice.replaced': ['reason'], 'transcript.delta': ['role', 'text'], 'transcript.final': ['role', 'text'],
|
|
97
|
+
'audio.delta': ['audio'], 'playback.interrupt': ['reason'], 'work.accepted': ['status', 'objective'], 'work.running': ['status'],
|
|
98
|
+
'work.progress': ['kind', 'detail'], 'work.milestone': ['announcement_id', 'milestone_type', 'summary'],
|
|
99
|
+
'work.completed': ['status', 'result'], 'work.failed': ['status'], 'connection.closed': ['request_id', 'outcome'], error: ['code', 'message'],
|
|
100
|
+
};
|
|
101
|
+
if ((required[value.type] ?? []).some(key => typeof p[key] !== 'string'))
|
|
102
|
+
throw invalid();
|
|
103
|
+
const optionalStrings = {
|
|
104
|
+
'transcript.delta': ['item_id', 'response_id'], 'transcript.final': ['item_id', 'response_id'],
|
|
105
|
+
'work.progress': ['title', 'event_id'], 'work.completed': ['event_id'], 'work.failed': ['event_id'],
|
|
106
|
+
};
|
|
107
|
+
if ((optionalStrings[value.type] ?? []).some(key => p[key] !== undefined && typeof p[key] !== 'string'))
|
|
108
|
+
throw invalid();
|
|
109
|
+
if (value.type === 'work.progress' && p.is_error !== undefined && typeof p.is_error !== 'boolean')
|
|
110
|
+
throw invalid();
|
|
111
|
+
if (value.type === 'error' && ((p.retryable !== undefined && typeof p.retryable !== 'boolean') || (p.retry_after_ms !== undefined && (!Number.isSafeInteger(p.retry_after_ms) || p.retry_after_ms < 0))))
|
|
112
|
+
throw invalid();
|
|
113
|
+
const statuses = { 'work.accepted': 'accepted', 'work.running': 'running', 'work.completed': 'completed', 'work.failed': 'failed' };
|
|
114
|
+
if (statuses[value.type] && p.status !== statuses[value.type])
|
|
115
|
+
throw invalid();
|
|
116
|
+
if (value.type === 'audio.delta' && (typeof p.audio !== 'string' || !p.audio || !base64.test(p.audio) || globalThis.atob(p.audio).length % 2))
|
|
117
|
+
throw invalid();
|
|
118
|
+
if (value.type === 'voice.ready') {
|
|
119
|
+
if (!isObject(p.config) || typeof p.provider !== 'string' || !isObject(p.input_audio) || !isObject(p.output_audio)
|
|
120
|
+
|| p.input_audio.format !== 'pcm16' || p.input_audio.sample_rate !== 16000 || p.input_audio.channels !== 1
|
|
121
|
+
|| p.output_audio.format !== 'pcm16' || p.output_audio.sample_rate !== 24000 || p.output_audio.channels !== 1
|
|
122
|
+
|| !isObject(p.capabilities) || typeof p.capabilities.graceful_close !== 'boolean')
|
|
123
|
+
throw invalid();
|
|
124
|
+
}
|
|
125
|
+
if (value.type === 'work.failed' && (!isObject(p.error) || typeof p.error.code !== 'string'))
|
|
126
|
+
throw invalid();
|
|
127
|
+
if (value.type === 'connection.closed' && !['no_active_response', 'no_content', 'saved', 'saved_interrupted'].includes(p.outcome))
|
|
128
|
+
throw invalid();
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
/** Decode an audio.delta payload into raw 24 kHz PCM16 bytes; this does not play it. */
|
|
132
|
+
function decodeRealtimeAudio(event) {
|
|
133
|
+
if (event.type !== 'audio.delta' || typeof event.payload.audio !== 'string' || !event.payload.audio || !base64.test(event.payload.audio))
|
|
134
|
+
throw new error_js_1.QoderError('Expected a valid audio.delta Base64 payload');
|
|
135
|
+
const binary = globalThis.atob(event.payload.audio);
|
|
136
|
+
if (binary.length % 2)
|
|
137
|
+
throw new error_js_1.QoderError('PCM16 output must contain complete samples');
|
|
138
|
+
return Uint8Array.from(binary, char => char.charCodeAt(0));
|
|
139
|
+
}
|
|
140
|
+
/** A Node-only connection with one receiver and bounded input/output queues. No reconnect or replay. */
|
|
141
|
+
class RealtimeConnection {
|
|
142
|
+
socket;
|
|
143
|
+
options;
|
|
144
|
+
conversationId;
|
|
145
|
+
ready;
|
|
146
|
+
request_id = null;
|
|
147
|
+
queue = [];
|
|
148
|
+
queueBytes = 0;
|
|
149
|
+
lastSequence = -1;
|
|
150
|
+
maxQueuedEvents;
|
|
151
|
+
maxQueueBytes;
|
|
152
|
+
sendTimeout;
|
|
153
|
+
closeTimeout;
|
|
154
|
+
readyPromise;
|
|
155
|
+
readyResolve;
|
|
156
|
+
readyReject;
|
|
157
|
+
receiver;
|
|
158
|
+
terminal;
|
|
159
|
+
ended = false;
|
|
160
|
+
closing = false;
|
|
161
|
+
sendTail = Promise.resolve();
|
|
162
|
+
sendCount = 0;
|
|
163
|
+
sendBytes = 0;
|
|
164
|
+
graceful;
|
|
165
|
+
closeAck;
|
|
166
|
+
handshakeTimer;
|
|
167
|
+
readyTimer;
|
|
168
|
+
abort;
|
|
169
|
+
constructor(socket, options) {
|
|
170
|
+
this.socket = socket;
|
|
171
|
+
this.options = options;
|
|
172
|
+
this.conversationId = options.conversationId;
|
|
173
|
+
this.maxQueuedEvents = positive(options.maxQueuedEvents, 256, 'maxQueuedEvents');
|
|
174
|
+
this.maxQueueBytes = positive(options.maxQueueBytes, 4 * 1024 * 1024, 'maxQueueBytes');
|
|
175
|
+
this.sendTimeout = positive(options.sendTimeout, 30000, 'sendTimeout');
|
|
176
|
+
this.closeTimeout = positive(options.closeTimeout, 10000, 'closeTimeout');
|
|
177
|
+
this.readyPromise = new Promise((resolve, reject) => { this.readyResolve = resolve; this.readyReject = reject; });
|
|
178
|
+
void this.readyPromise.catch(() => { });
|
|
179
|
+
this.abort = () => this.fail(new error_js_1.APIUserAbortError('Realtime connection was aborted'));
|
|
180
|
+
options.signal?.addEventListener('abort', this.abort, { once: true });
|
|
181
|
+
socket.on('upgrade', response => { this.request_id = String(response.headers['x-request-id'] ?? response.headers['request-id'] ?? '') || null; });
|
|
182
|
+
socket.on('open', () => {
|
|
183
|
+
clearTimeout(this.handshakeTimer);
|
|
184
|
+
this.readyTimer = setTimeout(() => this.fail(new error_js_1.APIConnectionTimeoutError('Realtime ready timed out')), positive(options.readyTimeout, 60000, 'readyTimeout'));
|
|
185
|
+
});
|
|
186
|
+
socket.on('message', (data, binary) => this.onMessage(data, binary));
|
|
187
|
+
socket.on('error', error => this.fail(error.message === 'Opening handshake has timed out'
|
|
188
|
+
? new error_js_1.APIConnectionTimeoutError('Realtime handshake timed out') : new error_js_1.APIConnectionError('Realtime WebSocket transport failed')));
|
|
189
|
+
socket.on('close', (code, reason) => this.finish(code === 1000 || code === 1001 ? undefined : new RealtimeConnectionClosedError(this.conversationId, code, reason.toString())));
|
|
190
|
+
socket.on('unexpected-response', (_request, response) => {
|
|
191
|
+
let raw = '';
|
|
192
|
+
let bytes = 0;
|
|
193
|
+
response.on('data', chunk => {
|
|
194
|
+
bytes += chunk.length;
|
|
195
|
+
if (bytes > 64 * 1024) {
|
|
196
|
+
response.destroy();
|
|
197
|
+
this.fail(new error_js_1.APIConnectionError('Realtime handshake error body exceeded its limit'));
|
|
198
|
+
}
|
|
199
|
+
else
|
|
200
|
+
raw += chunk.toString();
|
|
201
|
+
});
|
|
202
|
+
response.on('error', () => this.fail(new error_js_1.APIConnectionError('Realtime handshake response failed')));
|
|
203
|
+
response.on('end', () => {
|
|
204
|
+
let body = raw;
|
|
205
|
+
try {
|
|
206
|
+
body = JSON.parse(raw);
|
|
207
|
+
}
|
|
208
|
+
catch { /* Retain bounded gateway text. */ }
|
|
209
|
+
const headers = new Headers();
|
|
210
|
+
for (const [key, value] of Object.entries(response.headers))
|
|
211
|
+
if (value !== undefined)
|
|
212
|
+
headers.set(key, Array.isArray(value) ? value.join(', ') : value);
|
|
213
|
+
this.fail(error_js_1.APIError.generate(response.statusCode ?? 502, body, undefined, headers));
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
this.handshakeTimer = setTimeout(() => this.fail(new error_js_1.APIConnectionTimeoutError('Realtime handshake timed out')), positive(options.handshakeTimeout, 30000, 'handshakeTimeout'));
|
|
217
|
+
if (options.signal?.aborted)
|
|
218
|
+
this.abort();
|
|
219
|
+
}
|
|
220
|
+
/** @internal */
|
|
221
|
+
static async connect(client, options) {
|
|
222
|
+
if (typeof process === 'undefined' || !process.versions?.node)
|
|
223
|
+
throw new error_js_1.QoderError('Forward Realtime requires Node.js; browsers cannot provide Authorization headers');
|
|
224
|
+
if (typeof options.conversationId !== 'string' || !options.conversationId || options.conversationId.trim() !== options.conversationId || /[\x00-\x1f\x7f]/.test(options.conversationId))
|
|
225
|
+
throw new error_js_1.QoderError('conversationId must be nonempty without surrounding whitespace or control characters');
|
|
226
|
+
for (const [key, fallback] of Object.entries({ handshakeTimeout: 30000, readyTimeout: 60000, sendTimeout: 30000, closeTimeout: 10000, maxQueuedEvents: 256, maxQueueBytes: 4 * 1024 * 1024, maxReceiveBytes: 1024 * 1024 }))
|
|
227
|
+
positive(options[key], fallback, key);
|
|
228
|
+
const handshakeDeadline = Date.now() + (options.handshakeTimeout ?? 30000);
|
|
229
|
+
const preparationController = new AbortController();
|
|
230
|
+
const cancelPreparation = () => preparationController.abort();
|
|
231
|
+
options.signal?.addEventListener('abort', cancelPreparation, { once: true });
|
|
232
|
+
let preparation;
|
|
233
|
+
try {
|
|
234
|
+
preparation = await wait(Promise.all([client._prepareRealtimeRequest({ ...options, signal: preparationController.signal }), importWS()]), options.handshakeTimeout ?? 30000, options.signal, 'Realtime authentication');
|
|
235
|
+
}
|
|
236
|
+
finally {
|
|
237
|
+
options.signal?.removeEventListener('abort', cancelPreparation);
|
|
238
|
+
preparationController.abort();
|
|
239
|
+
}
|
|
240
|
+
if (options.signal?.aborted)
|
|
241
|
+
throw new error_js_1.APIUserAbortError('Realtime connection was aborted');
|
|
242
|
+
const [{ url, headers }, module] = preparation;
|
|
243
|
+
const handshakeRemaining = handshakeDeadline - Date.now();
|
|
244
|
+
if (handshakeRemaining <= 0)
|
|
245
|
+
throw new error_js_1.APIConnectionTimeoutError('Realtime handshake timed out');
|
|
246
|
+
const Socket = module.default;
|
|
247
|
+
const transport = options.transport ?? {};
|
|
248
|
+
const socket = new Socket(url, {
|
|
249
|
+
...transport,
|
|
250
|
+
headers: Object.fromEntries(headers.entries()),
|
|
251
|
+
followRedirects: false,
|
|
252
|
+
perMessageDeflate: false,
|
|
253
|
+
handshakeTimeout: handshakeRemaining,
|
|
254
|
+
maxPayload: options.maxReceiveBytes ?? 1024 * 1024,
|
|
255
|
+
});
|
|
256
|
+
const connection = new RealtimeConnection(socket, { ...options, handshakeTimeout: handshakeRemaining });
|
|
257
|
+
await connection.readyPromise;
|
|
258
|
+
return connection;
|
|
259
|
+
}
|
|
260
|
+
onMessage(data, binary) {
|
|
261
|
+
if (this.ended)
|
|
262
|
+
return;
|
|
263
|
+
try {
|
|
264
|
+
if (binary)
|
|
265
|
+
throw new RealtimeProtocolError('Realtime expects UTF-8 JSON text frames', this.conversationId);
|
|
266
|
+
const buffer = Array.isArray(data) ? Buffer.concat(data) : data instanceof ArrayBuffer ? Buffer.from(data) : data;
|
|
267
|
+
let value;
|
|
268
|
+
try {
|
|
269
|
+
value = JSON.parse(buffer.toString());
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
throw new RealtimeProtocolError('Invalid Realtime JSON', this.conversationId);
|
|
273
|
+
}
|
|
274
|
+
const event = validateEvent(value, this.conversationId);
|
|
275
|
+
if (event.sequence <= this.lastSequence)
|
|
276
|
+
throw new RealtimeProtocolError('Realtime sequence did not increase', this.conversationId);
|
|
277
|
+
this.lastSequence = event.sequence;
|
|
278
|
+
const size = buffer.byteLength;
|
|
279
|
+
if (this.receiver) {
|
|
280
|
+
const receiver = this.receiver;
|
|
281
|
+
this.receiver = undefined;
|
|
282
|
+
receiver.resolve({ done: false, value: event });
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
if (this.queue.length >= this.maxQueuedEvents || this.queueBytes + size > this.maxQueueBytes)
|
|
286
|
+
throw new RealtimeProtocolError('Realtime receive queue capacity exceeded', this.conversationId, 'queue_overflow');
|
|
287
|
+
this.queue.push({ event, bytes: size });
|
|
288
|
+
this.queueBytes += size;
|
|
289
|
+
}
|
|
290
|
+
if (event.type === 'voice.ready' && !this.ready) {
|
|
291
|
+
this.ready = event.payload;
|
|
292
|
+
clearTimeout(this.readyTimer);
|
|
293
|
+
this.readyResolve();
|
|
294
|
+
}
|
|
295
|
+
if (event.type === 'connection.closed' && event.payload.request_id === this.closeAck?.requestId)
|
|
296
|
+
this.closeAck?.resolve(event.payload);
|
|
297
|
+
if (event.type === 'voice.replaced')
|
|
298
|
+
this.fail(new RealtimeProtocolError('Realtime connection was replaced', this.conversationId, 'voice.replaced'));
|
|
299
|
+
if (event.type === 'error' && (!this.ready || terminalErrors.has(String(event.payload.code))))
|
|
300
|
+
this.fail(new RealtimeServerError(event));
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
this.fail(error instanceof Error ? error : new error_js_1.APIConnectionError('Realtime receive failed'));
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
finish(error) {
|
|
307
|
+
if (this.ended)
|
|
308
|
+
return;
|
|
309
|
+
this.ended = true;
|
|
310
|
+
this.terminal = error;
|
|
311
|
+
clearTimeout(this.handshakeTimer);
|
|
312
|
+
clearTimeout(this.readyTimer);
|
|
313
|
+
this.options.signal?.removeEventListener('abort', this.abort);
|
|
314
|
+
this.readyReject(error ?? new RealtimeConnectionClosedError(this.conversationId, 1000, 'Closed before ready'));
|
|
315
|
+
this.closeAck?.reject(error ?? new RealtimeConnectionClosedError(this.conversationId, 1000, 'Closed without matching acknowledgement'));
|
|
316
|
+
if (this.receiver) {
|
|
317
|
+
const receiver = this.receiver;
|
|
318
|
+
this.receiver = undefined;
|
|
319
|
+
if (error)
|
|
320
|
+
receiver.reject(error);
|
|
321
|
+
else
|
|
322
|
+
receiver.resolve({ done: true, value: undefined });
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
fail(error) { this.finish(error); this.socket.terminate(); }
|
|
326
|
+
/** Read one event. Concurrent consumers are rejected instead of stealing each other's events. */
|
|
327
|
+
async receive(options = {}) {
|
|
328
|
+
if (this.receiver)
|
|
329
|
+
throw new error_js_1.QoderError('Only one Realtime event consumer is allowed');
|
|
330
|
+
if (options.signal?.aborted)
|
|
331
|
+
throw new error_js_1.APIUserAbortError('Realtime receive was aborted');
|
|
332
|
+
const queued = this.queue.shift();
|
|
333
|
+
if (queued) {
|
|
334
|
+
this.queueBytes -= queued.bytes;
|
|
335
|
+
return { done: false, value: queued.event };
|
|
336
|
+
}
|
|
337
|
+
if (this.ended) {
|
|
338
|
+
if (this.terminal)
|
|
339
|
+
throw this.terminal;
|
|
340
|
+
return { done: true, value: undefined };
|
|
341
|
+
}
|
|
342
|
+
let receiver;
|
|
343
|
+
const pending = new Promise((resolve, reject) => { this.receiver = receiver = { resolve, reject }; });
|
|
344
|
+
try {
|
|
345
|
+
return await wait(pending, positive(options.timeout, 2 ** 31 - 1, 'receive timeout'), options.signal, 'Realtime receive');
|
|
346
|
+
}
|
|
347
|
+
finally {
|
|
348
|
+
if (this.receiver === receiver)
|
|
349
|
+
this.receiver = undefined;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
async *[Symbol.asyncIterator]() {
|
|
353
|
+
for (;;) {
|
|
354
|
+
const next = await this.receive();
|
|
355
|
+
if (next.done)
|
|
356
|
+
return;
|
|
357
|
+
yield next.value;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
/** Serialize sends in call order; no input is automatically replayed. */
|
|
361
|
+
sendEvent(event, options = {}) {
|
|
362
|
+
const timeout = positive(options.timeout, this.sendTimeout, 'send timeout');
|
|
363
|
+
if (options.signal?.aborted)
|
|
364
|
+
return Promise.reject(new error_js_1.APIUserAbortError('Realtime send was aborted'));
|
|
365
|
+
if (!event || event.version !== types_js_1.REALTIME_VERSION || typeof event.type !== 'string' || !event.type || !isObject(event.payload))
|
|
366
|
+
throw new error_js_1.QoderError('Client events require version, type and object payload');
|
|
367
|
+
if (this.ended || this.socket.readyState !== 1)
|
|
368
|
+
throw this.terminal ?? new error_js_1.QoderError('Realtime connection is closed');
|
|
369
|
+
if (this.closing && !['connection.close', 'ping'].includes(event.type))
|
|
370
|
+
throw new error_js_1.QoderError('Realtime connection is closing');
|
|
371
|
+
if (event.type === 'text.message' && (typeof event.payload.text !== 'string' || !event.payload.text.trim() || new TextEncoder().encode(event.payload.text.trim()).length > 16 * 1024))
|
|
372
|
+
throw new error_js_1.QoderError('Realtime text must be nonempty and at most 16 KiB UTF-8');
|
|
373
|
+
if (event.type === 'audio.append' && (typeof event.payload.audio !== 'string' || !event.payload.audio || !base64.test(event.payload.audio) || globalThis.atob(event.payload.audio).length % 2))
|
|
374
|
+
throw new error_js_1.QoderError('Audio append requires nonempty Base64 PCM16');
|
|
375
|
+
if (event.type === 'connection.close') {
|
|
376
|
+
const id = event.payload.request_id;
|
|
377
|
+
if (typeof id !== 'string' || !id || id.trim() !== id || Buffer.byteLength(id) > 128 || /[\x00-\x1f\x7f]/.test(id))
|
|
378
|
+
throw new error_js_1.QoderError('Invalid connection.close request_id');
|
|
379
|
+
}
|
|
380
|
+
const json = JSON.stringify(event);
|
|
381
|
+
const bytes = Buffer.byteLength(json);
|
|
382
|
+
if (bytes > CLIENT_MESSAGE_BYTES)
|
|
383
|
+
throw new error_js_1.QoderError('Realtime client JSON message exceeds 256 KiB');
|
|
384
|
+
if (this.sendCount >= this.maxQueuedEvents || this.sendBytes + bytes > this.maxQueueBytes)
|
|
385
|
+
throw new error_js_1.QoderError('Realtime send queue capacity exceeded');
|
|
386
|
+
this.sendCount++;
|
|
387
|
+
this.sendBytes += bytes;
|
|
388
|
+
const result = this.sendTail.then(async () => {
|
|
389
|
+
if (this.ended)
|
|
390
|
+
throw this.terminal ?? new error_js_1.QoderError('Realtime connection is closed');
|
|
391
|
+
if (options.signal?.aborted)
|
|
392
|
+
throw new error_js_1.APIUserAbortError('Realtime send was aborted');
|
|
393
|
+
const written = new Promise((resolve, reject) => this.socket.send(json, { binary: false }, error => error ? reject(new error_js_1.APIConnectionError('Realtime send failed')) : resolve()));
|
|
394
|
+
try {
|
|
395
|
+
await wait(written, timeout, options.signal, 'Realtime send');
|
|
396
|
+
}
|
|
397
|
+
catch (error) {
|
|
398
|
+
this.fail(error);
|
|
399
|
+
throw error;
|
|
400
|
+
}
|
|
401
|
+
}).finally(() => { this.sendCount--; this.sendBytes -= bytes; });
|
|
402
|
+
this.sendTail = result.catch(() => { });
|
|
403
|
+
const deadline = wait(result, timeout, options.signal, 'Realtime send');
|
|
404
|
+
return deadline.catch(error => { this.fail(error); throw error; });
|
|
405
|
+
}
|
|
406
|
+
sendText(text, options) {
|
|
407
|
+
if (typeof text !== 'string' || !text.trim() || new TextEncoder().encode(text.trim()).length > 16 * 1024)
|
|
408
|
+
throw new error_js_1.QoderError('Realtime text must be nonempty and at most 16 KiB UTF-8');
|
|
409
|
+
return this.sendEvent({ version: types_js_1.REALTIME_VERSION, type: 'text.message', payload: { text: text.trim() } }, options);
|
|
410
|
+
}
|
|
411
|
+
appendAudio(pcm, options) {
|
|
412
|
+
if (!(pcm instanceof Uint8Array) || !pcm.byteLength || pcm.byteLength % 2)
|
|
413
|
+
throw new error_js_1.QoderError('Audio must contain nonempty, complete PCM16 samples');
|
|
414
|
+
if (pcm.byteLength > CLIENT_MESSAGE_BYTES * 3 / 4)
|
|
415
|
+
throw new error_js_1.QoderError('Realtime client JSON message exceeds 256 KiB');
|
|
416
|
+
return this.sendEvent({ version: types_js_1.REALTIME_VERSION, type: 'audio.append', payload: { audio: Buffer.from(pcm.buffer, pcm.byteOffset, pcm.byteLength).toString('base64') } }, options);
|
|
417
|
+
}
|
|
418
|
+
interrupt(options) { return this.sendEvent({ version: types_js_1.REALTIME_VERSION, type: 'interrupt', payload: {} }, options); }
|
|
419
|
+
ping(options) { return this.sendEvent({ version: types_js_1.REALTIME_VERSION, type: 'ping', payload: {} }, options); }
|
|
420
|
+
playbackStarted(receipt = {}, options) { return this.playback('playback.started', receipt, options); }
|
|
421
|
+
playbackEnded(receipt = {}, options) { return this.playback('playback.ended', receipt, options); }
|
|
422
|
+
playbackCancelled(receipt = {}, options) { return this.playback('playback.cancelled', receipt, options); }
|
|
423
|
+
playback(type, receipt, options) {
|
|
424
|
+
for (const value of Object.values(receipt))
|
|
425
|
+
if (typeof value !== 'string' || !value)
|
|
426
|
+
throw new error_js_1.QoderError('Playback identifiers must be nonempty strings');
|
|
427
|
+
return this.sendEvent({ version: types_js_1.REALTIME_VERSION, type, payload: { ...receipt } }, options);
|
|
428
|
+
}
|
|
429
|
+
/** Send connection.close, require its matching persistence acknowledgement, then release transport. */
|
|
430
|
+
closeGracefully(options = {}) {
|
|
431
|
+
if (this.graceful)
|
|
432
|
+
return this.graceful;
|
|
433
|
+
if (this.ended)
|
|
434
|
+
return Promise.reject(this.terminal ?? new error_js_1.QoderError('Realtime connection is closed'));
|
|
435
|
+
if (!this.ready.capabilities.graceful_close)
|
|
436
|
+
return Promise.reject(new error_js_1.QoderError('Server does not support graceful close'));
|
|
437
|
+
const requestId = options.requestId ?? globalThis.crypto.randomUUID();
|
|
438
|
+
if (!requestId || requestId.trim() !== requestId || Buffer.byteLength(requestId) > 128 || /[\x00-\x1f\x7f]/.test(requestId))
|
|
439
|
+
throw new error_js_1.QoderError('Close requestId must be 1–128 UTF-8 bytes without surrounding whitespace or control characters');
|
|
440
|
+
const timeout = positive(options.timeout, this.closeTimeout, 'close timeout');
|
|
441
|
+
if (options.signal?.aborted)
|
|
442
|
+
return Promise.reject(new error_js_1.APIUserAbortError('Realtime graceful close was aborted'));
|
|
443
|
+
this.closing = true;
|
|
444
|
+
const acknowledgement = new Promise((resolve, reject) => { this.closeAck = { requestId, resolve, reject }; });
|
|
445
|
+
void acknowledgement.catch(() => { });
|
|
446
|
+
this.graceful = (async () => {
|
|
447
|
+
try {
|
|
448
|
+
const confirmed = wait(acknowledgement, timeout, options.signal, 'Realtime graceful close');
|
|
449
|
+
void confirmed.catch(() => { });
|
|
450
|
+
await this.sendEvent({ version: types_js_1.REALTIME_VERSION, type: 'connection.close', payload: { request_id: requestId } }, options);
|
|
451
|
+
return await confirmed;
|
|
452
|
+
}
|
|
453
|
+
finally {
|
|
454
|
+
this.close();
|
|
455
|
+
}
|
|
456
|
+
})();
|
|
457
|
+
return this.graceful;
|
|
458
|
+
}
|
|
459
|
+
/** Transport close does not promise history persistence or cancel background Work. */
|
|
460
|
+
close() {
|
|
461
|
+
this.finish();
|
|
462
|
+
if (this.socket.readyState === 1) {
|
|
463
|
+
this.socket.close(1000);
|
|
464
|
+
const timer = setTimeout(() => this.socket.terminate(), 1000);
|
|
465
|
+
timer.unref();
|
|
466
|
+
this.socket.once('close', () => clearTimeout(timer));
|
|
467
|
+
}
|
|
468
|
+
else
|
|
469
|
+
this.socket.terminate();
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
exports.RealtimeConnection = RealtimeConnection;
|
|
473
|
+
//# sourceMappingURL=connection.js.map
|