@livekit/agents 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/api-extractor.json +20 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +58 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/generator.d.ts +12 -0
  8. package/dist/generator.d.ts.map +1 -0
  9. package/dist/generator.js +8 -0
  10. package/dist/generator.js.map +1 -0
  11. package/dist/http_server.d.ts +11 -0
  12. package/dist/http_server.d.ts.map +1 -0
  13. package/dist/http_server.js +45 -0
  14. package/dist/http_server.js.map +1 -0
  15. package/dist/index.d.ts +14 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +17 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/ipc/job_main.d.ts +5 -0
  20. package/dist/ipc/job_main.d.ts.map +1 -0
  21. package/dist/ipc/job_main.js +77 -0
  22. package/dist/ipc/job_main.js.map +1 -0
  23. package/dist/ipc/job_process.d.ts +22 -0
  24. package/dist/ipc/job_process.d.ts.map +1 -0
  25. package/dist/ipc/job_process.js +73 -0
  26. package/dist/ipc/job_process.js.map +1 -0
  27. package/dist/ipc/protocol.d.ts +40 -0
  28. package/dist/ipc/protocol.d.ts.map +1 -0
  29. package/dist/ipc/protocol.js +14 -0
  30. package/dist/ipc/protocol.js.map +1 -0
  31. package/dist/job_context.d.ts +16 -0
  32. package/dist/job_context.d.ts.map +1 -0
  33. package/dist/job_context.js +31 -0
  34. package/dist/job_context.js.map +1 -0
  35. package/dist/job_request.d.ts +42 -0
  36. package/dist/job_request.d.ts.map +1 -0
  37. package/dist/job_request.js +79 -0
  38. package/dist/job_request.js.map +1 -0
  39. package/dist/log.d.ts +2 -0
  40. package/dist/log.d.ts.map +1 -0
  41. package/dist/log.js +13 -0
  42. package/dist/log.js.map +1 -0
  43. package/dist/plugin.d.ts +10 -0
  44. package/dist/plugin.d.ts.map +1 -0
  45. package/dist/plugin.js +22 -0
  46. package/dist/plugin.js.map +1 -0
  47. package/dist/stt/index.d.ts +3 -0
  48. package/dist/stt/index.d.ts.map +1 -0
  49. package/dist/stt/index.js +6 -0
  50. package/dist/stt/index.js.map +1 -0
  51. package/dist/stt/stream_adapter.d.ts +28 -0
  52. package/dist/stt/stream_adapter.d.ts.map +1 -0
  53. package/dist/stt/stream_adapter.js +82 -0
  54. package/dist/stt/stream_adapter.js.map +1 -0
  55. package/dist/stt/stt.d.ts +34 -0
  56. package/dist/stt/stt.d.ts.map +1 -0
  57. package/dist/stt/stt.js +30 -0
  58. package/dist/stt/stt.js.map +1 -0
  59. package/dist/tokenize.d.ts +15 -0
  60. package/dist/tokenize.d.ts.map +1 -0
  61. package/dist/tokenize.js +12 -0
  62. package/dist/tokenize.js.map +1 -0
  63. package/dist/tts/index.d.ts +4 -0
  64. package/dist/tts/index.d.ts.map +1 -0
  65. package/dist/tts/index.js +7 -0
  66. package/dist/tts/index.js.map +1 -0
  67. package/dist/tts/stream_adapter.d.ts +26 -0
  68. package/dist/tts/stream_adapter.d.ts.map +1 -0
  69. package/dist/tts/stream_adapter.js +77 -0
  70. package/dist/tts/stream_adapter.js.map +1 -0
  71. package/dist/tts/tts.d.ts +37 -0
  72. package/dist/tts/tts.d.ts.map +1 -0
  73. package/dist/tts/tts.js +48 -0
  74. package/dist/tts/tts.js.map +1 -0
  75. package/dist/utils.d.ts +4 -0
  76. package/dist/utils.d.ts.map +1 -0
  77. package/dist/utils.js +29 -0
  78. package/dist/utils.js.map +1 -0
  79. package/dist/vad.d.ts +28 -0
  80. package/dist/vad.d.ts.map +1 -0
  81. package/dist/vad.js +14 -0
  82. package/dist/vad.js.map +1 -0
  83. package/dist/version.d.ts +2 -0
  84. package/dist/version.d.ts.map +1 -0
  85. package/dist/version.js +5 -0
  86. package/dist/version.js.map +1 -0
  87. package/dist/worker.d.ts +84 -0
  88. package/dist/worker.d.ts.map +1 -0
  89. package/dist/worker.js +296 -0
  90. package/dist/worker.js.map +1 -0
  91. package/package.json +31 -0
  92. package/src/cli.ts +79 -0
  93. package/src/generator.ts +18 -0
  94. package/src/http_server.ts +47 -0
  95. package/src/index.ts +18 -0
  96. package/src/ipc/job_main.ts +83 -0
  97. package/src/ipc/job_process.ts +96 -0
  98. package/src/ipc/protocol.ts +51 -0
  99. package/src/job_context.ts +49 -0
  100. package/src/job_request.ts +118 -0
  101. package/src/log.ts +13 -0
  102. package/src/plugin.ts +28 -0
  103. package/src/stt/index.ts +6 -0
  104. package/src/stt/stream_adapter.ts +104 -0
  105. package/src/stt/stt.ts +58 -0
  106. package/src/tokenize.ts +22 -0
  107. package/src/tts/index.ts +23 -0
  108. package/src/tts/stream_adapter.ts +92 -0
  109. package/src/tts/tts.ts +78 -0
  110. package/src/utils.ts +37 -0
  111. package/src/vad.ts +42 -0
  112. package/src/version.ts +5 -0
  113. package/src/worker.ts +384 -0
  114. package/tsconfig.json +10 -0
@@ -0,0 +1,4 @@
1
+ import { AudioFrame } from '@livekit/rtc-node';
2
+ export type AudioBuffer = AudioFrame[] | AudioFrame;
3
+ export declare const mergeFrames: (buffer: AudioBuffer) => AudioFrame;
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,MAAM,WAAW,GAAG,UAAU,EAAE,GAAG,UAAU,CAAC;AAEpD,eAAO,MAAM,WAAW,WAAY,WAAW,KAAG,UA6BjD,CAAC"}
package/dist/utils.js ADDED
@@ -0,0 +1,29 @@
1
+ // SPDX-FileCopyrightText: 2024 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { AudioFrame } from '@livekit/rtc-node';
5
+ export const mergeFrames = (buffer) => {
6
+ if (Array.isArray(buffer)) {
7
+ buffer = buffer;
8
+ if (buffer.length == 0) {
9
+ throw new TypeError('buffer is empty');
10
+ }
11
+ const sampleRate = buffer[0].sampleRate;
12
+ const channels = buffer[0].channels;
13
+ let samplesPerChannel = 0;
14
+ let data = new Uint16Array();
15
+ for (const frame of buffer) {
16
+ if (frame.sampleRate !== sampleRate) {
17
+ throw new TypeError('sample rate mismatch');
18
+ }
19
+ if (frame.channels !== channels) {
20
+ throw new TypeError('channel count mismatch');
21
+ }
22
+ data = new Uint16Array([...data, ...frame.data]);
23
+ samplesPerChannel += frame.samplesPerChannel;
24
+ }
25
+ return new AudioFrame(data, sampleRate, channels, samplesPerChannel);
26
+ }
27
+ return buffer;
28
+ };
29
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,sCAAsC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAI/C,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAmB,EAAc,EAAE;IAC7D,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,MAAM,GAAG,MAAsB,CAAC;QAChC,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,SAAS,CAAC,iBAAiB,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QACpC,IAAI,iBAAiB,GAAG,CAAC,CAAC;QAC1B,IAAI,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC;QAE7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,KAAK,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;gBACpC,MAAM,IAAI,SAAS,CAAC,sBAAsB,CAAC,CAAC;YAC9C,CAAC;YAED,IAAI,KAAK,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAChC,MAAM,IAAI,SAAS,CAAC,wBAAwB,CAAC,CAAC;YAChD,CAAC;YAED,IAAI,GAAG,IAAI,WAAW,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YACjD,iBAAiB,IAAI,KAAK,CAAC,iBAAiB,CAAC;QAC/C,CAAC;QAED,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IACvE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
package/dist/vad.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ import type { AudioFrame } from '@livekit/rtc-node';
2
+ export declare enum VADEventType {
3
+ START_OF_SPEECH = 1,
4
+ SPEAKING = 2,
5
+ END_OF_SPEECH = 3
6
+ }
7
+ export interface VADEvent {
8
+ type: VADEventType;
9
+ samplesIndex: number;
10
+ duration: number;
11
+ speech: AudioFrame[];
12
+ }
13
+ export declare abstract class VAD {
14
+ abstract stream({ minSpeakingDuration, minSilenceDuration, paddingDuration, sampleRate, maxBufferedSpeech, }: {
15
+ minSpeakingDuration: number;
16
+ minSilenceDuration: number;
17
+ paddingDuration: number;
18
+ sampleRate: number;
19
+ maxBufferedSpeech: number;
20
+ }): VADStream;
21
+ }
22
+ export declare abstract class VADStream implements IterableIterator<VADEvent> {
23
+ abstract pushFrame(frame: AudioFrame): void;
24
+ abstract close(wait: boolean): Promise<void>;
25
+ abstract next(): IteratorResult<VADEvent>;
26
+ [Symbol.iterator](): VADStream;
27
+ }
28
+ //# sourceMappingURL=vad.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vad.d.ts","sourceRoot":"","sources":["../src/vad.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,oBAAY,YAAY;IACtB,eAAe,IAAI;IACnB,QAAQ,IAAI;IACZ,aAAa,IAAI;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,YAAY,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,8BAAsB,GAAG;IACvB,QAAQ,CAAC,MAAM,CAAC,EACd,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,UAAU,EACV,iBAAiB,GAClB,EAAE;QACD,mBAAmB,EAAE,MAAM,CAAC;QAC5B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,eAAe,EAAE,MAAM,CAAC;QACxB,UAAU,EAAE,MAAM,CAAC;QACnB,iBAAiB,EAAE,MAAM,CAAC;KAC3B,GAAG,SAAS;CACd;AAED,8BAAsB,SAAU,YAAW,gBAAgB,CAAC,QAAQ,CAAC;IACnE,QAAQ,CAAC,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAC3C,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAC5C,QAAQ,CAAC,IAAI,IAAI,cAAc,CAAC,QAAQ,CAAC;IACzC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,SAAS;CAG/B"}
package/dist/vad.js ADDED
@@ -0,0 +1,14 @@
1
+ export var VADEventType;
2
+ (function (VADEventType) {
3
+ VADEventType[VADEventType["START_OF_SPEECH"] = 1] = "START_OF_SPEECH";
4
+ VADEventType[VADEventType["SPEAKING"] = 2] = "SPEAKING";
5
+ VADEventType[VADEventType["END_OF_SPEECH"] = 3] = "END_OF_SPEECH";
6
+ })(VADEventType || (VADEventType = {}));
7
+ export class VAD {
8
+ }
9
+ export class VADStream {
10
+ [Symbol.iterator]() {
11
+ return this;
12
+ }
13
+ }
14
+ //# sourceMappingURL=vad.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vad.js","sourceRoot":"","sources":["../src/vad.ts"],"names":[],"mappings":"AAKA,MAAM,CAAN,IAAY,YAIX;AAJD,WAAY,YAAY;IACtB,qEAAmB,CAAA;IACnB,uDAAY,CAAA;IACZ,iEAAiB,CAAA;AACnB,CAAC,EAJW,YAAY,KAAZ,YAAY,QAIvB;AASD,MAAM,OAAgB,GAAG;CAcxB;AAED,MAAM,OAAgB,SAAS;IAI7B,CAAC,MAAM,CAAC,QAAQ,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export declare const version = "0.1.0";
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO,UAAU,CAAC"}
@@ -0,0 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2024 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ export const version = '0.1.0';
5
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,sCAAsC;AAEtC,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
@@ -0,0 +1,84 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import { type AvailabilityRequest, type Job, type JobAssignment, JobType } from '@livekit/protocol';
3
+ import { EventEmitter } from 'events';
4
+ import { WebSocket } from 'ws';
5
+ import { HTTPServer } from './http_server.js';
6
+ import { JobProcess } from './ipc/job_process.js';
7
+ import { JobRequest } from './job_request.js';
8
+ import type { AcceptData } from './job_request.js';
9
+ declare class WorkerPermissions {
10
+ canPublish: boolean;
11
+ canSubscribe: boolean;
12
+ canPublishData: boolean;
13
+ canUpdateMetadata: boolean;
14
+ hidden: boolean;
15
+ constructor(canPublish?: boolean, canSubscribe?: boolean, canPublishData?: boolean, canUpdateMetadata?: boolean, hidden?: boolean);
16
+ }
17
+ export declare class WorkerOptions {
18
+ requestFunc: (arg: JobRequest) => Promise<void>;
19
+ cpuLoadFunc: () => number;
20
+ namespace: string;
21
+ permissions: WorkerPermissions;
22
+ workerType: JobType;
23
+ maxRetry: number;
24
+ wsURL: string;
25
+ apiKey?: string;
26
+ apiSecret?: string;
27
+ host: string;
28
+ port: number;
29
+ constructor({ requestFunc, cpuLoadFunc, namespace, permissions, workerType, maxRetry, wsURL, apiKey, apiSecret, host, port, }: {
30
+ requestFunc: (arg: JobRequest) => Promise<void>;
31
+ cpuLoadFunc?: () => number;
32
+ namespace?: string;
33
+ permissions?: WorkerPermissions;
34
+ workerType?: JobType;
35
+ maxRetry?: number;
36
+ wsURL?: string;
37
+ apiKey?: string;
38
+ apiSecret?: string;
39
+ host?: string;
40
+ port?: number;
41
+ });
42
+ }
43
+ declare class ActiveJob {
44
+ job: Job;
45
+ acceptData: AcceptData;
46
+ constructor(job: Job, acceptData: AcceptData);
47
+ }
48
+ type AssignmentPair = {
49
+ raw: string;
50
+ asgn: JobAssignment;
51
+ };
52
+ declare class PendingAssignment {
53
+ promise: Promise<AssignmentPair>;
54
+ resolve(arg: AssignmentPair): void;
55
+ }
56
+ export declare class Worker {
57
+ #private;
58
+ opts: WorkerOptions;
59
+ session: WebSocket | undefined;
60
+ closed: boolean;
61
+ httpServer: HTTPServer;
62
+ logger: import("pino").default.Logger<never>;
63
+ event: EventEmitter<[never]>;
64
+ pending: {
65
+ [id: string]: {
66
+ value: PendingAssignment;
67
+ };
68
+ };
69
+ processes: {
70
+ [id: string]: {
71
+ proc: JobProcess;
72
+ activeJob: ActiveJob;
73
+ };
74
+ };
75
+ constructor(opts: WorkerOptions);
76
+ get id(): string;
77
+ run(): Promise<void>;
78
+ startProcess(job: Job, acceptData: AcceptData, raw: string): void;
79
+ runWS(ws: WebSocket): void;
80
+ availability(msg: AvailabilityRequest): Promise<void>;
81
+ close(): Promise<void>;
82
+ }
83
+ export {};
84
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":";AAGA,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,GAAG,EACR,KAAK,aAAa,EAClB,OAAO,EAIR,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAiB,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAkBnD,cAAM,iBAAiB;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;gBAGd,UAAU,UAAO,EACjB,YAAY,UAAO,EACnB,cAAc,UAAO,EACrB,iBAAiB,UAAO,EACxB,MAAM,UAAQ;CAQjB;AAED,qBAAa,aAAa;IACxB,WAAW,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,WAAW,EAAE,MAAM,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,iBAAiB,CAAC;IAC/B,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;gBAED,EACV,WAAW,EACX,WAAqB,EACrB,SAAqB,EACrB,WAAqC,EACrC,UAAiC,EACjC,QAAiC,EACjC,KAA6B,EAC7B,MAAkB,EAClB,SAAqB,EACrB,IAAkB,EAClB,IAAW,GACZ,EAAE;QACD,WAAW,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAChD,WAAW,CAAC,EAAE,MAAM,MAAM,CAAC;QAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,iBAAiB,CAAC;QAChC,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf;CAaF;AAED,cAAM,SAAS;IACb,GAAG,EAAE,GAAG,CAAC;IACT,UAAU,EAAE,UAAU,CAAC;gBAEX,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU;CAI7C;AAED,KAAK,cAAc,GAAG;IAGpB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,aAAa,CAAC;CACrB,CAAC;AAEF,cAAM,iBAAiB;IACrB,OAAO,0BAEJ;IACH,OAAO,CAAC,GAAG,EAAE,cAAc;CAG5B;AAED,qBAAa,MAAM;;IACjB,IAAI,EAAE,aAAa,CAAC;IAEpB,OAAO,EAAE,SAAS,GAAG,SAAS,CAAa;IAC3C,MAAM,UAAS;IACf,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,uCAA0B;IAChC,KAAK,wBAAsB;IAC3B,OAAO,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG;YAAE,KAAK,EAAE,iBAAiB,CAAA;SAAE,CAAA;KAAE,CAAM;IAC7D,SAAS,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG;YAAE,IAAI,EAAE,UAAU,CAAC;YAAC,SAAS,EAAE,SAAS,CAAA;SAAE,CAAA;KAAE,CAAM;gBAEjE,IAAI,EAAE,aAAa;IAS/B,IAAI,EAAE,IAAI,MAAM,CAEf;IAEK,GAAG;IAoDT,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM;IAc1D,KAAK,CAAC,EAAE,EAAE,SAAS;IA4Fb,YAAY,CAAC,GAAG,EAAE,mBAAmB;IAsDrC,KAAK;CAUZ"}
package/dist/worker.js ADDED
@@ -0,0 +1,296 @@
1
+ // SPDX-FileCopyrightText: 2024 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { JobType, ParticipantPermission, ServerMessage, WorkerMessage, } from '@livekit/protocol';
5
+ import { EventEmitter } from 'events';
6
+ import { AccessToken } from 'livekit-server-sdk';
7
+ import os from 'os';
8
+ import { WebSocket } from 'ws';
9
+ import { HTTPServer } from './http_server.js';
10
+ import { JobProcess } from './ipc/job_process.js';
11
+ import { JobRequest } from './job_request.js';
12
+ import { log } from './log.js';
13
+ import { version } from './version.js';
14
+ const MAX_RECONNECT_ATTEMPTS = 10;
15
+ const ASSIGNMENT_TIMEOUT = 15 * 1000;
16
+ const LOAD_INTERVAL = 5 * 1000;
17
+ const cpuLoad = () => (os
18
+ .cpus()
19
+ .reduce((acc, x) => acc + x.times.idle / Object.values(x.times).reduce((acc, x) => acc + x, 0), 0) /
20
+ os.cpus().length) *
21
+ 100;
22
+ class WorkerPermissions {
23
+ canPublish;
24
+ canSubscribe;
25
+ canPublishData;
26
+ canUpdateMetadata;
27
+ hidden;
28
+ constructor(canPublish = true, canSubscribe = true, canPublishData = true, canUpdateMetadata = true, hidden = false) {
29
+ this.canPublish = canPublish;
30
+ this.canSubscribe = canSubscribe;
31
+ this.canPublishData = canPublishData;
32
+ this.canUpdateMetadata = canUpdateMetadata;
33
+ this.hidden = hidden;
34
+ }
35
+ }
36
+ export class WorkerOptions {
37
+ requestFunc;
38
+ cpuLoadFunc;
39
+ namespace;
40
+ permissions;
41
+ workerType;
42
+ maxRetry;
43
+ wsURL;
44
+ apiKey;
45
+ apiSecret;
46
+ host;
47
+ port;
48
+ constructor({ requestFunc, cpuLoadFunc = cpuLoad, namespace = 'default', permissions = new WorkerPermissions(), workerType = JobType.JT_PUBLISHER, maxRetry = MAX_RECONNECT_ATTEMPTS, wsURL = 'ws://localhost:7880', apiKey = undefined, apiSecret = undefined, host = 'localhost', port = 8081, }) {
49
+ this.requestFunc = requestFunc;
50
+ this.cpuLoadFunc = cpuLoadFunc;
51
+ this.namespace = namespace;
52
+ this.permissions = permissions;
53
+ this.workerType = workerType;
54
+ this.maxRetry = maxRetry;
55
+ this.wsURL = wsURL;
56
+ this.apiKey = apiKey;
57
+ this.apiSecret = apiSecret;
58
+ this.host = host;
59
+ this.port = port;
60
+ }
61
+ }
62
+ class ActiveJob {
63
+ job;
64
+ acceptData;
65
+ constructor(job, acceptData) {
66
+ this.job = job;
67
+ this.acceptData = acceptData;
68
+ }
69
+ }
70
+ class PendingAssignment {
71
+ promise = new Promise((resolve) => {
72
+ this.resolve = resolve; // oh, JavaScript.
73
+ });
74
+ resolve(arg) {
75
+ arg;
76
+ }
77
+ }
78
+ export class Worker {
79
+ opts;
80
+ #id = 'unregistered';
81
+ session = undefined;
82
+ closed = false;
83
+ httpServer;
84
+ logger = log.child({ version });
85
+ event = new EventEmitter();
86
+ pending = {};
87
+ processes = {};
88
+ constructor(opts) {
89
+ opts.wsURL = opts.wsURL || process.env.LIVEKIT_URL || '';
90
+ opts.apiKey = opts.apiKey || process.env.LIVEKIT_API_KEY || '';
91
+ opts.apiSecret = opts.apiSecret || process.env.LIVEKIT_API_SECRET || '';
92
+ this.opts = opts;
93
+ this.httpServer = new HTTPServer(opts.host, opts.port);
94
+ }
95
+ get id() {
96
+ return this.#id;
97
+ }
98
+ async run() {
99
+ this.logger.info('starting worker');
100
+ if (this.opts.wsURL === '')
101
+ throw new Error('--url is required, or set LIVEKIT_URL env var');
102
+ if (this.opts.apiKey === '')
103
+ throw new Error('--api-key is required, or set LIVEKIT_API_KEY env var');
104
+ if (this.opts.apiSecret === '')
105
+ throw new Error('--api-secret is required, or set LIVEKIT_API_SECRET env var');
106
+ const workerWS = async () => {
107
+ let retries = 0;
108
+ while (!this.closed) {
109
+ const token = new AccessToken(this.opts.apiKey, this.opts.apiSecret);
110
+ token.addGrant({ agent: true });
111
+ const jwt = await token.toJwt();
112
+ const url = new URL(this.opts.wsURL);
113
+ url.protocol = url.protocol.replace('http', 'ws');
114
+ this.session = new WebSocket(url + 'agent', {
115
+ headers: { authorization: 'Bearer ' + jwt },
116
+ });
117
+ try {
118
+ await new Promise((resolve, reject) => {
119
+ this.session.on('open', resolve);
120
+ this.session.on('error', (error) => reject(error));
121
+ this.session.on('close', (code) => reject(`WebSocket returned ${code}`));
122
+ });
123
+ this.runWS(this.session);
124
+ return;
125
+ }
126
+ catch (e) {
127
+ if (this.closed)
128
+ return;
129
+ if (retries >= this.opts.maxRetry) {
130
+ throw new Error(`failed to connect to LiveKit server after ${retries} attempts: ${e}`);
131
+ }
132
+ retries++;
133
+ const delay = Math.min(retries * 2, 10);
134
+ this.logger.warn(`failed to connect to LiveKit server, retrying in ${delay} seconds: ${e} (${retries}/${this.opts.maxRetry})`);
135
+ await new Promise((resolve) => setTimeout(resolve, delay * 1000));
136
+ }
137
+ }
138
+ };
139
+ await Promise.all([workerWS(), this.httpServer.run()]);
140
+ }
141
+ startProcess(job, acceptData, raw) {
142
+ const proc = new JobProcess(job, acceptData, raw, this.opts.wsURL);
143
+ this.processes[job.id] = { proc, activeJob: new ActiveJob(job, acceptData) };
144
+ proc
145
+ .run()
146
+ .catch((e) => {
147
+ proc.logger.error(`error running job process ${proc.job.id}: ${e}`);
148
+ })
149
+ .finally(() => {
150
+ proc.clear();
151
+ delete this.processes[job.id];
152
+ });
153
+ }
154
+ runWS(ws) {
155
+ let closingWS = false;
156
+ const send = (msg) => {
157
+ if (closingWS) {
158
+ this.event.off('worker_msg', send);
159
+ return;
160
+ }
161
+ ws.send(msg.toBinary());
162
+ };
163
+ this.event.on('worker_msg', send);
164
+ ws.addEventListener('close', () => {
165
+ closingWS = true;
166
+ this.logger.error('worker connection closed unexpectedly');
167
+ this.close();
168
+ });
169
+ ws.addEventListener('message', (event) => {
170
+ if (event.type !== 'message') {
171
+ this.logger.warn('unexpected message type: ' + event.type);
172
+ return;
173
+ }
174
+ const msg = new ServerMessage();
175
+ msg.fromBinary(event.data);
176
+ switch (msg.message.case) {
177
+ case 'register': {
178
+ this.#id = msg.message.value.workerId;
179
+ log
180
+ .child({ id: this.id, server_info: msg.message.value.serverInfo })
181
+ .info('registered worker');
182
+ break;
183
+ }
184
+ case 'availability': {
185
+ this.availability(msg.message.value);
186
+ break;
187
+ }
188
+ case 'assignment': {
189
+ const job = msg.message.value.job;
190
+ if (job.id in this.pending) {
191
+ const task = this.pending[job.id];
192
+ delete this.pending[job.id];
193
+ task.value.resolve({
194
+ asgn: msg.message.value,
195
+ raw: msg.toJsonString(),
196
+ });
197
+ }
198
+ else {
199
+ log.child({ job }).warn('received assignment for unknown job ' + job.id);
200
+ }
201
+ break;
202
+ }
203
+ }
204
+ });
205
+ this.event.emit('worker_msg', new WorkerMessage({
206
+ message: {
207
+ case: 'register',
208
+ value: {
209
+ type: this.opts.workerType,
210
+ namespace: this.opts.namespace,
211
+ allowedPermissions: new ParticipantPermission({
212
+ canPublish: this.opts.permissions.canPublish,
213
+ canSubscribe: this.opts.permissions.canSubscribe,
214
+ canPublishData: this.opts.permissions.canPublishData,
215
+ hidden: this.opts.permissions.hidden,
216
+ agent: true,
217
+ }),
218
+ version,
219
+ },
220
+ },
221
+ }));
222
+ const loadMonitor = setInterval(() => {
223
+ if (closingWS)
224
+ clearInterval(loadMonitor);
225
+ this.event.emit('worker_msg', new WorkerMessage({
226
+ message: {
227
+ case: 'updateWorker',
228
+ value: {
229
+ load: cpuLoad(),
230
+ },
231
+ },
232
+ }));
233
+ }, LOAD_INTERVAL);
234
+ }
235
+ async availability(msg) {
236
+ const tx = new EventEmitter();
237
+ const req = new JobRequest(msg.job, tx);
238
+ tx.on('recv', async (av) => {
239
+ const msg = new WorkerMessage({
240
+ message: {
241
+ case: 'availability',
242
+ value: {
243
+ available: av.avail,
244
+ jobId: req.id,
245
+ participantIdentity: av.data?.identity,
246
+ participantName: av.data?.name,
247
+ participantMetadata: av.data?.metadata,
248
+ },
249
+ },
250
+ });
251
+ this.pending[req.id] = { value: new PendingAssignment() };
252
+ this.event.emit('worker_msg', msg);
253
+ if (!av.avail)
254
+ return;
255
+ const timer = setTimeout(() => {
256
+ log.child({ req }).warn(`assignment for job ${req.id} timed out`);
257
+ return;
258
+ }, ASSIGNMENT_TIMEOUT);
259
+ this.pending[req.id].value.promise.then(({ asgn, raw }) => {
260
+ clearTimeout(timer);
261
+ this.startProcess(asgn.job, av.data, raw);
262
+ });
263
+ });
264
+ try {
265
+ this.opts.requestFunc(req);
266
+ }
267
+ catch (e) {
268
+ log.child({ req }).error(`user request handler for job ${req.id} failed`);
269
+ }
270
+ finally {
271
+ if (!req.answered) {
272
+ log.child({ req }).error(`no answer for job ${req.id}, automatically rejecting the job`);
273
+ this.event.emit('worker_msg', new WorkerMessage({
274
+ message: {
275
+ case: 'availability',
276
+ value: {
277
+ available: false,
278
+ },
279
+ },
280
+ }));
281
+ }
282
+ }
283
+ }
284
+ async close() {
285
+ if (this.closed)
286
+ return;
287
+ this.closed = true;
288
+ this.logger.debug('shutting down worker');
289
+ await this.httpServer.close();
290
+ for await (const value of Object.values(this.processes)) {
291
+ await value.proc.close();
292
+ }
293
+ this.session?.close();
294
+ }
295
+ }
296
+ //# sourceMappingURL=worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@livekit/agents",
3
+ "version": "0.1.0",
4
+ "description": "LiveKit Node Agents",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "author": "aoife cassidy <aoife@cassidy.sh>",
8
+ "type": "module",
9
+ "devDependencies": {
10
+ "@microsoft/api-extractor": "^7.35.0",
11
+ "@types/ws": "^8.5.10"
12
+ },
13
+ "peerDependencies": {
14
+ "typescript": "^5.0.0"
15
+ },
16
+ "dependencies": {
17
+ "@livekit/rtc-node": "^0.1.0",
18
+ "@livekit/protocol": "^1.13.0",
19
+ "commander": "^12.0.0",
20
+ "livekit-server-sdk": "^2.1.2",
21
+ "pino": "^8.19.0",
22
+ "pino-pretty": "^11.0.0",
23
+ "ws": "^8.16.0"
24
+ },
25
+ "scripts": {
26
+ "build": "tsc",
27
+ "lint": "eslint -f unix \"src/**/*.ts\"",
28
+ "api:check": "api-extractor run --typescript-compiler-folder ../node_modules/typescript",
29
+ "api:update": "api-extractor run --local --typescript-compiler-folder ../node_modules/typescript --verbose"
30
+ }
31
+ }
package/src/cli.ts ADDED
@@ -0,0 +1,79 @@
1
+ // SPDX-FileCopyrightText: 2024 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { Command, Option } from 'commander';
5
+ import type { EventEmitter } from 'events';
6
+ import { log } from './log.js';
7
+ import { version } from './version.js';
8
+ import { Worker, type WorkerOptions } from './worker.js';
9
+
10
+ type CliArgs = {
11
+ opts: WorkerOptions;
12
+ logLevel: string;
13
+ production: boolean;
14
+ watch: boolean;
15
+ event?: EventEmitter;
16
+ };
17
+
18
+ const runWorker = async (args: CliArgs) => {
19
+ log.level = args.logLevel;
20
+ const worker = new Worker(args.opts);
21
+
22
+ process.on('SIGINT', async () => {
23
+ await worker.close();
24
+ log.info('worker closed');
25
+ process.exit(130); // SIGINT exit code
26
+ });
27
+
28
+ try {
29
+ await worker.run();
30
+ } catch {
31
+ log.fatal('worker failed');
32
+ process.exit(1);
33
+ }
34
+ };
35
+
36
+ export const runApp = (opts: WorkerOptions) => {
37
+ const program = new Command()
38
+ .name('agents')
39
+ .description('LiveKit Agents CLI')
40
+ .version(version)
41
+ .addOption(
42
+ new Option('--log-level <level>', 'Set the logging level')
43
+ .choices(['trace', 'debug', 'info', 'warn', 'error', 'fatal'])
44
+ .default('trace'),
45
+ )
46
+ .addOption(
47
+ new Option('--url <string>', 'LiveKit server or Cloud project websocket URL')
48
+ .makeOptionMandatory(true)
49
+ .env('LIVEKIT_URL'),
50
+ )
51
+ .addOption(
52
+ new Option('--api-key <string>', "LiveKit server or Cloud project's API key")
53
+ .makeOptionMandatory(true)
54
+ .env('LIVEKIT_API_KEY'),
55
+ )
56
+ .addOption(
57
+ new Option('--api-secret <string>', "LiveKit server or Cloud project's API secret")
58
+ .makeOptionMandatory(true)
59
+ .env('LIVEKIT_API_SECRET'),
60
+ );
61
+
62
+ program
63
+ .command('start')
64
+ .description('Start the worker in production mode')
65
+ .action(() => {
66
+ const options = program.optsWithGlobals();
67
+ opts.wsURL = options.url || opts.wsURL;
68
+ opts.apiKey = options.apiKey || opts.apiKey;
69
+ opts.apiSecret = options.apiSecret || opts.apiSecret;
70
+ runWorker({
71
+ opts,
72
+ production: true,
73
+ watch: false,
74
+ logLevel: options.logLevel,
75
+ });
76
+ });
77
+
78
+ program.parse();
79
+ };
@@ -0,0 +1,18 @@
1
+ // SPDX-FileCopyrightText: 2024 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import type { JobContext } from './job_context.js';
5
+
6
+ type entryFunction = (job: JobContext) => Promise<void>;
7
+
8
+ export interface Agent {
9
+ entry: entryFunction;
10
+ }
11
+
12
+ /**
13
+ * Helper to define an agent according to the required interface.
14
+ * @example `export default defineAgent(myAgent);`
15
+ */
16
+ export function defineAgent(entry: entryFunction): Agent {
17
+ return { entry };
18
+ }