@openchambery/web 1.17.1-beta.7 → 1.17.1-beta.8

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 (139) hide show
  1. package/README.md +3 -39
  2. package/bin/cli-output.js +0 -16
  3. package/bin/cli.js +3 -66
  4. package/bin/cli.test.js +4 -81
  5. package/bin/lib/DOCUMENTATION.md +5 -19
  6. package/bin/lib/cli-args.js +3 -327
  7. package/bin/lib/cli-http.js +0 -16
  8. package/bin/lib/cli-lifecycle.js +2 -111
  9. package/bin/lib/cli-paths.js +0 -57
  10. package/dist/assets/{AgentAvatar-htFrIvQx.js → AgentAvatar-C6Hxu5_o.js} +1 -1
  11. package/dist/assets/{AssistantView-BZiJsNuI.js → AssistantView-ZlXc0xFT.js} +1 -1
  12. package/dist/assets/{ChatContainer-CdmcMnL3.js → ChatContainer-BXFy3Uu2.js} +5 -5
  13. package/dist/assets/{DiagramView-B7sq74V-.js → DiagramView-CgotrQyK.js} +1 -1
  14. package/dist/assets/{FadeInOnReveal-8fY7XL23.js → FadeInOnReveal-CvNA_aGD.js} +1 -1
  15. package/dist/assets/{Icon-B7eLbnyj.js → Icon-BPJ_quEe.js} +1 -1
  16. package/dist/assets/{MarkdownRendererImpl-DICju9ve.js → MarkdownRendererImpl-Cj4y0P0S.js} +1 -1
  17. package/dist/assets/{MobileDetailNavigation-CuxWU1yf.js → MobileDetailNavigation-5tAL5d_M.js} +1 -1
  18. package/dist/assets/{MobileShareBridge-CPg9Eyro.js → MobileShareBridge-BL7Ehxhd.js} +1 -1
  19. package/dist/assets/{MobileSurface-D7sDH_tx.js → MobileSurface-ByMnQ5rD.js} +1 -1
  20. package/dist/assets/{MultiRunWindow-MSO0Equt.js → MultiRunWindow-Che7L3TX.js} +1 -1
  21. package/dist/assets/{OnboardingScreen-C87u_MLg.js → OnboardingScreen-CdvaEBtt.js} +1 -1
  22. package/dist/assets/{OverlayScrollbar-Kmmybw-z.js → OverlayScrollbar-C2pEDFq-.js} +1 -1
  23. package/dist/assets/SettingsView-D0p-e8Px.js +25 -0
  24. package/dist/assets/{SettingsWindow-Bl25cfXX.js → SettingsWindow-KYhsFUrb.js} +1 -1
  25. package/dist/assets/{TerminalView-jR5jP1b0.js → TerminalView-Da5aLqHR.js} +1 -1
  26. package/dist/assets/{ToolOutputDialog-DCEZb2DZ.js → ToolOutputDialog-DZI4uxx3.js} +1 -1
  27. package/dist/assets/{appThemeRegistry-aiRF-s3c.js → appThemeRegistry-DAgBeFsZ.js} +2 -2
  28. package/dist/assets/{button-bYWkDtDI.js → button-BmNJBT13.js} +1 -1
  29. package/dist/assets/{clipboard-CzpzN4Um.js → clipboard-CXWbHCAk.js} +1 -1
  30. package/dist/assets/{collapsible-A1PFvMRp.js → collapsible-68IqWBM1.js} +1 -1
  31. package/dist/assets/{context-menu-CkpHn-Bm.js → context-menu-BXH0AcOc.js} +1 -1
  32. package/dist/assets/desktopHosts-BpjUSDz4.js +1 -0
  33. package/dist/assets/{desktopRelayRestore-C5vYnSTd.js → desktopRelayRestore-BzUEk1i7.js} +1 -1
  34. package/dist/assets/{diagram-BkwKWaTO.js → diagram-YN0GZ1Q0.js} +1 -1
  35. package/dist/assets/{dialog-DW7-_iqo.js → dialog-BV1ENlLf.js} +1 -1
  36. package/dist/assets/es-EXZUX1sB.js +15 -0
  37. package/dist/assets/{fileQueries-P9SX4YwC.js → fileQueries-i4oziMnC.js} +1 -1
  38. package/dist/assets/fr-jWNPO91J.js +13 -0
  39. package/dist/assets/{gitApi-CMsZ2v08.js → gitApi-BW5AFgD1.js} +1 -1
  40. package/dist/assets/{gitApiHttp-DvIIcDAO.js → gitApiHttp-C1DaEMKR.js} +1 -1
  41. package/dist/assets/{input-B9aNttqV.js → input-BLVhPvhN.js} +1 -1
  42. package/dist/assets/{insertionBoundaries-Di3rCXgN.js → insertionBoundaries-D4KbXFFj.js} +1 -1
  43. package/dist/assets/ja-Dcb0VtDE.js +15 -0
  44. package/dist/assets/ko-CX71xNDX.js +15 -0
  45. package/dist/assets/{main-DY27kMV5.js → main-CcyyPAib.js} +2 -2
  46. package/dist/assets/{main-Chtf300b.js → main-DzxdsF_k.js} +5 -5
  47. package/dist/assets/{markdown-worker-BoB1_DPo.js → markdown-worker-Cq3Twp1A.js} +1 -1
  48. package/dist/assets/{markdownTheme-om5XcPqq.js → markdownTheme-CCnvI6L0.js} +1 -1
  49. package/dist/assets/{miniChat-BWbpl5SN.js → miniChat-BsNf9y48.js} +2 -2
  50. package/dist/assets/mobile-CsJg2IAq.js +2 -0
  51. package/dist/assets/{multirun-BfPcVktg.js → multirun-qs5hZkwM.js} +1 -1
  52. package/dist/assets/persistence-C_KCiMcY.js +3 -0
  53. package/dist/assets/{pl-BSjLn4dm.js → pl-mR_3Sqr8.js} +2 -2
  54. package/dist/assets/{projectMeta-CiAR7MRG.js → projectMeta-1SSTNg8w.js} +1 -1
  55. package/dist/assets/pt-BR-D1RpVOvC.js +15 -0
  56. package/dist/assets/radio-DBJG9Dd1.js +1 -0
  57. package/dist/assets/{renderElectronMiniChatApp-CiEXAVSt.js → renderElectronMiniChatApp-DOWE0jSA.js} +2 -2
  58. package/dist/assets/{renderMobileApp-BHvgSVPk.js → renderMobileApp-bklJJSZi.js} +3 -3
  59. package/dist/assets/{runtimeConfig-49YbZaqI.js → runtimeConfig-JSaYFA5x.js} +1 -1
  60. package/dist/assets/{runtimeEndpointReset-CdhtjuPe.js → runtimeEndpointReset-ix1NxqYw.js} +1 -1
  61. package/dist/assets/{sortable-tabs-strip-XeYica3j.js → sortable-tabs-strip-DncWjNx4.js} +1 -1
  62. package/dist/assets/src-B8mzksNL.css +2 -0
  63. package/dist/assets/store-oojlrF4d.js +15 -0
  64. package/dist/assets/{terminalApi-DAu7xKli.js → terminalApi-BYTA045F.js} +1 -1
  65. package/dist/assets/{tooltip-BSlxaNrR.js → tooltip-BYGBBTc2.js} +1 -1
  66. package/dist/assets/uk-UvnVqWv-.js +15 -0
  67. package/dist/assets/{url-DjkTDrad.js → url-CGHw6D-E.js} +1 -1
  68. package/dist/assets/useAppFontEffects-B1EhZNex.js +7 -0
  69. package/dist/assets/{useDesktopWindowControlsLayout-BwYnhrEy.js → useDesktopWindowControlsLayout-Dc69l-pm.js} +1 -1
  70. package/dist/assets/{useEffectiveDirectory-CEmsrrEs.js → useEffectiveDirectory-dCGvvYRh.js} +1 -1
  71. package/dist/assets/{useFontPreferences-BxMT_kty.js → useFontPreferences-Bu4ME5hk.js} +1 -1
  72. package/dist/assets/{useMobileNavigationStore-DryW-QdG.js → useMobileNavigationStore-DhkIZBJw.js} +4 -4
  73. package/dist/assets/useSessionAutoCleanup-D-r9oDye.js +1 -0
  74. package/dist/assets/{useWorkerHighlightedLines-CFW2AoPL.js → useWorkerHighlightedLines-05dLFgTI.js} +1 -1
  75. package/dist/assets/{utils-RUACCsOs.js → utils-DyUyiLje.js} +1 -1
  76. package/dist/assets/zh-CN-9v-RC966.js +15 -0
  77. package/dist/assets/zh-TW-BZ_wZdC-.js +15 -0
  78. package/dist/index.html +8 -8
  79. package/dist/mini-chat.html +8 -8
  80. package/dist/mobile.html +8 -8
  81. package/package.json +1 -1
  82. package/server/index.d.ts +0 -6
  83. package/server/index.js +5 -153
  84. package/server/lib/opencode/DOCUMENTATION.md +6 -10
  85. package/server/lib/opencode/cli-entry-runtime.js +0 -10
  86. package/server/lib/opencode/cli-options.js +0 -65
  87. package/server/lib/opencode/core-routes.js +2 -4
  88. package/server/lib/opencode/routes.test.js +0 -1
  89. package/server/lib/opencode/server-startup-runtime.js +0 -55
  90. package/server/lib/opencode/settings-helpers.js +0 -55
  91. package/server/lib/opencode/settings-helpers.test.js +0 -20
  92. package/server/lib/opencode/settings-normalization-runtime.js +0 -87
  93. package/server/lib/opencode/settings-normalization-runtime.test.js +0 -3
  94. package/server/lib/opencode/settings-runtime.js +9 -102
  95. package/server/lib/opencode/settings-runtime.test.js +0 -10
  96. package/server/lib/opencode/shutdown-runtime.js +1 -9
  97. package/server/lib/opencode/shutdown-runtime.test.js +0 -2
  98. package/server/lib/opencode/startup-pipeline-runtime.js +0 -20
  99. package/server/lib/opencode/startup-pipeline-runtime.test.js +2 -3
  100. package/server/lib/opencode/tunnel-wiring-runtime.js +2 -80
  101. package/server/lib/relay/DOCUMENTATION.md +1 -1
  102. package/bin/lib/cli-tunnel-capabilities.js +0 -9
  103. package/bin/lib/cli-tunnel-profiles.js +0 -366
  104. package/bin/lib/cli-tunnel-utils.js +0 -300
  105. package/bin/lib/commands-tunnel.js +0 -1761
  106. package/dist/assets/SettingsView-5YNu54KI.js +0 -25
  107. package/dist/assets/desktopHosts-D5m_ggY1.js +0 -1
  108. package/dist/assets/es-Cei_75Jt.js +0 -15
  109. package/dist/assets/fr-Dn7WSHh2.js +0 -13
  110. package/dist/assets/ja-DFARVqVj.js +0 -15
  111. package/dist/assets/ko-pyLnIyDY.js +0 -15
  112. package/dist/assets/mobile-DEQeGskq.js +0 -2
  113. package/dist/assets/persistence-CHA81Od7.js +0 -3
  114. package/dist/assets/pt-BR-DaWvr_0A.js +0 -15
  115. package/dist/assets/radio-BnF4XhCC.js +0 -1
  116. package/dist/assets/src-BtkWqMFu.css +0 -2
  117. package/dist/assets/store-DIpqFVjs.js +0 -15
  118. package/dist/assets/uk-CHCRqRKf.js +0 -15
  119. package/dist/assets/useAppFontEffects-BRNICZS2.js +0 -7
  120. package/dist/assets/useSessionAutoCleanup-DMJ1LiW_.js +0 -1
  121. package/dist/assets/zh-CN-BWEQZKXk.js +0 -15
  122. package/dist/assets/zh-TW-BbO-gJq3.js +0 -15
  123. package/server/lib/cloudflare-tunnel.js +0 -618
  124. package/server/lib/ngrok-tunnel.js +0 -343
  125. package/server/lib/ngrok-tunnel.test.js +0 -50
  126. package/server/lib/tunnels/DOCUMENTATION.md +0 -21
  127. package/server/lib/tunnels/executable-search.js +0 -140
  128. package/server/lib/tunnels/executable-search.test.js +0 -96
  129. package/server/lib/tunnels/index.js +0 -179
  130. package/server/lib/tunnels/index.test.js +0 -93
  131. package/server/lib/tunnels/install-help.js +0 -56
  132. package/server/lib/tunnels/install-help.test.js +0 -31
  133. package/server/lib/tunnels/managed-config.js +0 -201
  134. package/server/lib/tunnels/providers/cloudflare.js +0 -266
  135. package/server/lib/tunnels/providers/ngrok.js +0 -123
  136. package/server/lib/tunnels/registry.js +0 -51
  137. package/server/lib/tunnels/routes.js +0 -610
  138. package/server/lib/tunnels/types.js +0 -245
  139. package/server/lib/tunnels/types.test.js +0 -34
@@ -1,19 +1,11 @@
1
1
  export const createServerStartupRuntime = (dependencies) => {
2
2
  const {
3
3
  process,
4
- crypto,
5
4
  server,
6
- normalizeTunnelBootstrapTtlMs,
7
- readSettingsFromDiskMigrated,
8
- tunnelAuthController,
9
- startTunnelWithNormalizedRequest,
10
5
  gracefulShutdown,
11
6
  getSignalsAttached,
12
7
  setSignalsAttached,
13
8
  syncToHmrState,
14
- TUNNEL_MODE_QUICK,
15
- TUNNEL_MODE_MANAGED_LOCAL,
16
- TUNNEL_MODE_MANAGED_REMOTE,
17
9
  } = dependencies;
18
10
 
19
11
  const resolveBindHost = (host) =>
@@ -25,8 +17,6 @@ export const createServerStartupRuntime = (dependencies) => {
25
17
  const startListeningAndMaybeTunnel = async ({
26
18
  port,
27
19
  bindHost,
28
- startupTunnelRequest,
29
- onTunnelReady,
30
20
  }) => {
31
21
  let activePort = port;
32
22
 
@@ -69,51 +59,6 @@ export const createServerStartupRuntime = (dependencies) => {
69
59
  console.log(`Health check: http://${displayHost}:${activePort}/health`);
70
60
  console.log(`Web interface: http://${displayHost}:${activePort}`);
71
61
 
72
- if (startupTunnelRequest) {
73
- const startupModeLabel = startupTunnelRequest.mode === TUNNEL_MODE_QUICK
74
- ? 'Quick Tunnel'
75
- : (startupTunnelRequest.mode === TUNNEL_MODE_MANAGED_LOCAL
76
- ? 'Managed Local Tunnel'
77
- : (startupTunnelRequest.mode === TUNNEL_MODE_MANAGED_REMOTE ? 'Managed Remote Tunnel' : 'Tunnel'));
78
- console.log(`\nInitializing ${startupModeLabel} for provider '${startupTunnelRequest.provider}'...`);
79
- try {
80
- const { publicUrl, mode } = await startTunnelWithNormalizedRequest({
81
- provider: startupTunnelRequest.provider,
82
- mode: startupTunnelRequest.mode,
83
- intent: startupTunnelRequest.intent,
84
- hostname: startupTunnelRequest.hostname,
85
- token: startupTunnelRequest.token,
86
- configPath: startupTunnelRequest.configPath,
87
- selectedPresetId: '',
88
- selectedPresetName: '',
89
- });
90
- if (publicUrl) {
91
- tunnelAuthController.setActiveTunnel({
92
- tunnelId: crypto.randomUUID(),
93
- publicUrl,
94
- mode,
95
- });
96
- const settings = await readSettingsFromDiskMigrated();
97
- const bootstrapTtlMs = settings?.tunnelBootstrapTtlMs === null
98
- ? null
99
- : normalizeTunnelBootstrapTtlMs(settings?.tunnelBootstrapTtlMs);
100
- const bootstrapToken = tunnelAuthController.issueBootstrapToken({ ttlMs: bootstrapTtlMs });
101
- const connectUrl = `${publicUrl.replace(/\/$/, '')}/connect?t=${encodeURIComponent(bootstrapToken.token)}`;
102
- if (onTunnelReady) {
103
- onTunnelReady(publicUrl, connectUrl);
104
- } else {
105
- console.log(`\n🌐 Tunnel URL: ${connectUrl}`);
106
- console.log('🔑 One-time connect link (expires after first use)\n');
107
- }
108
- } else if (onTunnelReady) {
109
- onTunnelReady(publicUrl, null);
110
- }
111
- } catch (error) {
112
- console.error(`Failed to start tunnel: ${error.message}`);
113
- console.log('Continuing without tunnel...');
114
- }
115
- }
116
-
117
62
  resolve();
118
63
  } catch (error) {
119
64
  reject(error);
@@ -57,14 +57,6 @@ export const createSettingsHelpers = (dependencies) => {
57
57
  const {
58
58
  normalizePathForPersistence,
59
59
  normalizeDirectoryPath,
60
- normalizeTunnelBootstrapTtlMs,
61
- normalizeTunnelSessionTtlMs,
62
- normalizeTunnelProvider,
63
- normalizeTunnelMode,
64
- normalizeOptionalPath,
65
- normalizeManagedRemoteTunnelHostname,
66
- normalizeManagedRemoteTunnelPresets,
67
- normalizeManagedRemoteTunnelPresetTokens,
68
60
  sanitizeTypographySizesPartial,
69
61
  normalizeStringArray,
70
62
  sanitizeModelRefs,
@@ -408,50 +400,6 @@ export const createSettingsHelpers = (dependencies) => {
408
400
  const normalizedDays = Math.max(1, Math.min(365, Math.round(candidate.autoDeleteAfterDays)));
409
401
  result.autoDeleteAfterDays = normalizedDays;
410
402
  }
411
- if (candidate.tunnelBootstrapTtlMs === null) {
412
- result.tunnelBootstrapTtlMs = null;
413
- } else if (typeof candidate.tunnelBootstrapTtlMs === 'number' && Number.isFinite(candidate.tunnelBootstrapTtlMs)) {
414
- result.tunnelBootstrapTtlMs = normalizeTunnelBootstrapTtlMs(candidate.tunnelBootstrapTtlMs);
415
- }
416
- if (typeof candidate.tunnelSessionTtlMs === 'number' && Number.isFinite(candidate.tunnelSessionTtlMs)) {
417
- result.tunnelSessionTtlMs = normalizeTunnelSessionTtlMs(candidate.tunnelSessionTtlMs);
418
- }
419
- if (typeof candidate.tunnelProvider === 'string') {
420
- const provider = normalizeTunnelProvider(candidate.tunnelProvider);
421
- if (provider) {
422
- result.tunnelProvider = provider;
423
- }
424
- }
425
- if (typeof candidate.tunnelMode === 'string') {
426
- result.tunnelMode = normalizeTunnelMode(candidate.tunnelMode);
427
- }
428
- if (candidate.managedLocalTunnelConfigPath === null) {
429
- result.managedLocalTunnelConfigPath = null;
430
- } else if (typeof candidate.managedLocalTunnelConfigPath === 'string') {
431
- const trimmed = candidate.managedLocalTunnelConfigPath.trim();
432
- result.managedLocalTunnelConfigPath = trimmed.length > 0 ? normalizeOptionalPath(trimmed) : null;
433
- }
434
- if (typeof candidate.managedRemoteTunnelHostname === 'string') {
435
- const hostname = normalizeManagedRemoteTunnelHostname(candidate.managedRemoteTunnelHostname);
436
- result.managedRemoteTunnelHostname = hostname;
437
- }
438
- if (candidate.managedRemoteTunnelToken === null) {
439
- result.managedRemoteTunnelToken = null;
440
- } else if (typeof candidate.managedRemoteTunnelToken === 'string') {
441
- result.managedRemoteTunnelToken = candidate.managedRemoteTunnelToken.trim();
442
- }
443
- const managedRemoteTunnelPresets = normalizeManagedRemoteTunnelPresets(candidate.managedRemoteTunnelPresets);
444
- if (managedRemoteTunnelPresets) {
445
- result.managedRemoteTunnelPresets = managedRemoteTunnelPresets;
446
- }
447
- const managedRemoteTunnelPresetTokens = normalizeManagedRemoteTunnelPresetTokens(candidate.managedRemoteTunnelPresetTokens);
448
- if (managedRemoteTunnelPresetTokens) {
449
- result.managedRemoteTunnelPresetTokens = managedRemoteTunnelPresetTokens;
450
- }
451
- if (typeof candidate.managedRemoteTunnelSelectedPresetId === 'string') {
452
- const id = candidate.managedRemoteTunnelSelectedPresetId.trim();
453
- result.managedRemoteTunnelSelectedPresetId = id || undefined;
454
- }
455
403
 
456
404
  const typography = sanitizeTypographySizesPartial(candidate.typographySizes);
457
405
  if (typography) {
@@ -945,10 +893,8 @@ export const createSettingsHelpers = (dependencies) => {
945
893
 
946
894
  const formatSettingsResponse = (settings) => {
947
895
  const sanitized = sanitizeSettingsUpdate(settings);
948
- delete sanitized.managedRemoteTunnelToken;
949
896
  delete sanitized.summaryCustomAPIToken;
950
897
  const bookmarks = normalizeStringArray(settings.securityScopedBookmarks);
951
- const hasManagedRemoteTunnelToken = typeof settings?.managedRemoteTunnelToken === 'string' && settings.managedRemoteTunnelToken.trim().length > 0;
952
898
  const hasSummaryCustomAPIToken = typeof settings?.summaryCustomAPIToken === 'string' && settings.summaryCustomAPIToken.trim().length > 0;
953
899
  const pwaAppName = normalizePwaAppName(settings?.pwaAppName, '');
954
900
  const pwaOrientation = normalizePwaOrientation(settings?.pwaOrientation, 'system');
@@ -956,7 +902,6 @@ export const createSettingsHelpers = (dependencies) => {
956
902
 
957
903
  return {
958
904
  ...sanitized,
959
- hasManagedRemoteTunnelToken,
960
905
  hasSummaryCustomAPIToken,
961
906
  ...(pwaAppName ? { pwaAppName } : {}),
962
907
  pwaOrientation,
@@ -6,14 +6,6 @@ import { createSettingsNormalizationRuntime } from './settings-normalization-run
6
6
  const createTestHelpers = () => createSettingsHelpers({
7
7
  normalizePathForPersistence: (value) => value,
8
8
  normalizeDirectoryPath: (value) => value,
9
- normalizeTunnelBootstrapTtlMs: (value) => value,
10
- normalizeTunnelSessionTtlMs: (value) => value,
11
- normalizeTunnelProvider: (value) => value,
12
- normalizeTunnelMode: (value) => value,
13
- normalizeOptionalPath: (value) => value,
14
- normalizeManagedRemoteTunnelHostname: (value) => value,
15
- normalizeManagedRemoteTunnelPresets: () => undefined,
16
- normalizeManagedRemoteTunnelPresetTokens: () => undefined,
17
9
  sanitizeTypographySizesPartial: () => undefined,
18
10
  normalizeStringArray: (input) => input,
19
11
  sanitizeModelRefs: () => undefined,
@@ -31,9 +23,6 @@ const createTestHelpersWithRealSanitizers = () => {
31
23
  },
32
24
  processLike: { platform: 'linux', env: {} },
33
25
  realpathSync: (p) => p,
34
- tunnelBootstrapTtlDefaultMs: 600000,
35
- tunnelBootstrapTtlMinMs: 60000,
36
- tunnelBootstrapTtlMaxMs: 3600000,
37
26
  tunnelSessionTtlDefaultMs: 86400000,
38
27
  tunnelSessionTtlMinMs: 3600000,
39
28
  tunnelSessionTtlMaxMs: 604800000,
@@ -41,14 +30,6 @@ const createTestHelpersWithRealSanitizers = () => {
41
30
  return createSettingsHelpers({
42
31
  normalizePathForPersistence: (value) => value,
43
32
  normalizeDirectoryPath: (value) => value,
44
- normalizeTunnelBootstrapTtlMs: (value) => value,
45
- normalizeTunnelSessionTtlMs: (value) => value,
46
- normalizeTunnelProvider: (value) => value,
47
- normalizeTunnelMode: (value) => value,
48
- normalizeOptionalPath: (value) => value,
49
- normalizeManagedRemoteTunnelHostname: (value) => value,
50
- normalizeManagedRemoteTunnelPresets: () => undefined,
51
- normalizeManagedRemoteTunnelPresetTokens: () => undefined,
52
33
  sanitizeTypographySizesPartial: () => undefined,
53
34
  normalizeStringArray: runtime.normalizeStringArray,
54
35
  sanitizeModelRefs: runtime.sanitizeModelRefs,
@@ -305,7 +286,6 @@ describe('settings helpers', () => {
305
286
  const secretSentinel = 'bootstrap-secret-sentinel';
306
287
  const response = helpers.projectBootstrapSettingsResponse({
307
288
  summaryCustomAPIToken: secretSentinel,
308
- managedRemoteTunnelToken: secretSentinel,
309
289
  defaultModel: 'm'.repeat(513),
310
290
  messageStreamTransport: 'websocket',
311
291
  sttProvider: 'server',
@@ -4,9 +4,6 @@ export const createSettingsNormalizationRuntime = (dependencies) => {
4
4
  path,
5
5
  processLike,
6
6
  realpathSync,
7
- tunnelBootstrapTtlDefaultMs,
8
- tunnelBootstrapTtlMinMs,
9
- tunnelBootstrapTtlMaxMs,
10
7
  tunnelSessionTtlDefaultMs,
11
8
  tunnelSessionTtlMinMs,
12
9
  tunnelSessionTtlMaxMs,
@@ -267,16 +264,6 @@ export const createSettingsNormalizationRuntime = (dependencies) => {
267
264
 
268
265
  const clampNumber = (value, min, max) => Math.max(min, Math.min(max, value));
269
266
 
270
- const normalizeTunnelBootstrapTtlMs = (value) => {
271
- if (value === null) {
272
- return null;
273
- }
274
- if (!Number.isFinite(value)) {
275
- return tunnelBootstrapTtlDefaultMs;
276
- }
277
- return clampNumber(Math.round(value), tunnelBootstrapTtlMinMs, tunnelBootstrapTtlMaxMs);
278
- };
279
-
280
267
  const normalizeTunnelSessionTtlMs = (value) => {
281
268
  if (!Number.isFinite(value)) {
282
269
  return tunnelSessionTtlDefaultMs;
@@ -284,76 +271,6 @@ export const createSettingsNormalizationRuntime = (dependencies) => {
284
271
  return clampNumber(Math.round(value), tunnelSessionTtlMinMs, tunnelSessionTtlMaxMs);
285
272
  };
286
273
 
287
- const normalizeManagedRemoteTunnelHostname = (value) => {
288
- if (typeof value !== 'string') {
289
- return undefined;
290
- }
291
- const trimmed = value.trim();
292
- if (!trimmed) {
293
- return undefined;
294
- }
295
-
296
- const parsed = (() => {
297
- try {
298
- if (trimmed.includes('://')) {
299
- return new URL(trimmed);
300
- }
301
- return new URL(`https://${trimmed}`);
302
- } catch {
303
- return null;
304
- }
305
- })();
306
-
307
- const hostname = parsed?.hostname?.trim().toLowerCase() || '';
308
- if (!hostname) {
309
- return undefined;
310
- }
311
- return hostname;
312
- };
313
-
314
- const normalizeManagedRemoteTunnelPresets = (value) => {
315
- if (!Array.isArray(value)) {
316
- return undefined;
317
- }
318
-
319
- const result = [];
320
- const seenIds = new Set();
321
- const seenHostnames = new Set();
322
-
323
- for (const entry of value) {
324
- if (!entry || typeof entry !== 'object') continue;
325
- const candidate = entry;
326
- const id = typeof candidate.id === 'string' ? candidate.id.trim() : '';
327
- const name = typeof candidate.name === 'string' ? candidate.name.trim() : '';
328
- const hostname = normalizeManagedRemoteTunnelHostname(candidate.hostname);
329
- if (!id || !name || !hostname) continue;
330
- if (seenIds.has(id) || seenHostnames.has(hostname)) continue;
331
- seenIds.add(id);
332
- seenHostnames.add(hostname);
333
- result.push({ id, name, hostname });
334
- }
335
-
336
- return result;
337
- };
338
-
339
- const normalizeManagedRemoteTunnelPresetTokens = (value) => {
340
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
341
- return undefined;
342
- }
343
-
344
- const result = {};
345
- for (const [rawId, rawToken] of Object.entries(value)) {
346
- const id = typeof rawId === 'string' ? rawId.trim() : '';
347
- const token = typeof rawToken === 'string' ? rawToken.trim() : '';
348
- if (!id || !token) {
349
- continue;
350
- }
351
- result[id] = token;
352
- }
353
-
354
- return Object.keys(result).length > 0 ? result : undefined;
355
- };
356
-
357
274
  const isUnsafeSkillRelativePath = (value) => {
358
275
  if (typeof value !== 'string' || value.length === 0) {
359
276
  return true;
@@ -452,11 +369,7 @@ export const createSettingsNormalizationRuntime = (dependencies) => {
452
369
  normalizeDirectoryPath,
453
370
  normalizePathForPersistence,
454
371
  normalizeSettingsPaths,
455
- normalizeTunnelBootstrapTtlMs,
456
372
  normalizeTunnelSessionTtlMs,
457
- normalizeManagedRemoteTunnelHostname,
458
- normalizeManagedRemoteTunnelPresets,
459
- normalizeManagedRemoteTunnelPresetTokens,
460
373
  isUnsafeSkillRelativePath,
461
374
  sanitizeTypographySizesPartial,
462
375
  normalizeStringArray,
@@ -12,9 +12,6 @@ const createTestRuntime = (overrides = {}) => {
12
12
  },
13
13
  processLike: { platform: 'linux', env: {} },
14
14
  realpathSync: (p) => p,
15
- tunnelBootstrapTtlDefaultMs: 600000,
16
- tunnelBootstrapTtlMinMs: 60000,
17
- tunnelBootstrapTtlMaxMs: 3600000,
18
15
  tunnelSessionTtlDefaultMs: 86400000,
19
16
  tunnelSessionTtlMinMs: 3600000,
20
17
  tunnelSessionTtlMaxMs: 604800000,
@@ -39,11 +39,6 @@ export const createSettingsRuntime = (deps) => {
39
39
  normalizeStringArray,
40
40
  formatSettingsResponse,
41
41
  resolveDirectoryCandidate,
42
- normalizeManagedRemoteTunnelHostname,
43
- normalizeManagedRemoteTunnelPresets,
44
- normalizeManagedRemoteTunnelPresetTokens,
45
- syncManagedRemoteTunnelConfigWithPresets,
46
- upsertManagedRemoteTunnelToken,
47
42
  } = deps;
48
43
 
49
44
  let persistSettingsLock = Promise.resolve();
@@ -725,67 +720,6 @@ export const createSettingsRuntime = (deps) => {
725
720
  return { settings: changed ? next : settings, changed };
726
721
  };
727
722
 
728
- const migrateSettingsFromLegacyNamedTunnelKeys = async (current) => {
729
- const settings = current && typeof current === 'object' ? current : {};
730
- const next = { ...settings };
731
- let changed = false;
732
-
733
- if (!Object.prototype.hasOwnProperty.call(next, 'managedRemoteTunnelHostname')
734
- && Object.prototype.hasOwnProperty.call(next, 'namedTunnelHostname')) {
735
- next.managedRemoteTunnelHostname = normalizeManagedRemoteTunnelHostname(next.namedTunnelHostname);
736
- changed = true;
737
- }
738
-
739
- if (!Object.prototype.hasOwnProperty.call(next, 'managedRemoteTunnelToken')
740
- && Object.prototype.hasOwnProperty.call(next, 'namedTunnelToken')) {
741
- if (next.namedTunnelToken === null) {
742
- next.managedRemoteTunnelToken = null;
743
- } else if (typeof next.namedTunnelToken === 'string') {
744
- next.managedRemoteTunnelToken = next.namedTunnelToken.trim();
745
- }
746
- changed = true;
747
- }
748
-
749
- if (!Object.prototype.hasOwnProperty.call(next, 'managedRemoteTunnelPresets')
750
- && Object.prototype.hasOwnProperty.call(next, 'namedTunnelPresets')) {
751
- next.managedRemoteTunnelPresets = normalizeManagedRemoteTunnelPresets(next.namedTunnelPresets);
752
- changed = true;
753
- }
754
-
755
- if (!Object.prototype.hasOwnProperty.call(next, 'managedRemoteTunnelPresetTokens')
756
- && Object.prototype.hasOwnProperty.call(next, 'namedTunnelPresetTokens')) {
757
- next.managedRemoteTunnelPresetTokens = normalizeManagedRemoteTunnelPresetTokens(next.namedTunnelPresetTokens);
758
- changed = true;
759
- }
760
-
761
- if (!Object.prototype.hasOwnProperty.call(next, 'managedRemoteTunnelSelectedPresetId')
762
- && Object.prototype.hasOwnProperty.call(next, 'namedTunnelSelectedPresetId')) {
763
- const selectedPresetId = typeof next.namedTunnelSelectedPresetId === 'string'
764
- ? next.namedTunnelSelectedPresetId.trim()
765
- : '';
766
- if (selectedPresetId) {
767
- next.managedRemoteTunnelSelectedPresetId = selectedPresetId;
768
- }
769
- changed = true;
770
- }
771
-
772
- const legacyKeys = [
773
- 'namedTunnelHostname',
774
- 'namedTunnelToken',
775
- 'namedTunnelPresets',
776
- 'namedTunnelPresetTokens',
777
- 'namedTunnelSelectedPresetId',
778
- ];
779
- for (const key of legacyKeys) {
780
- if (Object.prototype.hasOwnProperty.call(next, key)) {
781
- delete next[key];
782
- changed = true;
783
- }
784
- }
785
-
786
- return { settings: changed ? next : settings, changed };
787
- };
788
-
789
723
  // `approvedDirectories` was a write-only registry: every project path and
790
724
  // visited directory was appended forever, but nothing ever read it. Strip
791
725
  // the stale key from persisted settings on upgrade.
@@ -839,21 +773,20 @@ export const createSettingsRuntime = (deps) => {
839
773
  const migration2 = await migrateSettingsFromLegacyThemePreferences(migration1.settings);
840
774
  const migration3 = await migrateSettingsFromLegacyCollapsedProjects(migration2.settings);
841
775
  const migration4 = await migrateSettingsNotificationDefaults(migration3.settings);
842
- const migration5 = await migrateSettingsFromLegacyNamedTunnelKeys(migration4.settings);
843
- const migration6 = normalizeSettingsPaths(migration5.settings);
844
- const migration7 = await migrateSettingsToDeterministicProjectIds(migration6.settings);
845
- const migration8 = migrateSettingsRemoveApprovedDirectories(migration7.settings);
846
- const migration9 = migrateSettingsCompactChatDefaults(migration8.settings);
847
- if (migration1.changed || migration2.changed || migration3.changed || migration4.changed || migration5.changed || migration6.changed || migration7.changed || migration8.changed || migration9.changed) {
848
- await writeSettingsToDisk(migration9.settings);
849
- }
850
- return migration9.settings;
776
+ const migration5 = normalizeSettingsPaths(migration4.settings);
777
+ const migration6 = await migrateSettingsToDeterministicProjectIds(migration5.settings);
778
+ const migration7 = migrateSettingsRemoveApprovedDirectories(migration6.settings);
779
+ const migration8 = migrateSettingsCompactChatDefaults(migration7.settings);
780
+ if (migration1.changed || migration2.changed || migration3.changed || migration4.changed || migration5.changed || migration6.changed || migration7.changed || migration8.changed) {
781
+ await writeSettingsToDisk(migration8.settings);
782
+ }
783
+ return migration8.settings;
851
784
  };
852
785
 
853
786
  const persistSettings = async (changes) => {
854
787
  persistSettingsLock = persistSettingsLock.then(async () => {
855
788
  // Log field names only — changes can carry credentials (UI password,
856
- // client tokens, tunnel tokens) that must never reach the log file.
789
+ // client tokens) that must never reach the log file.
857
790
  console.log('[persistSettings] Updating fields:', Object.keys(changes || {}).join(', ') || '(none)');
858
791
  const current = await readSettingsFromDisk();
859
792
  const sanitized = sanitizeSettingsUpdate(changes);
@@ -900,32 +833,6 @@ export const createSettingsRuntime = (deps) => {
900
833
  next = { ...next, activeProjectId: undefined };
901
834
  }
902
835
 
903
- if (Object.prototype.hasOwnProperty.call(sanitized, 'managedRemoteTunnelPresets')) {
904
- await syncManagedRemoteTunnelConfigWithPresets(next.managedRemoteTunnelPresets);
905
- }
906
-
907
- if (Object.prototype.hasOwnProperty.call(sanitized, 'managedRemoteTunnelPresetTokens') && sanitized.managedRemoteTunnelPresetTokens) {
908
- const presetsById = new Map((next.managedRemoteTunnelPresets || []).map((entry) => [entry.id, entry]));
909
- const updates = Object.entries(sanitized.managedRemoteTunnelPresetTokens)
910
- .map(([presetId, token]) => {
911
- const preset = presetsById.get(presetId);
912
- if (!preset || typeof token !== 'string' || token.trim().length === 0) {
913
- return null;
914
- }
915
- return {
916
- id: preset.id,
917
- name: preset.name,
918
- hostname: preset.hostname,
919
- token: token.trim(),
920
- };
921
- })
922
- .filter(Boolean);
923
-
924
- for (const update of updates) {
925
- await upsertManagedRemoteTunnelToken(update);
926
- }
927
- }
928
-
929
836
  await writeSettingsToDisk(next);
930
837
  return formatSettingsResponse(next);
931
838
  });
@@ -21,11 +21,6 @@ const createRuntime = async () => {
21
21
  normalizeStringArray: (values) => Array.isArray(values) ? values.filter((value) => typeof value === 'string') : [],
22
22
  formatSettingsResponse: (settings) => settings,
23
23
  resolveDirectoryCandidate: (value) => value,
24
- normalizeManagedRemoteTunnelHostname: (value) => value,
25
- normalizeManagedRemoteTunnelPresets: (value) => value,
26
- normalizeManagedRemoteTunnelPresetTokens: (value) => value,
27
- syncManagedRemoteTunnelConfigWithPresets: async () => {},
28
- upsertManagedRemoteTunnelToken: async () => {},
29
24
  });
30
25
 
31
26
  return {
@@ -218,11 +213,6 @@ describe('settings runtime', () => {
218
213
  normalizeStringArray: (values) => Array.isArray(values) ? values.filter((value) => typeof value === 'string') : [],
219
214
  formatSettingsResponse: (settings) => settings,
220
215
  resolveDirectoryCandidate: (value) => value,
221
- normalizeManagedRemoteTunnelHostname: (value) => value,
222
- normalizeManagedRemoteTunnelPresets: (value) => value,
223
- normalizeManagedRemoteTunnelPresetTokens: (value) => value,
224
- syncManagedRemoteTunnelConfigWithPresets: async () => {},
225
- upsertManagedRemoteTunnelToken: async () => {},
226
216
  });
227
217
 
228
218
  try {
@@ -27,8 +27,6 @@ export const createGracefulShutdownRuntime = (dependencies) => {
27
27
  getServer,
28
28
  getUiAuthController,
29
29
  setUiAuthController,
30
- getActiveTunnelController,
31
- setActiveTunnelController,
32
30
  tunnelAuthController,
33
31
  closeFeatureRoutes,
34
32
  } = dependencies;
@@ -135,13 +133,7 @@ export const createGracefulShutdownRuntime = (dependencies) => {
135
133
  setUiAuthController(null);
136
134
  }
137
135
 
138
- const activeTunnelController = getActiveTunnelController();
139
- if (activeTunnelController) {
140
- console.log('Stopping active tunnel...');
141
- activeTunnelController.stop();
142
- setActiveTunnelController(null);
143
- tunnelAuthController.clearActiveTunnel();
144
- }
136
+ tunnelAuthController?.clearActiveTunnel?.();
145
137
 
146
138
  console.log('Graceful shutdown complete');
147
139
  if (exitProcess) {
@@ -27,8 +27,6 @@ const createRuntime = (server, shutdownTimeoutMs = 1000, overrides = {}) => crea
27
27
  getServer: () => server,
28
28
  getUiAuthController: () => null,
29
29
  setUiAuthController: vi.fn(),
30
- getActiveTunnelController: () => null,
31
- setActiveTunnelController: vi.fn(),
32
30
  tunnelAuthController: { clearActiveTunnel: vi.fn() },
33
31
  ...overrides,
34
32
  });
@@ -35,22 +35,12 @@ export const createStartupPipelineRuntime = (dependencies) => {
35
35
  setManagedOpenCodeBridgeOrigin,
36
36
  staticRoutesRuntime,
37
37
  process,
38
- crypto,
39
- normalizeTunnelBootstrapTtlMs,
40
- readSettingsFromDiskMigrated,
41
- tunnelAuthController,
42
- startTunnelWithNormalizedRequest,
43
38
  gracefulShutdown,
44
39
  getSignalsAttached,
45
40
  setSignalsAttached,
46
41
  syncToHmrState,
47
- TUNNEL_MODE_QUICK,
48
- TUNNEL_MODE_MANAGED_LOCAL,
49
- TUNNEL_MODE_MANAGED_REMOTE,
50
42
  host,
51
43
  port,
52
- startupTunnelRequest,
53
- onTunnelReady,
54
44
  tunnelRuntimeContext,
55
45
  attachSignals,
56
46
  apiOnly,
@@ -109,27 +99,17 @@ export const createStartupPipelineRuntime = (dependencies) => {
109
99
 
110
100
  const serverStartupRuntime = createServerStartupRuntime({
111
101
  process,
112
- crypto,
113
102
  server,
114
- normalizeTunnelBootstrapTtlMs,
115
- readSettingsFromDiskMigrated,
116
- tunnelAuthController,
117
- startTunnelWithNormalizedRequest,
118
103
  gracefulShutdown,
119
104
  getSignalsAttached,
120
105
  setSignalsAttached,
121
106
  syncToHmrState,
122
- TUNNEL_MODE_QUICK,
123
- TUNNEL_MODE_MANAGED_LOCAL,
124
- TUNNEL_MODE_MANAGED_REMOTE,
125
107
  });
126
108
 
127
109
  const bindHost = serverStartupRuntime.resolveBindHost(host);
128
110
  const startupResult = await serverStartupRuntime.startListeningAndMaybeTunnel({
129
111
  port,
130
112
  bindHost,
131
- startupTunnelRequest,
132
- onTunnelReady,
133
113
  });
134
114
  tunnelRuntimeContext.setActivePort(startupResult.activePort);
135
115
  if (typeof setManagedOpenCodeBridgeOrigin === 'function') {
@@ -13,9 +13,8 @@ describe('startup pipeline runtime', () => {
13
13
  isRequestOriginAllowed: () => true, rejectWebSocketUpgrade: () => {}, buildOpenCodeUrl: () => '', getOpenCodeAuthHeaders: () => ({}), globalEventHub: {}, processForwardedEventPayload: () => {}, messageStreamWsClients: new Set(), triggerHealthCheck: () => {}, upstreamStallTimeoutMs: 1,
14
14
  terminalHeartbeatIntervalMs: 1, terminalRebindWindowMs: 1, terminalMaxRebindsPerWindow: 1, setupProxy: () => {}, scheduleOpenCodeApiDetection: () => {},
15
15
  bootstrapOpenCodeAtStartup: () => { order.push('bootstrap'); }, setManagedOpenCodeBridgeOrigin: (origin) => { order.push(origin); },
16
- staticRoutesRuntime: { registerStaticRoutes: () => {}, registerApiOnlyFallbackRoutes: () => {} }, process: {}, crypto: {}, normalizeTunnelBootstrapTtlMs: () => 1,
17
- readSettingsFromDiskMigrated: async () => ({}), tunnelAuthController: {}, startTunnelWithNormalizedRequest: () => {}, gracefulShutdown: () => {}, getSignalsAttached: () => false, setSignalsAttached: () => {}, syncToHmrState: () => {},
18
- TUNNEL_MODE_QUICK: 'quick', TUNNEL_MODE_MANAGED_LOCAL: 'local', TUNNEL_MODE_MANAGED_REMOTE: 'remote', host: '127.0.0.1', port: 0, startupTunnelRequest: null, onTunnelReady: () => {}, tunnelRuntimeContext: { setActivePort: () => {} }, attachSignals: false, apiOnly: false, dictationModelsDir: '',
16
+ staticRoutesRuntime: { registerStaticRoutes: () => {}, registerApiOnlyFallbackRoutes: () => {} }, process: {}, gracefulShutdown: () => {}, getSignalsAttached: () => false, setSignalsAttached: () => {}, syncToHmrState: () => {},
17
+ host: '127.0.0.1', port: 0, tunnelRuntimeContext: { setActivePort: () => {} }, attachSignals: false, apiOnly: false, dictationModelsDir: '',
19
18
  });
20
19
  expect(order).toEqual(['http://127.0.0.1:41234', 'bootstrap']);
21
20
  });