@openchambery/web 1.18.4-beta.13 → 1.18.4-beta.15

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 (93) hide show
  1. package/dist/assets/{AgentAvatar-DAnelAnB.js → AgentAvatar-DDcjamcJ.js} +1 -1
  2. package/dist/assets/AssistantView-8uU58vy0.js +1 -0
  3. package/dist/assets/{ChatContainer-6WieMUSp.js → ChatContainer-CimpaKcn.js} +40 -40
  4. package/dist/assets/{DiagramView-DlXrsDUG.js → DiagramView-euzFXO_O.js} +1 -1
  5. package/dist/assets/{FadeInOnReveal-QxF1vuqX.js → FadeInOnReveal-By2F9vcI.js} +1 -1
  6. package/dist/assets/{Icon-D-X70irR.js → Icon-DpjYnXxn.js} +1 -1
  7. package/dist/assets/{MarkdownRendererImpl-B-EoT0sb.js → MarkdownRendererImpl-Dit2Ib5h.js} +1 -1
  8. package/dist/assets/{MobileDetailNavigation-BoG7pVfo.js → MobileDetailNavigation-BUj1ICFS.js} +1 -1
  9. package/dist/assets/{MobileShareBridge-Fvj6YxGM.js → MobileShareBridge-DFHvcf7Q.js} +3 -3
  10. package/dist/assets/MobileSurface-CDowKkJL.js +2 -0
  11. package/dist/assets/{MultiRunWindow-DNcAO90A.js → MultiRunWindow-CvUMhyyj.js} +1 -1
  12. package/dist/assets/{OnboardingScreen-Cx79VlTN.js → OnboardingScreen-BKmuT7AL.js} +1 -1
  13. package/dist/assets/{OverlayScrollbar-CHXk_jvF.js → OverlayScrollbar-Ch3J6ASR.js} +1 -1
  14. package/dist/assets/{SettingsView-Btq8Dklr.js → SettingsView-By3I3xXH.js} +11 -11
  15. package/dist/assets/{SettingsWindow-BWBCXkbw.js → SettingsWindow-5n2DvzeP.js} +1 -1
  16. package/dist/assets/{TerminalView-C08kUtip.js → TerminalView-BmycLxLS.js} +1 -1
  17. package/dist/assets/{ToolOutputDialog-CYJJkU-t.js → ToolOutputDialog-BdhiH4i4.js} +1 -1
  18. package/dist/assets/{appThemeRegistry-CT3mdmod.js → appThemeRegistry-NoIEZNtX.js} +2 -2
  19. package/dist/assets/{button-CwLFtUNT.js → button-C7OXr4ae.js} +1 -1
  20. package/dist/assets/{clipboard-BfgFef1i.js → clipboard-DWuULPzo.js} +1 -1
  21. package/dist/assets/{collapsible-CP1-_pY6.js → collapsible-DaEya6b6.js} +1 -1
  22. package/dist/assets/{context-menu-8RbXKyth.js → context-menu-BOlxzatH.js} +1 -1
  23. package/dist/assets/{desktopHosts-Cr3LE55y.js → desktopHosts-Txp4xOVQ.js} +1 -1
  24. package/dist/assets/desktopRelayRestore-C_FSEHKM.js +1 -0
  25. package/dist/assets/{diagram-rYL80jaS.js → diagram-CHfginjS.js} +1 -1
  26. package/dist/assets/{dialog-GR7KoP1o.js → dialog-DPS0W9eS.js} +1 -1
  27. package/dist/assets/{es-Bi4m8Mm6.js → es-BX0Vm3Ac.js} +1 -1
  28. package/dist/assets/fileQueries-BrUKKgPW.js +1 -0
  29. package/dist/assets/{fr-B5UdepyS.js → fr-CuPzXTYx.js} +1 -1
  30. package/dist/assets/{gitApi-D9GCl6zm.js → gitApi-q_WNtocg.js} +3 -3
  31. package/dist/assets/{input-D52Jicb1.js → input-BzYA603C.js} +1 -1
  32. package/dist/assets/insertionBoundaries-tokUZ60O.js +1 -0
  33. package/dist/assets/{ja-KtFuRjvm.js → ja-DGtzjrFO.js} +1 -1
  34. package/dist/assets/{ko-CWpFVSCH.js → ko-DZ9Di0je.js} +1 -1
  35. package/dist/assets/{main-CJlCVnYv.js → main-B5n5utaj.js} +23 -23
  36. package/dist/assets/{main-tNr6I3vu.js → main-D08xX-l9.js} +2 -2
  37. package/dist/assets/{markdown-worker-N9d_Z-7s.js → markdown-worker-W06-MhF5.js} +1 -1
  38. package/dist/assets/{markdownTheme-Bl0Sy0Lf.js → markdownTheme-B89dbj3N.js} +1 -1
  39. package/dist/assets/{miniChat-DrpYcsWP.js → miniChat-S0KGzmRO.js} +2 -2
  40. package/dist/assets/mobile-BBGkZDcd.js +2 -0
  41. package/dist/assets/{multirun-C9meL62Q.js → multirun-CWuU0fcO.js} +1 -1
  42. package/dist/assets/{persistence-vZ7H8WKh.js → persistence-6sclr7B6.js} +2 -2
  43. package/dist/assets/{pl-30X8TD5i.js → pl-BuCO3qb1.js} +1 -1
  44. package/dist/assets/{platform-CTaznShj.js → platform-CbeLpKPk.js} +1 -1
  45. package/dist/assets/projectMeta-BKC7h4Rl.js +3 -0
  46. package/dist/assets/{pt-BR-Cm-Klf0E.js → pt-BR-Brf4RMsw.js} +1 -1
  47. package/dist/assets/radio-BNOD9XTZ.js +1 -0
  48. package/dist/assets/renderElectronMiniChatApp-CNL8yc53.js +2 -0
  49. package/dist/assets/renderMobileApp-DabtxHdO.js +23 -0
  50. package/dist/assets/{runtimeConfig-3yA9sxLc.js → runtimeConfig-Cfrfl4hH.js} +1 -1
  51. package/dist/assets/runtimeEndpointReset-C1vjUBL_.js +147 -0
  52. package/dist/assets/{sortable-tabs-strip-BYmWSdS9.js → sortable-tabs-strip-nLsPC06f.js} +1 -1
  53. package/dist/assets/{src-Dbdlm5x1.css → src-06zk77Ia.css} +1 -1
  54. package/dist/assets/{store-Z1MxUaP4.js → store-DQY8Fkb0.js} +2 -2
  55. package/dist/assets/{terminalApi-KDUc5mh2.js → terminalApi-BpPeXWIu.js} +1 -1
  56. package/dist/assets/{tooltip-CaCe-GAm.js → tooltip-D_orJMYd.js} +1 -1
  57. package/dist/assets/{uk-Cgc5wXrs.js → uk-C-wmaPTi.js} +1 -1
  58. package/dist/assets/{url-B-FWrnxu.js → url-BsaBG5-1.js} +1 -1
  59. package/dist/assets/useAppFontEffects-CkLk4g06.js +7 -0
  60. package/dist/assets/{useAssistantUIStore-ifqNyja4.js → useAssistantUIStore-BHsHXCKE.js} +1 -1
  61. package/dist/assets/{useDesktopWindowControlsLayout-CIG_KWdN.js → useDesktopWindowControlsLayout-BSeMY94L.js} +1 -1
  62. package/dist/assets/{useEffectiveDirectory-D2DbZw-O.js → useEffectiveDirectory-CA1iNlkc.js} +1 -1
  63. package/dist/assets/{useFontPreferences-D_LFFhFS.js → useFontPreferences-ckzpXQaJ.js} +1 -1
  64. package/dist/assets/useMobileNavigationStore-DyYYlEY1.js +475 -0
  65. package/dist/assets/useSessionAutoCleanup-LLUYctRd.js +1 -0
  66. package/dist/assets/useUIStore-DzwCfRqr.js +1 -0
  67. package/dist/assets/{useWorkerHighlightedLines-cpMCtMhM.js → useWorkerHighlightedLines-dTnogsPN.js} +1 -1
  68. package/dist/assets/{utils-C2P0wcWO.js → utils-B1EK5zKa.js} +1 -1
  69. package/dist/assets/{zh-CN-BdRwDJuj.js → zh-CN-DueRrIql.js} +1 -1
  70. package/dist/assets/{zh-TW-C3LubKzZ.js → zh-TW-6875X80V.js} +1 -1
  71. package/dist/index.html +9 -9
  72. package/dist/mini-chat.html +9 -9
  73. package/dist/mobile.html +9 -9
  74. package/package.json +1 -1
  75. package/server/lib/config-sync/config-sync.test.js +52 -0
  76. package/server/lib/config-sync/scripts.js +10 -2
  77. package/server/lib/ui-auth/ui-auth.js +3 -1
  78. package/server/lib/ui-auth/ui-auth.test.js +25 -0
  79. package/dist/assets/AssistantView-DRZAE96O.js +0 -1
  80. package/dist/assets/MobileSurface-CUUnqmxV.js +0 -2
  81. package/dist/assets/desktopRelayRestore-VfMK9fdk.js +0 -1
  82. package/dist/assets/fileQueries-CXaw4b1W.js +0 -1
  83. package/dist/assets/insertionBoundaries-BkekAoi1.js +0 -1
  84. package/dist/assets/mobile-DzytiZtA.js +0 -2
  85. package/dist/assets/projectMeta-CGVcN1ku.js +0 -3
  86. package/dist/assets/radio-BMVNzW4v.js +0 -1
  87. package/dist/assets/renderElectronMiniChatApp-8f7e09mu.js +0 -2
  88. package/dist/assets/renderMobileApp-DkJ7iHEs.js +0 -23
  89. package/dist/assets/runtimeEndpointReset-CloJudPr.js +0 -147
  90. package/dist/assets/useAppFontEffects-4sS5v6D7.js +0 -7
  91. package/dist/assets/useMobileNavigationStore-B-sGLR3i.js +0 -476
  92. package/dist/assets/useSessionAutoCleanup-DTsE7RL4.js +0 -1
  93. package/dist/assets/useUIStore-NfqK-HA7.js +0 -1
package/dist/index.html CHANGED
@@ -552,25 +552,25 @@
552
552
  opacity: 0.72;
553
553
  }
554
554
  </style>
555
- <script type="module" crossorigin src="/assets/main-tNr6I3vu.js"></script>
555
+ <script type="module" crossorigin src="/assets/main-D08xX-l9.js"></script>
556
556
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
557
557
  <link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CnHfUmDN.js">
558
558
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-B4dlGEM2.js">
559
- <link rel="modulepreload" crossorigin href="/assets/useUIStore-NfqK-HA7.js">
559
+ <link rel="modulepreload" crossorigin href="/assets/useUIStore-DzwCfRqr.js">
560
560
  <link rel="modulepreload" crossorigin href="/assets/vendor-pathe-vBmvQE8f.js">
561
561
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-DLPElpoQ.js">
562
562
  <link rel="modulepreload" crossorigin href="/assets/vendor-tanstack-query-core-BWz0ose6.js">
563
- <link rel="modulepreload" crossorigin href="/assets/persistence-vZ7H8WKh.js">
564
- <link rel="modulepreload" crossorigin href="/assets/desktopHosts-Cr3LE55y.js">
565
- <link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-VfMK9fdk.js">
563
+ <link rel="modulepreload" crossorigin href="/assets/persistence-6sclr7B6.js">
564
+ <link rel="modulepreload" crossorigin href="/assets/desktopHosts-Txp4xOVQ.js">
565
+ <link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-C_FSEHKM.js">
566
566
  <link rel="modulepreload" crossorigin href="/assets/vendor-opencode-sdk-C07HQypa.js">
567
567
  <link rel="modulepreload" crossorigin href="/assets/vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js">
568
- <link rel="modulepreload" crossorigin href="/assets/platform-CTaznShj.js">
569
- <link rel="modulepreload" crossorigin href="/assets/terminalApi-KDUc5mh2.js">
568
+ <link rel="modulepreload" crossorigin href="/assets/platform-CbeLpKPk.js">
569
+ <link rel="modulepreload" crossorigin href="/assets/terminalApi-BpPeXWIu.js">
570
570
  <link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
571
571
  <link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
572
- <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-3yA9sxLc.js">
573
- <link rel="stylesheet" crossorigin href="/assets/src-Dbdlm5x1.css">
572
+ <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-Cfrfl4hH.js">
573
+ <link rel="stylesheet" crossorigin href="/assets/src-06zk77Ia.css">
574
574
  </head>
575
575
  <body class="h-full bg-background text-foreground">
576
576
  <!-- Keep the startup layer outside #root. React replaces every child of
@@ -74,25 +74,25 @@
74
74
  }
75
75
  </style>
76
76
 
77
- <script type="module" crossorigin src="/assets/miniChat-DrpYcsWP.js"></script>
77
+ <script type="module" crossorigin src="/assets/miniChat-S0KGzmRO.js"></script>
78
78
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
79
79
  <link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CnHfUmDN.js">
80
80
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-B4dlGEM2.js">
81
- <link rel="modulepreload" crossorigin href="/assets/useUIStore-NfqK-HA7.js">
81
+ <link rel="modulepreload" crossorigin href="/assets/useUIStore-DzwCfRqr.js">
82
82
  <link rel="modulepreload" crossorigin href="/assets/vendor-pathe-vBmvQE8f.js">
83
83
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-DLPElpoQ.js">
84
84
  <link rel="modulepreload" crossorigin href="/assets/vendor-tanstack-query-core-BWz0ose6.js">
85
- <link rel="modulepreload" crossorigin href="/assets/persistence-vZ7H8WKh.js">
86
- <link rel="modulepreload" crossorigin href="/assets/desktopHosts-Cr3LE55y.js">
87
- <link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-VfMK9fdk.js">
85
+ <link rel="modulepreload" crossorigin href="/assets/persistence-6sclr7B6.js">
86
+ <link rel="modulepreload" crossorigin href="/assets/desktopHosts-Txp4xOVQ.js">
87
+ <link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-C_FSEHKM.js">
88
88
  <link rel="modulepreload" crossorigin href="/assets/vendor-opencode-sdk-C07HQypa.js">
89
89
  <link rel="modulepreload" crossorigin href="/assets/vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js">
90
- <link rel="modulepreload" crossorigin href="/assets/platform-CTaznShj.js">
91
- <link rel="modulepreload" crossorigin href="/assets/terminalApi-KDUc5mh2.js">
90
+ <link rel="modulepreload" crossorigin href="/assets/platform-CbeLpKPk.js">
91
+ <link rel="modulepreload" crossorigin href="/assets/terminalApi-BpPeXWIu.js">
92
92
  <link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
93
93
  <link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
94
- <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-3yA9sxLc.js">
95
- <link rel="stylesheet" crossorigin href="/assets/src-Dbdlm5x1.css">
94
+ <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-Cfrfl4hH.js">
95
+ <link rel="stylesheet" crossorigin href="/assets/src-06zk77Ia.css">
96
96
  </head>
97
97
  <body class="h-full bg-background text-foreground">
98
98
  <div id="root" class="h-full">
package/dist/mobile.html CHANGED
@@ -63,25 +63,25 @@
63
63
  })();
64
64
  </script>
65
65
 
66
- <script type="module" crossorigin src="/assets/mobile-DzytiZtA.js"></script>
66
+ <script type="module" crossorigin src="/assets/mobile-BBGkZDcd.js"></script>
67
67
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
68
68
  <link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CnHfUmDN.js">
69
69
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-B4dlGEM2.js">
70
- <link rel="modulepreload" crossorigin href="/assets/useUIStore-NfqK-HA7.js">
70
+ <link rel="modulepreload" crossorigin href="/assets/useUIStore-DzwCfRqr.js">
71
71
  <link rel="modulepreload" crossorigin href="/assets/vendor-pathe-vBmvQE8f.js">
72
72
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-DLPElpoQ.js">
73
73
  <link rel="modulepreload" crossorigin href="/assets/vendor-tanstack-query-core-BWz0ose6.js">
74
- <link rel="modulepreload" crossorigin href="/assets/persistence-vZ7H8WKh.js">
75
- <link rel="modulepreload" crossorigin href="/assets/desktopHosts-Cr3LE55y.js">
76
- <link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-VfMK9fdk.js">
74
+ <link rel="modulepreload" crossorigin href="/assets/persistence-6sclr7B6.js">
75
+ <link rel="modulepreload" crossorigin href="/assets/desktopHosts-Txp4xOVQ.js">
76
+ <link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-C_FSEHKM.js">
77
77
  <link rel="modulepreload" crossorigin href="/assets/vendor-opencode-sdk-C07HQypa.js">
78
78
  <link rel="modulepreload" crossorigin href="/assets/vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js">
79
- <link rel="modulepreload" crossorigin href="/assets/platform-CTaznShj.js">
80
- <link rel="modulepreload" crossorigin href="/assets/terminalApi-KDUc5mh2.js">
79
+ <link rel="modulepreload" crossorigin href="/assets/platform-CbeLpKPk.js">
80
+ <link rel="modulepreload" crossorigin href="/assets/terminalApi-BpPeXWIu.js">
81
81
  <link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
82
82
  <link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
83
- <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-3yA9sxLc.js">
84
- <link rel="stylesheet" crossorigin href="/assets/src-Dbdlm5x1.css">
83
+ <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-Cfrfl4hH.js">
84
+ <link rel="stylesheet" crossorigin href="/assets/src-06zk77Ia.css">
85
85
  </head>
86
86
  <body class="h-full bg-background text-foreground">
87
87
  <div id="root" class="h-full"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openchambery/web",
3
- "version": "1.18.4-beta.13",
3
+ "version": "1.18.4-beta.15",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./server/index.js",
@@ -14,6 +14,7 @@ import {
14
14
  assertTargetCapability,
15
15
  buildDefaultSyncSelections,
16
16
  buildRemoteSyncFinalizeScript,
17
+ buildRemoteSyncInventoryScript,
17
18
  buildRemoteSyncPrepareScript,
18
19
  createSshSyncTarget,
19
20
  filterPlanBySelections,
@@ -195,3 +196,54 @@ describe('generational prepare backups', () => {
195
196
  })).toThrow();
196
197
  });
197
198
  });
199
+
200
+ describe('remote inventory script', () => {
201
+ it('emits SYNC_INVENTORY as valid JSON with quoted path values (regression: bare quotes broke JSON.parse)', async () => {
202
+ const home = await makeTempDir();
203
+ const configDir = path.join(home, '.config', 'opencode');
204
+ await fsp.mkdir(path.join(configDir, 'agents'), { recursive: true });
205
+ await fsp.writeFile(path.join(configDir, 'opencode.jsonc'), '{"a":1}\n');
206
+ await fsp.writeFile(path.join(configDir, 'AGENTS.md'), '# agents\n');
207
+ await fsp.writeFile(path.join(configDir, 'agents', 'helper.md'), 'x'.repeat(7));
208
+ await fsp.mkdir(path.join(home, '.local', 'share', 'opencode'), { recursive: true });
209
+ await fsp.writeFile(path.join(home, '.local', 'share', 'opencode', 'auth.json'), '{}\n');
210
+
211
+ const stdout = execFileSync('sh', ['-c', buildRemoteSyncInventoryScript()], {
212
+ env: { ...process.env, HOME: home },
213
+ });
214
+ const line = stdout.toString().split(/\r?\n/).find((entry) => entry.startsWith('SYNC_INVENTORY='));
215
+ expect(line).toBeTruthy();
216
+
217
+ // This threw SyntaxError ("Unexpected token") before path values were
218
+ // escaped for the surrounding shell double-quoted string.
219
+ const inventory = JSON.parse(line.slice('SYNC_INVENTORY='.length));
220
+ const files = inventory.files.map((entry) => entry.path);
221
+ expect(files).toContain('opencode.jsonc');
222
+ expect(files).toContain('AGENTS.md');
223
+ const directories = inventory.directories.map((entry) => entry.path);
224
+ expect(directories).toContain('agents');
225
+ expect(inventory.authFile).toEqual({ bytes: 3 });
226
+ for (const entry of inventory.files) {
227
+ expect(typeof entry.path).toBe('string');
228
+ expect(typeof entry.bytes).toBe('number');
229
+ }
230
+ for (const entry of inventory.directories) {
231
+ expect(typeof entry.path).toBe('string');
232
+ expect(typeof entry.fileCount).toBe('number');
233
+ expect(typeof entry.bytes).toBe('number');
234
+ }
235
+ });
236
+
237
+ it('still parses when nothing exists on the remote', async () => {
238
+ const home = await makeTempDir();
239
+ const stdout = execFileSync('sh', ['-c', buildRemoteSyncInventoryScript()], {
240
+ env: { ...process.env, HOME: home },
241
+ });
242
+ const line = stdout.toString().split(/\r?\n/).find((entry) => entry.startsWith('SYNC_INVENTORY='));
243
+ const inventory = JSON.parse(line.slice('SYNC_INVENTORY='.length));
244
+ expect(inventory.files).toEqual([]);
245
+ expect(inventory.directories).toEqual([]);
246
+ expect(inventory.agentsRoot).toBeNull();
247
+ expect(inventory.authFile).toBeNull();
248
+ });
249
+ });
@@ -12,6 +12,14 @@ import {
12
12
 
13
13
  const shellQuote = (value) => `'${String(value).replace(/'/g, `'\\''`)}'`;
14
14
 
15
+ /**
16
+ * JSON.stringify yields bare double quotes, which terminate the surrounding
17
+ * shell double-quoted string in inventory lines. Escape them so the assembled
18
+ * SYNC_INVENTORY payload stays valid JSON after sh evaluation.
19
+ * @param {string} value
20
+ */
21
+ const jsonShellEscape = (value) => JSON.stringify(value).replace(/"/g, '\\"');
22
+
15
23
  /**
16
24
  * Sanitize syncRunId for use as a single path segment under backup roots.
17
25
  * @param {string} syncRunId
@@ -202,7 +210,7 @@ export const buildRemoteSyncInventoryScript = () => {
202
210
  const quoted = shellQuote(rel);
203
211
  lines.push(`if [ -f "$CFG"/${quoted} ]; then`);
204
212
  lines.push(` BYTES="$(wc -c < "$CFG"/${quoted} | tr -d ' ')"`);
205
- lines.push(` FILES="$FILES{\\"path\\":${JSON.stringify(rel)},\\"bytes\\":$BYTES},"`);
213
+ lines.push(` FILES="$FILES{\\"path\\":${jsonShellEscape(rel)},\\"bytes\\":$BYTES},"`);
206
214
  lines.push('fi');
207
215
  }
208
216
  for (const rel of dirPaths) {
@@ -210,7 +218,7 @@ export const buildRemoteSyncInventoryScript = () => {
210
218
  lines.push(`if [ -d "$CFG"/${quoted} ]; then`);
211
219
  lines.push(` COUNT="$(find "$CFG"/${quoted} -type f ! -path '*/node_modules/*' ! -name '*.backup' 2>/dev/null | wc -l | tr -d ' ')"`);
212
220
  lines.push(` BYTES="$(find "$CFG"/${quoted} -type f ! -path '*/node_modules/*' ! -name '*.backup' -exec wc -c {} + 2>/dev/null | awk 'END{print $1+0}')"`);
213
- lines.push(` DIRS="$DIRS{\\"path\\":${JSON.stringify(rel)},\\"fileCount\\":$COUNT,\\"bytes\\":$BYTES},"`);
221
+ lines.push(` DIRS="$DIRS{\\"path\\":${jsonShellEscape(rel)},\\"fileCount\\":$COUNT,\\"bytes\\":$BYTES},"`);
214
222
  lines.push('fi');
215
223
  }
216
224
  lines.push('AGENTS="null"');
@@ -714,7 +714,9 @@ export const createUiAuth = ({
714
714
  const respondUnauthorized = (req, res) => {
715
715
  res.status(401);
716
716
  const acceptsJson = req.headers.accept?.includes('application/json');
717
- if (acceptsJson || req.path?.startsWith('/api')) {
717
+ // Express strips the mount prefix from req.path (e.g. app.use('/api') turns
718
+ // /api/mcp into /mcp), so resolve the original pathname instead.
719
+ if (acceptsJson || getRequestPathname(req).startsWith('/api')) {
718
720
  res.json({ error: 'UI authentication required', locked: true });
719
721
  } else {
720
722
  res.type('text/plain').send('Authentication required');
@@ -259,6 +259,31 @@ describe('ui auth client credential seam', () => {
259
259
  }
260
260
  });
261
261
 
262
+ it('returns JSON 401 for unauthenticated API requests mounted under a sub-app', async () => {
263
+ const createUiAuth = await loadCreateUiAuth();
264
+ const auth = createUiAuth({ password: 'secret' });
265
+
266
+ // Express strips the mount prefix: app.use('/api') turns /api/mcp into
267
+ // req.path '/mcp'. The unauthorized response must still be identified as an
268
+ // API request (JSON + locked) so clients can react to the auth gate.
269
+ const req = {
270
+ method: 'GET',
271
+ baseUrl: '/api',
272
+ path: '/mcp',
273
+ originalUrl: '/api/mcp',
274
+ url: '/api/mcp',
275
+ headers: {},
276
+ };
277
+ const res = createResponse();
278
+ let called = false;
279
+ await auth.requireAuth(req, res, () => {
280
+ called = true;
281
+ });
282
+ expect(called).toBe(false);
283
+ expect(res.statusCode).toBe(401);
284
+ expect(res.body).toEqual({ error: 'UI authentication required', locked: true });
285
+ });
286
+
262
287
  it('issues desktop client tokens with the UI session expiry', async () => {
263
288
  const createUiAuth = await loadCreateUiAuth();
264
289
  let createClientInput = null;
@@ -1 +0,0 @@
1
- import{o as e,r as t}from"./rolldown-runtime-C0FnF6B9.js";import{A as n,E as r,t as i,w as a}from"./useUIStore-NfqK-HA7.js";import{Ot as o,et as s,rt as c,yt as l}from"./persistence-vZ7H8WKh.js";import{nt as u,rt as d}from"./vendor-base-ui-CnHfUmDN.js";import{r as f}from"./platform-CTaznShj.js";import{n as p}from"./vendor-react-DLPElpoQ.js";import{r as m}from"./vendor-sonner-DVzioF3d.js";import{n as h}from"./vendor-reactuses-core-DDoDDyM9.js";import{n as g}from"./clipboard-BfgFef1i.js";import{a as _,n as v,s as y}from"./MobileShareBridge-Fvj6YxGM.js";import{$a as b,Co as x,Lo as S,Qr as C,So as w,Ui as T,Xa as E,_n as D,fa as O,gn as k,in as A,ln as j,ni as M,o as N,vn as P,wi as F}from"./useMobileNavigationStore-B-sGLR3i.js";import{_ as I,a as L,c as R,d as ee,f as te,g as ne,l as re,n as ie,o as ae,p as oe,r as se,t as z,v as B,x as V,y as ce}from"./MobileDetailNavigation-BoG7pVfo.js";import{i as le,r as ue}from"./useAssistantUIStore-ifqNyja4.js";import{t as de}from"./AgentAvatar-DAnelAnB.js";import{t as fe}from"./utils-C2P0wcWO.js";import{n as pe}from"./Icon-D-X70irR.js";import{a as H,i as me,n as he,o as U,r as W,t as G}from"./dialog-GR7KoP1o.js";import{t as ge}from"./button-CwLFtUNT.js";import{i as _e}from"./OverlayScrollbar-CHXk_jvF.js";import{I as ve,L as ye,M as be,N as K,q as xe,t as q}from"./ChatContainer-6WieMUSp.js";import{a as Se,i as Ce,n as we,r as Te,t as Ee}from"./context-menu-8RbXKyth.js";var De=p(),J=e(d(),1),Y=u(),Oe=e=>{let t=(0,De.c)(46),{assistant:n,sessionID:r,warning:i,surface:a,onRevertMessage:o,onEditMessage:s,pendingUserMessages:c,onPendingUserMessagesMaterialized:l}=e,u=n.effectiveWorkspacePath,d;t[0]!==n.sessionGeneration||t[1]!==r?(d={sessionID:r,sessionGeneration:n.sessionGeneration},t[0]=n.sessionGeneration,t[1]=r,t[2]=d):d=t[2];let p=B(n.id,d,a.active);p.data?.pages;let m;t[3]===p.data?.pages?m=t[4]:(m=p.data?.pages??[],t[3]=p.data?.pages,t[4]=m);let g;t[5]===m?g=t[6]:(g=F(m),t[5]=m,t[6]=g);let _=g,v;if(t[7]!==_){v=new Map;for(let e of _){let t=v.get(e.sessionID);v.set(e.sessionID,t===void 0||t===e.directory?e.directory:null)}t[7]=_,t[8]=v}else v=t[8];let y=v,b;t[9]===p?b=t[10]:(b=async()=>{(p.hasNextPage||p.isFetchNextPageError)&&await p.fetchNextPage()},t[9]=p,t[10]=b);let x=h(b),S=n.mode===`continuous`,C=be(),w;t[11]!==u||t[12]!==y||t[13]!==C||t[14]!==r?(w=(e,t)=>{let n=e===r?u:y.get(e);if(!n||n!==t){D(e,`missing-directory`);return}P(e,t,{phoneShell:!!(C&&!f()),switchToChat:!0})},t[11]=u,t[12]=y,t[13]=C,t[14]=r,t[15]=w):w=t[15];let T=h(w),E;t[16]===S?E=t[17]:(E={...K,forkSession:!1,navigateNestedSession:!1,mutateSession:S},t[16]=S,t[17]=E);let O;t[18]===s?O=t[19]:(O=s?{onEditMessage:s}:{},t[18]=s,t[19]=O);let k;t[20]!==u||t[21]!==o||t[22]!==T||t[23]!==r||t[24]!==a.active||t[25]!==a.surfaceID||t[26]!==E||t[27]!==O?(k={kind:`embedded`,surfaceId:a.surfaceID,sessionId:r,directory:u,active:a.active,capabilities:E,onRevertMessage:o,...O,openSourceSession:T},t[20]=u,t[21]=o,t[22]=T,t[23]=r,t[24]=a.active,t[25]=a.surfaceID,t[26]=E,t[27]=O,t[28]=k):k=t[28];let A=k,j=p.isError||p.isSuccess&&!p.hasNextPage,M=p.isLoading||p.isFetchingNextPage,N;t[29]!==x||t[30]!==j||t[31]!==_||t[32]!==M?(N={entries:_,complete:j,loading:M,fetchPrevious:x},t[29]=x,t[30]=j,t[31]=_,t[32]=M,t[33]=N):N=t[33];let I;t[34]!==u||t[35]!==l||t[36]!==o||t[37]!==c||t[38]!==r||t[39]!==A||t[40]!==a||t[41]!==N||t[42]!==i?(I={sessionId:r,directory:u,composerSurface:a,sessionSurface:A,warning:i,pendingUserMessages:c,onPendingUserMessagesMaterialized:l,assistantHistory:N,onRevertMessage:o},t[34]=u,t[35]=l,t[36]=o,t[37]=c,t[38]=r,t[39]=A,t[40]=a,t[41]=N,t[42]=i,t[43]=I):I=t[43];let L=I,R;return t[44]===L?R=t[45]:(R=(0,Y.jsx)(q,{autoOpenDraft:!1,host:L}),t[44]=L,t[45]=R),R},ke=class extends Error{constructor(){super(`assistant_selection_stale`)}},Ae=(e,t)=>e.assistantID===t.assistantID&&e.transportIdentity===t.transportIdentity&&e.runtimeGeneration===t.runtimeGeneration,je=class{onBusyChange;onError;flight=null;authoritativeIdentity=null;constructor(e,t){this.onBusyChange=e,this.onError=t}activate(e){this.authoritativeIdentity&&!Ae(this.authoritativeIdentity,e)&&this.flight&&this.retire(this.flight),this.authoritativeIdentity=e}enqueue(e,t,n){if(!this.isAuthoritative(e))return Promise.reject(new ke);let r=this.flight;r||(r={identity:e,controller:new AbortController,running:!1,desired:null,waiters:[],activeWaiters:[],idleWaiters:[],retired:!1},this.flight=r),r.desired=t;let i=new Promise((e,t)=>{r.waiters.push({resolve:e,reject:t})});return r.running||(r.running=!0,this.onBusyChange(!0),this.run(r,n)),i}async flush(e){if(!this.isAuthoritative(e))throw new ke;let t=this.flight;t?.running&&await new Promise((e,n)=>t.idleWaiters.push({resolve:e,reject:n}))}assertAuthoritative(e){if(!this.isAuthoritative(e))throw new ke}dispose(){this.flight&&this.retire(this.flight),this.authoritativeIdentity=null}async run(e,t){for(;!e.retired&&e.desired;){let n=e.desired;e.desired=null;let r=e.waiters.splice(0);e.activeWaiters=r;try{if(await t({identity:e.identity,selection:n,signal:e.controller.signal}),!e.retired)for(let e of r)e.resolve()}catch(t){if(!e.retired){this.onError(t);for(let e of r)e.reject(t)}}e.activeWaiters=[]}e.running=!1;for(let t of e.idleWaiters.splice(0))t.resolve();this.flight===e&&this.onBusyChange(!1)}retire(e){e.retired=!0,e.controller.abort();let t=new ke;for(let n of e.activeWaiters.splice(0))n.reject(t);for(let n of e.waiters.splice(0))n.reject(t);for(let n of e.idleWaiters.splice(0))n.reject(t);this.flight===e&&(this.flight=null,this.onBusyChange(!1))}isAuthoritative(e){return this.authoritativeIdentity!==null&&Ae(this.authoritativeIdentity,e)}},X=(e,t)=>{let n=t.providerID??e.providerID,r=t.modelID??e.modelID,i=n!==e.providerID||r!==e.modelID;return{enabled:e.enabled,name:e.name,defaultPrompt:e.defaultPrompt,workspacePath:e.workspacePath,providerID:n,modelID:r,agent:t.agent??null,variant:i?null:t.variant??null,mode:e.mode}},Me=async(e,t,n)=>{n.assertAuthoritative();let r=n.readSnapshot()?.assistants.find(t=>t.id===e.assistantID);if(!r)throw Error(`assistant_unavailable`);try{n.assertAuthoritative(),await n.updateAssistant(r,X(r,t)),n.assertAuthoritative()}catch(i){if(n.assertAuthoritative(),n.signal.aborted)throw new ke;if(!(i instanceof V)||i.code!==`revision_conflict`)throw i;if(n.assertAuthoritative(),r=(await n.ensureSnapshot(n.signal)).assistants.find(t=>t.id===e.assistantID),n.assertAuthoritative(),!r)throw new V(`revision_conflict`,409);n.assertAuthoritative(),await n.updateAssistant(r,X(r,t)),n.assertAuthoritative()}};async function Z(e){await L(e);let t=le.getState().defaultShareAssistant;if(t?.assistantID!==e.id)return;let n=await R();n.serverInstanceID&&t.serverInstanceID===n.serverInstanceID&&le.getState().setDefaultShareAssistant(null)}function Ne({assistant:e,open:t,onOpenChange:n,onDeleted:r}){let{t:i}=g(),[a,o]=J.useState(!1),s=e?_(e.name).displayName||e.name:``,c=h(e=>{a&&!e||n(e)}),l=h(()=>{a||n(!1)}),u=h(async()=>{if(!(!e||a)){o(!0);try{await Z(e),r?.(e.id),n(!1),m.success(i(`assistants.settings.toast.deleted`))}catch{m.error(i(`assistants.settings.toast.deleteFailed`))}finally{o(!1)}}});return(0,Y.jsx)(G,{open:t&&e!==null,onOpenChange:c,children:(0,Y.jsxs)(he,{className:`max-w-md`,children:[(0,Y.jsxs)(H,{children:[(0,Y.jsx)(U,{children:i(`assistants.settings.delete`)}),(0,Y.jsx)(W,{children:i(`assistants.settings.deleteConfirm`,{name:s})})]}),(0,Y.jsxs)(me,{children:[(0,Y.jsx)(ge,{size:`sm`,variant:`ghost`,onClick:l,disabled:a,children:i(`settings.common.actions.cancel`)}),(0,Y.jsx)(ge,{size:`sm`,variant:`destructive`,onClick:u,disabled:a,children:i(`settings.common.actions.delete`)})]})]})})}var Pe=[0,500,1500,4e3],Fe=(e,t,n)=>{let r=!1,i=e.map(e=>e.info.id!==t||e.info.sessionID===n?e:(r=!0,{...e,info:{...e.info,sessionID:n}}));return r?i:e},Ie=e=>{let t=e.refreshDelaysMs??Pe,n=e.sleep??(e=>new Promise(t=>setTimeout(t,e)));(async()=>{for(let r of t){if(r>0&&await n(r),!e.isCurrent())return;try{await e.refresh(e.binding);break}catch{}}})()},Le=e=>`${e.transport}\u0000${e.assistantID}`,Re=e=>({transport:e.transport,assistantID:e.assistantID}),ze=(e,t)=>e.assistantID===t.assistantID&&e.sessionID===t.sessionID&&e.directory===t.directory&&e.sessionGeneration===t.sessionGeneration&&e.transport===t.transport&&e.runtimeGeneration===t.runtimeGeneration,Be=(e,t)=>e.assistantID===t.assistantID&&e.sessionID===t.sessionID&&e.directory===t.directory&&e.sessionGeneration===t.sessionGeneration&&e.messageID===t.messageID&&e.transport===t.transport&&e.runtimeGeneration===t.runtimeGeneration,Ve=()=>{let e=new Map,t=new Map,n=1,r=e=>Le(e),i=async(e,n)=>{let i=r(e),a=t.get(i)??Promise.resolve(),o,s=new Promise(e=>{o=e}),c=a.catch(()=>void 0).then(()=>s);t.set(i,c),await a.catch(()=>void 0);try{return await n()}finally{o(),t.get(i)===c&&t.delete(i)}},a=(t,i)=>{let a=r(Re(t)),o=n++;return e.set(a,{identity:t,rollback:i,token:o}),o},o=t=>e.get(r(t))?.identity,s=t=>e.delete(r(t)),c=async e=>i(e,()=>s(e)),l=async t=>{let n=r(t),i=e.get(n);if(!i)return{kind:`none`};let a=i.token,o=i.identity,s;try{s=await i.rollback()}catch{return{kind:`blocked`,status:`failed`}}let c=e.get(n);return!c||c.token!==a||!Be(c.identity,o)?{kind:`superseded`}:s.status===`rolled-back`||s.status===`conflict`?(e.delete(n),{kind:`cleared`,status:s.status}):{kind:`blocked`,status:s.status}},u=async(t,n)=>{let i=r(t),a=e.get(i);if(!a)return{kind:`none`};if(ze(a.identity,n))return{kind:`match`};let o=a.token,s=a.identity,c=await a.rollback(),l=e.get(i);return!l||l.token!==o||!Be(l.identity,s)?{kind:`superseded`}:c.status===`rolled-back`||c.status===`conflict`?(e.delete(i),{kind:`cleared`,status:c.status}):{kind:`rollback_failed`,retained:!0,status:c.status}};return{register:a,read:o,clear:s,clearExclusive:c,retireCurrent:l,rollbackAndClearIfBindingMismatch:async(e,t)=>i(e,()=>u(e,t)),rollbackAllBestEffort:async t=>{let n=[...e.entries()];await Promise.all(n.map(async([,n])=>{if(t?.excludeTransport!==void 0&&n.identity.transport===t.excludeTransport)return;let a=Re(n.identity);await i(a,async()=>{let t=r(a),i=e.get(t);if(!i||i.token!==n.token)return;let o=i.token,s=i.identity;try{let n=await i.rollback(),r=e.get(t);if(!r||r.token!==o||!Be(r.identity,s))return;(n.status===`rolled-back`||n.status===`conflict`)&&e.delete(t)}catch{}})}))},stageExclusive:async(e,t)=>i(e,async()=>{let n=await l(e);if(n.kind===`blocked`)return{kind:`blocked`,status:n.status};let r=await t();if(!r)return{kind:`skipped`};let i=a(r.identity,r.rollback);return r.protectOnStale?{kind:`stale_protected`,token:i,identity:r.identity}:{kind:`registered`,token:i,identity:r.identity}})}},He=(e,t)=>!e?.attachments?.length||!t?[]:e.attachments.flatMap(e=>{let n=t[e.attachmentRefID];return n?[n]:[]}),Ue=(e,t)=>{let n=t??{};return e.map(e=>({partID:e.partID,text:e.text,...e.synthetic===!0?{synthetic:!0}:{},attachments:e.attachments.flatMap(e=>n[e.attachmentRefID]?[n[e.attachmentRefID]]:[])}))},We=(e,t)=>{if(t.length===0)return[...e];let n=new Map;for(let t of e)n.set(t.partID,t);for(let e of t)n.set(e.partID,e);let r=new Set,i=[];for(let t of e){let e=n.get(t.partID);e&&(i.push(e),r.add(t.partID))}for(let e of t)r.has(e.partID)||(i.push(e),r.add(e.partID));return i},Ge=t({AssistantView:()=>Qe}),Ke={},qe=[],Je=[],Ye=(e,t,n)=>[...e===void 0?[]:[{type:`text`,text:e}],...(t??[]).flatMap(e=>[{type:`text`,text:e.text,...e.synthetic===!0?{synthetic:!0}:{}},...(e.attachments??[]).map(e=>({type:`file`,mime:e.mimeType,url:e.dataUrl}))]),...(n??[]).map(e=>({type:`file`,mime:e.mimeType,url:e.dataUrl}))],Xe=e=>{let t=(0,De.c)(11),{assistant:n,onBack:r}=e,{t:i}=g(),a;t[0]===n?a=t[1]:(a=n?_(n.name):null,t[0]=n,t[1]=a);let o=a,s=n&&o?o.displayName||n.name:``,c;t[2]!==s||t[3]!==i?(c=s||i(`assistants.title`),t[2]=s,t[3]=i,t[4]=c):c=t[4];let l;t[5]===i?l=t[6]:(l=i(`assistants.actions.backToChat`),t[5]=i,t[6]=l);let u;return t[7]!==r||t[8]!==c||t[9]!==l?(u=(0,Y.jsx)(z,{title:c,backAriaLabel:l,onBack:r}),t[7]=r,t[8]=c,t[9]=l,t[10]=u):u=t[10],u},Ze=e=>{let t=(0,De.c)(45),{assistantID:n,displayName:r,avatarEmoji:i,modeLabel:a,selected:o,enabled:s,editLabel:c,deleteLabel:l,onSelect:u,onEdit:d,onDelete:f}=e,[p,m]=J.useState(!1),g;t[0]===u?g=t[1]:(g=()=>u(),t[0]=u,t[1]=g);let _=h(g),v;t[2]===d?v=t[3]:(v=()=>{m(!1),d()},t[2]=d,t[3]=v);let y=h(v),b;t[4]===f?b=t[5]:(b=()=>{m(!1),f()},t[4]=f,t[5]=b);let x=h(b),S;t[6]===Symbol.for(`react.memo_cache_sentinel`)?(S=e=>{e.preventDefault(),m(!0)},t[6]=S):S=t[6];let C=o?`border-border/50 bg-[var(--surface-elevated)]`:`border-transparent hover:bg-interactive-hover`,w=!s&&`opacity-65`,T;t[7]!==C||t[8]!==w?(T=fe(`flex w-full min-h-11 items-center gap-3 rounded-xl border px-3 py-3 text-left outline-none transition-[background-color,border-color,transform,opacity] duration-150 ease-out active:scale-[0.995] focus-visible:ring-2 focus-visible:ring-[var(--interactive-focus-ring)] motion-reduce:transition-none`,C,w),t[7]=C,t[8]=w,t[9]=T):T=t[9];let E;t[10]!==_||t[11]!==o||t[12]!==T?(E=(0,Y.jsx)(`button`,{type:`button`,role:`option`,"aria-selected":o,onClick:_,onContextMenu:S,className:T}),t[10]=_,t[11]=o,t[12]=T,t[13]=E):E=t[13];let D;t[14]!==n||t[15]!==i||t[16]!==r?(D=(0,Y.jsx)(de,{name:n,emoji:i,size:24,label:r}),t[14]=n,t[15]=i,t[16]=r,t[17]=D):D=t[17];let O;t[18]===r?O=t[19]:(O=(0,Y.jsx)(`span`,{className:`block truncate typography-ui-label font-medium`,children:r}),t[18]=r,t[19]=O);let k;t[20]===a?k=t[21]:(k=(0,Y.jsx)(`span`,{className:`mt-0.5 block truncate typography-micro text-muted-foreground`,children:a}),t[20]=a,t[21]=k);let A;t[22]!==O||t[23]!==k?(A=(0,Y.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[O,k]}),t[22]=O,t[23]=k,t[24]=A):A=t[24];let j;t[25]!==A||t[26]!==E||t[27]!==D?(j=(0,Y.jsxs)(Se,{render:E,children:[D,A]}),t[25]=A,t[26]=E,t[27]=D,t[28]=j):j=t[28];let M;t[29]===Symbol.for(`react.memo_cache_sentinel`)?(M=(0,Y.jsx)(pe,{name:`edit`,className:`size-4`}),t[29]=M):M=t[29];let N;t[30]!==c||t[31]!==y?(N=(0,Y.jsxs)(Te,{onClick:y,children:[M,c]}),t[30]=c,t[31]=y,t[32]=N):N=t[32];let P;t[33]===Symbol.for(`react.memo_cache_sentinel`)?(P=(0,Y.jsx)(Ce,{}),t[33]=P):P=t[33];let F;t[34]===Symbol.for(`react.memo_cache_sentinel`)?(F=(0,Y.jsx)(pe,{name:`delete-bin`,className:`size-4`}),t[34]=F):F=t[34];let I;t[35]!==l||t[36]!==x?(I=(0,Y.jsxs)(Te,{onClick:x,className:`text-[var(--status-error)] focus:text-[var(--status-error)] data-[highlighted]:text-[var(--status-error)] [&_svg]:text-[var(--status-error)]`,children:[F,l]}),t[35]=l,t[36]=x,t[37]=I):I=t[37];let L;t[38]!==N||t[39]!==I?(L=(0,Y.jsxs)(we,{className:`min-w-[10rem]`,children:[N,P,I]}),t[38]=N,t[39]=I,t[40]=L):L=t[40];let R;return t[41]!==p||t[42]!==j||t[43]!==L?(R=(0,Y.jsxs)(Ee,{open:p,onOpenChange:m,children:[j,L]}),t[41]=p,t[42]=j,t[43]=L,t[44]=R):R=t[44],R},Qe=({activeOverride:e,onMobileBack:t})=>{let{t:u}=g(),{isMobile:d}=_e(),f=be(),p=J.useSyncExternalStore(n,r,r),D=a(),P=i(e=>e.activeMainTab===`assistant`),F=e??P,L=i(e=>e.isMobile),R=d||L,z=I(),B=ce(),V=B.data,H=le(e=>e.assistantByTransport[p]??null),me=le(e=>e.selectAssistant),he=le(e=>e.requestCreate),U=V?.assistants.find(e=>e.id===H)??null,W=U?.id??``,G=U?.sessionID??``,K=U?.effectiveWorkspacePath??``,q=J.useMemo(()=>o({transportIdentity:p},`assistant:${W}`),[W,p]),Se=l(q),Ce=S(e=>e.draftAttachmentViews[Se]??Ke),we=S(e=>e.drafts[Se]),Te=J.useMemo(()=>{let e=He(we,Ce);return e.length===0?qe:e},[Ce,we]),Ee=we?.attachments,De=we?.syntheticParts,Ae=J.useMemo(()=>!Ee||!De?``:`${Ee.map(e=>e.attachmentRefID).join(``)}\u0004${De.map(e=>`${e.partID}\u0002${e.attachments.map(e=>e.attachmentRefID).join(``)}`).join(``)}`,[Ee,De]);J.useEffect(()=>{W&&S.getState().hydrateDraftAttachments(q)},[W,q,Ae]);let X=x(K||null,{enabled:!!K&&F}),Z=w(K||null,{enabled:!!K&&F}),Pe=A(G,K||void 0),Le=j(G,K||void 0),ze=k(G),Be=xe(),[Ge,Qe]=J.useState(()=>new Map),$e=J.useRef(0),et=J.useRef(Ve()),tt=Ge.get(W)??Je,[,nt]=J.useState(!1),rt=J.useRef(()=>{});rt.current=()=>{m.error(u(`assistants.composer.selectionSaveFailed`))};let it=J.useRef(null);it.current||=new je(nt,e=>rt.current(e));let at=J.useMemo(()=>({assistantID:W,transportIdentity:p,runtimeGeneration:D}),[W,D,p]),Q=it.current,ot=J.useMemo(()=>({transport:p,assistantID:W}),[W,p]),st=h(async(e,t=p)=>{await et.current.clearExclusive({transport:t,assistantID:e})}),ct=h(e=>{et.current.rollbackAllBestEffort(e).catch(()=>void 0)});J.useEffect(()=>{!H&&V?.assistants[0]&&me(V.assistants[0].id)},[me,H,V?.assistants]),J.useEffect(()=>{B.isSuccess&&H&&!U&&me(V?.assistants[0]?.id??null)},[U,me,H,V?.assistants,B.isSuccess]),J.useEffect(()=>{F&&W&&!G&&ae(W)},[F,W,G]),J.useEffect(()=>{$e.current++,Qe(new Map),ct({excludeTransport:p})},[p,D,ct]),J.useEffect(()=>()=>{$e.current++,ct()},[ct]),J.useEffect(()=>{Q.activate(at)},[Q,at]),J.useEffect(()=>()=>{Q.dispose()},[Q]),J.useEffect(()=>{W&&et.current.rollbackAndClearIfBindingMismatch(ot,{assistantID:W,sessionID:G,directory:K,sessionGeneration:U?.sessionGeneration??-1,transport:p,runtimeGeneration:D}).catch(()=>void 0)},[U?.sessionGeneration,W,K,D,G,ot,p]);let lt=h(e=>at.assistantID?Q.enqueue(at,e,async({identity:e,selection:t,signal:n})=>{await Me(e,t,{readSnapshot:()=>te(void 0,e.transportIdentity),ensureSnapshot:e=>re(e),updateAssistant:ne,signal:n,assertAuthoritative:()=>{if(Q.assertAuthoritative(e),r()!==e.transportIdentity||a()!==e.runtimeGeneration)throw new ke}})}):Promise.reject(Error(`assistant_unavailable`))),ut=J.useMemo(()=>ye(Z.data),[Z.data]),dt=h(e=>{if(!U)return;let t=E(ut,U.agent??void 0,e);if(t){let e=b({providerID:U.providerID,modelID:U.modelID,agent:U.agent},t,ut,X.data??[]),n=e.providerID===U.providerID&&e.modelID===U.modelID;lt({...e,agent:e.agent??void 0,variant:n?U.variant??void 0:void 0})}}),$=h(async(e,t)=>{e.sessionID&&await Be.ensureSessionRenderable(e.sessionID,{directory:e.directory,...t?.force?{force:!0}:{}})}),ft=U?.sessionGeneration;J.useEffect(()=>{!F||!W||!G||!K||ft===void 0||$({sessionID:G,directory:K,sessionGeneration:ft},{force:!0})},[F,W,K,$,ft,G]);let pt=h((e,t)=>{if(t.length===0)return;let n=new Set(t);Qe(t=>{let r=t.get(e);if(!r?.some(e=>n.has(e.info.id)))return t;let i=new Map(t),a=r.filter(e=>!n.has(e.info.id));return a.length>0?i.set(e,a):i.delete(e),i})}),mt=h((e,t,n)=>{Qe(r=>{let i=r.get(e);if(!i)return r;let a=Fe(i,t,n);if(a===i)return r;let o=new Map(r);return o.set(e,a),o})}),ht=h(e=>{pt(W,e)}),gt=h(async e=>{if(!G||!K)throw Error(`assistant_unavailable`);O(G,K).some(t=>t?.id===e)&&(await C(G,e,{directory:K,draftKey:q,restorePrimaryInput:!1}),await st(W))}),_t=h(async(e,t)=>{if(!U||U.mode!==`continuous`)return;if(!G||!K)throw Error(`assistant_unavailable`);if(!O(G,K).some(t=>t?.id===e))return;if(t.info.id!==e||t.info.sessionID!==G||t.info.role!==`user`)throw Error(`The selected user message is unavailable`);let n={assistantID:U.id,sessionID:G,directory:K,sessionGeneration:U.sessionGeneration,messageID:e,transport:p,runtimeGeneration:D},i=Re(n),o=await et.current.stageExclusive(i,async()=>{let i=await M(G,e,t,{directory:K,draftKey:q}),o=r()===n.transport&&a()===n.runtimeGeneration,s=o?te(void 0,n.transport)?.assistants.find(e=>e.id===n.assistantID):void 0,c=!!(s&&s.mode===`continuous`&&s.sessionID===n.sessionID&&s.sessionGeneration===n.sessionGeneration&&(s.effectiveWorkspacePath??``)===n.directory);if(o&&c)return{identity:n,rollback:()=>i.rollback()};let l=await i.rollback();return l.status===`failed`||l.status===`skipped`?{identity:n,rollback:()=>i.rollback(),protectOnStale:!0}:null});if(o.kind===`blocked`)throw Error(`assistant_stage_message_edit_prior_blocked`);if(o.kind===`stale_protected`)throw Error(`assistant_stage_message_edit_rollback_failed`)}),vt=J.useMemo(()=>{let e=T(q,()=>S.getState());return{busy:!1,attachments:Te,addAttachment:t=>e.addLocal(t),removeAttachment:t=>e.removeByAttachmentID(t),clearAttachments:()=>e.clearRootAttachments(),restoreAttachments:t=>e.restoreRootAttachments(t),pendingInput:null,consumePendingInput:()=>null,pendingPreset:null,consumePendingPreset:()=>null,consumeSyntheticParts:()=>{let e=S.getState(),t=e.draftAttachmentViews[l(q)]??Ke,n=e.consumeDraftSyntheticParts(q,y);return n?Ue(n,t):null},restoreSyntheticParts:e=>{(async()=>{let t=S.getState(),n=e.map(e=>({partID:e.partID??s(),text:e.text,attachments:[],...e.synthetic===!0?{synthetic:!0}:{}})),r=We(t.getDraft(q)?.syntheticParts??[],n);t.setDraftSyntheticParts(q,r);for(let r=0;r<n.length;r++){let i=n[r].partID;for(let n of e[r]?.attachments??[])n.source===`server`&&n.dataUrl?t.addDraftDurableAttachment(q,{attachmentID:n.id,filename:n.filename,mimeType:n.mimeType,size:n.size,source:`server`,url:n.dataUrl,serverPath:n.serverPath,partID:i}):await t.addDraftLocalAttachment(q,n.file,{attachmentID:n.id,filename:n.filename,source:n.source===`vscode`?`vscode`:`local`,vscodePath:n.vscodePath,vscodeSource:n.vscodeSource===`selection`?`selection`:void 0,partID:i})}})()},inlineDrafts:[],removeInlineDraft:()=>{},restoreInlineDrafts:()=>{},history:ze,captureRuntime:()=>S.getState().captureDraftRuntime(),getDraft:e=>S.getState().getDraft(e),abortPrompt:{sessionID:null,clear:()=>{}}}},[Te,q,ze]),yt=J.useMemo(()=>{let e=(X.data??[]).find(e=>e.id===U?.providerID)?.models?.find(e=>e.id===U?.modelID);return ve(e)},[U?.modelID,U?.providerID,X.data]),bt=Pe.length>0,xt=J.useMemo(()=>{if(!U||!G||!K)return null;let e={sessionID:G,directory:K,sessionGeneration:U.sessionGeneration};return{kind:`secondary`,surfaceID:`assistant:${U.id}`,active:F,sessionID:G,directory:K,draftKey:q,transportIdentity:p,runtimeGeneration:D,deliveryTarget:{kind:`assistant`,assistantID:U.id},resources:vt,...U.mode===`stateless`?{queueSessionID:`assistant:${U.id}`}:{},selection:{value:{providerID:U.providerID,modelID:U.modelID,agent:U.agent??void 0,variant:U.variant??void 0},catalog:{providers:X.data??[],agents:ut,variants:yt,variantsReady:X.isSuccess,ready:X.isSuccess&&Z.isSuccess,loading:X.isPending||Z.isPending,error:X.isError||Z.isError},change:lt,flush:()=>Q.flush(at)},activity:{phase:Le?.type===`busy`?`busy`:Le?.type===`retry`?`retry`:`idle`,canAbort:Le?.type===`busy`||Le?.type===`retry`},commands:{sessionID:G,hasMessages:bt,hasNewDraft:!1},commandPolicy:e=>e.name!==`fork`&&e.name!==`thread`,backend:{send:async t=>{let n;for(let t of O(e.sessionID,e.directory)){let e=typeof t?.id==`string`?t.id:``;/^msg_[0-9a-f]{12}[0-9A-Za-z]{14}$/.test(e)&&(!n||e>n)&&(n=e)}let r=c(`msg`,n);t.options?.commitStagedMessageEdit&&et.current.clear({transport:p,assistantID:U.id});let i=N({messageID:r,sessionID:e.sessionID,providerID:t.providerID??U.providerID,modelID:t.modelID??U.modelID,agent:t.agent??U.agent??void 0,text:t.text,attachments:t.attachments,additionalParts:t.parts});Qe(e=>{let t=new Map(e);return t.set(U.id,[...e.get(U.id)??[],i]),t});let a;try{a=await oe(U.id,e,r,Ye(t.text,t.parts,t.attachments))}catch(e){throw pt(U.id,[r]),e}if(z.data?.serverInstanceID){let e=_(U.name);v({serverInstanceID:z.data.serverInstanceID,assistantID:U.id,name:e.displayName||U.name,avatarSeed:U.id,...e.avatarEmoji?{avatarEmoji:e.avatarEmoji}:{}}).catch(()=>void 0)}a.binding.sessionID&&mt(U.id,r,a.binding.sessionID);let o=$e.current;Ie({binding:a.binding,refresh:t=>$(t,{force:t.sessionID!==e.sessionID||t.sessionGeneration!==e.sessionGeneration}),isCurrent:()=>$e.current===o})},sendQueued:async()=>{throw Error(`assistant-server-queue-required`)},create:async()=>{let e=await ee(U.id);await st(U.id),await $(e,{force:!0})},compact:async()=>{let t=await se(U.id,e);await st(U.id),await $(t.binding,{force:!0})},abort:async()=>{await ie(U.id,e)}},shortcuts:{cycle:dt,new:async()=>{let e=await ee(U.id);await st(U.id),await $(e,{force:!0})},abort:async()=>{await ie(U.id,e)},submit:()=>{}}}},[F,U,z.data?.serverInstanceID,lt,st,dt,K,q,bt,X.data,X.isError,X.isPending,X.isSuccess,Z.isError,Z.isPending,Z.isSuccess,$,mt,pt,vt,D,Q,at,G,Le,p,yt,ut]),St=h(()=>{if(he(),f){f.openSettings();return}let e=i.getState();e.setSettingsPage(`assistants`),e.setSettingsDialogOpen(!0)}),Ct=h(e=>{ue(e,f?{openMobileSettings:f.openSettings}:void 0)}),[wt,Tt]=J.useState(null),Et=h(e=>{Tt(e)}),Dt=h(e=>{e||Tt(null)}),Ot=h(()=>{i.getState().setActiveMainTab(`chat`)}),kt=h(()=>{if(t){t();return}Ot()}),At=(e,t,n,r)=>(0,Y.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[R?(0,Y.jsx)(Xe,{assistant:U,onBack:kt}):null,(0,Y.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col items-center justify-center px-6 text-center`,children:[(0,Y.jsx)(pe,{name:e,className:`size-6 text-muted-foreground`}),(0,Y.jsx)(`h1`,{className:`mt-4 typography-ui-header font-semibold`,children:t}),n?(0,Y.jsx)(`p`,{className:`mt-2 max-w-md typography-ui text-muted-foreground`,children:n}):null,r?(0,Y.jsx)(`div`,{className:`mt-5`,children:r}):null]})]});if(z.isPending||B.isPending)return At(`ai-agent`,u(`assistants.state.unavailable`));if(z.isError||!z.data?.supported||!z.data.enabled||!V?.enabled)return At(`cloud-off`,u(`assistants.state.unavailable`));if(!V.assistants.length)return At(`ai-agent`,u(`assistants.onboarding.title`),u(`assistants.onboarding.description`),(0,Y.jsx)(ge,{onClick:St,children:u(`assistants.onboarding.action`)}));if(!U)return At(`ai-agent`,u(`assistants.state.unavailable`));if(!xt)return(0,Y.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col bg-background`,children:[R?(0,Y.jsx)(Xe,{assistant:U,onBack:kt}):null,(0,Y.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col items-center justify-center gap-3 px-6`,"aria-busy":`true`,"aria-label":u(`assistants.state.unavailable`),children:[(0,Y.jsx)(`div`,{className:`size-10 animate-pulse rounded-xl bg-[var(--surface-muted)] motion-reduce:animate-none`}),(0,Y.jsx)(`div`,{className:`h-3.5 w-36 animate-pulse rounded-md bg-[var(--surface-muted)] motion-reduce:animate-none`})]})]});let jt=_(U.name),Mt=U.enabled?B.isError?u(`assistants.state.staleSnapshot`):null:u(`assistants.state.assistantDisabled`);return(0,Y.jsxs)(`div`,{className:`relative flex h-full min-h-0 overflow-hidden bg-background`,"data-presentation":`workspace`,children:[R?null:(0,Y.jsxs)(`section`,{className:`flex h-full min-h-0 w-[clamp(16rem,22vw,20rem)] shrink-0 flex-col overflow-hidden`,children:[(0,Y.jsx)(`header`,{className:`shrink-0 px-4 pb-3 pt-4 sm:px-5`,children:(0,Y.jsx)(`h1`,{className:`truncate typography-ui-label font-semibold text-foreground`,children:u(`assistants.title`)})}),(0,Y.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-3 pb-4 sm:px-4`,role:`listbox`,"aria-label":u(`assistants.listAria`),children:(0,Y.jsx)(`div`,{className:`flex flex-col gap-1 border-t border-border/40 pt-3`,children:V.assistants.map(e=>{let t=e.id===H,n=_(e.name);return(0,Y.jsx)(Ze,{assistantID:e.id,displayName:n.displayName,avatarEmoji:n.avatarEmoji??void 0,modeLabel:e.mode===`stateless`?u(`assistants.mode.stateless`):u(`assistants.mode.continuous`),selected:t,enabled:e.enabled,editLabel:u(`assistants.menu.edit`),deleteLabel:u(`assistants.settings.delete`),onSelect:()=>me(e.id),onEdit:()=>Ct(e.id),onDelete:()=>Et(e)},e.id)})})})]}),(0,Y.jsx)(Ne,{assistant:wt,open:wt!==null,onOpenChange:Dt}),(0,Y.jsxs)(`div`,{className:fe(`flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden bg-background`,!R&&`border-l border-border/60`),children:[R?(0,Y.jsx)(Xe,{assistant:U,onBack:kt}):(0,Y.jsxs)(`header`,{className:`flex h-14 shrink-0 items-center gap-3 border-b border-border/40 px-4 sm:px-5`,children:[(0,Y.jsx)(de,{name:U.id,emoji:jt.avatarEmoji,size:24,label:jt.displayName||U.name}),(0,Y.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Y.jsx)(`div`,{className:`truncate typography-ui-label font-medium`,children:jt.displayName}),(0,Y.jsx)(`div`,{className:`mt-0.5 truncate typography-micro leading-none text-muted-foreground/70`,children:U.mode===`stateless`?u(`assistants.conversation.statelessHint`):u(`assistants.conversation.continuousHint`)})]})]}),(0,Y.jsx)(Oe,{onRevertMessage:gt,onEditMessage:U.mode===`continuous`?_t:void 0,assistant:U,sessionID:G,warning:Mt,surface:xt,pendingUserMessages:tt,onPendingUserMessagesMaterialized:ht})]})]})};export{Ge as n,Ne as r,Qe as t};