Skip to content

Commit 50ab896

Browse files
committed
feat: add a method to connect OpenAI agent to call
1 parent 7c70a91 commit 50ab896

File tree

7 files changed

+83
-3
lines changed

7 files changed

+83
-3
lines changed

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"@openapitools/openapi-generator-cli": "^2.7.0",
5050
"@rollup/plugin-replace": "^5.0.2",
5151
"@rollup/plugin-typescript": "^11.1.4",
52+
"@stream-io/openai-realtime-api": "prerelease",
5253
"@types/uuid": "^9.0.4",
5354
"@typescript-eslint/eslint-plugin": "^6.4.0",
5455
"dotenv": "^16.3.1",
@@ -74,6 +75,9 @@
7475
"jsonwebtoken": "^9.0.2",
7576
"uuid": "^9.0.1"
7677
},
78+
"peerDependencies": {
79+
"@stream-io/openai-realtime-api": "prerelease"
80+
},
7781
"engines": {
7882
"node": ">=18.0.0"
7983
},

rollup.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const nodeConfig = {
1111
{
1212
file: "dist/index.cjs.js",
1313
format: "cjs",
14+
dynamicImportInCjs: false,
1415
sourcemap: true,
1516
},
1617
{

src/BaseApi.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { APIError } from './gen/models';
44
import { getRateLimitFromResponseHeader } from './utils/rate-limit';
55

66
export class BaseApi {
7-
constructor(private readonly apiConfig: ApiConfig) {}
7+
constructor(protected readonly apiConfig: ApiConfig) {}
88

99
protected sendRequest = async <T>(
1010
method: string,

src/StreamClient.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export class StreamClient extends CommonApi {
3838
super({ apiKey, token, timeout, baseUrl: chatBaseUrl });
3939

4040
this.video = new StreamVideoClient({
41+
streamClient: this,
4142
apiKey,
4243
token,
4344
timeout,

src/StreamVideoClient.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,63 @@
11
import { VideoApi } from './gen/video/VideoApi';
22
import { StreamCall } from './StreamCall';
3+
import type { StreamClient } from './StreamClient';
4+
import type { ApiConfig } from './types';
5+
import type {
6+
RealtimeClient,
7+
createRealtimeClient,
8+
} from '@stream-io/openai-realtime-api';
39

410
export class StreamVideoClient extends VideoApi {
11+
private streamClient: StreamClient;
12+
13+
constructor({
14+
streamClient,
15+
...apiConfig
16+
}: ApiConfig & { streamClient: StreamClient }) {
17+
super(apiConfig);
18+
this.streamClient = streamClient;
19+
}
20+
521
call = (type: string, id: string) => {
622
return new StreamCall(this, type, id);
723
};
24+
25+
connectOpenAi = async (options: {
26+
call: StreamCall;
27+
agentUserId: string;
28+
openAiApiKey: string;
29+
validityInSeconds: number;
30+
}): Promise<RealtimeClient> => {
31+
let doCreateRealtimeClient: typeof createRealtimeClient;
32+
33+
try {
34+
doCreateRealtimeClient = (await import('@stream-io/openai-realtime-api'))
35+
.createRealtimeClient;
36+
} catch {
37+
throw new Error(
38+
'Cannot create Realtime API client. Is @stream-io/openai-realtime-api installed?',
39+
);
40+
}
41+
42+
if (!options.agentUserId) {
43+
throw new Error('"agentUserId" must by specified in options');
44+
}
45+
46+
const token = this.streamClient.generateCallToken({
47+
user_id: options.agentUserId,
48+
call_cids: [options.call.cid],
49+
validity_in_seconds: options.validityInSeconds,
50+
});
51+
52+
const realtimeClient = doCreateRealtimeClient({
53+
baseUrl: this.apiConfig.baseUrl,
54+
call: options.call,
55+
streamApiKey: this.apiConfig.apiKey,
56+
streamUserToken: token,
57+
openAiApiKey: options.openAiApiKey,
58+
});
59+
60+
await realtimeClient.connect();
61+
return realtimeClient;
62+
};
863
}

tsconfig.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"compilerOptions": {
33
"outDir": "./dist",
4-
"module": "ES2015",
5-
"target": "ES2015",
4+
"module": "ES2020",
5+
"target": "ES2020",
66
"lib": ["esnext", "dom"],
77
"noEmitOnError": true,
88
"noImplicitAny": true,

yarn.lock

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,12 @@
365365
consola "^2.15.0"
366366
node-fetch "^2.6.1"
367367

368+
"@openai/realtime-api-beta@openai/openai-realtime-api-beta#a5cb94824f625423858ebacb9f769226ca98945f":
369+
version "0.0.0"
370+
resolved "https://codeload.github.com/openai/openai-realtime-api-beta/tar.gz/a5cb94824f625423858ebacb9f769226ca98945f"
371+
dependencies:
372+
ws "^8.18.0"
373+
368374
"@openapitools/openapi-generator-cli@^2.7.0":
369375
version "2.7.0"
370376
resolved "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.7.0.tgz"
@@ -482,6 +488,14 @@
482488
resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz"
483489
integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==
484490

491+
"@stream-io/openai-realtime-api@prerelease":
492+
version "0.0.0-24dd081d4a88212c621cfee273690bebd4a5f298"
493+
resolved "https://registry.yarnpkg.com/@stream-io/openai-realtime-api/-/openai-realtime-api-0.0.0-24dd081d4a88212c621cfee273690bebd4a5f298.tgz#bb8aac285342f7390cead6414b3ebf7cdc1048b3"
494+
integrity sha512-1CKZnKaXumPZ4lrzVIam8qE27UVyEFTs4wbir0opZYE8+e4whtkx8hfgiwbn/Y2yStO6yZpCjwtWVKyi2jd65Q==
495+
dependencies:
496+
"@openai/realtime-api-beta" openai/openai-realtime-api-beta#a5cb94824f625423858ebacb9f769226ca98945f
497+
ws "^8.18.0"
498+
485499
"@types/[email protected]", "@types/estree@^1.0.0":
486500
version "1.0.5"
487501
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz"
@@ -3470,6 +3484,11 @@ wrappy@1:
34703484
resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
34713485
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
34723486

3487+
ws@^8.18.0:
3488+
version "8.18.0"
3489+
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
3490+
integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==
3491+
34733492
y18n@^5.0.5:
34743493
version "5.0.8"
34753494
resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz"

0 commit comments

Comments
 (0)