livedesk 0.1.681 → 0.1.683
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/electron/after-pack.cjs +41 -0
- package/electron/macos-permission-onboarding.mjs +21 -14
- package/electron/macos-screen-recording-permission.swift +13 -0
- package/electron/main.mjs +79 -15
- package/package.json +1 -1
- package/web/dist/app.html +1 -1
- package/web/dist/app.webmanifest +1 -1
- package/web/dist/assets/{AgentSettingsTab-DNeJ6MYv.js → AgentSettingsTab-BPa5FURp.js} +1 -1
- package/web/dist/assets/{AgentsPage-BecUuDhp.js → AgentsPage-CdfRk8mz.js} +1 -1
- package/web/dist/assets/{CaptureGallery-BGrMCJyi.js → CaptureGallery-D-GYgz_z.js} +1 -1
- package/web/dist/assets/{HubApp-CVaXT8PJ.js → HubApp-BOX09IGB.js} +3 -3
- package/web/dist/assets/{MonitorStackIcon-Bnu-aE9X.js → MonitorStackIcon-q_7f5mZs.js} +1 -1
- package/web/dist/assets/{SettingsPage-RIiBLrwL.js → SettingsPage-DazTNBy_.js} +1 -1
- package/web/dist/assets/{ShareFilesPage-4_r2kZEK.js → ShareFilesPage-CrUy6XJN.js} +1 -1
- package/web/dist/assets/{SupportPage-BuucN-JV.js → SupportPage-BD0JgKlO.js} +1 -1
- package/web/dist/assets/{VuvoDeskApp-DQavlXQk.js → VuvoDeskApp-TC24i27P.js} +1 -1
- package/web/dist/assets/{app-C0wgDWxx.js → app-CEj6iA0M.js} +2 -2
- package/web/dist/assets/{main-DNCd9BVT.js → main-DK6ReJk8.js} +2 -2
- package/web/dist/index.html +2 -2
- package/web/dist/sw.js +2 -2
- package/web/dist/vuvodesk-build-evidence.json +33 -33
package/electron/after-pack.cjs
CHANGED
|
@@ -1,12 +1,53 @@
|
|
|
1
|
+
const { execFileSync } = require('node:child_process');
|
|
1
2
|
const { chmodSync, existsSync, statSync } = require('node:fs');
|
|
2
3
|
const { dirname, join } = require('node:path');
|
|
3
4
|
|
|
5
|
+
const MACOS_SCREEN_PERMISSION_HELPER = 'vuvodesk-macos-screen-permission';
|
|
6
|
+
|
|
7
|
+
function buildMacosScreenPermissionHelper(context) {
|
|
8
|
+
const sourcePath = join(__dirname, 'macos-screen-recording-permission.swift');
|
|
9
|
+
const resourcesRoot = join(
|
|
10
|
+
context.appOutDir,
|
|
11
|
+
`${context.packager.appInfo.productFilename}.app`,
|
|
12
|
+
'Contents',
|
|
13
|
+
'Resources'
|
|
14
|
+
);
|
|
15
|
+
const outputPath = join(resourcesRoot, MACOS_SCREEN_PERMISSION_HELPER);
|
|
16
|
+
const target = context.arch === 1 || context.arch === 'x64'
|
|
17
|
+
? 'x86_64-apple-macos10.15'
|
|
18
|
+
: context.arch === 3 || context.arch === 'arm64'
|
|
19
|
+
? 'arm64-apple-macos11.0'
|
|
20
|
+
: '';
|
|
21
|
+
if (!target) {
|
|
22
|
+
throw new Error(`Unsupported macOS permission-helper architecture: ${context.arch}.`);
|
|
23
|
+
}
|
|
24
|
+
execFileSync('/usr/bin/xcrun', [
|
|
25
|
+
'swiftc',
|
|
26
|
+
'-parse-as-library',
|
|
27
|
+
'-O',
|
|
28
|
+
'-target',
|
|
29
|
+
target,
|
|
30
|
+
'-framework',
|
|
31
|
+
'CoreGraphics',
|
|
32
|
+
sourcePath,
|
|
33
|
+
'-o',
|
|
34
|
+
outputPath
|
|
35
|
+
], { stdio: 'inherit' });
|
|
36
|
+
chmodSync(outputPath, 0o755);
|
|
37
|
+
const executableMode = statSync(outputPath).mode & 0o777;
|
|
38
|
+
if ((executableMode & 0o111) !== 0o111) {
|
|
39
|
+
throw new Error(`Packaged macOS permission helper must be executable; mode=${executableMode.toString(8)}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
4
43
|
module.exports = async function afterPack(context) {
|
|
5
44
|
const platform = String(context.electronPlatformName || '');
|
|
6
45
|
if (platform !== 'linux' && platform !== 'darwin') {
|
|
7
46
|
return;
|
|
8
47
|
}
|
|
9
48
|
|
|
49
|
+
if (platform === 'darwin') buildMacosScreenPermissionHelper(context);
|
|
50
|
+
|
|
10
51
|
const unpackedRoot = platform === 'darwin'
|
|
11
52
|
? join(
|
|
12
53
|
context.appOutDir,
|
|
@@ -27,7 +27,7 @@ function claimOnce(path) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export function createMacosPermissionOnboardingOwner({
|
|
30
|
-
|
|
30
|
+
requestScreenRecording,
|
|
31
31
|
systemPreferences,
|
|
32
32
|
stateRoot,
|
|
33
33
|
runtimeStateDir,
|
|
@@ -59,6 +59,19 @@ export function createMacosPermissionOnboardingOwner({
|
|
|
59
59
|
'macos-screen-recording-requested-desktop-v1'
|
|
60
60
|
);
|
|
61
61
|
let primePromise = null;
|
|
62
|
+
let nativeMarkerClaimed = false;
|
|
63
|
+
let nativeMarkerError = '';
|
|
64
|
+
|
|
65
|
+
function claimNativePromptOwner() {
|
|
66
|
+
if (!supported || nativeMarkerClaimed) return nativeMarkerClaimed;
|
|
67
|
+
try {
|
|
68
|
+
claimOnce(nativeDesktopScreenMarkerPath);
|
|
69
|
+
nativeMarkerClaimed = true;
|
|
70
|
+
} catch {
|
|
71
|
+
nativeMarkerError = 'native-marker-unavailable';
|
|
72
|
+
}
|
|
73
|
+
return nativeMarkerClaimed;
|
|
74
|
+
}
|
|
62
75
|
|
|
63
76
|
function readScreenStatus() {
|
|
64
77
|
try {
|
|
@@ -99,12 +112,8 @@ export function createMacosPermissionOnboardingOwner({
|
|
|
99
112
|
return result;
|
|
100
113
|
}
|
|
101
114
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
claimOnce(nativeDesktopScreenMarkerPath);
|
|
105
|
-
} catch {
|
|
106
|
-
error = 'native-marker-unavailable';
|
|
107
|
-
}
|
|
115
|
+
claimNativePromptOwner();
|
|
116
|
+
let error = nativeMarkerError;
|
|
108
117
|
|
|
109
118
|
const screenBefore = readScreenStatus();
|
|
110
119
|
let screenRequested = false;
|
|
@@ -116,13 +125,10 @@ export function createMacosPermissionOnboardingOwner({
|
|
|
116
125
|
try {
|
|
117
126
|
if (claimOnce(screenMarkerPath)) {
|
|
118
127
|
screenRequested = true;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
thumbnailSize: { width: 0, height: 0 },
|
|
124
|
-
fetchWindowIcons: false
|
|
125
|
-
});
|
|
128
|
+
if (typeof requestScreenRecording !== 'function') {
|
|
129
|
+
throw new Error('macos-screen-requester-unavailable');
|
|
130
|
+
}
|
|
131
|
+
await requestScreenRecording();
|
|
126
132
|
}
|
|
127
133
|
} catch {
|
|
128
134
|
error ||= 'screen-request-failed';
|
|
@@ -164,6 +170,7 @@ export function createMacosPermissionOnboardingOwner({
|
|
|
164
170
|
}
|
|
165
171
|
|
|
166
172
|
return {
|
|
173
|
+
claimNativePromptOwner,
|
|
167
174
|
prime,
|
|
168
175
|
supported,
|
|
169
176
|
screenMarkerPath,
|
package/electron/main.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { app, autoUpdater as electronAutoUpdater, BrowserWindow, clipboard,
|
|
1
|
+
import { app, autoUpdater as electronAutoUpdater, BrowserWindow, clipboard, dialog, ipcMain, Menu, nativeImage, powerMonitor, safeStorage, shell, systemPreferences, Tray } from 'electron';
|
|
2
2
|
import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { dirname, join, resolve } from 'node:path';
|
|
@@ -95,7 +95,9 @@ const logDir = join(stateRoot, 'logs');
|
|
|
95
95
|
const logPath = join(logDir, 'desktop.log');
|
|
96
96
|
const authSessionPath = join(stateRoot, 'auth-session.json');
|
|
97
97
|
const authSessionBackupPath = join(stateRoot, 'auth-session.backup.json');
|
|
98
|
-
const runtimeStateDir = process.env.LIVEDESK_STATE_DIR || join(homedir(), '.livedesk');
|
|
98
|
+
const runtimeStateDir = process.env.LIVEDESK_STATE_DIR || join(homedir(), '.livedesk');
|
|
99
|
+
const MACOS_SCREEN_PERMISSION_HELPER = 'vuvodesk-macos-screen-permission';
|
|
100
|
+
const MACOS_SCREEN_PERMISSION_TIMEOUT_MS = 120000;
|
|
99
101
|
try { app.setPath('userData', stateRoot); } catch { /* Electron may reject late path changes in embedded test hosts. */ }
|
|
100
102
|
const appPath = app.getAppPath();
|
|
101
103
|
const unpackedAppPath = appPath.replace(/app\.asar([\\/]|$)/, 'app.asar.unpacked$1');
|
|
@@ -180,6 +182,58 @@ let lastKnownDesktopSession = null;
|
|
|
180
182
|
let desktopClipboardOwner = null;
|
|
181
183
|
let runtimeWindowLoadOwner = null;
|
|
182
184
|
let desktopAutoStartOwner = null;
|
|
185
|
+
let macosPermissionOnboardingOwner = null;
|
|
186
|
+
let macosScreenPermissionChild = null;
|
|
187
|
+
|
|
188
|
+
function requestMacosScreenRecordingAccess() {
|
|
189
|
+
if (process.platform !== 'darwin' || !app.isPackaged) return Promise.resolve(false);
|
|
190
|
+
const helperPath = join(process.resourcesPath, MACOS_SCREEN_PERMISSION_HELPER);
|
|
191
|
+
if (!existsSync(helperPath)) {
|
|
192
|
+
return Promise.reject(new Error('macos-screen-permission-helper-unavailable'));
|
|
193
|
+
}
|
|
194
|
+
if (macosScreenPermissionChild) {
|
|
195
|
+
return Promise.reject(new Error('macos-screen-permission-helper-already-running'));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return new Promise((resolvePermission, rejectPermission) => {
|
|
199
|
+
const child = spawn(helperPath, [], {
|
|
200
|
+
stdio: ['ignore', 'ignore', 'ignore'],
|
|
201
|
+
windowsHide: true
|
|
202
|
+
});
|
|
203
|
+
macosScreenPermissionChild = child;
|
|
204
|
+
let settled = false;
|
|
205
|
+
const finish = (callback, value) => {
|
|
206
|
+
if (settled) return;
|
|
207
|
+
settled = true;
|
|
208
|
+
clearTimeout(timeout);
|
|
209
|
+
if (macosScreenPermissionChild === child) macosScreenPermissionChild = null;
|
|
210
|
+
callback(value);
|
|
211
|
+
};
|
|
212
|
+
const timeout = setTimeout(() => {
|
|
213
|
+
try { child.kill('SIGTERM'); } catch { /* already terminal */ }
|
|
214
|
+
finish(rejectPermission, new Error('macos-screen-permission-helper-timeout'));
|
|
215
|
+
}, MACOS_SCREEN_PERMISSION_TIMEOUT_MS);
|
|
216
|
+
timeout.unref?.();
|
|
217
|
+
child.once('error', error => finish(rejectPermission, error));
|
|
218
|
+
child.once('exit', (code, signal) => {
|
|
219
|
+
if (code === 0 || code === 2) {
|
|
220
|
+
finish(resolvePermission, code === 0);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
finish(
|
|
224
|
+
rejectPermission,
|
|
225
|
+
new Error(`macos-screen-permission-helper-exit-${code ?? 'signal'}-${signal || 'none'}`)
|
|
226
|
+
);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function stopMacosScreenPermissionRequest() {
|
|
232
|
+
const child = macosScreenPermissionChild;
|
|
233
|
+
macosScreenPermissionChild = null;
|
|
234
|
+
if (!child || child.killed) return;
|
|
235
|
+
try { child.kill('SIGTERM'); } catch { /* already terminal */ }
|
|
236
|
+
}
|
|
183
237
|
const desktopAuthInvalidationGuard = createDesktopAuthInvalidationGuard();
|
|
184
238
|
const installerQuitGate = createInstallerQuitGate({
|
|
185
239
|
requestQuit: () => app.quit()
|
|
@@ -1190,10 +1244,12 @@ function showWindow() {
|
|
|
1190
1244
|
runtimeWindowLoadOwner?.start('window-show');
|
|
1191
1245
|
if (mainWindow.isMinimized()) mainWindow.restore();
|
|
1192
1246
|
mainWindow.show();
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1247
|
+
if (process.platform === 'darwin') app.focus({ steal: true });
|
|
1248
|
+
mainWindow.focus();
|
|
1249
|
+
if (mainWindow.isFocused()) void macosPermissionOnboardingOwner?.prime();
|
|
1250
|
+
if (!mainWindow.webContents.isDestroyed()) mainWindow.webContents.invalidate();
|
|
1251
|
+
requestDesktopResumeAuthRecovery('window-show');
|
|
1252
|
+
}
|
|
1197
1253
|
|
|
1198
1254
|
function createMainWindow({ showOnInitialLoad = true } = {}) {
|
|
1199
1255
|
const iconPath = appResource('electron', 'icon.png');
|
|
@@ -1256,7 +1312,10 @@ function createMainWindow({ showOnInitialLoad = true } = {}) {
|
|
|
1256
1312
|
event.preventDefault();
|
|
1257
1313
|
if (!window.isDestroyed()) window.setTitle(appWindowTitle());
|
|
1258
1314
|
});
|
|
1259
|
-
window.on('focus', () =>
|
|
1315
|
+
window.on('focus', () => {
|
|
1316
|
+
requestDesktopResumeAuthRecovery('window-focus');
|
|
1317
|
+
void macosPermissionOnboardingOwner?.prime();
|
|
1318
|
+
});
|
|
1260
1319
|
window.webContents.on('will-navigate', (event, url) => {
|
|
1261
1320
|
if (isAllowedRuntimeUrl(url) || url === DESKTOP_RUNTIME_RECOVERY_PAGE_URL) return;
|
|
1262
1321
|
event.preventDefault();
|
|
@@ -1550,8 +1609,8 @@ if (!app.requestSingleInstanceLock()) {
|
|
|
1550
1609
|
log
|
|
1551
1610
|
});
|
|
1552
1611
|
desktopAutoStartOwner.reconcile('startup');
|
|
1553
|
-
|
|
1554
|
-
|
|
1612
|
+
macosPermissionOnboardingOwner = createMacosPermissionOnboardingOwner({
|
|
1613
|
+
requestScreenRecording: requestMacosScreenRecordingAccess,
|
|
1555
1614
|
systemPreferences,
|
|
1556
1615
|
stateRoot,
|
|
1557
1616
|
runtimeStateDir,
|
|
@@ -1559,10 +1618,11 @@ if (!app.requestSingleInstanceLock()) {
|
|
|
1559
1618
|
bundleIdentifier: VUVODESK_MAC_BUNDLE_IDENTIFIER,
|
|
1560
1619
|
log
|
|
1561
1620
|
});
|
|
1562
|
-
//
|
|
1563
|
-
//
|
|
1564
|
-
//
|
|
1565
|
-
|
|
1621
|
+
// Claim native prompt ownership before RemoteFast starts, but wait until
|
|
1622
|
+
// the signed GUI app has a visible, focused window before asking macOS to
|
|
1623
|
+
// present consent UI. The asynchronous request never holds Hub/Client
|
|
1624
|
+
// startup or an automatic hidden launch.
|
|
1625
|
+
macosPermissionOnboardingOwner.claimNativePromptOwner();
|
|
1566
1626
|
if (process.argv.includes('--updated')) {
|
|
1567
1627
|
log(
|
|
1568
1628
|
`desktop update event=post-install-startup platform=${process.platform} version=${app.getVersion()} marker=updated`,
|
|
@@ -1668,9 +1728,13 @@ if (!app.requestSingleInstanceLock()) {
|
|
|
1668
1728
|
event.preventDefault();
|
|
1669
1729
|
return;
|
|
1670
1730
|
}
|
|
1671
|
-
if (installerQuitDecision === InstallerQuitDecision.ALLOW)
|
|
1731
|
+
if (installerQuitDecision === InstallerQuitDecision.ALLOW) {
|
|
1732
|
+
stopMacosScreenPermissionRequest();
|
|
1733
|
+
return;
|
|
1734
|
+
}
|
|
1672
1735
|
event.preventDefault();
|
|
1673
|
-
recurringProductUpdates?.stop();
|
|
1736
|
+
recurringProductUpdates?.stop();
|
|
1737
|
+
stopMacosScreenPermissionRequest();
|
|
1674
1738
|
quitSequenceStarted = true;
|
|
1675
1739
|
isQuitting = true;
|
|
1676
1740
|
void quiesceDesktopAuthOwner('application-quit').then(() => {
|
package/package.json
CHANGED
package/web/dist/app.html
CHANGED
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
.vuvodesk-static-boot [hidden] { display: none; }
|
|
53
53
|
@keyframes vuvodesk-static-boot-spin { to { transform: rotate(360deg); } }
|
|
54
54
|
</style>
|
|
55
|
-
<script type="module" crossorigin src="/assets/app-
|
|
55
|
+
<script type="module" crossorigin src="/assets/app-CEj6iA0M.js" data-vuvodesk-entry></script>
|
|
56
56
|
<link rel="modulepreload" crossorigin href="/assets/preload-helper-DD1OZmLC.js">
|
|
57
57
|
<link rel="modulepreload" crossorigin href="/assets/pwa-bootstrap-ljOQTt2e.js">
|
|
58
58
|
</head>
|
package/web/dist/app.webmanifest
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as t}from"./pwa-startup-DvbrYEQi.js";import{r as c,d as A,S as q,T as I,e as z}from"./icons-CuXJn-Hz.js";import{h as x}from"./MonitorStackIcon-
|
|
1
|
+
import{j as t}from"./pwa-startup-DvbrYEQi.js";import{r as c,d as A,S as q,T as I,e as z}from"./icons-CuXJn-Hz.js";import{h as x}from"./MonitorStackIcon-q_7f5mZs.js";import"./pwa-bootstrap-ljOQTt2e.js";const E={enabled:!0};function w(i){return{enabled:i?.enabled===!0}}async function L(i,p,f){let l=null;for(let s=0;s<2;s+=1){const g=await x("/api/settings",{signal:f},p);if(g.settings.agent?.enabled===i)return;try{await x("/api/settings",{method:"PATCH",signal:f,body:JSON.stringify({revision:g.revision,agent:{enabled:i}})},p);return}catch(a){if(l=a,s!==0||!String(a instanceof Error?a.message:a).startsWith("409 "))throw a}}throw l}function H({hubUrl:i,showToast:p}){const[f,l]=c.useState(E),[s,g]=c.useState(null),[a,m]=c.useState(""),[j,v]=c.useState(""),[y,d]=c.useState(""),b=c.useRef(0),u=c.useRef(null);c.useEffect(()=>{let e=!0;u.current?.abort();const n=new AbortController;u.current=n;const h=++b.current;return g(null),l(E),m(""),d(""),v(""),x("/api/settings/agent",{signal:n.signal},i).then(o=>{!e||n.signal.aborted||h!==b.current||(g(o.settings),l(w(o.settings)))}).catch(o=>{e&&!n.signal.aborted&&h===b.current&&d(o instanceof Error?o.message:String(o))}),()=>{e=!1,n.abort(),u.current===n&&(u.current=null)}},[i]);const k=(e,n)=>l(h=>({...h,[e]:n})),C=e=>{g(e),l(w(e))},S=()=>({generation:b.current,controller:u.current}),r=e=>e.generation===b.current&&e.controller!==null&&e.controller===u.current&&!e.controller.signal.aborted,R=async()=>{if(!s){d("Agent settings are not available yet.");return}const e=S();if(r(e)){m("save"),d(""),v("");try{if(await L(f.enabled,i,e.controller.signal),!r(e))return;const n=await x("/api/settings/agent",{signal:e.controller.signal},i);if(!r(e))return;C(n.settings),v("Codex Agent settings saved.")}catch(n){r(e)&&d(n instanceof Error?n.message:String(n))}finally{r(e)&&m("")}}},T=async()=>{const e=S();if(r(e)){m("test"),d(""),v("");try{const n=await x("/api/settings/agent/test",{method:"POST",signal:e.controller.signal,body:JSON.stringify({})},i);if(!r(e))return;const h=await x("/api/settings/agent",{signal:e.controller.signal},i);if(!r(e))return;C(h.settings);const o=Number.isFinite(n.connection?.latencyMs)?Math.max(0,Math.round(n.connection.latencyMs)):null;p(`Codex Agent connection verified${o!==null?` in ${o} ms.`:"."}`,"success")}catch(n){r(e)&&d(n instanceof Error?n.message:String(n))}finally{r(e)&&m("")}}},D=s?.codexInstallation==="installed"&&s.codexAuth==="signed-in",N=s!==null;return t.jsxs("div",{className:"settings-tab-content agent-settings-content",children:[t.jsxs("section",{className:"settings-section-card agent-enable-card",children:[t.jsxs("label",{className:"settings-toggle agent-enable-toggle",children:[t.jsx("input",{type:"checkbox",checked:f.enabled,onChange:e=>k("enabled",e.target.checked),disabled:!N||a!==""}),t.jsx("span",{children:"Enable Codex Agent"})]}),t.jsxs("p",{className:"settings-help",children:[t.jsx(A,{size:12})," Enabled by default. Agent commands use only the Codex account signed in on this Hub."]})]}),y&&t.jsx("div",{className:"agent-settings-alert error",role:"alert",children:y}),j&&t.jsx("div",{className:"agent-settings-alert success",role:"status",children:j}),t.jsxs("section",{className:"settings-section-card",children:[t.jsxs("div",{className:"settings-section-heading",children:[t.jsxs("div",{children:[t.jsx("span",{children:"Connection"}),t.jsx("h3",{children:"Codex SDK / CLI"})]}),t.jsx(q,{size:20})]}),t.jsxs("div",{className:"agent-connection-row",children:[t.jsx("span",{className:`agent-connection-dot ${D?"connected":s?.codexAuth==="not-signed-in"?"unavailable":""}`}),t.jsx("span",{children:s?.codexInstallation==="not-installed"?"Codex SDK not installed":s?.codexAuth==="signed-in"?"Codex CLI signed in":s?.codexAuth==="not-signed-in"?"Codex CLI sign-in required":"Codex status not tested"}),t.jsxs("button",{className:"settings-reset",onClick:()=>{T()},disabled:a!=="",type:"button",children:[t.jsx(I,{size:15})," ",a==="test"?"Testing":"Test connection"]})]}),t.jsxs("p",{className:"settings-help",children:[t.jsx(A,{size:12})," The Hub uses the installed Codex SDK / CLI to plan approved commands and run them through VuvoDesk Agent tools on selected computers. VuvoDesk never asks for separate credentials."]})]}),t.jsx("div",{className:"settings-action-row agent-settings-actions",children:t.jsxs("button",{className:"text-button primary",onClick:()=>{R()},disabled:!N||a!=="",type:"button",children:[t.jsx(z,{size:15})," ",a==="save"?"Saving":"Save Agent settings"]})})]})}export{H as AgentSettingsTab};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{j as t}from"./pwa-startup-DvbrYEQi.js";import{r as d,ae as ht,af as Ce,z as yt,G as ee,X as xe,ag as vt,ah as wt,ai as Ze,aj as kt,ak as bt,al as Se,b as H,am as Ct,p as xt,an as _e,o as St,ao as jt,S as Je,ap as At,a9 as Rt,c as Nt,aq as Pt,ar as It,A as Tt,as as ue,M as Xe}from"./icons-CuXJn-Hz.js";import{r as Et,h as F}from"./MonitorStackIcon-
|
|
1
|
+
import{j as t}from"./pwa-startup-DvbrYEQi.js";import{r as d,ae as ht,af as Ce,z as yt,G as ee,X as xe,ag as vt,ah as wt,ai as Ze,aj as kt,ak as bt,al as Se,b as H,am as Ct,p as xt,an as _e,o as St,ao as jt,S as Je,ap as At,a9 as Rt,c as Nt,aq as Pt,ar as It,A as Tt,as as ue,M as Xe}from"./icons-CuXJn-Hz.js";import{r as Et,h as F}from"./MonitorStackIcon-q_7f5mZs.js";import"./pwa-bootstrap-ljOQTt2e.js";const Ot=d.forwardRef(function({value:s,onChange:n,onSubmit:r,onOpenSuggestedTasks:i,suggestedOpen:f=!1,suggestedTaskCount:c,disabled:v=!1,placeholder:S="Ask VuvoDesk to work across your machines...",compact:g=!1},x){return t.jsxs("form",{className:"agents-composer",onSubmit:w=>{w.preventDefault(),r()},children:[t.jsx("button",{className:`agents-suggested-trigger ${f?"active":""}`,type:"button","aria-label":c===void 0?"Open Suggested tasks":`Open Suggested tasks (${c} available)`,"aria-expanded":f,onClick:i,disabled:v,children:t.jsx(ht,{size:17})}),t.jsx("textarea",{ref:x,value:s,onChange:w=>n(w.target.value.slice(0,4e3)),placeholder:S,"aria-label":"Ask VuvoDesk",rows:g?1:2,disabled:v}),t.jsxs("button",{className:"agents-run-button",type:"submit",disabled:v||!s.trim(),children:[v?t.jsx(Ce,{className:"spin",size:16}):t.jsx(yt,{size:16}),v?"Running":"Run"]})]})}),$t=["read","processControl","serviceControl","applicationControl","fileRead","fileWrite","fileDelete","shell","script","softwareInstall","network","systemPower","systemConfiguration","userAccount"];function de(e){return e.deviceName?.trim()||e.hostname?.trim()||e.deviceId}function pe(e){return e.connected!==!0?!1:e.synthetic===!0?!0:!e.channels||e.channels.control===!0}function Dt(e){return e==="running"||e==="completed"||e==="failed"||e==="cancelled"?e:"queued"}function _t(e){switch(e){case"process.list":return"Process list";case"system.health":return"System health";case"gpu.status":return"GPU status";case"disk.status":return"Disk status";case"service.status":return"Service status";case"diagnostics.collect":return"Diagnostics";case"process.control":return"Process control";case"service.control":return"Service control";case"application.launch":return"Launch application";case"application.close":return"Close application";case"file.read":return"Read file";case"file.write":return"Write file";case"file.delete":return"Delete file";case"file.list":return"List directory";case"command.run":return"Run command";case"script.run":return"Run script";case"software.install":return"Install software";case"network.status":return"Network status";case"system.power":return"Power action";case"system.configure":return"System configuration";case"logs.collect":return"Collect logs"}}const Mt=64*1024,Me="[Earlier log output hidden by PWA display limit.]",Qe=new TextEncoder,zt=new TextDecoder("utf-8",{fatal:!0}),ze=16*1024,Lt=200,Le="(?:access[_-]?(?:token|key)|refresh[_-]?token|id[_-]?token|pair[_-]?(?:token|key)|authorization|api[_-]?key|private[_-]?key|connection[_-]?string|credential|password|passwd|secret|cookie|set-cookie)",Ft="(?:access[_-]?(?:token|key)|refresh[_-]?token|id[_-]?token|pair[_-]?(?:token|key)|token|authorization|api[_-]?key|private[_-]?key|connection[_-]?string|credential|password|passwd|secret|cookie|set-cookie)",Bt="(?:access[_-]?(?:token|key)|refresh[_-]?token|id[_-]?token|pair[_-]?(?:token|key)|token|authorization|api[_-]?key|credential|password|secret|cookie)",qt=/\b(?:sk-(?:proj-|ant-)?[A-Za-z0-9_-]{8,}|gh[pousr]_[A-Za-z0-9]{8,}|github_pat_[A-Za-z0-9_]{8,}|(?:AKIA|ASIA)[A-Z0-9]{16}|AIza[A-Za-z0-9_-]{35}|npm_[A-Za-z0-9]{8,}|xox[a-z]-[A-Za-z0-9-]{8,}|(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{8,})\b/g;function Ut(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function Fe(e){return Qe.encode(e).byteLength}function Be(e,s){const n=Qe.encode(e);if(n.byteLength<=s)return{value:e,truncated:!1};let r=n.byteLength-s;for(;r<n.byteLength&&(n[r]&192)===128;)r+=1;let i=zt.decode(n.subarray(r));const f=i.indexOf(`
|
|
2
2
|
`);return f>=0&&f<i.length-1&&(i=i.slice(f+1)),{value:i,truncated:!0}}function et(e){return e.replace(/-----BEGIN [^-\r\n]*PRIVATE KEY-----[\s\S]*?-----END [^-\r\n]*PRIVATE KEY-----/gi,"[REDACTED PRIVATE KEY]").replace(/\b(?:proxy-)?authorization\s*[:=]\s*[^\r\n]*|\b(?:set-)?cookie\s*[:=]\s*[^\r\n]*/gi,"credential-header=[REDACTED]").replace(/\bBearer\s+(?:"[^"]*"|'[^']*'|[^\s,;]+)/gi,"Bearer [REDACTED]").replace(new RegExp(`("${Le}"\\s*:\\s*")[^"\\r\\n]*(")`,"gi"),"$1[REDACTED]$2").replace(new RegExp(`('${Le}'\\s*:\\s*')[^'\\r\\n]*(')`,"gi"),"$1[REDACTED]$2").replace(new RegExp(`((?:[A-Za-z0-9.-]+[_-])?${Ft}\\s*[:=]\\s*)(?!\\[REDACTED\\])[^\\s,;&]+`,"gi"),"$1[REDACTED]").replace(new RegExp(`([?&]${Bt}=)[^&\\s]+`,"gi"),"$1[REDACTED]").replace(/\b(?:eyJ|[A-Za-z0-9_-]{8,}\.)[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g,"[REDACTED TOKEN]").replace(qt,"[REDACTED KEY]")}function Gt(e){return typeof e!="string"?"source unknown":et(e).replace(/[\u0000-\u001f\u007f]/g," ").trim().slice(0,64)||"source unknown"}function qe(e){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=0?Math.floor(e):null}function Vt(e){if(typeof e!="string"||e.length===0)return{output:"",displayTruncated:!1};const s=Be(e.replace(/\r\n?/g,`
|
|
3
3
|
`),Mt);let n=et(s.value).replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g," ").trim(),r=s.truncated;const i=n?n.split(`
|
|
4
4
|
`):[];if(i.length>Lt-1&&(n=i.slice(-199).join(`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./pwa-startup-DvbrYEQi.js";import{r as i,R as x,E as j,D as u,f as g,h as f}from"./icons-CuXJn-Hz.js";import{l as b,c as d,d as y}from"./HubApp-
|
|
1
|
+
import{j as e}from"./pwa-startup-DvbrYEQi.js";import{r as i,R as x,E as j,D as u,f as g,h as f}from"./icons-CuXJn-Hz.js";import{l as b,c as d,d as y}from"./HubApp-BOX09IGB.js";import"./pwa-bootstrap-ljOQTt2e.js";import"./preload-helper-DD1OZmLC.js";import"./MonitorStackIcon-q_7f5mZs.js";import"./supabase-C7qjtLN3.js";import"./frame-lifecycle-D91nchvm.js";function z({hubUrl:s,onToast:n}){const[o,m]=i.useState([]),[h,c]=i.useState(!0),r=i.useCallback(async()=>{c(!0);try{m((await b(s)).captures||[])}catch(t){n(t instanceof Error?t.message:String(t))}finally{c(!1)}},[s,n]);i.useEffect(()=>{r()},[r]);const p=async t=>{const a=d(t.id,s);if(navigator.share)try{await navigator.share({title:t.fileName,url:a});return}catch{}window.open(a,"_blank","noopener,noreferrer")};return e.jsxs("section",{className:"capture-gallery",children:[e.jsxs("header",{children:[e.jsxs("div",{children:[e.jsx("span",{className:"settings-eyebrow",children:"Capture Gallery"}),e.jsx("h2",{children:"Saved captures"})]}),e.jsxs("button",{className:"text-button",onClick:()=>{r()},type:"button",children:[e.jsx(x,{size:15})," Refresh"]})]}),h?e.jsx("p",{className:"settings-help",children:"Loading captures..."}):o.length===0?e.jsx("p",{className:"settings-help",children:"No captures saved yet."}):e.jsx("div",{className:"capture-gallery-grid",children:o.map(t=>{const a=d(t.id,s);return e.jsxs("article",{className:"capture-gallery-card",children:[t.mimeType.startsWith("image/")?e.jsx("img",{src:a,alt:t.target.label}):e.jsx("video",{src:a,controls:!0,preload:"metadata"}),e.jsxs("div",{className:"capture-gallery-card-body",children:[e.jsx("strong",{children:t.fileName}),e.jsxs("small",{children:[t.target.label," · ",new Date(t.createdAt).toLocaleString()," · ",Math.ceil(t.sizeBytes/1024)," KB"]}),e.jsxs("div",{children:[e.jsx("button",{className:"icon-button",title:"Open","aria-label":"Open",onClick:()=>window.open(a,"_blank","noopener,noreferrer"),type:"button",children:e.jsx(j,{size:15})}),e.jsx("a",{className:"icon-button",title:"Download","aria-label":"Download",href:`${a}?download=1`,download:t.fileName,children:e.jsx(u,{size:15})}),e.jsx("button",{className:"icon-button",title:"Share","aria-label":"Share",onClick:()=>{p(t)},type:"button",children:e.jsx(g,{size:15})}),e.jsx("button",{className:"icon-button danger",title:"Delete","aria-label":"Delete",onClick:()=>{window.confirm(`Delete ${t.fileName}?`)&&y(t.id,s).then(()=>r()).catch(l=>n(l instanceof Error?l.message:String(l)))},type:"button",children:e.jsx(f,{size:15})})]})]})]},t.id)})})]})}export{z as CaptureGallery};
|