@recallai/desktop-sdk 2.0.37 → 2.0.38
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 +7 -0
- package/index.d.ts +1 -6
- package/index.js +102 -26
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
### 2.0.38 [patch] (MacOS+Windows) - 2026-10-14
|
|
2
|
+
- Add telemetryMode field to init method
|
|
3
|
+
- Fix for compliance messaging failing to send for Zoom Desktop on macOS
|
|
4
|
+
- Fix for focus issue with compliance messaging for Zoom Desktop on macOS
|
|
5
|
+
- Fix for meeting detection for Teams Desktop v26246+ on macOS
|
|
6
|
+
- Fix for title extraction for Zoom Desktop on macOS
|
|
7
|
+
|
|
1
8
|
### 2.0.37 [patch] (MacOS+Windows) - 2026-10-08
|
|
2
9
|
- Fix Arc meeting detection
|
|
3
10
|
- Add anonymizeLogging field to init method
|
package/index.d.ts
CHANGED
|
@@ -111,12 +111,7 @@ export interface RecallAiSdkConfig {
|
|
|
111
111
|
* Ignored on Windows, where these permission flows are unnecessary.
|
|
112
112
|
*/
|
|
113
113
|
acquirePermissionsOnStartup?: Exclude<Permission, 'teams-automation' | 'browser-automation'>[];
|
|
114
|
-
|
|
115
|
-
* Anonymizes debug logging when enabled. (Default: false).
|
|
116
|
-
*
|
|
117
|
-
* This will make debugging issues harder, so please keep that in mind before enabling.
|
|
118
|
-
* This setting may be required for data privacy.
|
|
119
|
-
*/
|
|
114
|
+
telemetryMode?: 'full' | 'limited' | 'off';
|
|
120
115
|
anonymizeLogging?: boolean;
|
|
121
116
|
[key: string]: any;
|
|
122
117
|
}
|
package/index.js
CHANGED
|
@@ -78,6 +78,7 @@ const listeners = [];
|
|
|
78
78
|
const lastErrorOut = [];
|
|
79
79
|
const pendingCommands = {};
|
|
80
80
|
let lastOptions;
|
|
81
|
+
let telemetryMode = 'off';
|
|
81
82
|
let remainingAutomaticRestarts = 10;
|
|
82
83
|
let unexpectedShutdown = false;
|
|
83
84
|
let exiting = false;
|
|
@@ -111,12 +112,17 @@ function getPackageVersion() {
|
|
|
111
112
|
process.on("exit", () => {
|
|
112
113
|
exiting = true;
|
|
113
114
|
if (proc && !proc.killed) {
|
|
114
|
-
|
|
115
|
+
if (telemetryMode !== 'off') {
|
|
116
|
+
console.warn("Desktop SDK received exit signal and is still running, killing the process.");
|
|
117
|
+
}
|
|
115
118
|
proc.kill();
|
|
116
119
|
proc = null;
|
|
117
120
|
}
|
|
118
121
|
});
|
|
119
122
|
function appendError(error) {
|
|
123
|
+
if (telemetryMode !== 'full') {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
120
126
|
lastErrorOut.push(error);
|
|
121
127
|
if (lastErrorOut.length > 100) {
|
|
122
128
|
lastErrorOut.shift();
|
|
@@ -131,7 +137,7 @@ function flushLogBuffer() {
|
|
|
131
137
|
// and know that Nick and Tucker spent at least 10 minutes debating this
|
|
132
138
|
for (const idx in buf) {
|
|
133
139
|
const { level, log, echo } = buf[idx];
|
|
134
|
-
doLog(level, [log], echo);
|
|
140
|
+
doLog(level, { full: () => [log] }, echo);
|
|
135
141
|
}
|
|
136
142
|
}
|
|
137
143
|
function isPlainObject(value) {
|
|
@@ -175,8 +181,16 @@ function sortedStringify(value, replacer, space) {
|
|
|
175
181
|
}
|
|
176
182
|
return JSON.stringify(normalize(value), replacer, space);
|
|
177
183
|
}
|
|
178
|
-
async function doLog(level,
|
|
184
|
+
async function doLog(level, messages, echo = true) {
|
|
185
|
+
if (telemetryMode === 'off') {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const render = telemetryMode === 'limited' && messages.limited !== true ? messages.limited : messages.full;
|
|
189
|
+
if (!render) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
179
192
|
try {
|
|
193
|
+
const log = render();
|
|
180
194
|
const levelMap = {
|
|
181
195
|
"info": "log",
|
|
182
196
|
"warning": "warn",
|
|
@@ -186,6 +200,9 @@ async function doLog(level, log, echo = true) {
|
|
|
186
200
|
const consoleMethod = console[levelMap[level] ?? "log"];
|
|
187
201
|
consoleMethod(...log);
|
|
188
202
|
}
|
|
203
|
+
if (telemetryMode === 'limited') {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
189
206
|
const logPayload = {
|
|
190
207
|
log: log.join(" "),
|
|
191
208
|
level: level,
|
|
@@ -201,25 +218,27 @@ async function doLog(level, log, echo = true) {
|
|
|
201
218
|
delete logBuffer[idx];
|
|
202
219
|
}
|
|
203
220
|
}
|
|
204
|
-
catch
|
|
221
|
+
catch {
|
|
205
222
|
if (proc?.exitCode === 0 || exiting) {
|
|
206
223
|
return;
|
|
207
224
|
}
|
|
208
|
-
|
|
225
|
+
if (telemetryMode === 'full' || telemetryMode === 'limited') {
|
|
226
|
+
console.error("Failed to send log to Desktop SDK");
|
|
227
|
+
}
|
|
209
228
|
}
|
|
210
229
|
}
|
|
211
230
|
function log(...log) {
|
|
212
|
-
doLog("info", log);
|
|
231
|
+
doLog("info", { full: () => log });
|
|
213
232
|
}
|
|
214
233
|
function logWarning(...log) {
|
|
215
|
-
doLog("warning", log);
|
|
234
|
+
doLog("warning", { full: () => log });
|
|
216
235
|
}
|
|
217
236
|
function logError(...log) {
|
|
218
|
-
doLog("error", log);
|
|
237
|
+
doLog("error", { full: () => log });
|
|
219
238
|
}
|
|
220
239
|
function emitEvent(type, payload) {
|
|
221
240
|
if (type !== "upload-progress" && type !== "realtime-event" && type !== "log") {
|
|
222
|
-
doLog("info", ["Receiving event: " + type + " | " + sortedStringify(payload)], false);
|
|
241
|
+
doLog("info", { full: () => ["Receiving event: " + type + " | " + sortedStringify(payload)] }, false);
|
|
223
242
|
}
|
|
224
243
|
for (const listener of listeners) {
|
|
225
244
|
if (listener.type === type) {
|
|
@@ -315,7 +334,7 @@ function flushPendingStdinWrites() {
|
|
|
315
334
|
activeDrainWriteSequence = null;
|
|
316
335
|
waitingForStdinDrain = false;
|
|
317
336
|
flushingPendingStdinWrites = false;
|
|
318
|
-
if (drainStartMs !== null && drainStartIso) {
|
|
337
|
+
if (telemetryMode === 'full' && drainStartMs !== null && drainStartIso) {
|
|
319
338
|
const drainStopIso = new Date(drainStopMs).toISOString();
|
|
320
339
|
const durationMs = drainStopMs - drainStartMs;
|
|
321
340
|
void enqueueCommand("log", {
|
|
@@ -326,10 +345,18 @@ function flushPendingStdinWrites() {
|
|
|
326
345
|
if (proc?.exitCode === 0 || exiting) {
|
|
327
346
|
return;
|
|
328
347
|
}
|
|
329
|
-
|
|
348
|
+
if (telemetryMode === 'full') {
|
|
349
|
+
console.error("Failed to enqueue stdin drain log", error.stack, error.message);
|
|
350
|
+
}
|
|
330
351
|
});
|
|
331
352
|
return;
|
|
332
353
|
}
|
|
354
|
+
if (telemetryMode === 'limited' && drainStartMs !== null) {
|
|
355
|
+
void doLog("info", {
|
|
356
|
+
full: () => [],
|
|
357
|
+
limited: () => [`stdin drain completed | durationMs=${drainStopMs - drainStartMs} | blockedWriteSequence=${drainWriteSequence ?? "unknown"}`]
|
|
358
|
+
});
|
|
359
|
+
}
|
|
333
360
|
flushPendingStdinWrites();
|
|
334
361
|
});
|
|
335
362
|
return;
|
|
@@ -383,7 +410,7 @@ function enqueueCommand(command, params = {}, options = {}) {
|
|
|
383
410
|
const payloadStr = JSON.stringify(payload);
|
|
384
411
|
enqueueStdinWrite({ command, commandId, data: payloadStr + "\n", writeSequence }, options.front ?? false);
|
|
385
412
|
if (!options.suppressSendLog && command !== "log") {
|
|
386
|
-
doLog("info", [`Sending command [${writeSequence}]: ` + payloadStr], false);
|
|
413
|
+
doLog("info", { full: () => [`Sending command [${writeSequence}]: ` + payloadStr] }, false);
|
|
387
414
|
}
|
|
388
415
|
});
|
|
389
416
|
}
|
|
@@ -394,7 +421,10 @@ function startProcess() {
|
|
|
394
421
|
}
|
|
395
422
|
const exe_path = exe_paths.find(fs.existsSync);
|
|
396
423
|
if (!exe_path) {
|
|
397
|
-
|
|
424
|
+
void doLog("error", {
|
|
425
|
+
full: () => ["Desktop SDK: Couldn't launch! This is likely an issue with the build tool you're using."],
|
|
426
|
+
limited: true
|
|
427
|
+
});
|
|
398
428
|
for (const exe_path of exe_paths) {
|
|
399
429
|
logError("Tried:", exe_path);
|
|
400
430
|
}
|
|
@@ -442,7 +472,7 @@ function startProcess() {
|
|
|
442
472
|
fs.mkdirSync(gst_dump_dir);
|
|
443
473
|
}
|
|
444
474
|
catch (e) {
|
|
445
|
-
|
|
475
|
+
void doLog("error", { full: () => ["Failed to create gst dump dir:", String(e)] });
|
|
446
476
|
}
|
|
447
477
|
}
|
|
448
478
|
// The diarization debug dashboard parses smart_annotator's per-word
|
|
@@ -465,6 +495,13 @@ function startProcess() {
|
|
|
465
495
|
// MallocStackLogging: "1",
|
|
466
496
|
// MallocStackLoggingNoCompact: "1",
|
|
467
497
|
...envExtra,
|
|
498
|
+
RECALL_DSDK_TELEMETRY_MODE: telemetryMode,
|
|
499
|
+
...(telemetryMode !== 'full' ? {
|
|
500
|
+
GST_DEBUG: "0",
|
|
501
|
+
GST_RECALL_DEBUG: "0",
|
|
502
|
+
GST_DEBUG_DUMP_DOT_DIR: undefined,
|
|
503
|
+
RUST_BACKTRACE: "0",
|
|
504
|
+
} : {}),
|
|
468
505
|
}
|
|
469
506
|
});
|
|
470
507
|
const currentProc = proc;
|
|
@@ -473,7 +510,12 @@ function startProcess() {
|
|
|
473
510
|
return;
|
|
474
511
|
}
|
|
475
512
|
// Do not use logError here: it sends a command through this same stdin.
|
|
476
|
-
|
|
513
|
+
if (telemetryMode === 'full') {
|
|
514
|
+
console.error(`Desktop SDK: stdin stream error: ${error.stack ?? error.message}`);
|
|
515
|
+
}
|
|
516
|
+
else if (telemetryMode === 'limited') {
|
|
517
|
+
console.error("Desktop SDK: stdin stream error");
|
|
518
|
+
}
|
|
477
519
|
resetPendingStdinWrites();
|
|
478
520
|
flushPendingCommands(new Error(`Desktop SDK stdin error: ${error.message}`));
|
|
479
521
|
if (currentProc.exitCode === null && !currentProc.killed) {
|
|
@@ -515,11 +557,14 @@ function startProcess() {
|
|
|
515
557
|
}
|
|
516
558
|
}
|
|
517
559
|
catch (err) {
|
|
518
|
-
|
|
560
|
+
void doLog("error", {
|
|
561
|
+
full: () => ["Desktop SDK: Failed to parse incoming data:", String(err)],
|
|
562
|
+
limited: () => ["Desktop SDK: Failed to parse incoming data"]
|
|
563
|
+
});
|
|
519
564
|
}
|
|
520
565
|
}
|
|
521
566
|
else {
|
|
522
|
-
if (process.env.RECALLAI_DESKTOP_SDK_DEV) {
|
|
567
|
+
if (telemetryMode === 'full' && process.env.RECALLAI_DESKTOP_SDK_DEV) {
|
|
523
568
|
console.log(line);
|
|
524
569
|
}
|
|
525
570
|
}
|
|
@@ -528,7 +573,7 @@ function startProcess() {
|
|
|
528
573
|
rlStdout.on('line', onLine);
|
|
529
574
|
rlStderr.on('line', (line) => {
|
|
530
575
|
appendError(line);
|
|
531
|
-
if (process.env.RECALLAI_DESKTOP_SDK_DEV) {
|
|
576
|
+
if (telemetryMode === 'full' && process.env.RECALLAI_DESKTOP_SDK_DEV) {
|
|
532
577
|
console.error(line);
|
|
533
578
|
}
|
|
534
579
|
});
|
|
@@ -549,7 +594,10 @@ function startProcess() {
|
|
|
549
594
|
type: 'process',
|
|
550
595
|
message: `The Desktop SDK server process has failed to start or exited improperly.`
|
|
551
596
|
});
|
|
552
|
-
|
|
597
|
+
void doLog("error", {
|
|
598
|
+
full: () => [`Desktop SDK: Process error: ${error.message}`],
|
|
599
|
+
limited: () => ["Desktop SDK: Process error"]
|
|
600
|
+
});
|
|
553
601
|
});
|
|
554
602
|
proc.on('close', async (code, signal) => {
|
|
555
603
|
if (proc !== currentProc) {
|
|
@@ -566,10 +614,12 @@ function startProcess() {
|
|
|
566
614
|
rlStdout = null;
|
|
567
615
|
rlStderr = null;
|
|
568
616
|
if (code === 0 || signal === 'SIGINT' || signal === 'SIGTERM' || exiting) {
|
|
569
|
-
|
|
617
|
+
const message = `Desktop SDK: Process closed with code ${code}, signal ${signal}, exiting ${exiting}`;
|
|
618
|
+
void doLog("info", { full: () => [message], limited: true });
|
|
570
619
|
return;
|
|
571
620
|
}
|
|
572
|
-
|
|
621
|
+
const message = `Desktop SDK: Process exited with code ${code}, signal ${signal}, exiting ${exiting}`;
|
|
622
|
+
void doLog("error", { full: () => [message], limited: true });
|
|
573
623
|
emitEvent('error', {
|
|
574
624
|
type: 'process',
|
|
575
625
|
message: "The Desktop SDK server process exited unexpectedly."
|
|
@@ -577,10 +627,16 @@ function startProcess() {
|
|
|
577
627
|
unexpectedShutdown = true;
|
|
578
628
|
if (lastOptions.restartOnError && remainingAutomaticRestarts > 0) {
|
|
579
629
|
remainingAutomaticRestarts--;
|
|
580
|
-
|
|
581
|
-
|
|
630
|
+
const restartMessage = `Automatically restarting Desktop SDK due to unexpected exit! Automatic restarts left: ${remainingAutomaticRestarts}`;
|
|
631
|
+
void doLog("error", { full: () => [restartMessage], limited: true });
|
|
632
|
+
void doLog("error", { full: () => [`Last error output from Desktop SDK:\n${lastErrorOut.join("\n")}`] });
|
|
582
633
|
lastErrorOut.length = 0;
|
|
583
|
-
doInit(lastOptions)
|
|
634
|
+
void doInit(lastOptions).catch((error) => {
|
|
635
|
+
void doLog("error", {
|
|
636
|
+
full: () => ["Desktop SDK: Automatic restart failed:", String(error)],
|
|
637
|
+
limited: () => ["Desktop SDK: Automatic restart failed"]
|
|
638
|
+
});
|
|
639
|
+
});
|
|
584
640
|
}
|
|
585
641
|
});
|
|
586
642
|
}
|
|
@@ -590,7 +646,10 @@ function sendCommand(command, params = {}) {
|
|
|
590
646
|
async function doInit(options) {
|
|
591
647
|
startProcess();
|
|
592
648
|
if (unexpectedShutdown) {
|
|
593
|
-
|
|
649
|
+
void doLog("error", {
|
|
650
|
+
full: () => ["Desktop SDK: Recovered from unexpected shutdown"],
|
|
651
|
+
limited: true
|
|
652
|
+
});
|
|
594
653
|
unexpectedShutdown = false;
|
|
595
654
|
}
|
|
596
655
|
await sendCommand("init", { config: JSON.stringify(options) });
|
|
@@ -610,13 +669,30 @@ async function doInit(options) {
|
|
|
610
669
|
* @see https://docs.recall.ai/docs/dsdk-supported-platforms
|
|
611
670
|
*/
|
|
612
671
|
async function init(options) {
|
|
672
|
+
if (options.telemetryMode !== undefined && !['full', 'limited', 'off'].includes(options.telemetryMode)) {
|
|
673
|
+
throw new Error("telemetryMode must be full, limited, or off");
|
|
674
|
+
}
|
|
675
|
+
if (options.anonymizeLogging !== undefined && typeof options.anonymizeLogging !== 'boolean') {
|
|
676
|
+
throw new Error("anonymizeLogging must be a boolean");
|
|
677
|
+
}
|
|
678
|
+
if (proc && proc.exitCode === null) {
|
|
679
|
+
throw new Error("The Desktop SDK is already started; call shutdown before initializing again");
|
|
680
|
+
}
|
|
681
|
+
telemetryMode = options.anonymizeLogging === true ? 'off' : options.telemetryMode ?? 'full';
|
|
682
|
+
if (telemetryMode !== 'full') {
|
|
683
|
+
logBuffer = [];
|
|
684
|
+
logIndex = 0;
|
|
685
|
+
lastErrorOut.length = 0;
|
|
686
|
+
}
|
|
613
687
|
if (process.platform !== "darwin" && process.platform !== "win32") {
|
|
614
688
|
throw new Error(`Platform ${process.platform} is not supported by Desktop SDK`);
|
|
615
689
|
}
|
|
616
690
|
const { api_url, apiUrl, dev } = options;
|
|
617
691
|
options.api_url = api_url ?? apiUrl ?? "https://api.recall.ai";
|
|
618
692
|
if (!dev && (!options.api_url || !options.api_url.startsWith("https"))) {
|
|
619
|
-
throw new Error(
|
|
693
|
+
throw new Error(telemetryMode === 'full'
|
|
694
|
+
? `apiUrl must be an https url, got: ${options.api_url}`
|
|
695
|
+
: "apiUrl must be an https url");
|
|
620
696
|
}
|
|
621
697
|
if (options.restartOnError === undefined) {
|
|
622
698
|
options.restartOnError = true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@recallai/desktop-sdk",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.38",
|
|
4
4
|
"description": "Recall Desktop SDK",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -20,5 +20,5 @@
|
|
|
20
20
|
"@types/node": "^24.2.0",
|
|
21
21
|
"typescript": "^5.3.3"
|
|
22
22
|
},
|
|
23
|
-
"commit_sha": "
|
|
23
|
+
"commit_sha": "82799f1ae5ad0c08f58c6605a6a73992325588ce"
|
|
24
24
|
}
|