@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 +26 -0
- package/index.d.ts +3 -0
- package/index.js +73 -7
- package/package.json +3 -3
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 + " | " +
|
|
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
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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.
|
|
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
|
|
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": "
|
|
23
|
+
"commit_sha": "3b3394ac612c9f13bd39bf245ddb8499a0092453"
|
|
24
24
|
}
|