@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
@@ -63,23 +63,11 @@ function parseArgs(argv = process.argv.slice(2)) {
63
63
  all: false,
64
64
  follow: true,
65
65
  lines: DEFAULT_TAIL_LINES,
66
- provider: undefined,
67
- mode: undefined,
68
- profile: undefined,
69
66
  name: undefined,
70
- configPath: undefined,
71
- token: undefined,
72
- tokenFile: undefined,
73
- tokenStdin: false,
74
67
  hostname: undefined,
75
68
  server: undefined,
76
- connectTtl: undefined,
77
- sessionTtl: undefined,
78
69
  qr: false,
79
70
  explicitQr: false,
80
- force: false,
81
- showSecrets: false,
82
- dryRun: false,
83
71
  plain: false,
84
72
  quiet: false,
85
73
  explicitPort: false,
@@ -170,51 +158,12 @@ function parseArgs(argv = process.argv.slice(2)) {
170
158
  options.explicitUiPassword = true;
171
159
  break;
172
160
  }
173
- case 'provider': {
174
- const { value, nextIndex } = consumeValue(i, inlineValue);
175
- i = nextIndex;
176
- options.provider = typeof value === 'string' ? value : options.provider;
177
- break;
178
- }
179
- case 'mode': {
180
- const { value, nextIndex } = consumeValue(i, inlineValue);
181
- i = nextIndex;
182
- options.mode = typeof value === 'string' ? value : options.mode;
183
- break;
184
- }
185
- case 'profile': {
186
- const { value, nextIndex } = consumeValue(i, inlineValue);
187
- i = nextIndex;
188
- options.profile = typeof value === 'string' ? value : options.profile;
189
- break;
190
- }
191
161
  case 'name': {
192
162
  const { value, nextIndex } = consumeValue(i, inlineValue);
193
163
  i = nextIndex;
194
164
  options.name = typeof value === 'string' ? value : options.name;
195
165
  break;
196
166
  }
197
- case 'config': {
198
- const { value, nextIndex } = consumeValue(i, inlineValue);
199
- i = nextIndex;
200
- options.configPath = typeof value === 'string' ? value : null;
201
- break;
202
- }
203
- case 'token': {
204
- const { value, nextIndex } = consumeValue(i, inlineValue);
205
- i = nextIndex;
206
- options.token = typeof value === 'string' ? value : options.token;
207
- break;
208
- }
209
- case 'token-file': {
210
- const { value, nextIndex } = consumeValue(i, inlineValue);
211
- i = nextIndex;
212
- options.tokenFile = typeof value === 'string' ? value : options.tokenFile;
213
- break;
214
- }
215
- case 'token-stdin':
216
- options.tokenStdin = true;
217
- break;
218
167
  case 'hostname': {
219
168
  const { value, nextIndex } = consumeValue(i, inlineValue);
220
169
  i = nextIndex;
@@ -231,18 +180,6 @@ function parseArgs(argv = process.argv.slice(2)) {
231
180
  options.server = value.trim();
232
181
  break;
233
182
  }
234
- case 'connect-ttl': {
235
- const { value, nextIndex } = consumeValue(i, inlineValue);
236
- i = nextIndex;
237
- options.connectTtl = typeof value === 'string' ? value : options.connectTtl;
238
- break;
239
- }
240
- case 'session-ttl': {
241
- const { value, nextIndex } = consumeValue(i, inlineValue);
242
- i = nextIndex;
243
- options.sessionTtl = typeof value === 'string' ? value : options.sessionTtl;
244
- break;
245
- }
246
183
  case 'json':
247
184
  options.json = true;
248
185
  break;
@@ -275,15 +212,6 @@ function parseArgs(argv = process.argv.slice(2)) {
275
212
  options.qr = false;
276
213
  options.explicitQr = true;
277
214
  break;
278
- case 'force':
279
- options.force = true;
280
- break;
281
- case 'show-secrets':
282
- options.showSecrets = true;
283
- break;
284
- case 'dry-run':
285
- options.dryRun = true;
286
- break;
287
215
  case 'plain':
288
216
  options.plain = true;
289
217
  break;
@@ -312,21 +240,15 @@ function parseArgs(argv = process.argv.slice(2)) {
312
240
  // may still pass this when starting a remote server.
313
241
  break;
314
242
  case 'try-cf-tunnel':
315
- removedFlagErrors.push('`--try-cf-tunnel` was removed. Use: openchamber tunnel start --provider cloudflare --mode quick');
316
- break;
317
243
  case 'tunnel-qr':
318
- removedFlagErrors.push('`--tunnel-qr` was removed. Use: openchamber tunnel start ... --qr');
319
- break;
320
244
  case 'tunnel-password-url':
321
- removedFlagErrors.push('`--tunnel-password-url` was removed. Use UI password auth directly after tunnel start.');
322
- break;
323
245
  case 'tunnel-provider':
324
246
  case 'tunnel-mode':
325
247
  case 'tunnel-config':
326
248
  case 'tunnel-token':
327
249
  case 'tunnel-hostname':
328
250
  case 'tunnel':
329
- removedFlagErrors.push(`\`--${name}\` was removed from top-level serve flow. Use: openchamber tunnel start ...`);
251
+ removedFlagErrors.push(`\`--${name}\` was removed. Use LAN pairing (\`openchamber connect-url\`) or private relay instead.`);
330
252
  break;
331
253
  default:
332
254
  if (!long && name.length === 1) {
@@ -339,22 +261,18 @@ function parseArgs(argv = process.argv.slice(2)) {
339
261
  }
340
262
 
341
263
  const command = positional[0] || 'serve';
342
- const subcommand = command === 'tunnel' ? (positional[1] || 'help') : null;
343
- const tunnelAction = command === 'tunnel' ? (positional[2] || null) : null;
344
264
  const startupAction = command === 'startup' ? (positional[1] || 'status') : null;
345
265
 
346
266
  if (options.lan && typeof options.host !== 'string') {
347
267
  options.host = '0.0.0.0';
348
268
  }
349
269
 
350
- if (command !== 'tunnel' && typeof options.hostname === 'string' && typeof options.host !== 'string') {
270
+ if (typeof options.hostname === 'string' && typeof options.host !== 'string') {
351
271
  options.host = options.hostname;
352
272
  }
353
273
 
354
274
  return {
355
275
  command,
356
- subcommand,
357
- tunnelAction,
358
276
  startupAction,
359
277
  options,
360
278
  removedFlagErrors,
@@ -375,7 +293,6 @@ COMMANDS:
375
293
  stop Stop running instance(s)
376
294
  restart Stop and start the server
377
295
  status Show server status
378
- tunnel Tunnel lifecycle commands
379
296
  startup Manage launch at system startup
380
297
  logs Tail OpenChamber logs
381
298
  connect-url Generate URL/QR for connecting another client
@@ -384,7 +301,7 @@ COMMANDS:
384
301
  OPTIONS:
385
302
  -p, --port Web server port (default: ${DEFAULT_PORT})
386
303
  --host Bind address (default: 127.0.0.1)
387
- --hostname Alias for --host outside tunnel commands
304
+ --hostname Alias for --host
388
305
  --lan Bind to 0.0.0.0 for LAN access
389
306
  --server <url> Public/server URL for connect-url links
390
307
  --relay connect-url: also include the end-to-end-encrypted relay transport
@@ -413,7 +330,6 @@ EXAMPLES:
413
330
  openchamber connect-url --port 3000 --qr
414
331
  openchamber connect-url --server https://openchamber.example.com
415
332
  openchamber startup enable # Start OpenChamber at user login
416
- openchamber tunnel help # Show tunnel lifecycle help
417
333
  openchamber logs # Follow logs for latest running instance
418
334
  `);
419
335
  }
@@ -486,251 +402,11 @@ EXAMPLES:
486
402
  `);
487
403
  }
488
404
 
489
- function showTunnelHelp() {
490
- console.log(`
491
- Tunnel Lifecycle Commands
492
-
493
- USAGE:
494
- openchamber tunnel <SUBCOMMAND> [OPTIONS]
495
-
496
- SUBCOMMANDS:
497
- help Show this tunnel help
498
- providers Show available tunnel providers and capabilities
499
- ready Check tunnel readiness for a provider
500
- doctor Run deep tunnel diagnostics
501
- status Show tunnel status
502
- start Start a tunnel
503
- stop Stop active tunnel (keep server running)
504
- profile Manage saved managed-remote profiles
505
-
506
- COMMON OPTIONS:
507
- -p, --port Target OpenChamber instance port
508
- --host Bind address when auto-starting an instance
509
- --lan Bind to 0.0.0.0 when auto-starting an instance
510
- --ui-password Protect browser UI when auto-starting an instance
511
- --api-only Start API routes only when auto-starting an instance
512
- --json Output machine-readable JSON
513
- --all Apply to all running instances (doctor default, stop)
514
-
515
- START OPTIONS:
516
- --provider <id> Tunnel provider id (default: cloudflare)
517
- --mode <id> Tunnel mode (default: quick)
518
- --profile <name> Start tunnel from saved profile name
519
- --config [path] Managed-local config path (optional)
520
- --token <token> Managed-remote token (visible in process list)
521
- --token-file <path> Read token from file (recommended)
522
- --token-stdin Read token from stdin
523
- --hostname <hostname> Managed-remote hostname
524
- --connect-ttl <value> Connect-link TTL (e.g. 30m, 24h, 1d)
525
- --session-ttl <value> Session TTL (e.g. 8h, 24h, 1d)
526
- --qr Print QR code for resulting tunnel URL
527
- --no-qr Disable QR output
528
- --dry-run Validate inputs without applying changes
529
-
530
- OUTPUT OPTIONS:
531
- --show-secrets Show full tokens in output (default: redacted)
532
- --plain Disable colors and decorations
533
- -q, --quiet Suppress non-essential output
534
- --json Output machine-readable JSON
535
-
536
- BEHAVIOR NOTES:
537
- - One active tunnel per OpenChamber instance.
538
- - Starting a different mode/provider replaces the current tunnel and revokes old connect links/sessions.
539
- - Connect links are one-time; generating a new link revokes the previous unused link.
540
-
541
- PROFILE USAGE:
542
- openchamber tunnel profile list [--provider <id>] [--json]
543
- openchamber tunnel profile show --name <name> [--provider <id>] [--json]
544
- openchamber tunnel profile add --provider <id> --mode managed-remote --name <name> --hostname <host> --token <token> [--force] [--json]
545
- openchamber tunnel profile add --provider <id> --mode managed-remote --name <name> --hostname <host> --token-file <path> [--force] [--json]
546
- openchamber tunnel profile remove --name <name> [--provider <id>] [--json]
547
-
548
- SHELL COMPLETION:
549
- openchamber tunnel completion bash Generate Bash completion script
550
- openchamber tunnel completion zsh Generate Zsh completion script
551
- openchamber tunnel completion fish Generate Fish completion script
552
-
553
- EXAMPLES:
554
- openchamber tunnel providers
555
- openchamber tunnel ready --provider cloudflare
556
- openchamber tunnel doctor --provider cloudflare
557
- openchamber tunnel status
558
- openchamber tunnel start --qr
559
- openchamber tunnel start --profile prod-main
560
- openchamber tunnel start --provider cloudflare --mode managed-remote --token-file ~/.secrets/cf-token --hostname app.example.com
561
- openchamber tunnel start --provider cloudflare --mode managed-local --config ~/.cloudflared/config.yml
562
- openchamber tunnel start --dry-run --provider cloudflare --mode managed-remote --token-file ~/.secrets/cf-token --hostname app.example.com
563
- echo "$TOKEN" | openchamber tunnel profile add --provider cloudflare --mode managed-remote --name prod-main --hostname app.example.com --token-stdin
564
- openchamber tunnel profile list --provider cloudflare
565
- openchamber tunnel profile list --json --show-secrets
566
- openchamber tunnel stop --port 3000
567
- `);
568
- }
569
-
570
- function generateCompletionScript(shell) {
571
- const normalized = typeof shell === 'string' ? shell.trim().toLowerCase() : '';
572
-
573
- if (normalized === 'bash') {
574
- return `# Bash completion for openchamber tunnel
575
- # Add to ~/.bashrc: eval "$(openchamber tunnel completion bash)"
576
- _openchamber_tunnel() {
577
- local cur prev commands tunnel_commands profile_commands common_flags start_flags
578
- COMPREPLY=()
579
- cur="\${COMP_WORDS[COMP_CWORD]}"
580
- prev="\${COMP_WORDS[COMP_CWORD-1]}"
581
-
582
- commands="serve stop restart status tunnel logs update"
583
- tunnel_commands="help providers ready doctor status start stop profile completion"
584
- profile_commands="list show add remove"
585
- common_flags="--port --foreground --no-daemon --json --all --help --version --plain --quiet"
586
- start_flags="--provider --mode --profile --config --token --token-file --token-stdin --hostname --connect-ttl --session-ttl --qr --no-qr --dry-run --show-secrets"
587
-
588
- if [[ \${COMP_CWORD} -eq 1 ]]; then
589
- COMPREPLY=( $(compgen -W "\${commands}" -- "\${cur}") )
590
- return 0
591
- fi
592
-
593
- if [[ "\${COMP_WORDS[1]}" == "tunnel" ]]; then
594
- if [[ \${COMP_CWORD} -eq 2 ]]; then
595
- COMPREPLY=( $(compgen -W "\${tunnel_commands}" -- "\${cur}") )
596
- return 0
597
- fi
598
- if [[ "\${COMP_WORDS[2]}" == "profile" && \${COMP_CWORD} -eq 3 ]]; then
599
- COMPREPLY=( $(compgen -W "\${profile_commands}" -- "\${cur}") )
600
- return 0
601
- fi
602
- if [[ "\${COMP_WORDS[2]}" == "completion" && \${COMP_CWORD} -eq 3 ]]; then
603
- COMPREPLY=( $(compgen -W "bash zsh fish" -- "\${cur}") )
604
- return 0
605
- fi
606
- if [[ "\${COMP_WORDS[2]}" == "start" ]]; then
607
- COMPREPLY=( $(compgen -W "\${start_flags} \${common_flags}" -- "\${cur}") )
608
- return 0
609
- fi
610
- COMPREPLY=( $(compgen -W "\${common_flags}" -- "\${cur}") )
611
- return 0
612
- fi
613
-
614
- COMPREPLY=( $(compgen -W "\${common_flags}" -- "\${cur}") )
615
- return 0
616
- }
617
- complete -F _openchamber_tunnel openchamber
618
- `;
619
- }
620
-
621
- if (normalized === 'zsh') {
622
- return `#compdef openchamber
623
- # Zsh completion for openchamber tunnel
624
- # Add to ~/.zshrc: eval "$(openchamber tunnel completion zsh)"
625
-
626
- _openchamber() {
627
- local -a commands tunnel_commands profile_commands
628
-
629
- commands=(
630
- 'serve:Start the web server'
631
- 'stop:Stop running instance(s)'
632
- 'restart:Stop and start the server'
633
- 'status:Show server status'
634
- 'tunnel:Tunnel lifecycle commands'
635
- 'logs:Tail OpenChamber logs'
636
- 'update:Check for and install updates'
637
- )
638
-
639
- tunnel_commands=(
640
- 'help:Show tunnel help'
641
- 'providers:Show available providers'
642
- 'ready:Check tunnel readiness'
643
- 'doctor:Run tunnel diagnostics'
644
- 'status:Show tunnel status'
645
- 'start:Start a tunnel'
646
- 'stop:Stop active tunnel'
647
- 'profile:Manage saved profiles'
648
- 'completion:Generate shell completion'
649
- )
650
-
651
- profile_commands=(
652
- 'list:List profiles'
653
- 'show:Show profile details'
654
- 'add:Add a profile'
655
- 'remove:Remove a profile'
656
- )
657
-
658
- _arguments -C \\
659
- '1:command:->command' \\
660
- '*::arg:->args'
661
-
662
- case \$state in
663
- command)
664
- _describe 'command' commands
665
- ;;
666
- args)
667
- case \$words[1] in
668
- tunnel)
669
- if (( CURRENT == 2 )); then
670
- _describe 'tunnel command' tunnel_commands
671
- elif [[ \$words[2] == "profile" ]] && (( CURRENT == 3 )); then
672
- _describe 'profile action' profile_commands
673
- elif [[ \$words[2] == "completion" ]] && (( CURRENT == 3 )); then
674
- _values 'shell' bash zsh fish
675
- fi
676
- ;;
677
- esac
678
- ;;
679
- esac
680
- }
681
-
682
- compdef _openchamber openchamber
683
- `;
684
- }
685
-
686
- if (normalized === 'fish') {
687
- return `# Fish completion for openchamber tunnel
688
- # Save to ~/.config/fish/completions/openchamber.fish
689
-
690
- complete -c openchamber -n '__fish_use_subcommand' -a 'serve' -d 'Start the web server'
691
- complete -c openchamber -n '__fish_seen_subcommand_from serve' -l foreground -d 'Run in foreground (for systemd/process managers)'
692
- complete -c openchamber -n '__fish_seen_subcommand_from serve' -l no-daemon -d 'Run in foreground (alias for --foreground)'
693
- complete -c openchamber -n '__fish_use_subcommand' -a 'stop' -d 'Stop running instance(s)'
694
- complete -c openchamber -n '__fish_use_subcommand' -a 'restart' -d 'Stop and start the server'
695
- complete -c openchamber -n '__fish_use_subcommand' -a 'status' -d 'Show server status'
696
- complete -c openchamber -n '__fish_use_subcommand' -a 'tunnel' -d 'Tunnel lifecycle commands'
697
- complete -c openchamber -n '__fish_use_subcommand' -a 'logs' -d 'Tail logs'
698
- complete -c openchamber -n '__fish_use_subcommand' -a 'update' -d 'Check for updates'
699
-
700
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and not __fish_seen_subcommand_from help providers ready doctor status start stop profile completion' -a 'help' -d 'Show tunnel help'
701
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and not __fish_seen_subcommand_from help providers ready doctor status start stop profile completion' -a 'providers' -d 'Show providers'
702
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and not __fish_seen_subcommand_from help providers ready doctor status start stop profile completion' -a 'ready' -d 'Check readiness'
703
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and not __fish_seen_subcommand_from help providers ready doctor status start stop profile completion' -a 'doctor' -d 'Run diagnostics'
704
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and not __fish_seen_subcommand_from help providers ready doctor status start stop profile completion' -a 'status' -d 'Show tunnel status'
705
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and not __fish_seen_subcommand_from help providers ready doctor status start stop profile completion' -a 'start' -d 'Start a tunnel'
706
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and not __fish_seen_subcommand_from help providers ready doctor status start stop profile completion' -a 'stop' -d 'Stop tunnel'
707
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and not __fish_seen_subcommand_from help providers ready doctor status start stop profile completion' -a 'profile' -d 'Manage profiles'
708
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and not __fish_seen_subcommand_from help providers ready doctor status start stop profile completion' -a 'completion' -d 'Generate completions'
709
-
710
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and __fish_seen_subcommand_from start' -l provider -d 'Provider id'
711
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and __fish_seen_subcommand_from start' -l mode -d 'Tunnel mode'
712
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and __fish_seen_subcommand_from start' -l profile -d 'Profile name'
713
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and __fish_seen_subcommand_from start' -l config -d 'Config path'
714
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and __fish_seen_subcommand_from start' -l token -d 'Token'
715
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and __fish_seen_subcommand_from start' -l token-file -d 'Token file path'
716
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and __fish_seen_subcommand_from start' -l token-stdin -d 'Read token from stdin'
717
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and __fish_seen_subcommand_from start' -l hostname -d 'Hostname'
718
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and __fish_seen_subcommand_from start' -l dry-run -d 'Validate without applying'
719
- complete -c openchamber -n '__fish_seen_subcommand_from tunnel; and __fish_seen_subcommand_from start' -l qr -d 'Show QR code'
720
- `;
721
- }
722
-
723
- return null;
724
- }
725
-
726
-
727
405
  export {
728
406
  DEFAULT_PORT,
729
407
  parseArgs,
730
408
  showHelp,
731
409
  showStartupHelp,
732
410
  showConnectUrlHelp,
733
- showTunnelHelp,
734
- generateCompletionScript,
735
411
  findClosestMatch,
736
412
  };
@@ -163,21 +163,6 @@ async function waitForServerHealth(port, {
163
163
  }
164
164
 
165
165
 
166
- async function fetchTunnelProvidersFromPort(port, fetchImpl = globalThis.fetch) {
167
- if (!Number.isFinite(port) || port <= 0 || typeof fetchImpl !== 'function') {
168
- return null;
169
- }
170
- try {
171
- const response = await fetchImpl(buildLocalUrl(port, '/api/openchamber/tunnel/providers'));
172
- if (!response.ok) return null;
173
- const body = await response.json().catch(() => null);
174
- if (!body || !Array.isArray(body.providers)) return null;
175
- return body.providers;
176
- } catch {
177
- return null;
178
- }
179
- }
180
-
181
166
  async function fetchSystemInfoFromPort(port, fetchImpl = globalThis.fetch, hostOverride) {
182
167
  if (!Number.isFinite(port) || port <= 0 || typeof fetchImpl !== 'function') {
183
168
  return null;
@@ -211,6 +196,5 @@ export {
211
196
  requestJson,
212
197
  isServerHealthReady,
213
198
  waitForServerHealth,
214
- fetchTunnelProvidersFromPort,
215
199
  fetchSystemInfoFromPort,
216
200
  };
@@ -1,9 +1,8 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import { DEFAULT_PORT } from './cli-args.js';
4
3
  import { getRunDir, readDesktopLocalPortFromSettings } from './cli-paths.js';
5
- import { resolveApiHost, buildLocalUrl } from './cli-network.js';
6
- import { fetchTunnelProvidersFromPort, fetchSystemInfoFromPort, isServerHealthReady } from './cli-http.js';
4
+ import { resolveApiHost } from './cli-network.js';
5
+ import { fetchSystemInfoFromPort, isServerHealthReady } from './cli-http.js';
7
6
  import { isPortAvailable } from './cli-ports.js';
8
7
  import {
9
8
  getPidFilePath,
@@ -15,8 +14,6 @@ import {
15
14
  getOpenchamberProcessState,
16
15
  hasOpenchamberRuntimeInfo,
17
16
  } from './cli-process.js';
18
- import { DEFAULT_TUNNEL_PROVIDER_CAPABILITIES } from './cli-tunnel-capabilities.js';
19
-
20
17
  function createLivePortInstance(port, info, host) {
21
18
  if (!hasOpenchamberRuntimeInfo(info)) return null;
22
19
  return {
@@ -87,79 +84,6 @@ async function fetchSystemInfoFromPortCandidates(port, fetchImpl, hosts, expecte
87
84
  return { info: null, host: null };
88
85
  }
89
86
 
90
- async function resolveDoctorPortStatuses(options = {}) {
91
- const runningEntries = await discoverRunningInstances();
92
- const desktopEntry = await discoverDesktopInstance();
93
- const statuses = [];
94
-
95
- if (options.explicitPort) {
96
- const requestedPort = options.port;
97
- const runningMatch = runningEntries.find((entry) => entry.port === requestedPort);
98
- if (runningMatch) {
99
- statuses.push({
100
- port: requestedPort,
101
- available: true,
102
- status: 'success',
103
- line: `port ${requestedPort} available for tunneling`,
104
- detail: 'Double-check this same port is configured in your provider dashboard/config.',
105
- });
106
- return { statuses, availableEntries: [runningMatch] };
107
- }
108
-
109
- if (desktopEntry && desktopEntry.port === requestedPort) {
110
- statuses.push({
111
- port: requestedPort,
112
- available: false,
113
- status: 'warning',
114
- line: `port ${requestedPort} not available (desktop runtime)`,
115
- detail: 'Use a CLI instance port from `openchamber serve` for tunneling.',
116
- });
117
- return { statuses, availableEntries: [] };
118
- }
119
-
120
- statuses.push({
121
- port: requestedPort,
122
- available: false,
123
- status: 'error',
124
- line: `port ${requestedPort} not available (no running instance)`,
125
- detail: `Start one with \`openchamber serve --port ${requestedPort}\`.`,
126
- });
127
- return { statuses, availableEntries: [] };
128
- }
129
-
130
- for (const entry of runningEntries) {
131
- statuses.push({
132
- port: entry.port,
133
- available: true,
134
- status: 'success',
135
- line: `port ${entry.port} available for tunneling`,
136
- detail: 'Double-check this same port is configured in your provider dashboard/config.',
137
- });
138
- }
139
-
140
- if (desktopEntry && !runningEntries.some((entry) => entry.port === desktopEntry.port)) {
141
- statuses.push({
142
- port: desktopEntry.port,
143
- available: false,
144
- status: 'warning',
145
- line: `port ${desktopEntry.port} not available (desktop runtime)`,
146
- detail: 'Use a CLI instance port from `openchamber serve` for tunneling.',
147
- });
148
- }
149
-
150
- if (runningEntries.length === 0) {
151
- statuses.push({
152
- port: null,
153
- available: false,
154
- status: 'warning',
155
- line: 'no CLI ports available for tunneling',
156
- detail: 'Start one with `openchamber serve`.',
157
- });
158
- }
159
-
160
- return { statuses, availableEntries: runningEntries };
161
- }
162
-
163
87
  async function discoverRunningInstances(options = {}) {
164
88
  const instances = [];
165
89
  const runDir = getRunDir();
@@ -376,39 +300,7 @@ async function discoverDesktopInstance(fetchImpl = globalThis.fetch) {
376
300
  };
377
301
  }
378
302
 
379
- async function resolveTunnelProviders(options = {}, deps = {}) {
380
- const readPorts = typeof deps.readPorts === 'function'
381
- ? deps.readPorts
382
- : async () => (await discoverRunningInstances()).map((entry) => entry.port);
383
- const fetchImpl = typeof deps.fetchImpl === 'function' ? deps.fetchImpl : globalThis.fetch;
384
-
385
- const candidatePorts = [];
386
- if (Number.isFinite(options.port) && options.port > 0) {
387
- candidatePorts.push(options.port);
388
- }
389
-
390
- const discoveredPorts = await Promise.resolve(readPorts());
391
- if (Array.isArray(discoveredPorts)) {
392
- candidatePorts.push(...discoveredPorts);
393
- }
394
-
395
- if (!candidatePorts.includes(DEFAULT_PORT)) {
396
- candidatePorts.push(DEFAULT_PORT);
397
- }
398
-
399
- for (const port of candidatePorts) {
400
- const providers = await fetchTunnelProvidersFromPort(port, fetchImpl);
401
- if (providers) {
402
- return { providers, source: `api:${port}` };
403
- }
404
- }
405
-
406
- return { providers: DEFAULT_TUNNEL_PROVIDER_CAPABILITIES, source: 'fallback' };
407
- }
408
-
409
-
410
303
  export {
411
- resolveDoctorPortStatuses,
412
304
  discoverRunningInstances,
413
305
  discoverOpenChamberInstanceOnPort,
414
306
  discoverLifecycleInstances,
@@ -417,5 +309,4 @@ export {
417
309
  isDesktopRuntimeForPort,
418
310
  inspectTunnelAttachability,
419
311
  discoverDesktopInstance,
420
- resolveTunnelProviders,
421
312
  };
@@ -2,10 +2,6 @@ import fs from 'fs';
2
2
  import os from 'os';
3
3
  import path from 'path';
4
4
 
5
- const TUNNEL_PROFILES_FILE_NAME = 'tunnel-profiles.json';
6
- const LEGACY_CLOUDFLARE_MANAGED_REMOTE_FILE_NAME = 'cloudflare-managed-remote-tunnels.json';
7
- const TUNNEL_CLI_STATE_FILE_NAME = 'tunnel-cli-state.json';
8
-
9
5
  function getDataDir() {
10
6
  if (typeof process.env.OPENCHAMBER_DATA_DIR === 'string' && process.env.OPENCHAMBER_DATA_DIR.trim().length > 0) {
11
7
  return path.resolve(process.env.OPENCHAMBER_DATA_DIR.trim());
@@ -43,55 +39,6 @@ function getLogFilePath(port) {
43
39
  return path.join(getLogsDir(), `openchamber-${port}.log`);
44
40
  }
45
41
 
46
- function getTunnelProfilesFilePath() {
47
- return path.join(getDataDir(), TUNNEL_PROFILES_FILE_NAME);
48
- }
49
-
50
- function getLegacyCloudflareManagedRemoteFilePath() {
51
- return path.join(getDataDir(), LEGACY_CLOUDFLARE_MANAGED_REMOTE_FILE_NAME);
52
- }
53
-
54
- function getTunnelCliStateFilePath() {
55
- return path.join(getDataDir(), TUNNEL_CLI_STATE_FILE_NAME);
56
- }
57
-
58
- function readTunnelCliState() {
59
- const filePath = getTunnelCliStateFilePath();
60
- try {
61
- const raw = fs.readFileSync(filePath, 'utf8');
62
- const parsed = JSON.parse(raw);
63
- if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
64
- return {};
65
- }
66
- return parsed;
67
- } catch {
68
- return {};
69
- }
70
- }
71
-
72
- function readLastManagedLocalConfigPath() {
73
- const state = readTunnelCliState();
74
- if (typeof state.lastManagedLocalConfigPath !== 'string') {
75
- return '';
76
- }
77
- return state.lastManagedLocalConfigPath.trim();
78
- }
79
-
80
- function writeLastManagedLocalConfigPath(configPath) {
81
- if (typeof configPath !== 'string' || configPath.trim().length === 0) {
82
- return;
83
- }
84
- const filePath = getTunnelCliStateFilePath();
85
- const current = readTunnelCliState();
86
- const next = {
87
- ...current,
88
- lastManagedLocalConfigPath: configPath.trim(),
89
- updatedAt: Date.now(),
90
- };
91
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
92
- fs.writeFileSync(filePath, JSON.stringify(next, null, 2), 'utf8');
93
- }
94
-
95
42
 
96
43
  function getRunDir() {
97
44
  const dir = path.join(getDataDir(), 'run');
@@ -105,9 +52,5 @@ export {
105
52
  readDesktopLocalPortFromSettings,
106
53
  ensureLogsDir,
107
54
  getLogFilePath,
108
- getTunnelProfilesFilePath,
109
- getLegacyCloudflareManagedRemoteFilePath,
110
- readLastManagedLocalConfigPath,
111
- writeLastManagedLocalConfigPath,
112
55
  getRunDir,
113
56
  };