@livekit/agents-plugin-anam 1.3.0 → 1.3.3
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/dist/avatar.cjs +3 -1
- package/dist/avatar.cjs.map +1 -1
- package/dist/avatar.d.cts +1 -1
- package/dist/avatar.d.ts +1 -1
- package/dist/avatar.d.ts.map +1 -1
- package/dist/avatar.js +3 -1
- package/dist/avatar.js.map +1 -1
- package/dist/avatar.test.cjs +23 -0
- package/dist/avatar.test.cjs.map +1 -0
- package/dist/avatar.test.d.cts +2 -0
- package/dist/avatar.test.d.ts +2 -0
- package/dist/avatar.test.d.ts.map +1 -0
- package/dist/avatar.test.js +22 -0
- package/dist/avatar.test.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +7 -7
- package/src/avatar.test.ts +30 -0
- package/src/avatar.ts +6 -2
package/dist/avatar.cjs
CHANGED
|
@@ -46,13 +46,15 @@ async function mintAvatarJoinToken({
|
|
|
46
46
|
}
|
|
47
47
|
const AVATAR_IDENTITY = "anam-avatar-agent";
|
|
48
48
|
const _AVATAR_NAME = "anam-avatar-agent";
|
|
49
|
-
class AvatarSession {
|
|
49
|
+
class AvatarSession extends import_agents.voice.AvatarSession {
|
|
50
50
|
constructor(opts) {
|
|
51
|
+
super();
|
|
51
52
|
this.opts = opts;
|
|
52
53
|
}
|
|
53
54
|
sessionId;
|
|
54
55
|
async start(agentSession, room, params) {
|
|
55
56
|
var _a, _b, _c, _d;
|
|
57
|
+
await super.start(agentSession, room);
|
|
56
58
|
const logger = (0, import_agents.log)().child({ module: "AnamAvatar" });
|
|
57
59
|
const apiKey = this.opts.apiKey ?? process.env.ANAM_API_KEY;
|
|
58
60
|
if (!apiKey) throw new import_types.AnamException("ANAM_API_KEY is required");
|
package/dist/avatar.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/avatar.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { log, voice } from '@livekit/agents';\nimport type { Room } from '@livekit/rtc-node';\nimport { TrackKind } from '@livekit/rtc-node';\nimport { AccessToken, type VideoGrant } from 'livekit-server-sdk';\nimport { AnamAPI } from './api.js';\nimport { type APIConnectOptions, AnamException, type PersonaConfig } from './types.js';\n\nexport async function mintAvatarJoinToken({\n roomName,\n avatarIdentity,\n publishOnBehalf,\n apiKey = process.env.LIVEKIT_API_KEY!,\n apiSecret = process.env.LIVEKIT_API_SECRET!,\n ttl = '60s',\n}: {\n roomName: string;\n avatarIdentity: string;\n publishOnBehalf: string;\n apiKey?: string;\n apiSecret?: string;\n ttl?: string | number;\n}): Promise<string> {\n const at = new AccessToken(apiKey, apiSecret);\n at.identity = avatarIdentity;\n at.name = 'Anam Avatar';\n at.kind = 'agent';\n at.ttl = ttl;\n at.attributes = { 'lk.publish_on_behalf': publishOnBehalf };\n\n at.addGrant({ roomJoin: true, room: roomName } as VideoGrant);\n return at.toJwt();\n}\n\nconst AVATAR_IDENTITY = 'anam-avatar-agent';\nconst _AVATAR_NAME = 'anam-avatar-agent';\n\nexport class AvatarSession {\n private sessionId?: string;\n\n constructor(\n private opts: {\n personaConfig: PersonaConfig;\n apiUrl?: string;\n apiKey?: string;\n avatarParticipantIdentity?: string;\n avatarParticipantName?: string;\n connOptions?: APIConnectOptions;\n },\n ) {}\n\n async start(\n agentSession: voice.AgentSession,\n room: Room,\n params?: {\n livekitUrl?: string;\n livekitApiKey?: string;\n livekitApiSecret?: string;\n },\n ) {\n const logger = log().child({ module: 'AnamAvatar' });\n const apiKey = this.opts.apiKey ?? process.env.ANAM_API_KEY;\n if (!apiKey) throw new AnamException('ANAM_API_KEY is required');\n\n const apiUrl = this.opts.apiUrl ?? process.env.ANAM_API_URL;\n const livekitUrl = params?.livekitUrl ?? process.env.LIVEKIT_URL;\n const lkKey = params?.livekitApiKey ?? process.env.LIVEKIT_API_KEY;\n const lkSecret = params?.livekitApiSecret ?? process.env.LIVEKIT_API_SECRET;\n\n if (!livekitUrl || !lkKey || !lkSecret) {\n throw new AnamException('LIVEKIT_URL/API_KEY/API_SECRET must be set');\n }\n\n const localIdentity = (room.localParticipant && room.localParticipant.identity) || 'agent';\n\n logger.debug(\n {\n personaName: this.opts.personaConfig?.name,\n avatarId: this.opts.personaConfig?.avatarId,\n apiUrl: apiUrl ?? '(default https://api.anam.ai)',\n livekitUrl,\n avatarParticipantIdentity: this.opts.avatarParticipantIdentity ?? 'anam-avatar-agent',\n publishOnBehalf: localIdentity,\n },\n 'starting Anam avatar session',\n );\n\n const jwt = await mintAvatarJoinToken({\n roomName: room.name!,\n avatarIdentity: this.opts.avatarParticipantIdentity ?? AVATAR_IDENTITY,\n publishOnBehalf: localIdentity,\n apiKey: lkKey,\n apiSecret: lkSecret,\n });\n\n const anam = new AnamAPI(apiKey, apiUrl, this.opts.connOptions);\n logger.debug({ livekitUrl }, 'requesting Anam session token');\n\n const { sessionToken } = await anam.createSessionToken({\n personaConfig: {\n name: this.opts.personaConfig?.name,\n avatarId: this.opts.personaConfig?.avatarId,\n },\n livekitUrl,\n livekitToken: jwt,\n });\n logger.debug('starting Anam engine session');\n const started = await anam.startEngineSession({ sessionToken });\n this.sessionId = started.sessionId;\n\n agentSession.output.audio = new voice.DataStreamAudioOutput({\n room,\n destinationIdentity: this.opts.avatarParticipantIdentity ?? AVATAR_IDENTITY,\n waitRemoteTrack: TrackKind.KIND_VIDEO,\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,oBAA2B;AAE3B,sBAA0B;AAC1B,gCAA6C;AAC7C,iBAAwB;AACxB,mBAA0E;AAE1E,eAAsB,oBAAoB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS,QAAQ,IAAI;AAAA,EACrB,YAAY,QAAQ,IAAI;AAAA,EACxB,MAAM;AACR,GAOoB;AAClB,QAAM,KAAK,IAAI,sCAAY,QAAQ,SAAS;AAC5C,KAAG,WAAW;AACd,KAAG,OAAO;AACV,KAAG,OAAO;AACV,KAAG,MAAM;AACT,KAAG,aAAa,EAAE,wBAAwB,gBAAgB;AAE1D,KAAG,SAAS,EAAE,UAAU,MAAM,MAAM,SAAS,CAAe;AAC5D,SAAO,GAAG,MAAM;AAClB;AAEA,MAAM,kBAAkB;AACxB,MAAM,eAAe;AAEd,MAAM,cAAc;AAAA,
|
|
1
|
+
{"version":3,"sources":["../src/avatar.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { log, voice } from '@livekit/agents';\nimport type { Room } from '@livekit/rtc-node';\nimport { TrackKind } from '@livekit/rtc-node';\nimport { AccessToken, type VideoGrant } from 'livekit-server-sdk';\nimport { AnamAPI } from './api.js';\nimport { type APIConnectOptions, AnamException, type PersonaConfig } from './types.js';\n\nexport async function mintAvatarJoinToken({\n roomName,\n avatarIdentity,\n publishOnBehalf,\n apiKey = process.env.LIVEKIT_API_KEY!,\n apiSecret = process.env.LIVEKIT_API_SECRET!,\n ttl = '60s',\n}: {\n roomName: string;\n avatarIdentity: string;\n publishOnBehalf: string;\n apiKey?: string;\n apiSecret?: string;\n ttl?: string | number;\n}): Promise<string> {\n const at = new AccessToken(apiKey, apiSecret);\n at.identity = avatarIdentity;\n at.name = 'Anam Avatar';\n at.kind = 'agent';\n at.ttl = ttl;\n at.attributes = { 'lk.publish_on_behalf': publishOnBehalf };\n\n at.addGrant({ roomJoin: true, room: roomName } as VideoGrant);\n return at.toJwt();\n}\n\nconst AVATAR_IDENTITY = 'anam-avatar-agent';\nconst _AVATAR_NAME = 'anam-avatar-agent';\n\nexport class AvatarSession extends voice.AvatarSession {\n private sessionId?: string;\n\n constructor(\n private opts: {\n personaConfig: PersonaConfig;\n apiUrl?: string;\n apiKey?: string;\n avatarParticipantIdentity?: string;\n avatarParticipantName?: string;\n connOptions?: APIConnectOptions;\n },\n ) {\n super();\n }\n\n async start(\n agentSession: voice.AgentSession,\n room: Room,\n params?: {\n livekitUrl?: string;\n livekitApiKey?: string;\n livekitApiSecret?: string;\n },\n ) {\n await super.start(agentSession, room);\n\n const logger = log().child({ module: 'AnamAvatar' });\n const apiKey = this.opts.apiKey ?? process.env.ANAM_API_KEY;\n if (!apiKey) throw new AnamException('ANAM_API_KEY is required');\n\n const apiUrl = this.opts.apiUrl ?? process.env.ANAM_API_URL;\n const livekitUrl = params?.livekitUrl ?? process.env.LIVEKIT_URL;\n const lkKey = params?.livekitApiKey ?? process.env.LIVEKIT_API_KEY;\n const lkSecret = params?.livekitApiSecret ?? process.env.LIVEKIT_API_SECRET;\n\n if (!livekitUrl || !lkKey || !lkSecret) {\n throw new AnamException('LIVEKIT_URL/API_KEY/API_SECRET must be set');\n }\n\n const localIdentity = (room.localParticipant && room.localParticipant.identity) || 'agent';\n\n logger.debug(\n {\n personaName: this.opts.personaConfig?.name,\n avatarId: this.opts.personaConfig?.avatarId,\n apiUrl: apiUrl ?? '(default https://api.anam.ai)',\n livekitUrl,\n avatarParticipantIdentity: this.opts.avatarParticipantIdentity ?? 'anam-avatar-agent',\n publishOnBehalf: localIdentity,\n },\n 'starting Anam avatar session',\n );\n\n const jwt = await mintAvatarJoinToken({\n roomName: room.name!,\n avatarIdentity: this.opts.avatarParticipantIdentity ?? AVATAR_IDENTITY,\n publishOnBehalf: localIdentity,\n apiKey: lkKey,\n apiSecret: lkSecret,\n });\n\n const anam = new AnamAPI(apiKey, apiUrl, this.opts.connOptions);\n logger.debug({ livekitUrl }, 'requesting Anam session token');\n\n const { sessionToken } = await anam.createSessionToken({\n personaConfig: {\n name: this.opts.personaConfig?.name,\n avatarId: this.opts.personaConfig?.avatarId,\n },\n livekitUrl,\n livekitToken: jwt,\n });\n logger.debug('starting Anam engine session');\n const started = await anam.startEngineSession({ sessionToken });\n this.sessionId = started.sessionId;\n\n agentSession.output.audio = new voice.DataStreamAudioOutput({\n room,\n destinationIdentity: this.opts.avatarParticipantIdentity ?? AVATAR_IDENTITY,\n waitRemoteTrack: TrackKind.KIND_VIDEO,\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,oBAA2B;AAE3B,sBAA0B;AAC1B,gCAA6C;AAC7C,iBAAwB;AACxB,mBAA0E;AAE1E,eAAsB,oBAAoB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS,QAAQ,IAAI;AAAA,EACrB,YAAY,QAAQ,IAAI;AAAA,EACxB,MAAM;AACR,GAOoB;AAClB,QAAM,KAAK,IAAI,sCAAY,QAAQ,SAAS;AAC5C,KAAG,WAAW;AACd,KAAG,OAAO;AACV,KAAG,OAAO;AACV,KAAG,MAAM;AACT,KAAG,aAAa,EAAE,wBAAwB,gBAAgB;AAE1D,KAAG,SAAS,EAAE,UAAU,MAAM,MAAM,SAAS,CAAe;AAC5D,SAAO,GAAG,MAAM;AAClB;AAEA,MAAM,kBAAkB;AACxB,MAAM,eAAe;AAEd,MAAM,sBAAsB,oBAAM,cAAc;AAAA,EAGrD,YACU,MAQR;AACA,UAAM;AATE;AAAA,EAUV;AAAA,EAbQ;AAAA,EAeR,MAAM,MACJ,cACA,MACA,QAKA;AA/DJ;AAgEI,UAAM,MAAM,MAAM,cAAc,IAAI;AAEpC,UAAM,aAAS,mBAAI,EAAE,MAAM,EAAE,QAAQ,aAAa,CAAC;AACnD,UAAM,SAAS,KAAK,KAAK,UAAU,QAAQ,IAAI;AAC/C,QAAI,CAAC,OAAQ,OAAM,IAAI,2BAAc,0BAA0B;AAE/D,UAAM,SAAS,KAAK,KAAK,UAAU,QAAQ,IAAI;AAC/C,UAAM,cAAa,iCAAQ,eAAc,QAAQ,IAAI;AACrD,UAAM,SAAQ,iCAAQ,kBAAiB,QAAQ,IAAI;AACnD,UAAM,YAAW,iCAAQ,qBAAoB,QAAQ,IAAI;AAEzD,QAAI,CAAC,cAAc,CAAC,SAAS,CAAC,UAAU;AACtC,YAAM,IAAI,2BAAc,4CAA4C;AAAA,IACtE;AAEA,UAAM,gBAAiB,KAAK,oBAAoB,KAAK,iBAAiB,YAAa;AAEnF,WAAO;AAAA,MACL;AAAA,QACE,cAAa,UAAK,KAAK,kBAAV,mBAAyB;AAAA,QACtC,WAAU,UAAK,KAAK,kBAAV,mBAAyB;AAAA,QACnC,QAAQ,UAAU;AAAA,QAClB;AAAA,QACA,2BAA2B,KAAK,KAAK,6BAA6B;AAAA,QAClE,iBAAiB;AAAA,MACnB;AAAA,MACA;AAAA,IACF;AAEA,UAAM,MAAM,MAAM,oBAAoB;AAAA,MACpC,UAAU,KAAK;AAAA,MACf,gBAAgB,KAAK,KAAK,6BAA6B;AAAA,MACvD,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,WAAW;AAAA,IACb,CAAC;AAED,UAAM,OAAO,IAAI,mBAAQ,QAAQ,QAAQ,KAAK,KAAK,WAAW;AAC9D,WAAO,MAAM,EAAE,WAAW,GAAG,+BAA+B;AAE5D,UAAM,EAAE,aAAa,IAAI,MAAM,KAAK,mBAAmB;AAAA,MACrD,eAAe;AAAA,QACb,OAAM,UAAK,KAAK,kBAAV,mBAAyB;AAAA,QAC/B,WAAU,UAAK,KAAK,kBAAV,mBAAyB;AAAA,MACrC;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IAChB,CAAC;AACD,WAAO,MAAM,8BAA8B;AAC3C,UAAM,UAAU,MAAM,KAAK,mBAAmB,EAAE,aAAa,CAAC;AAC9D,SAAK,YAAY,QAAQ;AAEzB,iBAAa,OAAO,QAAQ,IAAI,oBAAM,sBAAsB;AAAA,MAC1D;AAAA,MACA,qBAAqB,KAAK,KAAK,6BAA6B;AAAA,MAC5D,iBAAiB,0BAAU;AAAA,IAC7B,CAAC;AAAA,EACH;AACF;","names":[]}
|
package/dist/avatar.d.cts
CHANGED
|
@@ -9,7 +9,7 @@ export declare function mintAvatarJoinToken({ roomName, avatarIdentity, publishO
|
|
|
9
9
|
apiSecret?: string;
|
|
10
10
|
ttl?: string | number;
|
|
11
11
|
}): Promise<string>;
|
|
12
|
-
export declare class AvatarSession {
|
|
12
|
+
export declare class AvatarSession extends voice.AvatarSession {
|
|
13
13
|
private opts;
|
|
14
14
|
private sessionId?;
|
|
15
15
|
constructor(opts: {
|
package/dist/avatar.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare function mintAvatarJoinToken({ roomName, avatarIdentity, publishO
|
|
|
9
9
|
apiSecret?: string;
|
|
10
10
|
ttl?: string | number;
|
|
11
11
|
}): Promise<string>;
|
|
12
|
-
export declare class AvatarSession {
|
|
12
|
+
export declare class AvatarSession extends voice.AvatarSession {
|
|
13
13
|
private opts;
|
|
14
14
|
private sessionId?;
|
|
15
15
|
constructor(opts: {
|
package/dist/avatar.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../src/avatar.ts"],"names":[],"mappings":"AAGA,OAAO,EAAO,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAI9C,OAAO,EAAE,KAAK,iBAAiB,EAAiB,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAEvF,wBAAsB,mBAAmB,CAAC,EACxC,QAAQ,EACR,cAAc,EACd,eAAe,EACf,MAAqC,EACrC,SAA2C,EAC3C,GAAW,GACZ,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,MAAM,CAAC,CAUlB;AAKD,qBAAa,aAAa;
|
|
1
|
+
{"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../src/avatar.ts"],"names":[],"mappings":"AAGA,OAAO,EAAO,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAI9C,OAAO,EAAE,KAAK,iBAAiB,EAAiB,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAEvF,wBAAsB,mBAAmB,CAAC,EACxC,QAAQ,EACR,cAAc,EACd,eAAe,EACf,MAAqC,EACrC,SAA2C,EAC3C,GAAW,GACZ,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,MAAM,CAAC,CAUlB;AAKD,qBAAa,aAAc,SAAQ,KAAK,CAAC,aAAa;IAIlD,OAAO,CAAC,IAAI;IAHd,OAAO,CAAC,SAAS,CAAC,CAAS;gBAGjB,IAAI,EAAE;QACZ,aAAa,EAAE,aAAa,CAAC;QAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,yBAAyB,CAAC,EAAE,MAAM,CAAC;QACnC,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,WAAW,CAAC,EAAE,iBAAiB,CAAC;KACjC;IAKG,KAAK,CACT,YAAY,EAAE,KAAK,CAAC,YAAY,EAChC,IAAI,EAAE,IAAI,EACV,MAAM,CAAC,EAAE;QACP,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B;CA4DJ"}
|
package/dist/avatar.js
CHANGED
|
@@ -22,13 +22,15 @@ async function mintAvatarJoinToken({
|
|
|
22
22
|
}
|
|
23
23
|
const AVATAR_IDENTITY = "anam-avatar-agent";
|
|
24
24
|
const _AVATAR_NAME = "anam-avatar-agent";
|
|
25
|
-
class AvatarSession {
|
|
25
|
+
class AvatarSession extends voice.AvatarSession {
|
|
26
26
|
constructor(opts) {
|
|
27
|
+
super();
|
|
27
28
|
this.opts = opts;
|
|
28
29
|
}
|
|
29
30
|
sessionId;
|
|
30
31
|
async start(agentSession, room, params) {
|
|
31
32
|
var _a, _b, _c, _d;
|
|
33
|
+
await super.start(agentSession, room);
|
|
32
34
|
const logger = log().child({ module: "AnamAvatar" });
|
|
33
35
|
const apiKey = this.opts.apiKey ?? process.env.ANAM_API_KEY;
|
|
34
36
|
if (!apiKey) throw new AnamException("ANAM_API_KEY is required");
|
package/dist/avatar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/avatar.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { log, voice } from '@livekit/agents';\nimport type { Room } from '@livekit/rtc-node';\nimport { TrackKind } from '@livekit/rtc-node';\nimport { AccessToken, type VideoGrant } from 'livekit-server-sdk';\nimport { AnamAPI } from './api.js';\nimport { type APIConnectOptions, AnamException, type PersonaConfig } from './types.js';\n\nexport async function mintAvatarJoinToken({\n roomName,\n avatarIdentity,\n publishOnBehalf,\n apiKey = process.env.LIVEKIT_API_KEY!,\n apiSecret = process.env.LIVEKIT_API_SECRET!,\n ttl = '60s',\n}: {\n roomName: string;\n avatarIdentity: string;\n publishOnBehalf: string;\n apiKey?: string;\n apiSecret?: string;\n ttl?: string | number;\n}): Promise<string> {\n const at = new AccessToken(apiKey, apiSecret);\n at.identity = avatarIdentity;\n at.name = 'Anam Avatar';\n at.kind = 'agent';\n at.ttl = ttl;\n at.attributes = { 'lk.publish_on_behalf': publishOnBehalf };\n\n at.addGrant({ roomJoin: true, room: roomName } as VideoGrant);\n return at.toJwt();\n}\n\nconst AVATAR_IDENTITY = 'anam-avatar-agent';\nconst _AVATAR_NAME = 'anam-avatar-agent';\n\nexport class AvatarSession {\n private sessionId?: string;\n\n constructor(\n private opts: {\n personaConfig: PersonaConfig;\n apiUrl?: string;\n apiKey?: string;\n avatarParticipantIdentity?: string;\n avatarParticipantName?: string;\n connOptions?: APIConnectOptions;\n },\n ) {}\n\n async start(\n agentSession: voice.AgentSession,\n room: Room,\n params?: {\n livekitUrl?: string;\n livekitApiKey?: string;\n livekitApiSecret?: string;\n },\n ) {\n const logger = log().child({ module: 'AnamAvatar' });\n const apiKey = this.opts.apiKey ?? process.env.ANAM_API_KEY;\n if (!apiKey) throw new AnamException('ANAM_API_KEY is required');\n\n const apiUrl = this.opts.apiUrl ?? process.env.ANAM_API_URL;\n const livekitUrl = params?.livekitUrl ?? process.env.LIVEKIT_URL;\n const lkKey = params?.livekitApiKey ?? process.env.LIVEKIT_API_KEY;\n const lkSecret = params?.livekitApiSecret ?? process.env.LIVEKIT_API_SECRET;\n\n if (!livekitUrl || !lkKey || !lkSecret) {\n throw new AnamException('LIVEKIT_URL/API_KEY/API_SECRET must be set');\n }\n\n const localIdentity = (room.localParticipant && room.localParticipant.identity) || 'agent';\n\n logger.debug(\n {\n personaName: this.opts.personaConfig?.name,\n avatarId: this.opts.personaConfig?.avatarId,\n apiUrl: apiUrl ?? '(default https://api.anam.ai)',\n livekitUrl,\n avatarParticipantIdentity: this.opts.avatarParticipantIdentity ?? 'anam-avatar-agent',\n publishOnBehalf: localIdentity,\n },\n 'starting Anam avatar session',\n );\n\n const jwt = await mintAvatarJoinToken({\n roomName: room.name!,\n avatarIdentity: this.opts.avatarParticipantIdentity ?? AVATAR_IDENTITY,\n publishOnBehalf: localIdentity,\n apiKey: lkKey,\n apiSecret: lkSecret,\n });\n\n const anam = new AnamAPI(apiKey, apiUrl, this.opts.connOptions);\n logger.debug({ livekitUrl }, 'requesting Anam session token');\n\n const { sessionToken } = await anam.createSessionToken({\n personaConfig: {\n name: this.opts.personaConfig?.name,\n avatarId: this.opts.personaConfig?.avatarId,\n },\n livekitUrl,\n livekitToken: jwt,\n });\n logger.debug('starting Anam engine session');\n const started = await anam.startEngineSession({ sessionToken });\n this.sessionId = started.sessionId;\n\n agentSession.output.audio = new voice.DataStreamAudioOutput({\n room,\n destinationIdentity: this.opts.avatarParticipantIdentity ?? AVATAR_IDENTITY,\n waitRemoteTrack: TrackKind.KIND_VIDEO,\n });\n }\n}\n"],"mappings":"AAGA,SAAS,KAAK,aAAa;AAE3B,SAAS,iBAAiB;AAC1B,SAAS,mBAAoC;AAC7C,SAAS,eAAe;AACxB,SAAiC,qBAAyC;AAE1E,eAAsB,oBAAoB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS,QAAQ,IAAI;AAAA,EACrB,YAAY,QAAQ,IAAI;AAAA,EACxB,MAAM;AACR,GAOoB;AAClB,QAAM,KAAK,IAAI,YAAY,QAAQ,SAAS;AAC5C,KAAG,WAAW;AACd,KAAG,OAAO;AACV,KAAG,OAAO;AACV,KAAG,MAAM;AACT,KAAG,aAAa,EAAE,wBAAwB,gBAAgB;AAE1D,KAAG,SAAS,EAAE,UAAU,MAAM,MAAM,SAAS,CAAe;AAC5D,SAAO,GAAG,MAAM;AAClB;AAEA,MAAM,kBAAkB;AACxB,MAAM,eAAe;AAEd,MAAM,cAAc;AAAA,
|
|
1
|
+
{"version":3,"sources":["../src/avatar.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { log, voice } from '@livekit/agents';\nimport type { Room } from '@livekit/rtc-node';\nimport { TrackKind } from '@livekit/rtc-node';\nimport { AccessToken, type VideoGrant } from 'livekit-server-sdk';\nimport { AnamAPI } from './api.js';\nimport { type APIConnectOptions, AnamException, type PersonaConfig } from './types.js';\n\nexport async function mintAvatarJoinToken({\n roomName,\n avatarIdentity,\n publishOnBehalf,\n apiKey = process.env.LIVEKIT_API_KEY!,\n apiSecret = process.env.LIVEKIT_API_SECRET!,\n ttl = '60s',\n}: {\n roomName: string;\n avatarIdentity: string;\n publishOnBehalf: string;\n apiKey?: string;\n apiSecret?: string;\n ttl?: string | number;\n}): Promise<string> {\n const at = new AccessToken(apiKey, apiSecret);\n at.identity = avatarIdentity;\n at.name = 'Anam Avatar';\n at.kind = 'agent';\n at.ttl = ttl;\n at.attributes = { 'lk.publish_on_behalf': publishOnBehalf };\n\n at.addGrant({ roomJoin: true, room: roomName } as VideoGrant);\n return at.toJwt();\n}\n\nconst AVATAR_IDENTITY = 'anam-avatar-agent';\nconst _AVATAR_NAME = 'anam-avatar-agent';\n\nexport class AvatarSession extends voice.AvatarSession {\n private sessionId?: string;\n\n constructor(\n private opts: {\n personaConfig: PersonaConfig;\n apiUrl?: string;\n apiKey?: string;\n avatarParticipantIdentity?: string;\n avatarParticipantName?: string;\n connOptions?: APIConnectOptions;\n },\n ) {\n super();\n }\n\n async start(\n agentSession: voice.AgentSession,\n room: Room,\n params?: {\n livekitUrl?: string;\n livekitApiKey?: string;\n livekitApiSecret?: string;\n },\n ) {\n await super.start(agentSession, room);\n\n const logger = log().child({ module: 'AnamAvatar' });\n const apiKey = this.opts.apiKey ?? process.env.ANAM_API_KEY;\n if (!apiKey) throw new AnamException('ANAM_API_KEY is required');\n\n const apiUrl = this.opts.apiUrl ?? process.env.ANAM_API_URL;\n const livekitUrl = params?.livekitUrl ?? process.env.LIVEKIT_URL;\n const lkKey = params?.livekitApiKey ?? process.env.LIVEKIT_API_KEY;\n const lkSecret = params?.livekitApiSecret ?? process.env.LIVEKIT_API_SECRET;\n\n if (!livekitUrl || !lkKey || !lkSecret) {\n throw new AnamException('LIVEKIT_URL/API_KEY/API_SECRET must be set');\n }\n\n const localIdentity = (room.localParticipant && room.localParticipant.identity) || 'agent';\n\n logger.debug(\n {\n personaName: this.opts.personaConfig?.name,\n avatarId: this.opts.personaConfig?.avatarId,\n apiUrl: apiUrl ?? '(default https://api.anam.ai)',\n livekitUrl,\n avatarParticipantIdentity: this.opts.avatarParticipantIdentity ?? 'anam-avatar-agent',\n publishOnBehalf: localIdentity,\n },\n 'starting Anam avatar session',\n );\n\n const jwt = await mintAvatarJoinToken({\n roomName: room.name!,\n avatarIdentity: this.opts.avatarParticipantIdentity ?? AVATAR_IDENTITY,\n publishOnBehalf: localIdentity,\n apiKey: lkKey,\n apiSecret: lkSecret,\n });\n\n const anam = new AnamAPI(apiKey, apiUrl, this.opts.connOptions);\n logger.debug({ livekitUrl }, 'requesting Anam session token');\n\n const { sessionToken } = await anam.createSessionToken({\n personaConfig: {\n name: this.opts.personaConfig?.name,\n avatarId: this.opts.personaConfig?.avatarId,\n },\n livekitUrl,\n livekitToken: jwt,\n });\n logger.debug('starting Anam engine session');\n const started = await anam.startEngineSession({ sessionToken });\n this.sessionId = started.sessionId;\n\n agentSession.output.audio = new voice.DataStreamAudioOutput({\n room,\n destinationIdentity: this.opts.avatarParticipantIdentity ?? AVATAR_IDENTITY,\n waitRemoteTrack: TrackKind.KIND_VIDEO,\n });\n }\n}\n"],"mappings":"AAGA,SAAS,KAAK,aAAa;AAE3B,SAAS,iBAAiB;AAC1B,SAAS,mBAAoC;AAC7C,SAAS,eAAe;AACxB,SAAiC,qBAAyC;AAE1E,eAAsB,oBAAoB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS,QAAQ,IAAI;AAAA,EACrB,YAAY,QAAQ,IAAI;AAAA,EACxB,MAAM;AACR,GAOoB;AAClB,QAAM,KAAK,IAAI,YAAY,QAAQ,SAAS;AAC5C,KAAG,WAAW;AACd,KAAG,OAAO;AACV,KAAG,OAAO;AACV,KAAG,MAAM;AACT,KAAG,aAAa,EAAE,wBAAwB,gBAAgB;AAE1D,KAAG,SAAS,EAAE,UAAU,MAAM,MAAM,SAAS,CAAe;AAC5D,SAAO,GAAG,MAAM;AAClB;AAEA,MAAM,kBAAkB;AACxB,MAAM,eAAe;AAEd,MAAM,sBAAsB,MAAM,cAAc;AAAA,EAGrD,YACU,MAQR;AACA,UAAM;AATE;AAAA,EAUV;AAAA,EAbQ;AAAA,EAeR,MAAM,MACJ,cACA,MACA,QAKA;AA/DJ;AAgEI,UAAM,MAAM,MAAM,cAAc,IAAI;AAEpC,UAAM,SAAS,IAAI,EAAE,MAAM,EAAE,QAAQ,aAAa,CAAC;AACnD,UAAM,SAAS,KAAK,KAAK,UAAU,QAAQ,IAAI;AAC/C,QAAI,CAAC,OAAQ,OAAM,IAAI,cAAc,0BAA0B;AAE/D,UAAM,SAAS,KAAK,KAAK,UAAU,QAAQ,IAAI;AAC/C,UAAM,cAAa,iCAAQ,eAAc,QAAQ,IAAI;AACrD,UAAM,SAAQ,iCAAQ,kBAAiB,QAAQ,IAAI;AACnD,UAAM,YAAW,iCAAQ,qBAAoB,QAAQ,IAAI;AAEzD,QAAI,CAAC,cAAc,CAAC,SAAS,CAAC,UAAU;AACtC,YAAM,IAAI,cAAc,4CAA4C;AAAA,IACtE;AAEA,UAAM,gBAAiB,KAAK,oBAAoB,KAAK,iBAAiB,YAAa;AAEnF,WAAO;AAAA,MACL;AAAA,QACE,cAAa,UAAK,KAAK,kBAAV,mBAAyB;AAAA,QACtC,WAAU,UAAK,KAAK,kBAAV,mBAAyB;AAAA,QACnC,QAAQ,UAAU;AAAA,QAClB;AAAA,QACA,2BAA2B,KAAK,KAAK,6BAA6B;AAAA,QAClE,iBAAiB;AAAA,MACnB;AAAA,MACA;AAAA,IACF;AAEA,UAAM,MAAM,MAAM,oBAAoB;AAAA,MACpC,UAAU,KAAK;AAAA,MACf,gBAAgB,KAAK,KAAK,6BAA6B;AAAA,MACvD,iBAAiB;AAAA,MACjB,QAAQ;AAAA,MACR,WAAW;AAAA,IACb,CAAC;AAED,UAAM,OAAO,IAAI,QAAQ,QAAQ,QAAQ,KAAK,KAAK,WAAW;AAC9D,WAAO,MAAM,EAAE,WAAW,GAAG,+BAA+B;AAE5D,UAAM,EAAE,aAAa,IAAI,MAAM,KAAK,mBAAmB;AAAA,MACrD,eAAe;AAAA,QACb,OAAM,UAAK,KAAK,kBAAV,mBAAyB;AAAA,QAC/B,WAAU,UAAK,KAAK,kBAAV,mBAAyB;AAAA,MACrC;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IAChB,CAAC;AACD,WAAO,MAAM,8BAA8B;AAC3C,UAAM,UAAU,MAAM,KAAK,mBAAmB,EAAE,aAAa,CAAC;AAC9D,SAAK,YAAY,QAAQ;AAEzB,iBAAa,OAAO,QAAQ,IAAI,MAAM,sBAAsB;AAAA,MAC1D;AAAA,MACA,qBAAqB,KAAK,KAAK,6BAA6B;AAAA,MAC5D,iBAAiB,UAAU;AAAA,IAC7B,CAAC;AAAA,EACH;AACF;","names":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var import_agents = require("@livekit/agents");
|
|
3
|
+
var import_vitest = require("vitest");
|
|
4
|
+
var import_avatar = require("./avatar.cjs");
|
|
5
|
+
(0, import_vitest.describe)("Anam AvatarSession", () => {
|
|
6
|
+
(0, import_vitest.afterEach)(() => {
|
|
7
|
+
import_vitest.vi.restoreAllMocks();
|
|
8
|
+
});
|
|
9
|
+
(0, import_vitest.it)("calls base AvatarSession.start first", async () => {
|
|
10
|
+
const sentinel = new Error("super-start-called");
|
|
11
|
+
const superStartSpy = import_vitest.vi.spyOn(import_agents.voice.AvatarSession.prototype, "start").mockRejectedValue(sentinel);
|
|
12
|
+
const avatar = new import_avatar.AvatarSession({
|
|
13
|
+
personaConfig: {
|
|
14
|
+
personaId: "persona-test"
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
await (0, import_vitest.expect)(
|
|
18
|
+
avatar.start({ _started: false, output: { audio: null } }, {})
|
|
19
|
+
).rejects.toThrow("super-start-called");
|
|
20
|
+
(0, import_vitest.expect)(superStartSpy).toHaveBeenCalledTimes(1);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=avatar.test.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/avatar.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { voice } from '@livekit/agents';\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport { AvatarSession } from './avatar.js';\n\ndescribe('Anam AvatarSession', () => {\n afterEach(() => {\n vi.restoreAllMocks();\n });\n\n it('calls base AvatarSession.start first', async () => {\n const sentinel = new Error('super-start-called');\n const superStartSpy = vi\n .spyOn(voice.AvatarSession.prototype, 'start')\n .mockRejectedValue(sentinel);\n\n const avatar = new AvatarSession({\n personaConfig: {\n personaId: 'persona-test',\n },\n });\n\n await expect(\n avatar.start({ _started: false, output: { audio: null } } as any, {} as any),\n ).rejects.toThrow('super-start-called');\n expect(superStartSpy).toHaveBeenCalledTimes(1);\n });\n});\n"],"mappings":";AAGA,oBAAsB;AACtB,oBAAoD;AACpD,oBAA8B;AAAA,IAE9B,wBAAS,sBAAsB,MAAM;AACnC,+BAAU,MAAM;AACd,qBAAG,gBAAgB;AAAA,EACrB,CAAC;AAED,wBAAG,wCAAwC,YAAY;AACrD,UAAM,WAAW,IAAI,MAAM,oBAAoB;AAC/C,UAAM,gBAAgB,iBACnB,MAAM,oBAAM,cAAc,WAAW,OAAO,EAC5C,kBAAkB,QAAQ;AAE7B,UAAM,SAAS,IAAI,4BAAc;AAAA,MAC/B,eAAe;AAAA,QACb,WAAW;AAAA,MACb;AAAA,IACF,CAAC;AAED,cAAM;AAAA,MACJ,OAAO,MAAM,EAAE,UAAU,OAAO,QAAQ,EAAE,OAAO,KAAK,EAAE,GAAU,CAAC,CAAQ;AAAA,IAC7E,EAAE,QAAQ,QAAQ,oBAAoB;AACtC,8BAAO,aAAa,EAAE,sBAAsB,CAAC;AAAA,EAC/C,CAAC;AACH,CAAC;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avatar.test.d.ts","sourceRoot":"","sources":["../src/avatar.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { voice } from "@livekit/agents";
|
|
2
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { AvatarSession } from "./avatar.js";
|
|
4
|
+
describe("Anam AvatarSession", () => {
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
vi.restoreAllMocks();
|
|
7
|
+
});
|
|
8
|
+
it("calls base AvatarSession.start first", async () => {
|
|
9
|
+
const sentinel = new Error("super-start-called");
|
|
10
|
+
const superStartSpy = vi.spyOn(voice.AvatarSession.prototype, "start").mockRejectedValue(sentinel);
|
|
11
|
+
const avatar = new AvatarSession({
|
|
12
|
+
personaConfig: {
|
|
13
|
+
personaId: "persona-test"
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
await expect(
|
|
17
|
+
avatar.start({ _started: false, output: { audio: null } }, {})
|
|
18
|
+
).rejects.toThrow("super-start-called");
|
|
19
|
+
expect(superStartSpy).toHaveBeenCalledTimes(1);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=avatar.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/avatar.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { voice } from '@livekit/agents';\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport { AvatarSession } from './avatar.js';\n\ndescribe('Anam AvatarSession', () => {\n afterEach(() => {\n vi.restoreAllMocks();\n });\n\n it('calls base AvatarSession.start first', async () => {\n const sentinel = new Error('super-start-called');\n const superStartSpy = vi\n .spyOn(voice.AvatarSession.prototype, 'start')\n .mockRejectedValue(sentinel);\n\n const avatar = new AvatarSession({\n personaConfig: {\n personaId: 'persona-test',\n },\n });\n\n await expect(\n avatar.start({ _started: false, output: { audio: null } } as any, {} as any),\n ).rejects.toThrow('super-start-called');\n expect(superStartSpy).toHaveBeenCalledTimes(1);\n });\n});\n"],"mappings":"AAGA,SAAS,aAAa;AACtB,SAAS,WAAW,UAAU,QAAQ,IAAI,UAAU;AACpD,SAAS,qBAAqB;AAE9B,SAAS,sBAAsB,MAAM;AACnC,YAAU,MAAM;AACd,OAAG,gBAAgB;AAAA,EACrB,CAAC;AAED,KAAG,wCAAwC,YAAY;AACrD,UAAM,WAAW,IAAI,MAAM,oBAAoB;AAC/C,UAAM,gBAAgB,GACnB,MAAM,MAAM,cAAc,WAAW,OAAO,EAC5C,kBAAkB,QAAQ;AAE7B,UAAM,SAAS,IAAI,cAAc;AAAA,MAC/B,eAAe;AAAA,QACb,WAAW;AAAA,MACb;AAAA,IACF,CAAC;AAED,UAAM;AAAA,MACJ,OAAO,MAAM,EAAE,UAAU,OAAO,QAAQ,EAAE,OAAO,KAAK,EAAE,GAAU,CAAC,CAAQ;AAAA,IAC7E,EAAE,QAAQ,QAAQ,oBAAoB;AACtC,WAAO,aAAa,EAAE,sBAAsB,CAAC;AAAA,EAC/C,CAAC;AACH,CAAC;","names":[]}
|
package/dist/index.cjs
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livekit/agents-plugin-anam",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
4
4
|
"description": "Anam plugin for LiveKit Node Agents",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"require": "dist/index.cjs",
|
|
@@ -25,22 +25,22 @@
|
|
|
25
25
|
"README.md"
|
|
26
26
|
],
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@livekit/rtc-node": "^0.13.
|
|
28
|
+
"@livekit/rtc-node": "^0.13.27",
|
|
29
29
|
"@microsoft/api-extractor": "^7.35.0",
|
|
30
30
|
"@types/ws": "^8.5.10",
|
|
31
31
|
"tsup": "^8.3.5",
|
|
32
32
|
"typescript": "^5.0.0",
|
|
33
|
-
"@livekit/agents": "1.3.
|
|
34
|
-
"@livekit/agents-plugin-openai": "1.3.
|
|
35
|
-
"@livekit/agents-plugins-test": "1.3.
|
|
33
|
+
"@livekit/agents": "1.3.3",
|
|
34
|
+
"@livekit/agents-plugin-openai": "1.3.3",
|
|
35
|
+
"@livekit/agents-plugins-test": "1.3.3"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"livekit-server-sdk": "^2.9.2",
|
|
39
39
|
"ws": "^8.18.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@livekit/rtc-node": "^0.13.
|
|
43
|
-
"@livekit/agents": "1.3.
|
|
42
|
+
"@livekit/rtc-node": "^0.13.27",
|
|
43
|
+
"@livekit/agents": "1.3.3"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "tsup --onSuccess \"pnpm build:types\"",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 LiveKit, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
import { voice } from '@livekit/agents';
|
|
5
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
6
|
+
import { AvatarSession } from './avatar.js';
|
|
7
|
+
|
|
8
|
+
describe('Anam AvatarSession', () => {
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
vi.restoreAllMocks();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('calls base AvatarSession.start first', async () => {
|
|
14
|
+
const sentinel = new Error('super-start-called');
|
|
15
|
+
const superStartSpy = vi
|
|
16
|
+
.spyOn(voice.AvatarSession.prototype, 'start')
|
|
17
|
+
.mockRejectedValue(sentinel);
|
|
18
|
+
|
|
19
|
+
const avatar = new AvatarSession({
|
|
20
|
+
personaConfig: {
|
|
21
|
+
personaId: 'persona-test',
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
await expect(
|
|
26
|
+
avatar.start({ _started: false, output: { audio: null } } as any, {} as any),
|
|
27
|
+
).rejects.toThrow('super-start-called');
|
|
28
|
+
expect(superStartSpy).toHaveBeenCalledTimes(1);
|
|
29
|
+
});
|
|
30
|
+
});
|
package/src/avatar.ts
CHANGED
|
@@ -37,7 +37,7 @@ export async function mintAvatarJoinToken({
|
|
|
37
37
|
const AVATAR_IDENTITY = 'anam-avatar-agent';
|
|
38
38
|
const _AVATAR_NAME = 'anam-avatar-agent';
|
|
39
39
|
|
|
40
|
-
export class AvatarSession {
|
|
40
|
+
export class AvatarSession extends voice.AvatarSession {
|
|
41
41
|
private sessionId?: string;
|
|
42
42
|
|
|
43
43
|
constructor(
|
|
@@ -49,7 +49,9 @@ export class AvatarSession {
|
|
|
49
49
|
avatarParticipantName?: string;
|
|
50
50
|
connOptions?: APIConnectOptions;
|
|
51
51
|
},
|
|
52
|
-
) {
|
|
52
|
+
) {
|
|
53
|
+
super();
|
|
54
|
+
}
|
|
53
55
|
|
|
54
56
|
async start(
|
|
55
57
|
agentSession: voice.AgentSession,
|
|
@@ -60,6 +62,8 @@ export class AvatarSession {
|
|
|
60
62
|
livekitApiSecret?: string;
|
|
61
63
|
},
|
|
62
64
|
) {
|
|
65
|
+
await super.start(agentSession, room);
|
|
66
|
+
|
|
63
67
|
const logger = log().child({ module: 'AnamAvatar' });
|
|
64
68
|
const apiKey = this.opts.apiKey ?? process.env.ANAM_API_KEY;
|
|
65
69
|
if (!apiKey) throw new AnamException('ANAM_API_KEY is required');
|