@recallai/desktop-sdk 2025.3.20-daa9afad0e8b396cbde4cc76835f277cf9f86955 → 2025.3.24-281fab31aa87043b2fbe0ed81ae984c326e4d33e

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;
@@ -24,59 +24,93 @@ declare module '@recallai/desktop-sdk' {
24
24
  'error': ErrorEvent;
25
25
  'media-capture-status': MediaCaptureStatusEvent;
26
26
  'permissions-granted': PermissionsGrantedEvent;
27
+ 'permission-status': PermissionStatusEvent;
27
28
  'realtime-event': RealtimeEvent;
29
+ 'shutdown': ShutdownEvent;
28
30
  };
29
31
 
32
+ export type Permission =
33
+ | 'accessibility'
34
+ | 'screen-capture'
35
+ | 'microphone';
36
+
30
37
  export function addEventListener<T extends keyof EventTypeToPayloadMap>(
31
38
  type: T,
32
39
  listener: (event: EventTypeToPayloadMap[T]) => void
33
40
  ): void;
34
41
 
35
- export function startRecording(config: StartRecordingConfig): void;
36
- export function stopRecording(config: StopRecordingConfig): void;
37
- export function uploadRecording(config: UploadRecordingConfig): void;
42
+ export function init(config: RecallAiSdkConfig): Promise<null>;
43
+ export function startRecording(config: StartRecordingConfig): Promise<null>;
44
+ export function pauseRecording(config: PauseRecordingConfig): Promise<null>;
45
+ export function resumeRecording(config: ResumeRecordingConfig): Promise<null>;
46
+ export function stopRecording(config: StopRecordingConfig): Promise<null>;
47
+ export function uploadRecording(config: UploadRecordingConfig): Promise<null>;
38
48
  export function prepareDesktopAudioRecording(): Promise<string>;
49
+ export function requestPermission(permission: Permission): Promise<null>;
50
+ export function shutdown(): Promise<null>;
51
+
52
+ ///
39
53
 
40
54
  export interface RecallAiSdkWindow {
41
55
  id: string;
42
- title: string | undefined;
43
- url: string | undefined;
56
+ title?: string;
57
+ url?: string;
44
58
  platform: string;
45
59
  }
46
60
 
47
61
  export interface RecallAiSdkConfig {
48
62
  api_url: string;
63
+ acquirePermissionsOnStartup?: Permission[]
49
64
  }
65
+
50
66
  export interface StartRecordingConfig {
51
67
  windowId: string;
52
68
  uploadToken: string;
53
69
  }
70
+
54
71
  export interface StopRecordingConfig {
55
72
  windowId: string;
56
73
  }
74
+
75
+ export interface PauseRecordingConfig {
76
+ windowId: string;
77
+ }
78
+
79
+ export interface ResumeRecordingConfig {
80
+ windowId: string;
81
+ }
82
+
57
83
  export interface UploadRecordingConfig {
58
84
  windowId: string;
59
85
  }
60
86
 
87
+ ///
88
+
61
89
  export interface RecordingStartEvent {
62
90
  window: RecallAiSdkWindow;
63
91
  }
92
+
64
93
  export interface RecordingStopEvent {
65
94
  window: RecallAiSdkWindow;
66
95
  }
96
+
67
97
  export interface UploadProgressEvent {
68
98
  window: { id: string };
69
99
  progress: number;
70
100
  }
101
+
71
102
  export interface MeetingDetectedEvent {
72
103
  window: RecallAiSdkWindow;
73
104
  }
105
+
74
106
  export interface MeetingUpdatedEvent {
75
107
  window: RecallAiSdkWindow;
76
108
  }
109
+
77
110
  export interface MeetingClosedEvent {
78
111
  window: RecallAiSdkWindow;
79
112
  }
113
+
80
114
  export interface SdkStateChangeEvent {
81
115
  sdk: {
82
116
  state: {
@@ -84,22 +118,34 @@ declare module '@recallai/desktop-sdk' {
84
118
  };
85
119
  };
86
120
  }
121
+
87
122
  export interface MediaCaptureStatusEvent {
88
123
  window: RecallAiSdkWindow;
89
124
  type: 'video' | 'audio';
90
125
  capturing: boolean;
91
126
  }
92
- export interface PermissionsGrantedEvent {
127
+
128
+ export interface PermissionsGrantedEvent {}
129
+
130
+ export interface PermissionStatusEvent {
131
+ permission: Permission;
132
+ granted: bool;
93
133
  }
134
+
94
135
  export interface ErrorEvent {
95
- error: {
96
- type: string;
97
- message: string;
98
- };
136
+ window?: RecallAiSdkWindow;
137
+ type: string;
138
+ message: string;
99
139
  }
140
+
100
141
  export interface RealtimeEvent {
101
142
  window: RecallAiSdkWindow;
102
143
  event: string;
103
144
  data: any;
104
145
  }
146
+
147
+ export interface ShutdownEvent {
148
+ code: number;
149
+ signal: string;
150
+ }
105
151
  }
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,53 +171,67 @@ 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");
216
+ }
217
+
218
+ function requestPermission(permission) {
219
+ return sendCommand("requestPermission", { permission });
174
220
  }
175
221
 
176
222
  function addEventListener(type, callback) {
177
223
  listeners.push({ type, callback });
178
224
  }
179
225
 
180
- // Start the process initially
181
- startProcess();
182
-
183
226
  module.exports = {
184
227
  init,
228
+ shutdown,
185
229
  addEventListener,
186
230
  startRecording,
231
+ pauseRecording,
232
+ resumeRecording,
187
233
  stopRecording,
188
234
  uploadRecording,
189
235
  prepareDesktopAudioRecording,
236
+ requestPermission
190
237
  };
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.24-281fab31aa87043b2fbe0ed81ae984c326e4d33e",
4
4
  "description": "Recall Desktop SDK (Alpha)",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",