@recallai/desktop-sdk 2025.3.20-daa9afad0e8b396cbde4cc76835f277cf9f86955 → 2025.3.21-bac17c323e1c541c8e37a11aa29e369f59b0dc28

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.
Binary file
Binary file
package/index.d.ts CHANGED
@@ -1,6 +1,4 @@
1
1
  declare module '@recallai/desktop-sdk' {
2
- export function init(config: RecallAiSdkConfig): void;
3
-
4
2
  export type RecallAiSdkEvent =
5
3
  | RecordingStartEvent
6
4
  | RecordingStopEvent
@@ -11,7 +9,9 @@ declare module '@recallai/desktop-sdk' {
11
9
  | SdkStateChangeEvent
12
10
  | ErrorEvent
13
11
  | MediaCaptureStatusEvent
14
- | PermissionsGrantedEvent;
12
+ | PermissionsGrantedEvent
13
+ | RealtimeEvent
14
+ | ShutdownEvent;
15
15
 
16
16
  export type EventTypeToPayloadMap = {
17
17
  'recording-started': RecordingStartEvent;
@@ -25,6 +25,7 @@ declare module '@recallai/desktop-sdk' {
25
25
  'media-capture-status': MediaCaptureStatusEvent;
26
26
  'permissions-granted': PermissionsGrantedEvent;
27
27
  'realtime-event': RealtimeEvent;
28
+ 'shutdown': ShutdownEvent;
28
29
  };
29
30
 
30
31
  export function addEventListener<T extends keyof EventTypeToPayloadMap>(
@@ -32,51 +33,76 @@ declare module '@recallai/desktop-sdk' {
32
33
  listener: (event: EventTypeToPayloadMap[T]) => void
33
34
  ): void;
34
35
 
35
- export function startRecording(config: StartRecordingConfig): void;
36
- export function stopRecording(config: StopRecordingConfig): void;
37
- export function uploadRecording(config: UploadRecordingConfig): void;
36
+ export function init(config: RecallAiSdkConfig): Promise<null>;
37
+ export function startRecording(config: StartRecordingConfig): Promise<null>;
38
+ export function pauseRecording(config: PauseRecordingConfig): Promise<null>;
39
+ export function resumeRecording(config: ResumeRecordingConfig): Promise<null>;
40
+ export function stopRecording(config: StopRecordingConfig): Promise<null>;
41
+ export function uploadRecording(config: UploadRecordingConfig): Promise<null>;
38
42
  export function prepareDesktopAudioRecording(): Promise<string>;
43
+ export function shutdown(): Promise<null>;
44
+
45
+ ///
39
46
 
40
47
  export interface RecallAiSdkWindow {
41
48
  id: string;
42
- title: string | undefined;
43
- url: string | undefined;
49
+ title?: string;
50
+ url?: string;
44
51
  platform: string;
45
52
  }
46
53
 
47
54
  export interface RecallAiSdkConfig {
48
55
  api_url: string;
49
56
  }
57
+
50
58
  export interface StartRecordingConfig {
51
59
  windowId: string;
52
60
  uploadToken: string;
53
61
  }
62
+
54
63
  export interface StopRecordingConfig {
55
64
  windowId: string;
56
65
  }
66
+
67
+ export interface PauseRecordingConfig {
68
+ windowId: string;
69
+ }
70
+
71
+ export interface ResumeRecordingConfig {
72
+ windowId: string;
73
+ }
74
+
57
75
  export interface UploadRecordingConfig {
58
76
  windowId: string;
59
77
  }
60
78
 
79
+ ///
80
+
61
81
  export interface RecordingStartEvent {
62
82
  window: RecallAiSdkWindow;
63
83
  }
84
+
64
85
  export interface RecordingStopEvent {
65
86
  window: RecallAiSdkWindow;
66
87
  }
88
+
67
89
  export interface UploadProgressEvent {
68
90
  window: { id: string };
69
91
  progress: number;
70
92
  }
93
+
71
94
  export interface MeetingDetectedEvent {
72
95
  window: RecallAiSdkWindow;
73
96
  }
97
+
74
98
  export interface MeetingUpdatedEvent {
75
99
  window: RecallAiSdkWindow;
76
100
  }
101
+
77
102
  export interface MeetingClosedEvent {
78
103
  window: RecallAiSdkWindow;
79
104
  }
105
+
80
106
  export interface SdkStateChangeEvent {
81
107
  sdk: {
82
108
  state: {
@@ -84,22 +110,29 @@ declare module '@recallai/desktop-sdk' {
84
110
  };
85
111
  };
86
112
  }
113
+
87
114
  export interface MediaCaptureStatusEvent {
88
115
  window: RecallAiSdkWindow;
89
116
  type: 'video' | 'audio';
90
117
  capturing: boolean;
91
118
  }
92
- export interface PermissionsGrantedEvent {
93
- }
119
+
120
+ export interface PermissionsGrantedEvent {}
121
+
94
122
  export interface ErrorEvent {
95
- error: {
96
- type: string;
97
- message: string;
98
- };
123
+ window?: RecallAiSdkWindow;
124
+ type: string;
125
+ message: string;
99
126
  }
127
+
100
128
  export interface RealtimeEvent {
101
129
  window: RecallAiSdkWindow;
102
130
  event: string;
103
131
  data: any;
104
132
  }
133
+
134
+ export interface ShutdownEvent {
135
+ code: number;
136
+ signal: string;
137
+ }
105
138
  }
package/index.js CHANGED
@@ -45,7 +45,23 @@ let proc;
45
45
  const listeners = [];
46
46
  const pendingCommands = {};
47
47
 
48
+ function emitEvent(type, payload) {
49
+ for (const listener of listeners) {
50
+ if (listener.type === type)
51
+ listener.callback(payload);
52
+ }
53
+ }
54
+
55
+ function flushPendingCommands(err) {
56
+ Object.keys(pendingCommands).forEach(commandId => {
57
+ pendingCommands[commandId].reject(err);
58
+ delete pendingCommands[commandId];
59
+ });
60
+ }
61
+
48
62
  function startProcess() {
63
+ if (proc && proc.exitCode === null) return;
64
+
49
65
  const exe_path = exe_paths.find(fs.existsSync);
50
66
 
51
67
  if (!exe_path) {
@@ -68,11 +84,13 @@ function startProcess() {
68
84
  const rlStderr = readline.createInterface({ input: proc.stderr, crlfDelay: Infinity });
69
85
 
70
86
  rlStdout.on('line', (data) => {
71
- if (process.env.RECALLAI_DESKTOP_SDK_DEV) console.log(data);
87
+ if (process.env.RECALLAI_DESKTOP_SDK_DEV)
88
+ console.log(data);
72
89
  });
73
90
 
74
91
  rlStderr.on('line', (data) => {
75
- if (process.env.RECALLAI_DESKTOP_SDK_DEV) console.error(data);
92
+ if (process.env.RECALLAI_DESKTOP_SDK_DEV)
93
+ console.error(data);
76
94
  });
77
95
 
78
96
  rl.on('line', (line) => {
@@ -82,27 +100,21 @@ function startProcess() {
82
100
  switch (data.type) {
83
101
  case "event":
84
102
  const event = JSON.parse(data.event);
85
- for (const { type, callback } of listeners) {
86
- if (type === event.type) callback(event.payload);
87
- }
103
+ emitEvent(event.type, event.payload);
88
104
  break;
89
105
 
90
106
  case "response":
91
107
  const pendingCommand = pendingCommands[data.commandId];
92
108
  if (pendingCommand) {
93
- pendingCommand.resolve(data.result);
109
+ if (data.status === "success") {
110
+ pendingCommand.resolve(data.result);
111
+ }
112
+ else {
113
+ pendingCommand.reject(new Error(data.result));
114
+ }
94
115
  delete pendingCommands[data.commandId];
95
116
  }
96
117
  break;
97
- case "status":
98
- const status = data.status;
99
-
100
- if (status == "success")
101
- break;
102
- else if (status == "error")
103
- console.error(`Desktop SDK: Error response from command. ${data.command} - ${data.status}`);
104
-
105
- break;
106
118
  }
107
119
  } catch (err) {
108
120
  console.error("Desktop SDK: Failed to parse incoming data:", err);
@@ -110,27 +122,48 @@ function startProcess() {
110
122
  });
111
123
 
112
124
  proc.on('error', (error) => {
125
+ flushPendingCommands(new Error(`Process error: ${error.message}`));
126
+ emitEvent('error', {
127
+ type: 'process',
128
+ message: `The Desktop SDK server process has failed to start or exited improperly.`
129
+ });
113
130
  console.error(`Desktop SDK: Process error: ${error.message}`);
114
131
  });
115
132
 
116
- proc.on('close', (code) => {
117
- console.error(`Desktop SDK: Process exited with code ${code}. Restarting...`);
118
- startProcess();
133
+ proc.on('close', (code, signal) => {
134
+ flushPendingCommands(new Error(`Process exited with code ${code}, signal ${signal}.`));
135
+ emitEvent('shutdown', { code, signal });
119
136
 
120
- for (const { type, callback } of listeners) {
121
- if (type === 'error')
122
- callback({
123
- type: "crash",
124
- message: "The Desktop SDK server process crashed and has restarted."
125
- });
126
- }
137
+ if (code === 0 || signal == 'SIGINT')
138
+ return;
139
+
140
+ console.error(`Desktop SDK: Process exited with code ${code}, signal ${signal}`);
141
+
142
+ emitEvent('error', {
143
+ type: 'process',
144
+ message: "The Desktop SDK server process exited unexpectedly."
145
+ });
127
146
  });
128
147
  }
129
148
 
130
- function sendJSON(obj) {
131
- if (proc && proc.stdin) {
132
- proc.stdin.write(JSON.stringify(obj) + "\n");
133
- }
149
+ function sendCommand(command, params = {}) {
150
+ return new Promise((resolve, reject) => {
151
+ if (!proc || !proc.stdin) {
152
+ reject(new Error("The Desktop SDK is not started; call `init` to start it."));
153
+ return;
154
+ }
155
+
156
+ const commandId = uuidv4();
157
+ pendingCommands[commandId] = { resolve, reject };
158
+
159
+ const payload = {
160
+ command,
161
+ commandId,
162
+ params
163
+ };
164
+
165
+ proc.stdin.write(JSON.stringify(payload) + "\n");
166
+ });
134
167
  }
135
168
 
136
169
  function init(options) {
@@ -138,52 +171,61 @@ function init(options) {
138
171
  if (!dev && (!api_url || !api_url.startsWith("https"))) {
139
172
  throw new Error(`api_url must be an https url, got: ${api_url}`);
140
173
  }
141
- sendJSON({
142
- command: "init",
143
- config: JSON.stringify(options)
144
- });
174
+
175
+ startProcess();
176
+ return sendCommand("init", { config: JSON.stringify(options) });
177
+ }
178
+
179
+ async function shutdown() {
180
+ const result = await sendCommand("shutdown");
181
+
182
+ if (proc) {
183
+ const currentProc = proc;
184
+ setTimeout(() => {
185
+ if (!currentProc.killed) {
186
+ currentProc.kill();
187
+ }
188
+ }, 5000);
189
+ }
190
+
191
+ return result;
145
192
  }
146
193
 
147
194
  function startRecording(config) {
148
- sendJSON({ command: "startRecording", config: JSON.stringify(config) });
195
+ return sendCommand("startRecording", { config: JSON.stringify(config) });
149
196
  }
150
197
 
151
198
  function stopRecording({ windowId }) {
152
- sendJSON({
153
- command: "stopRecording",
154
- windowId
155
- });
199
+ return sendCommand("stopRecording", { windowId });
200
+ }
201
+
202
+ function pauseRecording({ windowId }) {
203
+ return sendCommand("pauseRecording", { windowId });
204
+ }
205
+
206
+ function resumeRecording({ windowId }) {
207
+ return sendCommand("resumeRecording", { windowId });
156
208
  }
157
209
 
158
210
  function uploadRecording({ windowId }) {
159
- sendJSON({
160
- command: "uploadRecording",
161
- windowId
162
- });
211
+ return sendCommand("uploadRecording", { windowId });
163
212
  }
164
213
 
165
214
  function prepareDesktopAudioRecording() {
166
- return new Promise((resolve, reject) => {
167
- let commandId = uuidv4();
168
- pendingCommands[commandId] = { resolve, reject };
169
- sendJSON({
170
- command: "prepareDesktopAudioRecording",
171
- commandId
172
- });
173
- });
215
+ return sendCommand("prepareDesktopAudioRecording");
174
216
  }
175
217
 
176
218
  function addEventListener(type, callback) {
177
219
  listeners.push({ type, callback });
178
220
  }
179
221
 
180
- // Start the process initially
181
- startProcess();
182
-
183
222
  module.exports = {
184
223
  init,
224
+ shutdown,
185
225
  addEventListener,
186
226
  startRecording,
227
+ pauseRecording,
228
+ resumeRecording,
187
229
  stopRecording,
188
230
  uploadRecording,
189
231
  prepareDesktopAudioRecording,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@recallai/desktop-sdk",
3
- "version": "2025.03.20-daa9afad0e8b396cbde4cc76835f277cf9f86955",
3
+ "version": "2025.03.21-bac17c323e1c541c8e37a11aa29e369f59b0dc28",
4
4
  "description": "Recall Desktop SDK (Alpha)",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",