@recallai/desktop-sdk 1.1.0 → 1.3.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ ### 1.3.0 [minor] (MacOS+Windows) - 2025-10-17
2
+
3
+ - Initial support for Google Meet on macOS Safari
4
+ - Fixed more issues with missing participants on Windows
5
+ - Fixed active speaker detection on teams for Windows
6
+ - Fixed missing audio on teams for Windows
7
+ - Added enhanced crash detection and reporting for macOS
8
+ - Fixed some audio issues on macOS
9
+ - Fixed issue getting meet urls on multiple profile installs
10
+ - Support more languages for Zoom and Google Meet on macOS
11
+ - Support google meet titles on Windows
12
+
13
+ ### 1.2.0 [minor] (MacOS+Windows) - 2025-09-26
14
+
15
+ - Initial support for Google Meet on Windows
16
+ - Fixed issues with participant mapping on Windows
17
+ - Mixed audio mp3 support for Windows
18
+ - Zoom, Teams, Google Meet url scraping for Windows
19
+ - Gladia streaming support for transcription
20
+ - Fixed an issue where Zoom video capture would be affected when chat is open
21
+ - Improved acoustic audio cancellation
22
+ - Added the ability to get URL from Zoom and Teams meetings
23
+ - Various improvements for Google Meet support on macOS
24
+ - Speeded up starting a recording
25
+ - Caused recording to stop when the laptop lid is closed
26
+
1
27
  ### 1.1.0 [minor] (MacOS+Windows) - 2025-08-29
2
28
 
3
29
  - Reduce idle power consumption by 80%
package/index.d.ts CHANGED
@@ -105,6 +105,7 @@ export interface ShutdownEvent {
105
105
  }
106
106
  export declare function init(options: RecallAiSdkConfig): Promise<null>;
107
107
  export declare function shutdown(): Promise<null>;
108
+ export declare function dumpAXTree(procName: string): Promise<any>;
108
109
  export declare function startRecording(config: StartRecordingConfig): Promise<null>;
109
110
  export declare function stopRecording({ windowId }: StopRecordingConfig): Promise<null>;
110
111
  export declare function pauseRecording({ windowId }: PauseRecordingConfig): Promise<null>;
@@ -112,6 +113,7 @@ export declare function resumeRecording({ windowId }: ResumeRecordingConfig): Pr
112
113
  export declare function uploadRecording({ windowId }: UploadRecordingConfig): Promise<null>;
113
114
  export declare function prepareDesktopAudioRecording(): Promise<string>;
114
115
  export declare function requestPermission(permission: Permission): Promise<null>;
116
+ export declare function testUnexpectedShutdown(): Promise<null>;
115
117
  export declare function addEventListener<T extends keyof EventTypeToPayloadMap>(type: T, callback: (event: EventTypeToPayloadMap[T]) => void): void;
116
118
  declare const RecallAiSdk: {
117
119
  init: typeof init;
@@ -124,5 +126,6 @@ declare const RecallAiSdk: {
124
126
  prepareDesktopAudioRecording: typeof prepareDesktopAudioRecording;
125
127
  requestPermission: typeof requestPermission;
126
128
  addEventListener: typeof addEventListener;
129
+ testUnexpectedShutdown: typeof testUnexpectedShutdown;
127
130
  };
128
131
  export default RecallAiSdk;
package/index.js CHANGED
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.init = init;
37
37
  exports.shutdown = shutdown;
38
+ exports.dumpAXTree = dumpAXTree;
38
39
  exports.startRecording = startRecording;
39
40
  exports.stopRecording = stopRecording;
40
41
  exports.pauseRecording = pauseRecording;
@@ -42,10 +43,12 @@ exports.resumeRecording = resumeRecording;
42
43
  exports.uploadRecording = uploadRecording;
43
44
  exports.prepareDesktopAudioRecording = prepareDesktopAudioRecording;
44
45
  exports.requestPermission = requestPermission;
46
+ exports.testUnexpectedShutdown = testUnexpectedShutdown;
45
47
  exports.addEventListener = addEventListener;
46
48
  const path = __importStar(require("path"));
47
49
  const child_process_1 = require("child_process");
48
50
  const readline = __importStar(require("node:readline"));
51
+ const node_stream_1 = require("node:stream");
49
52
  const fs = __importStar(require("node:fs"));
50
53
  const os = __importStar(require("node:os"));
51
54
  const uuid_1 = require("uuid");
@@ -62,6 +65,9 @@ else if (process.platform === "win32") {
62
65
  exe_paths.push(path.join(__dirname, "agent-windows.exe"));
63
66
  }
64
67
  let proc;
68
+ let rlData;
69
+ let rlStdout;
70
+ let rlStderr;
65
71
  const listeners = [];
66
72
  const pendingCommands = {};
67
73
  let lastOptions;
@@ -81,6 +87,47 @@ function flushLogBuffer() {
81
87
  doLog(level, [log], echo);
82
88
  }
83
89
  }
90
+ function isPlainObject(value) {
91
+ return (value !== null &&
92
+ typeof value === "object" &&
93
+ Object.getPrototypeOf(value) === Object.prototype);
94
+ }
95
+ /**
96
+ * JSON.stringify with alphabetically sorted object keys (deep).
97
+ * - Preserves array order
98
+ * - Leaves non-plain objects (Date, Map, Set, class instances with toJSON, etc.) intact
99
+ * - Detects circular references like JSON.stringify and throws
100
+ */
101
+ function sortedStringify(value, replacer, space) {
102
+ const seen = new WeakSet();
103
+ function normalize(v) {
104
+ if (v === null || typeof v !== "object")
105
+ return v;
106
+ const obj = v;
107
+ if (seen.has(obj)) {
108
+ throw new TypeError("Converting circular structure to JSON");
109
+ }
110
+ seen.add(obj);
111
+ if (Array.isArray(v)) {
112
+ const out = v.map(normalize);
113
+ seen.delete(obj);
114
+ return out;
115
+ }
116
+ if (isPlainObject(v)) {
117
+ const src = v;
118
+ const out = {};
119
+ for (const key of Object.keys(src).sort()) {
120
+ out[key] = normalize(src[key]);
121
+ }
122
+ seen.delete(obj);
123
+ return out;
124
+ }
125
+ // Non-plain object: keep as-is so built-in toJSON/serialization applies.
126
+ seen.delete(obj);
127
+ return v;
128
+ }
129
+ return JSON.stringify(normalize(value), replacer, space);
130
+ }
84
131
  async function doLog(level, log, echo = true) {
85
132
  try {
86
133
  const levelMap = {
@@ -119,7 +166,7 @@ function logError(...log) {
119
166
  }
120
167
  function emitEvent(type, payload) {
121
168
  if (type !== "upload-progress" && type !== "realtime-event") {
122
- doLog("info", ["Receiving event: " + type + " | " + JSON.stringify(payload)], false);
169
+ doLog("info", ["Receiving event: " + type + " | " + sortedStringify(payload)], false);
123
170
  }
124
171
  for (const listener of listeners) {
125
172
  if (listener.type === type) {
@@ -160,7 +207,7 @@ function startProcess() {
160
207
  }
161
208
  }
162
209
  proc = (0, child_process_1.spawn)(exe_path, {
163
- stdio: "pipe",
210
+ stdio: (process.platform === "darwin" ? ["pipe", "pipe", "pipe", "pipe"] : "pipe"),
164
211
  env: {
165
212
  GST_DEBUG: "2",
166
213
  GST_DEBUG_DUMP_DOT_DIR: gst_dump_dir,
@@ -171,10 +218,16 @@ function startProcess() {
171
218
  ...envExtra,
172
219
  }
173
220
  });
174
- const rlStdout = readline.createInterface({ input: proc.stdout, crlfDelay: Infinity });
175
- const rlStderr = readline.createInterface({ input: proc.stderr, crlfDelay: Infinity });
176
- rlStdout.on('line', (line) => {
177
- if (line.startsWith("recall_ai_command|")) {
221
+ if (process.platform === "darwin") {
222
+ const fd3 = proc.stdio[3];
223
+ if (fd3 && fd3 instanceof node_stream_1.Readable) {
224
+ rlData = readline.createInterface({ input: fd3, crlfDelay: Infinity });
225
+ }
226
+ }
227
+ rlStdout = readline.createInterface({ input: proc.stdout, crlfDelay: Infinity });
228
+ rlStderr = readline.createInterface({ input: proc.stderr, crlfDelay: Infinity });
229
+ let onLine = (line) => {
230
+ if (line?.startsWith("recall_ai_command|")) {
178
231
  try {
179
232
  const data = JSON.parse(line.substring(18));
180
233
  switch (data.type) {
@@ -207,7 +260,9 @@ function startProcess() {
207
260
  console.log(line);
208
261
  }
209
262
  }
210
- });
263
+ };
264
+ rlData?.on('line', onLine);
265
+ rlStdout.on('line', onLine);
211
266
  rlStderr.on('line', (line) => {
212
267
  if (process.env.RECALLAI_DESKTOP_SDK_DEV) {
213
268
  console.error(line);
@@ -224,6 +279,10 @@ function startProcess() {
224
279
  proc.on('close', async (code, signal) => {
225
280
  flushPendingCommands(new Error(`Process exited with code ${code}, signal ${signal}.`));
226
281
  emitEvent('shutdown', { code: code ?? 0, signal: signal ?? '' });
282
+ rlStdout?.close();
283
+ rlStderr?.close();
284
+ rlStdout = null;
285
+ rlStderr = null;
227
286
  if (code === 0 || signal === 'SIGINT') {
228
287
  return;
229
288
  }
@@ -298,6 +357,9 @@ async function shutdown() {
298
357
  }
299
358
  return result;
300
359
  }
360
+ function dumpAXTree(procName) {
361
+ return sendCommand("dumpAXTree", { procName });
362
+ }
301
363
  function startRecording(config) {
302
364
  return sendCommand("startRecording", { config: JSON.stringify(config) });
303
365
  }
@@ -319,6 +381,9 @@ function prepareDesktopAudioRecording() {
319
381
  function requestPermission(permission) {
320
382
  return sendCommand("requestPermission", { permission });
321
383
  }
384
+ function testUnexpectedShutdown() {
385
+ return sendCommand("unexpectedShutdown", {});
386
+ }
322
387
  function addEventListener(type, callback) {
323
388
  listeners.push({ type, callback });
324
389
  }
@@ -333,5 +398,6 @@ const RecallAiSdk = {
333
398
  prepareDesktopAudioRecording,
334
399
  requestPermission,
335
400
  addEventListener,
401
+ testUnexpectedShutdown
336
402
  };
337
403
  exports.default = RecallAiSdk;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@recallai/desktop-sdk",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Recall Desktop SDK",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
@@ -13,12 +13,12 @@
13
13
  },
14
14
  "scripts": {
15
15
  "install": "node ./setup.js",
16
- "validate-types": "tsc --noEmit index.d.ts",
16
+ "validate-types": "tsc --noEmit",
17
17
  "build": "tsc -p tsconfig.build.json"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@types/node": "^24.2.0",
21
21
  "typescript": "^5.3.3"
22
22
  },
23
- "commit_sha": "6b2ffc56b52550ef46336f4ed9646d20f0e4b722"
23
+ "commit_sha": "3b3394ac612c9f13bd39bf245ddb8499a0092453"
24
24
  }