livedesk 0.1.692 → 0.1.695

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.
Files changed (52) hide show
  1. package/README.md +13 -9
  2. package/bin/livedesk.js +12 -12
  3. package/electron/electron-builder.linux-x64.yml +17 -1
  4. package/electron/linux-icons/128x128.png +0 -0
  5. package/electron/linux-icons/16x16.png +0 -0
  6. package/electron/linux-icons/256x256.png +0 -0
  7. package/electron/linux-icons/32x32.png +0 -0
  8. package/electron/linux-icons/48x48.png +0 -0
  9. package/electron/linux-icons/512x512.png +0 -0
  10. package/electron/linux-icons/64x64.png +0 -0
  11. package/electron/vuvodesk.metainfo.xml +25 -0
  12. package/hub/package.json +1 -1
  13. package/hub/src/plan-device-access.test.mjs +10 -4
  14. package/hub/src/server.js +1 -1
  15. package/package.json +1 -1
  16. package/web/dist/_headers +3 -0
  17. package/web/dist/app.html +2 -2
  18. package/web/dist/app.webmanifest +1 -1
  19. package/web/dist/assets/{AgentSettingsTab-DO2Z6NkJ.js → AgentSettingsTab-DUUxlm9j.js} +1 -1
  20. package/web/dist/assets/{AgentsPage-_shsjGZi.js → AgentsPage-Cqp2uXJm.js} +8 -8
  21. package/web/dist/assets/CaptureGallery-yJ9Z2oAV.js +1 -0
  22. package/web/dist/assets/{DesktopUpdatePanel-DuatXF9C.js → DesktopUpdatePanel-DopP2EeD.js} +1 -1
  23. package/web/dist/assets/{HubApp-Cl6KXmZZ.js → HubApp-DGbc5N_w.js} +4 -4
  24. package/web/dist/assets/{MonitorStackIcon-BCZRKGg9.js → MonitorStackIcon-D0aNf3fk.js} +5 -5
  25. package/web/dist/assets/{SettingsPage-fj5cHPfI.js → SettingsPage-gPMYkJ7M.js} +1 -1
  26. package/web/dist/assets/SettingsTabs-v57M-CCZ.js +1 -0
  27. package/web/dist/assets/{ShareFilesPage-DwpF_ImR.js → ShareFilesPage-Ou3F9U8g.js} +1 -1
  28. package/web/dist/assets/SupportPage-DKGBA5uL.js +2 -0
  29. package/web/dist/assets/VuvoDeskApp-CP5bEUhN.js +1 -0
  30. package/web/dist/assets/app-yqW82BcW.js +2 -0
  31. package/web/dist/assets/{client-8jUbxy3j.js → client-D-D35ghV.js} +1 -1
  32. package/web/dist/assets/{icons-CuXJn-Hz.js → icons-ChMazCZR.js} +1 -1
  33. package/web/dist/assets/main-Bnj1Y1s_.js +2 -0
  34. package/web/dist/assets/main-CVbEVGge.css +1 -0
  35. package/web/dist/assets/public-site-routing-pddZbLCj.js +1 -0
  36. package/web/dist/assets/{pwa-startup-DvbrYEQi.js → pwa-startup-BiuYh5eN.js} +1 -1
  37. package/web/dist/assets/{react-rvm9rmed.js → react-CnkEM7Rb.js} +1 -1
  38. package/web/dist/assets/vuvodesk-mobile-wall.jpg +0 -0
  39. package/web/dist/assets/vuvodesk-wall.png +0 -0
  40. package/web/dist/index.html +8 -8
  41. package/web/dist/robots.txt +1 -1
  42. package/web/dist/sitemap.xml +7 -7
  43. package/web/dist/sw.js +2 -2
  44. package/web/dist/vuvodesk-build-evidence.json +80 -70
  45. package/web/dist/assets/CaptureGallery-YQRtdPdf.js +0 -1
  46. package/web/dist/assets/SettingsTabs-CbCpfIYW.js +0 -1
  47. package/web/dist/assets/SupportPage-FMuoakR7.js +0 -2
  48. package/web/dist/assets/VuvoDeskApp-BG169yB2.js +0 -1
  49. package/web/dist/assets/app-Cy9L1xCR.js +0 -2
  50. package/web/dist/assets/main-BL1yIEvm.js +0 -2
  51. package/web/dist/assets/main-CLwaKs4-.css +0 -1
  52. package/web/dist/assets/preload-helper-DD1OZmLC.js +0 -1
package/README.md CHANGED
@@ -22,10 +22,14 @@ capture helpers, stale monitor generations, unbounded frame queues, or an
22
22
  unproven Direct/P2P/relay transition. Release builds run the same lifecycle,
23
23
  transport recovery, and browser H.264 population gates used by CI.
24
24
 
25
- ## Unified launch
25
+ ## Unified launch
26
+
27
+ The public command is `vuvodesk`. Its small npm entry package loads this exact
28
+ `livedesk` runtime version in the same process. Existing `livedesk@latest`
29
+ commands and update storage remain supported.
26
30
 
27
31
  ```powershell
28
- npx -y --prefer-online livedesk@latest
32
+ npx -y --prefer-online vuvodesk@latest
29
33
  ```
30
34
 
31
35
  The first interactive launch asks whether this computer is a Hub or Client.
@@ -36,14 +40,14 @@ device role is available, it takes precedence over the offline cache.
36
40
  For development and migration checks, the role can be forced for one run:
37
41
 
38
42
  ```powershell
39
- npx -y --prefer-online livedesk@latest --force-role hub
40
- npx -y --prefer-online livedesk@latest --force-role client
43
+ npx -y --prefer-online vuvodesk@latest --force-role hub
44
+ npx -y --prefer-online vuvodesk@latest --force-role client
41
45
  ```
42
46
 
43
47
  ## Hub
44
48
 
45
49
  ```powershell
46
- npx -y --prefer-online livedesk@latest hub
50
+ npx -y --prefer-online vuvodesk@latest hub
47
51
  ```
48
52
 
49
53
  This starts the VuvoDesk Hub, opens the local screen wall, accepts clients, and
@@ -67,7 +71,7 @@ and startup retry, then exits without looping.
67
71
  ## Client compatibility
68
72
 
69
73
  ```powershell
70
- npx -y --prefer-online livedesk@latest client 3
74
+ npx -y --prefer-online vuvodesk@latest client 3
71
75
  ```
72
76
 
73
77
  The `client` form remains as a legacy compatibility alias. It records the
@@ -85,7 +89,7 @@ Screen Recording and Accessibility permissions, then explicitly confirm that
85
89
  the motion is already running:
86
90
 
87
91
  ```bash
88
- npx -y --prefer-online livedesk@latest diagnose mac-physical --confirm-active-motion
92
+ npx -y --prefer-online vuvodesk@latest diagnose mac-physical --confirm-active-motion
89
93
  ```
90
94
 
91
95
  This command branches before role resolution, state migration, and the normal
@@ -105,7 +109,7 @@ result. It is written under `~/.livedesk/diagnostics`. To select a path relative
105
109
  to the directory where the command was invoked:
106
110
 
107
111
  ```bash
108
- npx -y --prefer-online livedesk@latest diagnose mac-physical --confirm-active-motion --report ./mac-result.json
112
+ npx -y --prefer-online vuvodesk@latest diagnose mac-physical --confirm-active-motion --report ./mac-result.json
109
113
  ```
110
114
 
111
115
  Use `diagnose mac-physical --help` to inspect requirements without starting a
@@ -130,7 +134,7 @@ While the local Hub is running and at least one Client is sending a current
130
134
  Mode 3 H.264 stream, run:
131
135
 
132
136
  ```bash
133
- npx -y --prefer-online livedesk@latest diagnose transport-physical
137
+ npx -y --prefer-online vuvodesk@latest diagnose transport-physical
134
138
  ```
135
139
 
136
140
  The diagnostic proves one unchanged stream identity through Direct TCP,
package/bin/livedesk.js CHANGED
@@ -343,11 +343,11 @@ function printHelp() {
343
343
  VuvoDesk
344
344
 
345
345
  Usage:
346
- npx -y --prefer-online livedesk@latest
347
- npx -y --prefer-online livedesk@latest --force-role hub
348
- npx -y --prefer-online livedesk@latest --force-role client
349
- npx -y --prefer-online livedesk@latest diagnose mac-physical --confirm-active-motion
350
- npx -y --prefer-online livedesk@latest diagnose transport-physical
346
+ npx -y --prefer-online vuvodesk@latest
347
+ npx -y --prefer-online vuvodesk@latest --force-role hub
348
+ npx -y --prefer-online vuvodesk@latest --force-role client
349
+ npx -y --prefer-online vuvodesk@latest diagnose mac-physical --confirm-active-motion
350
+ npx -y --prefer-online vuvodesk@latest diagnose transport-physical
351
351
 
352
352
  Commands:
353
353
  No command Resolve the signed-in device role and start the matching runtime.
@@ -386,8 +386,8 @@ function printMacPhysicalDiagnosticHelp() {
386
386
  VuvoDesk macOS physical diagnostic
387
387
 
388
388
  Usage:
389
- npx -y --prefer-online livedesk@latest diagnose mac-physical --confirm-active-motion
390
- npx -y --prefer-online livedesk@latest diagnose mac-physical --confirm-active-motion --report ./mac-result.json
389
+ npx -y --prefer-online vuvodesk@latest diagnose mac-physical --confirm-active-motion
390
+ npx -y --prefer-online vuvodesk@latest diagnose mac-physical --confirm-active-motion --report ./mac-result.json
391
391
 
392
392
  Requirements:
393
393
  macOS with two connected displays showing visibly different, continuously moving content.
@@ -455,8 +455,8 @@ function printClientHelp() {
455
455
  VuvoDesk Client
456
456
 
457
457
  Usage:
458
- npx -y --prefer-online livedesk@latest client
459
- npx -y --prefer-online livedesk@latest client 3
458
+ npx -y --prefer-online vuvodesk@latest client
459
+ npx -y --prefer-online vuvodesk@latest client 3
460
460
 
461
461
  Default flow:
462
462
  Opens a VuvoDesk connection page with Google sign-in or a 6-digit PIN.
@@ -3270,7 +3270,7 @@ async function main() {
3270
3270
  const commandArgs = args.slice(1).map(value => String(value || '').trim().toLowerCase());
3271
3271
  if (commandArgs.some(value => value === '--help' || value === '-h' || value === 'help')) {
3272
3272
  if (command === 'client') {
3273
- console.warn('[VuvoDesk] Legacy client command detected. Use `npx -y --prefer-online livedesk@latest` for automatic role selection.');
3273
+ console.warn('[VuvoDesk] Legacy client command detected. Use `npx -y --prefer-online vuvodesk@latest` for automatic role selection.');
3274
3274
  printClientHelp();
3275
3275
  } else {
3276
3276
  printHelp();
@@ -3279,7 +3279,7 @@ async function main() {
3279
3279
  }
3280
3280
  if (commandArgs.some(value => value === '--version' || value === '-v' || value === 'version')) {
3281
3281
  if (command === 'client') {
3282
- console.warn('[VuvoDesk] Legacy client command detected. Use `npx -y --prefer-online livedesk@latest` for automatic role selection.');
3282
+ console.warn('[VuvoDesk] Legacy client command detected. Use `npx -y --prefer-online vuvodesk@latest` for automatic role selection.');
3283
3283
  }
3284
3284
  console.log(readVersion());
3285
3285
  return;
@@ -3302,7 +3302,7 @@ async function main() {
3302
3302
  writeRoleCache({ ...resolvedRole, source: 'local-cache', isOfflineFallback: false }, roleStateOptions);
3303
3303
  runtimeArgs = args.slice(1);
3304
3304
  if (command === 'client') {
3305
- console.warn('[VuvoDesk] Legacy client command detected. Use `npx -y --prefer-online livedesk@latest` for automatic role selection.');
3305
+ console.warn('[VuvoDesk] Legacy client command detected. Use `npx -y --prefer-online vuvodesk@latest` for automatic role selection.');
3306
3306
  }
3307
3307
  } else {
3308
3308
  const forceDesktopBootstrap = process.env.LIVEDESK_DESKTOP_HOST === '1'
@@ -26,10 +26,11 @@ asarUnpack:
26
26
  - node_modules/node-datachannel/**
27
27
  - node_modules/@node-datachannel/linux-x64-gnu/**
28
28
  linux:
29
- icon: packages/vuvodesk/electron/icon.png
29
+ icon: packages/vuvodesk/electron/linux-icons
30
30
  category: Utility
31
31
  executableName: livedesk
32
32
  maintainer: "lovecrdm <lovecrdm@gmail.com>"
33
+ synopsis: VuvoDesk remote desktop and screen wall
33
34
  target:
34
35
  - target: AppImage
35
36
  arch:
@@ -37,6 +38,21 @@ linux:
37
38
  - target: deb
38
39
  arch:
39
40
  - x64
41
+ deb:
42
+ packageName: vuvodesk
43
+ packageCategory: utils
44
+ description: >-
45
+ View your computers together and control a selected screen with VuvoDesk.
46
+ Updates are checked and downloaded inside VuvoDesk. Installing a deb update
47
+ may require your administrator password.
48
+ fpm:
49
+ - --replaces
50
+ - livedesk
51
+ - --conflicts
52
+ - livedesk
53
+ - --provides
54
+ - livedesk
55
+ - packages/vuvodesk/electron/vuvodesk.metainfo.xml=/usr/share/metainfo/com.livedesk.desktop.metainfo.xml
40
56
  extraMetadata:
41
57
  homepage: https://vuvodesk.com
42
58
  publish:
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,25 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <component type="desktop-application">
3
+ <id>com.livedesk.desktop</id>
4
+ <metadata_license>MIT</metadata_license>
5
+ <project_license>MIT</project_license>
6
+ <name>VuvoDesk</name>
7
+ <summary>View and control your computers from one screen</summary>
8
+ <developer id="com.vuvodesk">
9
+ <name>VuvoDesk</name>
10
+ </developer>
11
+ <description>
12
+ <p>VuvoDesk brings your computers into a screen wall and lets you control a selected screen.</p>
13
+ <p>Connect with the desktop application or the mobile web app. Updates are checked inside VuvoDesk; installing a deb update may require your administrator password.</p>
14
+ </description>
15
+ <launchable type="desktop-id">livedesk.desktop</launchable>
16
+ <icon type="stock">livedesk</icon>
17
+ <url type="homepage">https://www.vuvodesk.com</url>
18
+ <url type="help">https://www.vuvodesk.com/support</url>
19
+ <categories>
20
+ <category>Utility</category>
21
+ </categories>
22
+ <provides>
23
+ <binary>livedesk</binary>
24
+ </provides>
25
+ </component>
package/hub/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livedesk/hub",
3
- "version": "0.1.73",
3
+ "version": "0.1.74",
4
4
  "description": "VuvoDesk local Hub API and browser frame bridge",
5
5
  "type": "module",
6
6
  "main": "src/server.js",
@@ -15,7 +15,7 @@ const clients = [6, 3, 1, 5, 2, 4].map(slotNumber => ({
15
15
  }));
16
16
 
17
17
  test('Hub and browser choose the same stable Free, Plus, Pro, and Team device owners', () => {
18
- for (const limit of [5, 15, 50, Number.POSITIVE_INFINITY]) {
18
+ for (const limit of [5, 20, 50, Number.POSITIVE_INFINITY]) {
19
19
  assert.deepEqual(
20
20
  stableHubPlanAllowedDeviceIds(clients, limit),
21
21
  stableBrowserPlanAllowedDeviceIds(clients, limit)
@@ -27,15 +27,21 @@ test('Hub and browser choose the same stable Free, Plus, Pro, and Team device ow
27
27
  );
28
28
  });
29
29
 
30
- test('Plus stops at 15 Clients, Pro stops at 50, and Team remains unbounded', () => {
30
+ test('Plus stops at 20 Clients, Pro stops at 50, and Team remains unbounded', () => {
31
31
  const manyClients = Array.from({ length: 51 }, (_, index) => ({
32
32
  deviceId: `client-${index + 1}`,
33
33
  slotNumber: index + 1,
34
34
  connected: true
35
35
  }));
36
36
 
37
- assert.equal(createPlanDeviceAccessSnapshot(manyClients, 15).allowedDeviceIds.length, 15);
38
- assert.equal(createPlanDeviceAccessSnapshot(manyClients, 15).blockedDeviceIds.length, 36);
37
+ assert.equal(createPlanDeviceAccessSnapshot(manyClients, 20).allowedDeviceIds.length, 20);
38
+ assert.equal(createPlanDeviceAccessSnapshot(manyClients, 20).blockedDeviceIds.length, 31);
39
+ const plus = createPlanDeviceAccessSnapshot(manyClients, 20);
40
+ assert.equal(plus.allowedDeviceIdSet.has('client-20'), true);
41
+ assert.equal(plus.allowedDeviceIdSet.has('client-21'), false);
42
+ assert.deepEqual(partitionPlanDeviceIds(['client-20', 'client-21'], plus), {
43
+ allowedDeviceIds: ['client-20'], blockedDeviceIds: ['client-21']
44
+ });
39
45
  assert.equal(createPlanDeviceAccessSnapshot(manyClients, 50).allowedDeviceIds.length, 50);
40
46
  assert.deepEqual(createPlanDeviceAccessSnapshot(manyClients, 50).blockedDeviceIds, ['client-51']);
41
47
  assert.equal(
package/hub/src/server.js CHANGED
@@ -178,7 +178,7 @@ const atlasPool = new Mode4AtlasPool({
178
178
  const inputClients = new Set();
179
179
  const audioClients = new Set();
180
180
  const FREE_DEVICE_LIMIT = 5;
181
- const PLUS_DEVICE_LIMIT = 15;
181
+ const PLUS_DEVICE_LIMIT = 20;
182
182
  const PRO_DEVICE_LIMIT = 50;
183
183
  const LICENSE_VERIFY_MAX_AGE_MS = 6 * 60 * 60 * 1000;
184
184
  const ROLE_TRANSITION_EXIT_CODE = 43;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "livedesk",
3
- "version": "0.1.692",
3
+ "version": "0.1.695",
4
4
  "livedeskClientVersion": "0.1.276",
5
5
  "buildFlavor": "production",
6
6
  "description": "VuvoDesk Hub and client launcher",
package/web/dist/_headers CHANGED
@@ -7,6 +7,9 @@
7
7
  /app
8
8
  Cache-Control: no-cache, no-store, must-revalidate
9
9
 
10
+ /download
11
+ Cache-Control: no-cache, no-store, must-revalidate
12
+
10
13
  /assets/*
11
14
  Cache-Control: public, max-age=31556952, immutable
12
15
 
package/web/dist/app.html CHANGED
@@ -52,8 +52,8 @@
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-Cy9L1xCR.js" data-vuvodesk-entry></script>
56
- <link rel="modulepreload" crossorigin href="/assets/preload-helper-DD1OZmLC.js">
55
+ <script type="module" crossorigin src="/assets/app-yqW82BcW.js" data-vuvodesk-entry></script>
56
+ <link rel="modulepreload" crossorigin href="/assets/public-site-routing-pddZbLCj.js">
57
57
  <link rel="modulepreload" crossorigin href="/assets/pwa-bootstrap-ljOQTt2e.js">
58
58
  </head>
59
59
  <body>
@@ -4,7 +4,7 @@
4
4
  "short_name": "VuvoDesk",
5
5
  "description": "Monitor and control your VuvoDesk computers from your phone.",
6
6
  "lang": "en",
7
- "start_url": "/app?pwa=0.1.692",
7
+ "start_url": "/app?pwa=0.1.695",
8
8
  "scope": "/",
9
9
  "display": "standalone",
10
10
  "orientation": "any",
@@ -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-BCZRKGg9.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
+ import{j as t}from"./pwa-startup-BiuYh5eN.js";import{r as c,d as A,S as q,T as I,e as z}from"./icons-ChMazCZR.js";import{h as x}from"./MonitorStackIcon-D0aNf3fk.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};