@openchambery/web 1.18.4-beta.2 → 1.18.4-beta.21

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 (138) hide show
  1. package/bin/cli.test.js +25 -0
  2. package/bin/lib/DOCUMENTATION.md +2 -1
  3. package/bin/lib/cli-args.js +19 -0
  4. package/bin/lib/commands-serve.js +73 -4
  5. package/dist/assets/{AgentAvatar-BvhXxFvg.js → AgentAvatar-DDcjamcJ.js} +1 -1
  6. package/dist/assets/AssistantView-CBUHztv3.js +1 -0
  7. package/dist/assets/{ChatContainer-Ba2Qqd2R.js → ChatContainer-DTMkRFkU.js} +42 -42
  8. package/dist/assets/{DiagramView--CkYLtF9.js → DiagramView-H_hx57OK.js} +1 -1
  9. package/dist/assets/{FadeInOnReveal-98buIVdv.js → FadeInOnReveal-By2F9vcI.js} +1 -1
  10. package/dist/assets/{Icon-BhSwbLaF.js → Icon-DpjYnXxn.js} +1 -1
  11. package/dist/assets/{MarkdownRendererImpl-CuaQbwUx.js → MarkdownRendererImpl-DuSIWzp7.js} +1 -1
  12. package/dist/assets/{MobileDetailNavigation-ld2mS8hq.js → MobileDetailNavigation-B30JPnMG.js} +1 -1
  13. package/dist/assets/MobileShareBridge-BNGFVq24.js +4 -0
  14. package/dist/assets/MobileSurface-ib_NED0_.js +2 -0
  15. package/dist/assets/{MultiRunWindow-kryfNvF6.js → MultiRunWindow-DwFiIcie.js} +1 -1
  16. package/dist/assets/{OnboardingScreen-C1n_wVb-.js → OnboardingScreen-BKmuT7AL.js} +1 -1
  17. package/dist/assets/{OverlayScrollbar-CXFN6Cqq.js → OverlayScrollbar-Ch3J6ASR.js} +1 -1
  18. package/dist/assets/{SettingsView-BBTUVI-a.js → SettingsView-DHcIrBaL.js} +11 -11
  19. package/dist/assets/{SettingsWindow-4RS_41Wb.js → SettingsWindow-15swlv3g.js} +1 -1
  20. package/dist/assets/{TerminalView-B1he4xRe.js → TerminalView-DLl70YcD.js} +1 -1
  21. package/dist/assets/{ToolOutputDialog-ak07C60J.js → ToolOutputDialog-8g4OEYEr.js} +1 -1
  22. package/dist/assets/appThemeRegistry-DaDEaQDy.js +2 -0
  23. package/dist/assets/{button-BQY5ugjh.js → button-C7OXr4ae.js} +1 -1
  24. package/dist/assets/{clipboard-BvJ7NunE.js → clipboard-DWuULPzo.js} +1 -1
  25. package/dist/assets/{collapsible-CqcZGw3W.js → collapsible-DaEya6b6.js} +1 -1
  26. package/dist/assets/{context-menu-DSUJY2i3.js → context-menu-FwmpZgyk.js} +1 -1
  27. package/dist/assets/desktopHosts-Txp4xOVQ.js +1 -0
  28. package/dist/assets/desktopRelayRestore-C_FSEHKM.js +1 -0
  29. package/dist/assets/{diagram-B8D9Klct.js → diagram-CHfginjS.js} +1 -1
  30. package/dist/assets/{dialog-sGFkIKP2.js → dialog-DPS0W9eS.js} +1 -1
  31. package/dist/assets/{es-BuinIayO.js → es-BX0Vm3Ac.js} +4 -4
  32. package/dist/assets/fileQueries-BrUKKgPW.js +1 -0
  33. package/dist/assets/{fr-CT7us58h.js → fr-CuPzXTYx.js} +4 -4
  34. package/dist/assets/{gitApi-DtV2V_Fp.js → gitApi-Cr_QlQXs.js} +2 -2
  35. package/dist/assets/{input-CgIoxUJc.js → input-BzYA603C.js} +1 -1
  36. package/dist/assets/insertionBoundaries-D-zzR5OY.js +1 -0
  37. package/dist/assets/{ja-CCuAH4nO.js → ja-DGtzjrFO.js} +4 -4
  38. package/dist/assets/{ko-lXbhGt6P.js → ko-DZ9Di0je.js} +4 -4
  39. package/dist/assets/main-CkiZazqn.js +172 -0
  40. package/dist/assets/{main-CoNVZvj1.js → main-CttsY04u.js} +2 -2
  41. package/dist/assets/{markdown-worker-C5Om4TVK.js → markdown-worker-W06-MhF5.js} +1 -1
  42. package/dist/assets/{markdownTheme-BdF4C4-o.js → markdownTheme-B89dbj3N.js} +1 -1
  43. package/dist/assets/{miniChat-CYd1PMdJ.js → miniChat-CbXvcgmp.js} +2 -2
  44. package/dist/assets/mobile-CXNz8Y5x.js +2 -0
  45. package/dist/assets/multirun-DPXFxNKu.js +4 -0
  46. package/dist/assets/persistence-6sclr7B6.js +3 -0
  47. package/dist/assets/pl-BuCO3qb1.js +15 -0
  48. package/dist/assets/platform-CbeLpKPk.js +2 -0
  49. package/dist/assets/projectMeta-BeKggJtg.js +3 -0
  50. package/dist/assets/{pt-BR-DWbGs1bc.js → pt-BR-Brf4RMsw.js} +4 -4
  51. package/dist/assets/radio-CbhIwTx1.js +1 -0
  52. package/dist/assets/renderElectronMiniChatApp-BsNtI4rY.js +2 -0
  53. package/dist/assets/renderMobileApp-Ba7AqNsq.js +23 -0
  54. package/dist/assets/runtimeConfig-MkHvmR2Q.js +2 -0
  55. package/dist/assets/runtimeEndpointReset-CXv8MCtK.js +147 -0
  56. package/dist/assets/{sortable-tabs-strip-pSnPuBXA.js → sortable-tabs-strip-nLsPC06f.js} +1 -1
  57. package/dist/assets/src-Yqt5hwRm.css +2 -0
  58. package/dist/assets/{store-BuXogmxp.js → store-DQY8Fkb0.js} +4 -4
  59. package/dist/assets/{terminalApi-jfes-HIU.js → terminalApi-BpPeXWIu.js} +1 -1
  60. package/dist/assets/{tooltip-rN8LrxMF.js → tooltip-D_orJMYd.js} +1 -1
  61. package/dist/assets/{uk-DgOxtvS7.js → uk-C-wmaPTi.js} +4 -4
  62. package/dist/assets/{url-B0Ak7X6b.js → url-BsaBG5-1.js} +1 -1
  63. package/dist/assets/useAppFontEffects--0Fj9fci.js +7 -0
  64. package/dist/assets/{useAssistantUIStore-SPh025NE.js → useAssistantUIStore-BHsHXCKE.js} +1 -1
  65. package/dist/assets/{useDesktopWindowControlsLayout-BSHPIcFE.js → useDesktopWindowControlsLayout-Dbt0n68f.js} +1 -1
  66. package/dist/assets/{useEffectiveDirectory-Cbsu48gT.js → useEffectiveDirectory-CA5I2S-L.js} +1 -1
  67. package/dist/assets/{useFontPreferences-Bz3crRRO.js → useFontPreferences-ckzpXQaJ.js} +1 -1
  68. package/dist/assets/useMobileNavigationStore-u6UQremF.js +475 -0
  69. package/dist/assets/useSessionAutoCleanup-HxU0AYLr.js +1 -0
  70. package/dist/assets/useUIStore-DzwCfRqr.js +1 -0
  71. package/dist/assets/{useWorkerHighlightedLines-D7ZRwkm3.js → useWorkerHighlightedLines-BlvimLRz.js} +1 -1
  72. package/dist/assets/{utils-DfPDhqys.js → utils-B1EK5zKa.js} +1 -1
  73. package/dist/assets/{zh-CN-BPGatJp9.js → zh-CN-DueRrIql.js} +4 -4
  74. package/dist/assets/{zh-TW-qUWWsaxK.js → zh-TW-6875X80V.js} +4 -4
  75. package/dist/index.html +9 -9
  76. package/dist/mini-chat.html +9 -9
  77. package/dist/mobile.html +9 -9
  78. package/package.json +1 -1
  79. package/server/index.d.ts +0 -4
  80. package/server/index.js +11 -20
  81. package/server/lib/client-auth/pairing.js +1 -7
  82. package/server/lib/client-auth/pairing.test.js +0 -45
  83. package/server/lib/config-sync/config-sync.test.js +52 -0
  84. package/server/lib/config-sync/scripts.js +10 -2
  85. package/server/lib/notifications/DOCUMENTATION.md +2 -1
  86. package/server/lib/notifications/emitter-runtime.js +78 -1
  87. package/server/lib/notifications/emitter-runtime.test.js +94 -1
  88. package/server/lib/opencode/DOCUMENTATION.md +4 -4
  89. package/server/lib/opencode/bootstrap-runtime.js +0 -6
  90. package/server/lib/opencode/cli-entry-runtime.js +5 -1
  91. package/server/lib/opencode/cli-entry-runtime.test.js +17 -0
  92. package/server/lib/opencode/core-routes.js +0 -3
  93. package/server/lib/opencode/core-routes.test.js +0 -15
  94. package/server/lib/opencode/openchamber-routes.js +0 -11
  95. package/server/lib/relay/DOCUMENTATION.md +3 -45
  96. package/server/lib/relay/host-client.js +1 -4
  97. package/server/lib/relay/service.js +28 -16
  98. package/server/lib/relay/service.test.js +64 -4
  99. package/server/lib/relay/tunnel-host.js +2 -52
  100. package/server/lib/relay/tunnel-host.test.js +2 -250
  101. package/server/lib/scheduled-tasks/DOCUMENTATION.md +4 -1
  102. package/server/lib/scheduled-tasks/routes.js +51 -8
  103. package/server/lib/session-assist/DOCUMENTATION.md +4 -2
  104. package/server/lib/session-assist/runtime.js +67 -30
  105. package/server/lib/session-assist/runtime.test.js +114 -0
  106. package/server/lib/session-title/DOCUMENTATION.md +15 -10
  107. package/server/lib/session-title/runtime.js +24 -0
  108. package/server/lib/session-title/runtime.test.js +143 -0
  109. package/server/lib/ui-auth/ui-auth.js +3 -1
  110. package/server/lib/ui-auth/ui-auth.test.js +25 -0
  111. package/server/sse-routes.test.js +64 -1
  112. package/dist/assets/AssistantView-DMK-KCPX.js +0 -1
  113. package/dist/assets/MobileShareBridge-lTfofNXr.js +0 -4
  114. package/dist/assets/MobileSurface-Bc_pAGrN.js +0 -2
  115. package/dist/assets/appThemeRegistry-ChhJvOPo.js +0 -2
  116. package/dist/assets/desktopHosts-aA40MHzB.js +0 -1
  117. package/dist/assets/desktopRelayRestore-CxUYRC6v.js +0 -1
  118. package/dist/assets/fileQueries-BSE4ycQt.js +0 -1
  119. package/dist/assets/insertionBoundaries-BIS62xbD.js +0 -1
  120. package/dist/assets/main-ClQdYXuu.js +0 -172
  121. package/dist/assets/mobile-CJkbELE1.js +0 -2
  122. package/dist/assets/multirun-DfYluvqf.js +0 -4
  123. package/dist/assets/persistence-DwXJK4-j.js +0 -3
  124. package/dist/assets/pl-DCsKBRAg.js +0 -15
  125. package/dist/assets/platform-CXJwZIZe.js +0 -2
  126. package/dist/assets/projectMeta-jG2rzIks.js +0 -3
  127. package/dist/assets/radio-CIR_xKSG.js +0 -1
  128. package/dist/assets/renderElectronMiniChatApp-D6cOGBOZ.js +0 -2
  129. package/dist/assets/renderMobileApp-BuiAqCNI.js +0 -23
  130. package/dist/assets/runtimeConfig-B9P24SI-.js +0 -2
  131. package/dist/assets/runtimeEndpointReset-BLmUiRJq.js +0 -147
  132. package/dist/assets/src-DF4hiLrB.css +0 -2
  133. package/dist/assets/useAppFontEffects-DCQnaU6M.js +0 -7
  134. package/dist/assets/useMobileNavigationStore-BYiwDqQe.js +0 -476
  135. package/dist/assets/useSessionAutoCleanup-DDdudIWc.js +0 -1
  136. package/dist/assets/useUIStore-BJpkPwky.js +0 -1
  137. package/server/lib/desktop-hosts/routes.js +0 -157
  138. package/server/lib/desktop-hosts/routes.test.js +0 -227
package/bin/cli.test.js CHANGED
@@ -199,6 +199,31 @@ describe('cli args', () => {
199
199
  expect(parsed.options.name).toBe('My laptop');
200
200
  });
201
201
 
202
+ it('parses serve --relay-host with optional URL', () => {
203
+ expect(parseArgs(['serve', '--relay-host']).options.relayHost).toBe(true);
204
+ expect(parseArgs(['serve', '--relay-host', 'wss://relay.example/ws']).options.relayHost)
205
+ .toBe('wss://relay.example/ws');
206
+ expect(parseArgs(['serve', '--relay-host=wss://relay.example/ws']).options.relayHost)
207
+ .toBe('wss://relay.example/ws');
208
+ });
209
+
210
+ it('preserves ssh-remote serve runtime and writes --relay-host opt-in', async () => {
211
+ const { applyRelayHostOptIn, resolveServeRuntime } = await import('./lib/commands-serve.js');
212
+ expect(resolveServeRuntime({ OPENCHAMBER_RUNTIME: 'ssh-remote' })).toBe('ssh-remote');
213
+ expect(resolveServeRuntime({ OPENCHAMBER_RUNTIME: 'desktop' })).toBe('web');
214
+ expect(resolveServeRuntime({})).toBe('web');
215
+
216
+ const { assertServeRelayHostAllowed } = await import('./lib/commands-serve.js');
217
+ expect(() => assertServeRelayHostAllowed('web', { relayHost: true })).toThrow(/ssh-remote/);
218
+ expect(() => assertServeRelayHostAllowed('ssh-remote', { relayHost: true })).not.toThrow();
219
+
220
+ await withTempOpenChamberDataDir(async (dir) => {
221
+ applyRelayHostOptIn({ relayHost: true });
222
+ const settings = JSON.parse(fs.readFileSync(path.join(dir, 'settings.json'), 'utf8'));
223
+ expect(settings.privateRelay).toMatchObject({ enabled: true });
224
+ });
225
+ });
226
+
202
227
  it('parses connect-url api-only help', () => {
203
228
  const parsed = parseArgs(['connect-url', '--api-only', '--help']);
204
229
 
@@ -19,7 +19,8 @@ Command modules implement user-facing commands and preserve output contracts acr
19
19
  - Implements `openchamber serve`.
20
20
  - Owns OpenCode CLI checks, port resolution, log rotation, PID/instance registry writes, foreground/background server launch, startup summaries, and foreground shutdown behavior.
21
21
  - The Host process always inherits the CLI's Node executable. Do not select Bun based on PATH availability: the Web API owns `better-sqlite3` and requires the prepared Node ABI.
22
- - Sets `OPENCHAMBER_RUNTIME=web` for both foreground and daemon children so a leftover desktop env cannot host or probe the private relay.
22
+ - Sets `OPENCHAMBER_RUNTIME=web` for ordinary CLI serve (foreground and daemon) so a leftover desktop env cannot host or probe the private relay. Preserves `OPENCHAMBER_RUNTIME=ssh-remote` when SSH manager already set it.
23
+ - `--relay-host [url]` is valid only when `OPENCHAMBER_RUNTIME=ssh-remote`. It enables the private relay host before startup: writes `settings.privateRelay.enabled=true` (and optional pinned `relayUrl`), and when a URL is provided also sets `OPENCHAMBER_RELAY_URL`. Ordinary `web` serve rejects the flag.
23
24
 
24
25
  - `commands-lifecycle.js`
25
26
  - Implements `openchamber stop` and `openchamber restart`.
@@ -76,6 +76,8 @@ function parseArgs(argv = process.argv.slice(2)) {
76
76
  foreground: false,
77
77
  lan: false,
78
78
  apiOnly: false,
79
+ // false = unset; true = enable with default/stored URL; string = pin URL
80
+ relayHost: false,
79
81
  };
80
82
 
81
83
  const removedFlagErrors = [];
@@ -204,6 +206,18 @@ function parseArgs(argv = process.argv.slice(2)) {
204
206
  case 'relay':
205
207
  options.relay = true;
206
208
  break;
209
+ case 'relay-host': {
210
+ // Optional value: `--relay-host` enables with default/stored URL;
211
+ // `--relay-host wss://…` (or `=`) pins a custom endpoint.
212
+ const { value, nextIndex } = consumeValue(i, inlineValue);
213
+ i = nextIndex;
214
+ if (typeof value === 'string' && value.trim().length > 0) {
215
+ options.relayHost = value.trim();
216
+ } else {
217
+ options.relayHost = true;
218
+ }
219
+ break;
220
+ }
207
221
  case 'qr':
208
222
  options.qr = true;
209
223
  options.explicitQr = true;
@@ -305,6 +319,8 @@ OPTIONS:
305
319
  --lan Bind to 0.0.0.0 for LAN access
306
320
  --server <url> Public/server URL for connect-url links
307
321
  --relay connect-url: also include the end-to-end-encrypted relay transport
322
+ --relay-host [url] serve: enable the private relay host (desktop/SSH-remote only).
323
+ Optional ws(s) URL pins the relay endpoint.
308
324
  --ui-password Protect browser UI with single password
309
325
  --api-only Start API routes only, without serving browser UI assets
310
326
  --foreground Run server in foreground (use with systemd/process managers)
@@ -317,6 +333,7 @@ ENVIRONMENT:
317
333
  OPENCHAMBER_UI_PASSWORD Alternative to --ui-password flag
318
334
  OPENCHAMBER_API_ONLY Set to true/1 to start API routes only
319
335
  OPENCHAMBER_DATA_DIR Override OpenChamber data directory
336
+ OPENCHAMBER_RELAY_URL Pin private relay endpoint (ws:// or wss://)
320
337
  OPENCODE_HOST External OpenCode server base URL, e.g. http://hostname:4096
321
338
  OPENCODE_PORT Port of external OpenCode server to connect to
322
339
  OPENCODE_SKIP_START Skip starting OpenCode, use external server
@@ -327,6 +344,8 @@ EXAMPLES:
327
344
  openchamber --port 8080 # Start on port 8080 (daemon)
328
345
  openchamber --lan --port 3002 # Start on LAN at 0.0.0.0:3002
329
346
  openchamber serve --foreground # Start in foreground (for systemd Type=simple)
347
+ openchamber serve --relay-host # Enable private relay host (SSH-managed remote)
348
+ openchamber serve --relay-host wss://relay.example/ws
330
349
  openchamber connect-url --port 3000 --qr
331
350
  openchamber connect-url --server https://openchamber.example.com
332
351
  openchamber startup enable # Start OpenChamber at user login
@@ -1,15 +1,20 @@
1
1
  import fs from 'fs';
2
+ import path from 'path';
2
3
  import { pathToFileURL } from 'url';
3
4
  import { spawn } from 'child_process';
4
5
  import { EXIT_CODE, TunnelCliError } from './cli-errors.js';
5
6
  import { buildLocalUrl, resolveServeHost, assertSafeBrowserPort, hasUiPasswordConfigured, assertAuthenticatedNetworkExposure } from './cli-network.js';
6
7
  import { fetchSystemInfoFromPort } from './cli-http.js';
7
8
  import { isPortAvailable, resolveAvailablePort } from './cli-ports.js';
8
- import { ensureLogsDir, getLogFilePath } from './cli-paths.js';
9
+ import { ensureLogsDir, getDataDir, getLogFilePath } from './cli-paths.js';
9
10
  import { rotateLogFile } from './cli-log-files.js';
10
11
  import { discoverOpenChamberInstanceOnPort, isDesktopRuntimeForPort } from './cli-lifecycle.js';
11
12
  import { getPidFilePath, getInstanceFilePath, writePidFile, writeInstanceOptions, removePidFile, removeInstanceFile, isProcessRunning, terminateProcessTree } from './cli-process.js';
12
13
  import { isNetworkExposedBindHost } from '../../server/lib/security/bind-host.js';
14
+ import {
15
+ canonicalizeRelayUrl,
16
+ DEFAULT_RELAY_URL,
17
+ } from '../../server/lib/relay/service.js';
13
18
  import {
14
19
  intro as clackIntro,
15
20
  outro as clackOutro,
@@ -22,6 +27,67 @@ import {
22
27
  } from '../cli-output.js';
23
28
 
24
29
  const DAEMON_READY_TIMEOUT_MS = 30000;
30
+ const SETTINGS_FILE_NAME = 'settings.json';
31
+
32
+ // Ordinary CLI serve must not inherit a leftover desktop env and become a
33
+ // relay host. SSH-manager remotes set OPENCHAMBER_RUNTIME=ssh-remote and may
34
+ // pass --relay-host — preserve that so the remote can host a private relay.
35
+ function resolveServeRuntime(env = process.env) {
36
+ return env?.OPENCHAMBER_RUNTIME === 'ssh-remote' ? 'ssh-remote' : 'web';
37
+ }
38
+
39
+ function assertServeRelayHostAllowed(serveRuntime, options) {
40
+ if (options?.relayHost && serveRuntime !== 'ssh-remote') {
41
+ throw new TunnelCliError(
42
+ '--relay-host is only valid for an SSH-managed remote (OPENCHAMBER_RUNTIME=ssh-remote). Ordinary `openchamber serve` cannot host the private relay.',
43
+ EXIT_CODE.USAGE_ERROR,
44
+ );
45
+ }
46
+ }
47
+
48
+ // Persist privateRelay.enabled before the server starts so reconcile /
49
+ // startIfEnabled sees the opt-in. Optional URL pins the endpoint in settings
50
+ // and OPENCHAMBER_RELAY_URL (env override stays authoritative while set).
51
+ function applyRelayHostOptIn(options) {
52
+ if (!options?.relayHost) return;
53
+
54
+ let pinnedUrl = null;
55
+ if (typeof options.relayHost === 'string') {
56
+ pinnedUrl = canonicalizeRelayUrl(options.relayHost);
57
+ if (!pinnedUrl) {
58
+ throw new TunnelCliError(
59
+ 'Invalid --relay-host URL. Use a ws:// or wss:// URL without credentials.',
60
+ EXIT_CODE.USAGE_ERROR,
61
+ );
62
+ }
63
+ process.env.OPENCHAMBER_RELAY_URL = pinnedUrl;
64
+ }
65
+
66
+ const settingsPath = path.join(getDataDir(), SETTINGS_FILE_NAME);
67
+ let settings = {};
68
+ try {
69
+ settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
70
+ if (!settings || typeof settings !== 'object' || Array.isArray(settings)) settings = {};
71
+ } catch {
72
+ settings = {};
73
+ }
74
+
75
+ const existingUrl = typeof settings?.privateRelay?.relayUrl === 'string'
76
+ ? settings.privateRelay.relayUrl
77
+ : null;
78
+ const relayUrl = pinnedUrl
79
+ ?? (canonicalizeRelayUrl(existingUrl) || DEFAULT_RELAY_URL);
80
+
81
+ fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
82
+ fs.writeFileSync(
83
+ settingsPath,
84
+ `${JSON.stringify({
85
+ ...settings,
86
+ privateRelay: { enabled: true, relayUrl },
87
+ }, null, 2)}\n`,
88
+ 'utf8',
89
+ );
90
+ }
25
91
 
26
92
  function createServeCommand({
27
93
  serverPath,
@@ -103,6 +169,9 @@ async function serveCommand(options) {
103
169
  // package scripts. Selecting Bun merely because it is installed makes an
104
170
  // otherwise valid CLI launch fail before the Host can report readiness.
105
171
  const runtimeBin = process.execPath;
172
+ const serveRuntime = resolveServeRuntime();
173
+ assertServeRelayHostAllowed(serveRuntime, options);
174
+ applyRelayHostOptIn(options);
106
175
 
107
176
  ensureLogsDir();
108
177
  const initialLogPort = targetPort === 0 ? 'auto' : String(targetPort);
@@ -156,7 +225,7 @@ async function serveCommand(options) {
156
225
  process.env.OPENCHAMBER_UI_PASSWORD = effectiveUiPassword;
157
226
  }
158
227
  process.env.OPENCHAMBER_HOST = effectiveHost;
159
- process.env.OPENCHAMBER_RUNTIME = 'web';
228
+ process.env.OPENCHAMBER_RUNTIME = serveRuntime;
160
229
 
161
230
  // In --quiet mode, redirect stdout/stderr to the log file so that
162
231
  // server runtime output (console.log calls) does not pollute the
@@ -270,7 +339,7 @@ async function serveCommand(options) {
270
339
  env: {
271
340
  ...process.env,
272
341
  OPENCHAMBER_PORT: String(targetPort),
273
- OPENCHAMBER_RUNTIME: 'web',
342
+ OPENCHAMBER_RUNTIME: serveRuntime,
274
343
  OPENCODE_BINARY: opencodeBinary,
275
344
  OPENCHAMBER_HOST: effectiveHost,
276
345
  ...(effectiveUiPassword ? { OPENCHAMBER_UI_PASSWORD: effectiveUiPassword } : {}),
@@ -393,4 +462,4 @@ async function serveCommand(options) {
393
462
  return serveCommand;
394
463
  }
395
464
 
396
- export { createServeCommand };
465
+ export { createServeCommand, resolveServeRuntime, applyRelayHostOptIn, assertServeRelayHostAllowed };
@@ -1 +1 @@
1
- import"./rolldown-runtime-C0FnF6B9.js";import{nt as e,rt as t}from"./vendor-base-ui-CnHfUmDN.js";import{n}from"./vendor-react-DLPElpoQ.js";import{t as r}from"./utils-DfPDhqys.js";t();var i=n(),a=[{var:`--status-success`,class:`agent-success`},{var:`--syntax-keyword`,class:`agent-keyword`},{var:`--syntax-type`,class:`agent-type`},{var:`--syntax-function`,class:`agent-function`},{var:`--syntax-number`,class:`agent-number`},{var:`--status-info`,class:`agent-info`},{var:`--status-warning`,class:`agent-warning`},{var:`--syntax-variable`,class:`agent-variable`}];function o(e){if(!e||e===`build`)return a[0];let t=0;for(let n=0;n<e.length;n++){let r=e.charCodeAt(n);t=(t<<5)-t+r,t&=t}return a[1+Math.abs(t)%(a.length-1)]}var s=5,c=Math.ceil(s/2);function l(e){let t=0;for(let n=0;n<e.length;n++)t=(t<<5)-t+e.charCodeAt(n),t|=0;return t>>>0}function u(e){let t=Array.from({length:s},()=>Array.from({length:s},()=>!1));if(!e)return t;let n=l(e);for(let e=0;e<s;e++)for(let r=0;r<c;r++){let i=(n&1)==1;n>>>=1,t[e][r]=i,t[e][4-r]=i}return t}var d=e(),f=e=>{let t=(0,i.c)(27),{name:n,emoji:a,size:s,className:c,label:l}=e,f=s===void 0?16:s,m,h,g;if(t[0]!==c||t[1]!==a||t[2]!==n){m=o(n);let e;t[6]===n?e=t[7]:(e=u(n),t[6]=n,t[7]=e),h=e,g=r(`inline-flex aspect-square shrink-0 overflow-hidden rounded-sm`,a&&`items-center justify-center select-none`,m.class,c),t[0]=c,t[1]=a,t[2]=n,t[3]=m,t[4]=h,t[5]=g}else m=t[3],h=t[4],g=t[5];let _=`calc(${f}px * var(--dpt-n, 1))`,v=`calc(${f}px * var(--dpt-n, 1))`,y=`calc(${f}px * var(--dpt-n, 1))`,b=`calc(${f}px * var(--dpt-n, 1))`,x=`calc(${f}px * var(--dpt-n, 1))`,S=`calc(${f}px * var(--dpt-n, 1))`,C=`var(${m.var})`,w;t[8]!==_||t[9]!==v||t[10]!==y||t[11]!==b||t[12]!==x||t[13]!==S||t[14]!==C?(w={width:_,minWidth:v,maxWidth:y,height:b,minHeight:x,maxHeight:S,color:C},t[8]=_,t[9]=v,t[10]=y,t[11]=b,t[12]=x,t[13]=S,t[14]=C,t[15]=w):w=t[15];let T=l?`img`:void 0,E=!l||void 0,D;t[16]!==a||t[17]!==h||t[18]!==f?(D=a?(0,d.jsx)(`span`,{"aria-hidden":`true`,style:{fontSize:`calc(${f*.75}px * var(--dpt-n, 1))`,lineHeight:1},children:a}):(0,d.jsxs)(`svg`,{width:f,height:f,viewBox:`0 0 5 5`,shapeRendering:`crispEdges`,className:`oc-agent-avatar block h-full w-full`,"aria-hidden":`true`,children:[(0,d.jsx)(`rect`,{width:`5`,height:`5`,fill:`currentColor`,opacity:.14}),h.map(p)]}),t[16]=a,t[17]=h,t[18]=f,t[19]=D):D=t[19];let O;return t[20]!==l||t[21]!==w||t[22]!==T||t[23]!==E||t[24]!==D||t[25]!==g?(O=(0,d.jsx)(`span`,{className:g,style:w,role:T,"aria-label":l,"aria-hidden":E,children:D}),t[20]=l,t[21]=w,t[22]=T,t[23]=E,t[24]=D,t[25]=g,t[26]=O):O=t[26],O};function p(e,t){return e.map((e,n)=>e?(0,d.jsx)(`rect`,{x:n,y:t,width:`1`,height:`1`,fill:`currentColor`},`${n}-${t}`):null)}export{o as n,f as t};
1
+ import"./rolldown-runtime-C0FnF6B9.js";import{nt as e,rt as t}from"./vendor-base-ui-CnHfUmDN.js";import{n}from"./vendor-react-DLPElpoQ.js";import{t as r}from"./utils-B1EK5zKa.js";t();var i=n(),a=[{var:`--status-success`,class:`agent-success`},{var:`--syntax-keyword`,class:`agent-keyword`},{var:`--syntax-type`,class:`agent-type`},{var:`--syntax-function`,class:`agent-function`},{var:`--syntax-number`,class:`agent-number`},{var:`--status-info`,class:`agent-info`},{var:`--status-warning`,class:`agent-warning`},{var:`--syntax-variable`,class:`agent-variable`}];function o(e){if(!e||e===`build`)return a[0];let t=0;for(let n=0;n<e.length;n++){let r=e.charCodeAt(n);t=(t<<5)-t+r,t&=t}return a[1+Math.abs(t)%(a.length-1)]}var s=5,c=Math.ceil(s/2);function l(e){let t=0;for(let n=0;n<e.length;n++)t=(t<<5)-t+e.charCodeAt(n),t|=0;return t>>>0}function u(e){let t=Array.from({length:s},()=>Array.from({length:s},()=>!1));if(!e)return t;let n=l(e);for(let e=0;e<s;e++)for(let r=0;r<c;r++){let i=(n&1)==1;n>>>=1,t[e][r]=i,t[e][4-r]=i}return t}var d=e(),f=e=>{let t=(0,i.c)(27),{name:n,emoji:a,size:s,className:c,label:l}=e,f=s===void 0?16:s,m,h,g;if(t[0]!==c||t[1]!==a||t[2]!==n){m=o(n);let e;t[6]===n?e=t[7]:(e=u(n),t[6]=n,t[7]=e),h=e,g=r(`inline-flex aspect-square shrink-0 overflow-hidden rounded-sm`,a&&`items-center justify-center select-none`,m.class,c),t[0]=c,t[1]=a,t[2]=n,t[3]=m,t[4]=h,t[5]=g}else m=t[3],h=t[4],g=t[5];let _=`calc(${f}px * var(--dpt-n, 1))`,v=`calc(${f}px * var(--dpt-n, 1))`,y=`calc(${f}px * var(--dpt-n, 1))`,b=`calc(${f}px * var(--dpt-n, 1))`,x=`calc(${f}px * var(--dpt-n, 1))`,S=`calc(${f}px * var(--dpt-n, 1))`,C=`var(${m.var})`,w;t[8]!==_||t[9]!==v||t[10]!==y||t[11]!==b||t[12]!==x||t[13]!==S||t[14]!==C?(w={width:_,minWidth:v,maxWidth:y,height:b,minHeight:x,maxHeight:S,color:C},t[8]=_,t[9]=v,t[10]=y,t[11]=b,t[12]=x,t[13]=S,t[14]=C,t[15]=w):w=t[15];let T=l?`img`:void 0,E=!l||void 0,D;t[16]!==a||t[17]!==h||t[18]!==f?(D=a?(0,d.jsx)(`span`,{"aria-hidden":`true`,style:{fontSize:`calc(${f*.75}px * var(--dpt-n, 1))`,lineHeight:1},children:a}):(0,d.jsxs)(`svg`,{width:f,height:f,viewBox:`0 0 5 5`,shapeRendering:`crispEdges`,className:`oc-agent-avatar block h-full w-full`,"aria-hidden":`true`,children:[(0,d.jsx)(`rect`,{width:`5`,height:`5`,fill:`currentColor`,opacity:.14}),h.map(p)]}),t[16]=a,t[17]=h,t[18]=f,t[19]=D):D=t[19];let O;return t[20]!==l||t[21]!==w||t[22]!==T||t[23]!==E||t[24]!==D||t[25]!==g?(O=(0,d.jsx)(`span`,{className:g,style:w,role:T,"aria-label":l,"aria-hidden":E,children:D}),t[20]=l,t[21]=w,t[22]=T,t[23]=E,t[24]=D,t[25]=g,t[26]=O):O=t[26],O};function p(e,t){return e.map((e,n)=>e?(0,d.jsx)(`rect`,{x:n,y:t,width:`1`,height:`1`,fill:`currentColor`},`${n}-${t}`):null)}export{o as n,f as t};
@@ -0,0 +1 @@
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-DzwCfRqr.js";import{Ot as o,et as s,rt as c,yt as l}from"./persistence-6sclr7B6.js";import{nt as u,rt as d}from"./vendor-base-ui-CnHfUmDN.js";import{r as f}from"./platform-CbeLpKPk.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-DWuULPzo.js";import{a as _,n as v,s as y}from"./MobileShareBridge-BNGFVq24.js";import{Fo as b,Ja as x,Si as S,Vi as C,Xr as w,Za as T,_n as E,bo as D,cn as O,ei as k,gn as A,hn as j,o as M,rn as N,ua as P,xo as F}from"./useMobileNavigationStore-u6UQremF.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 ce,x as B,y as le}from"./MobileDetailNavigation-B30JPnMG.js";import{i as ue,r as de}from"./useAssistantUIStore-BHsHXCKE.js";import{t as fe}from"./AgentAvatar-DDcjamcJ.js";import{t as pe}from"./utils-B1EK5zKa.js";import{n as me}from"./Icon-DpjYnXxn.js";import{a as V,i as he,n as ge,o as H,r as U,t as W}from"./dialog-DPS0W9eS.js";import{t as _e}from"./button-C7OXr4ae.js";import{i as ve}from"./OverlayScrollbar-Ch3J6ASR.js";import{J as ye,L as be,N as xe,P as G,R as Se,t as K}from"./ChatContainer-DTMkRFkU.js";import{a as Ce,i as we,n as Te,r as Ee,t as De}from"./context-menu-FwmpZgyk.js";var q=p(),J=e(d(),1),Y=u(),Oe=e=>{let t=(0,q.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=ce(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=S(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),C=n.mode===`continuous`,w=xe(),T;t[11]!==u||t[12]!==y||t[13]!==w||t[14]!==r?(T=(e,t)=>{let n=e===r?u:y.get(e);if(!n||n!==t){A(e,`missing-directory`);return}E(e,t,{phoneShell:!!(w&&!f()),switchToChat:!0})},t[11]=u,t[12]=y,t[13]=w,t[14]=r,t[15]=T):T=t[15];let D=h(T),O;t[16]===C?O=t[17]:(O={...G,forkSession:!1,navigateNestedSession:!1,mutateSession:C},t[16]=C,t[17]=O);let k;t[18]===s?k=t[19]:(k=s?{onEditMessage:s}:{},t[18]=s,t[19]=k);let j;t[20]!==u||t[21]!==o||t[22]!==D||t[23]!==r||t[24]!==a.active||t[25]!==a.surfaceID||t[26]!==O||t[27]!==k?(j={kind:`embedded`,surfaceId:a.surfaceID,sessionId:r,directory:u,active:a.active,capabilities:O,onRevertMessage:o,...k,openSourceSession:D},t[20]=u,t[21]=o,t[22]=D,t[23]=r,t[24]=a.active,t[25]=a.surfaceID,t[26]=O,t[27]=k,t[28]=j):j=t[28];let M=j,N=p.isError||p.isSuccess&&!p.hasNextPage,P=p.isLoading||p.isFetchingNextPage,F;t[29]!==x||t[30]!==N||t[31]!==_||t[32]!==P?(F={entries:_,complete:N,loading:P,fetchPrevious:x},t[29]=x,t[30]=N,t[31]=_,t[32]=P,t[33]=F):F=t[33];let I;t[34]!==u||t[35]!==l||t[36]!==o||t[37]!==c||t[38]!==r||t[39]!==M||t[40]!==a||t[41]!==F||t[42]!==i?(I={sessionId:r,directory:u,composerSurface:a,sessionSurface:M,warning:i,pendingUserMessages:c,onPendingUserMessagesMaterialized:l,assistantHistory:F,onRevertMessage:o},t[34]=u,t[35]=l,t[36]=o,t[37]=c,t[38]=r,t[39]=M,t[40]=a,t[41]=F,t[42]=i,t[43]=I):I=t[43];let L=I,R;return t[44]===L?R=t[45]:(R=(0,Y.jsx)(K,{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 B)||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 B(`revision_conflict`,409);n.assertAuthoritative(),await n.updateAssistant(r,X(r,t)),n.assertAuthoritative()}};async function Z(e){await L(e);let t=ue.getState().defaultShareAssistant;if(t?.assistantID!==e.id)return;let n=await R();n.serverInstanceID&&t.serverInstanceID===n.serverInstanceID&&ue.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)(W,{open:t&&e!==null,onOpenChange:c,children:(0,Y.jsxs)(ge,{className:`max-w-md`,children:[(0,Y.jsxs)(V,{children:[(0,Y.jsx)(H,{children:i(`assistants.settings.delete`)}),(0,Y.jsx)(U,{children:i(`assistants.settings.deleteConfirm`,{name:s})})]}),(0,Y.jsxs)(he,{children:[(0,Y.jsx)(_e,{size:`sm`,variant:`ghost`,onClick:l,disabled:a,children:i(`settings.common.actions.cancel`)}),(0,Y.jsx)(_e,{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,q.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,q.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=pe(`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)(fe,{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)(Ce,{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)(me,{name:`edit`,className:`size-4`}),t[29]=M):M=t[29];let N;t[30]!==c||t[31]!==y?(N=(0,Y.jsxs)(Ee,{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)(we,{}),t[33]=P):P=t[33];let F;t[34]===Symbol.for(`react.memo_cache_sentinel`)?(F=(0,Y.jsx)(me,{name:`delete-bin`,className:`size-4`}),t[34]=F):F=t[34];let I;t[35]!==l||t[36]!==x?(I=(0,Y.jsxs)(Ee,{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)(Te,{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)(De,{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}=ve(),f=xe(),p=J.useSyncExternalStore(n,r,r),S=a(),E=i(e=>e.activeMainTab===`assistant`),A=e??E,L=i(e=>e.isMobile),R=d||L,z=I(),ce=le(),B=ce.data,V=ue(e=>e.assistantByTransport[p]??null),he=ue(e=>e.selectAssistant),ge=ue(e=>e.requestCreate),H=B?.assistants.find(e=>e.id===V)??null,U=H?.id??``,W=H?.sessionID??``,G=H?.effectiveWorkspacePath??``,K=J.useMemo(()=>o({transportIdentity:p},`assistant:${U}`),[U,p]),Ce=l(K),we=b(e=>e.draftAttachmentViews[Ce]??Ke),Te=b(e=>e.drafts[Ce]),Ee=J.useMemo(()=>{let e=He(Te,we);return e.length===0?qe:e},[we,Te]),De=Te?.attachments,q=Te?.syntheticParts,Ae=J.useMemo(()=>!De||!q?``:`${De.map(e=>e.attachmentRefID).join(``)}\u0004${q.map(e=>`${e.partID}\u0002${e.attachments.map(e=>e.attachmentRefID).join(``)}`).join(``)}`,[De,q]);J.useEffect(()=>{U&&b.getState().hydrateDraftAttachments(K)},[U,K,Ae]);let X=F(G||null,{enabled:!!G&&A}),Z=D(G||null,{enabled:!!G&&A}),Pe=N(W,G||void 0),Le=O(W,G||void 0),ze=j(W),Be=ye(),[Ge,Qe]=J.useState(()=>new Map),$e=J.useRef(0),et=J.useRef(Ve()),tt=Ge.get(U)??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:U,transportIdentity:p,runtimeGeneration:S}),[U,S,p]),Q=it.current,ot=J.useMemo(()=>({transport:p,assistantID:U}),[U,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(()=>{!V&&B?.assistants[0]&&he(B.assistants[0].id)},[he,V,B?.assistants]),J.useEffect(()=>{ce.isSuccess&&V&&!H&&he(B?.assistants[0]?.id??null)},[H,he,V,B?.assistants,ce.isSuccess]),J.useEffect(()=>{A&&U&&!W&&ae(U)},[A,U,W]),J.useEffect(()=>{$e.current++,Qe(new Map),ct({excludeTransport:p})},[p,S,ct]),J.useEffect(()=>()=>{$e.current++,ct()},[ct]),J.useEffect(()=>{Q.activate(at)},[Q,at]),J.useEffect(()=>()=>{Q.dispose()},[Q]),J.useEffect(()=>{U&&et.current.rollbackAndClearIfBindingMismatch(ot,{assistantID:U,sessionID:W,directory:G,sessionGeneration:H?.sessionGeneration??-1,transport:p,runtimeGeneration:S}).catch(()=>void 0)},[H?.sessionGeneration,U,G,S,W,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(()=>Se(Z.data),[Z.data]),dt=h(e=>{if(!H)return;let t=x(ut,H.agent??void 0,e);if(t){let e=T({providerID:H.providerID,modelID:H.modelID,agent:H.agent},t,ut,X.data??[]),n=e.providerID===H.providerID&&e.modelID===H.modelID;lt({...e,agent:e.agent??void 0,variant:n?H.variant??void 0:void 0})}}),$=h(async(e,t)=>{e.sessionID&&await Be.ensureSessionRenderable(e.sessionID,{directory:e.directory,...t?.force?{force:!0}:{}})}),ft=H?.sessionGeneration;J.useEffect(()=>{!A||!U||!W||!G||ft===void 0||$({sessionID:W,directory:G,sessionGeneration:ft},{force:!0})},[A,U,G,$,ft,W]);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(U,e)}),gt=h(async e=>{if(!W||!G)throw Error(`assistant_unavailable`);P(W,G).some(t=>t?.id===e)&&(await w(W,e,{directory:G,draftKey:K,restorePrimaryInput:!1}),await st(U))}),_t=h(async(e,t)=>{if(!H||H.mode!==`continuous`)return;if(!W||!G)throw Error(`assistant_unavailable`);if(!P(W,G).some(t=>t?.id===e))return;if(t.info.id!==e||t.info.sessionID!==W||t.info.role!==`user`)throw Error(`The selected user message is unavailable`);let n={assistantID:H.id,sessionID:W,directory:G,sessionGeneration:H.sessionGeneration,messageID:e,transport:p,runtimeGeneration:S},i=Re(n),o=await et.current.stageExclusive(i,async()=>{let i=await k(W,e,t,{directory:G,draftKey:K}),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=C(K,()=>b.getState());return{busy:!1,attachments:Ee,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=b.getState(),t=e.draftAttachmentViews[l(K)]??Ke,n=e.consumeDraftSyntheticParts(K,y);return n?Ue(n,t):null},restoreSyntheticParts:e=>{(async()=>{let t=b.getState(),n=e.map(e=>({partID:e.partID??s(),text:e.text,attachments:[],...e.synthetic===!0?{synthetic:!0}:{}})),r=We(t.getDraft(K)?.syntheticParts??[],n);t.setDraftSyntheticParts(K,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(K,{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(K,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:()=>b.getState().captureDraftRuntime(),getDraft:e=>b.getState().getDraft(e),abortPrompt:{sessionID:null,clear:()=>{}}}},[Ee,K,ze]),yt=J.useMemo(()=>{let e=(X.data??[]).find(e=>e.id===H?.providerID)?.models?.find(e=>e.id===H?.modelID);return be(e)},[H?.modelID,H?.providerID,X.data]),bt=Pe.length>0,xt=J.useMemo(()=>{if(!H||!W||!G)return null;let e={sessionID:W,directory:G,sessionGeneration:H.sessionGeneration};return{kind:`secondary`,surfaceID:`assistant:${H.id}`,active:A,sessionID:W,directory:G,draftKey:K,transportIdentity:p,runtimeGeneration:S,deliveryTarget:{kind:`assistant`,assistantID:H.id},resources:vt,...H.mode===`stateless`?{queueSessionID:`assistant:${H.id}`}:{},selection:{value:{providerID:H.providerID,modelID:H.modelID,agent:H.agent??void 0,variant:H.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:W,hasMessages:bt,hasNewDraft:!1},commandPolicy:e=>e.name!==`fork`&&e.name!==`thread`,backend:{send:async t=>{let n;for(let t of P(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:H.id});let i=M({messageID:r,sessionID:e.sessionID,providerID:t.providerID??H.providerID,modelID:t.modelID??H.modelID,agent:t.agent??H.agent??void 0,text:t.text,attachments:t.attachments,additionalParts:t.parts});Qe(e=>{let t=new Map(e);return t.set(H.id,[...e.get(H.id)??[],i]),t});let a;try{a=await oe(H.id,e,r,Ye(t.text,t.parts,t.attachments))}catch(e){throw pt(H.id,[r]),e}if(z.data?.serverInstanceID){let e=_(H.name);v({serverInstanceID:z.data.serverInstanceID,assistantID:H.id,name:e.displayName||H.name,avatarSeed:H.id,...e.avatarEmoji?{avatarEmoji:e.avatarEmoji}:{}}).catch(()=>void 0)}a.binding.sessionID&&mt(H.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(H.id);await st(H.id),await $(e,{force:!0})},compact:async()=>{let t=await se(H.id,e);await st(H.id),await $(t.binding,{force:!0})},abort:async()=>{await ie(H.id,e)}},shortcuts:{cycle:dt,new:async()=>{let e=await ee(H.id);await st(H.id),await $(e,{force:!0})},abort:async()=>{await ie(H.id,e)},submit:()=>{}}}},[A,H,z.data?.serverInstanceID,lt,st,dt,G,K,bt,X.data,X.isError,X.isPending,X.isSuccess,Z.isError,Z.isPending,Z.isSuccess,$,mt,pt,vt,S,Q,at,W,Le,p,yt,ut]),St=h(()=>{if(ge(),f){f.openSettings();return}let e=i.getState();e.setSettingsPage(`assistants`),e.setSettingsDialogOpen(!0)}),Ct=h(e=>{de(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:H,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)(me,{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||ce.isPending)return At(`ai-agent`,u(`assistants.state.unavailable`));if(z.isError||!z.data?.supported||!z.data.enabled||!B?.enabled)return At(`cloud-off`,u(`assistants.state.unavailable`));if(!B.assistants.length)return At(`ai-agent`,u(`assistants.onboarding.title`),u(`assistants.onboarding.description`),(0,Y.jsx)(_e,{onClick:St,children:u(`assistants.onboarding.action`)}));if(!H)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:H,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=_(H.name),Mt=H.enabled?ce.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:B.assistants.map(e=>{let t=e.id===V,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:()=>he(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:pe(`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:H,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)(fe,{name:H.id,emoji:jt.avatarEmoji,size:24,label:jt.displayName||H.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:H.mode===`stateless`?u(`assistants.conversation.statelessHint`):u(`assistants.conversation.continuousHint`)})]})]}),(0,Y.jsx)(Oe,{onRevertMessage:gt,onEditMessage:H.mode===`continuous`?_t:void 0,assistant:H,sessionID:W,warning:Mt,surface:xt,pendingUserMessages:tt,onPendingUserMessagesMaterialized:ht})]})]})};export{Ge as n,Ne as r,Qe as t};