@aglit-ai/cli 0.1.17089 → 0.1.17101
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/package.json +1 -1
- package/src/installation.cjs +1 -0
- package/src/mac-audio.cjs +38 -0
- package/src/updates.cjs +20 -4
package/package.json
CHANGED
package/src/installation.cjs
CHANGED
|
@@ -215,6 +215,7 @@ function start() {
|
|
|
215
215
|
fs.closeSync(log);
|
|
216
216
|
run('/usr/bin/open', ['-n', '-g', '-a', bundle,
|
|
217
217
|
'--env', 'AGLIT_USER_DATA_PATH=' + profile, '--env', 'AGLIT_ELECTRON_USER_DATA_PATH=' + profile,
|
|
218
|
+
...(env.PATH ? ['--env', 'PATH=' + env.PATH] : []),
|
|
218
219
|
'--stdout', path.join(root, 'runtime.log'), '--stderr', path.join(root, 'runtime.log'),
|
|
219
220
|
'--args', '--computer-use'], { env });
|
|
220
221
|
return { launched: true };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const fs = require('node:fs');
|
|
3
|
+
const { spawnSync } = require('node:child_process');
|
|
4
|
+
const driver = '/Library/Audio/Plug-Ins/HAL/BlackHole2ch.driver';
|
|
5
|
+
const signingRequirement = '=identifier "audio.existential.BlackHole2ch" and anchor apple generic and certificate leaf[subject.OU] = "Q5C99V536K"';
|
|
6
|
+
function run(file, args, options = {}) {
|
|
7
|
+
const result = spawnSync(file, args, { encoding: 'utf8', timeout: 20000, shell: false, ...options });
|
|
8
|
+
if (result.error || result.status !== 0) throw Error('macOS audio setup failed; existing audio configuration was preserved.');
|
|
9
|
+
return result.stdout || '';
|
|
10
|
+
}
|
|
11
|
+
function status() {
|
|
12
|
+
if (process.platform !== 'darwin') return { supported: false, installed: false };
|
|
13
|
+
if (!fs.existsSync(driver)) return { supported: true, installed: false };
|
|
14
|
+
const stat = fs.lstatSync(driver);
|
|
15
|
+
if (!stat.isDirectory() || stat.isSymbolicLink() || stat.uid !== 0) throw Error('Existing BlackHole driver needs review; it will not be replaced.');
|
|
16
|
+
run('/usr/bin/codesign', ['--verify', '--deep', '--strict', '-R', signingRequirement, driver]);
|
|
17
|
+
const version = run('/usr/libexec/PlistBuddy', ['-c', 'Print :CFBundleShortVersionString', driver + '/Contents/Info.plist']).trim();
|
|
18
|
+
const devices = run('/usr/sbin/system_profiler', ['SPAudioDataType', '-json', '-timeout', '10']);
|
|
19
|
+
return { supported: true, installed: true, version, restartRequired: !devices.includes('"BlackHole 2ch"') };
|
|
20
|
+
}
|
|
21
|
+
function setup({ interactive = false } = {}) {
|
|
22
|
+
const current = status();
|
|
23
|
+
if (!current.supported || current.installed) return current;
|
|
24
|
+
// Preserve other variants: the vendor installer may alter all BlackHole bundles.
|
|
25
|
+
if (fs.readdirSync('/Library/Audio/Plug-Ins/HAL').some(name => /^BlackHole.*ch\.driver$/.test(name)))
|
|
26
|
+
throw Error('Another BlackHole variant is installed. Select it in the remote app instead of replacing it.');
|
|
27
|
+
if (!interactive) return { ...current, actionRequired: 'Run aglit init in an interactive terminal to install BlackHole 2ch.' };
|
|
28
|
+
const brew = ['/opt/homebrew/bin/brew', '/usr/local/bin/brew'].find(file => fs.existsSync(file));
|
|
29
|
+
if (!brew) return { ...current, actionRequired: 'Install Homebrew, then rerun aglit init. See https://brew.sh/.' };
|
|
30
|
+
// Homebrew verifies the official cask package. Administrator approval stays in
|
|
31
|
+
// the user's terminal. Never restart CoreAudio or change their default devices.
|
|
32
|
+
run(brew, ['install', '--cask', 'homebrew/cask/blackhole-2ch'], { stdio: 'inherit', timeout: 180000,
|
|
33
|
+
env: { ...process.env, HOMEBREW_NO_AUTO_UPDATE: '1', HOMEBREW_NO_INSTALL_CLEANUP: '1' } });
|
|
34
|
+
const installed = status();
|
|
35
|
+
if (!installed.installed) throw Error('BlackHole installation did not produce a verified driver.');
|
|
36
|
+
return installed;
|
|
37
|
+
}
|
|
38
|
+
module.exports = { status, setup };
|
package/src/updates.cjs
CHANGED
|
@@ -320,13 +320,29 @@ function removeHold(runtime) {
|
|
|
320
320
|
hold.sha256 === runtime.sha256 && hold.sourceCommit === runtime.sourceCommit && hold.root === installation.root && hold.profile === installation.profile, 'Candidate activation hold changed');
|
|
321
321
|
fs.unlinkSync(file);
|
|
322
322
|
}
|
|
323
|
-
async function acceptCandidate(config, pid,
|
|
323
|
+
async function acceptCandidate(config, pid, runtime, original) {
|
|
324
|
+
const version = runtime.version;
|
|
324
325
|
// The native contract makes this action idempotent for one running occurrence.
|
|
325
326
|
// Retry only this explicit acknowledgement, never general mutation commands.
|
|
326
327
|
let result;
|
|
327
328
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
328
329
|
try { result = await control(config, 'update-accept'); break; }
|
|
329
|
-
catch (error) {
|
|
330
|
+
catch (error) {
|
|
331
|
+
if (attempt === 1) {
|
|
332
|
+
// Published runtimes before this native acknowledgement can finish a
|
|
333
|
+
// signed-out migration only. An active account still requires its native
|
|
334
|
+
// continuity acknowledgement; never accept a lost or changed identity.
|
|
335
|
+
if (error.message !== 'Unknown Computer Use command or field' || original.email !== null || original.enabled !== false) throw error;
|
|
336
|
+
const observed = await control(config, 'status');
|
|
337
|
+
need(observed.pid === pid && observed.connected === false && continuity(observed, original, runtime), 'Signed-out migration continuity differs');
|
|
338
|
+
const hold = privateJson(path.join(installation.root, 'update-activation.json'));
|
|
339
|
+
need(JSON.stringify(hold) === JSON.stringify(activationHold(runtime, original)), 'Signed-out migration hold differs');
|
|
340
|
+
installation.verifyRuntime(runtime.executable, runtime);
|
|
341
|
+
removeHold(runtime);
|
|
342
|
+
return {accepted: true, pid, version, legacySignedOut: true};
|
|
343
|
+
}
|
|
344
|
+
await delay(250);
|
|
345
|
+
}
|
|
330
346
|
}
|
|
331
347
|
need(result?.accepted === true && result.pid === pid && result.version === version, 'Updated runtime did not accept its continuity hold');
|
|
332
348
|
return result;
|
|
@@ -352,7 +368,7 @@ async function recoverActivation(ownedLock = false) {
|
|
|
352
368
|
await delay(1000);
|
|
353
369
|
} while (Date.now() < deadline && !runtimeStopped(current));
|
|
354
370
|
if (measured) {
|
|
355
|
-
if (fs.existsSync(holdFile)) { await acceptCandidate(config, measured.pid, tx.runtime.
|
|
371
|
+
if (fs.existsSync(holdFile)) { await acceptCandidate(config, measured.pid, tx.runtime, tx.original); }
|
|
356
372
|
fs.unlinkSync(file); const pending = path.join(installation.root, 'pending-update.json'); if (fs.existsSync(pending)) fs.unlinkSync(pending);
|
|
357
373
|
return {recovered: true, accepted: true, runtimePid: measured.pid};
|
|
358
374
|
}
|
|
@@ -471,7 +487,7 @@ async function update({check = false, channel} = {}) {
|
|
|
471
487
|
} catch { /* Allow the replacement account/provider settings to restore. */ }
|
|
472
488
|
} while (live(launched.pid) && Date.now() < deadline);
|
|
473
489
|
need(replacement, 'Updated Desktop continuity did not match before its readiness deadline'); cancelled();
|
|
474
|
-
await acceptCandidate(config, launched.pid, runtime
|
|
490
|
+
await acceptCandidate(config, launched.pid, runtime, original);
|
|
475
491
|
accepted = true;
|
|
476
492
|
let windowRestored = true;
|
|
477
493
|
if ((retiring?.mode || original.mode) === 'headed') { try { await control(config, 'window', {mode: 'headed'}); } catch { windowRestored = false; } }
|