@openchamber/web 1.2.7 → 1.2.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.
package/README.md CHANGED
@@ -5,13 +5,22 @@ Web interface for the [OpenCode](https://opencode.ai) AI coding agent.
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm add -g @openchamber/web
8
+ # Quick install (auto-detects your package manager)
9
+ curl -fsSL https://raw.githubusercontent.com/btriapitsyn/openchamber/main/scripts/install.sh | bash
9
10
 
11
+ # Or install manually
12
+ npm add -g @openchamber/web # or pnpm, yarn, bun
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```bash
10
18
  openchamber # Start on port 3000
11
19
  openchamber --port 8080 # Custom port
12
20
  openchamber --daemon # Background mode
13
21
  openchamber --ui-password secret # Password-protect UI
14
22
  openchamber stop # Stop server
23
+ openchamber update # Update to latest version
15
24
  ```
16
25
 
17
26
  ## Prerequisites
package/bin/cli.js CHANGED
@@ -94,6 +94,7 @@ COMMANDS:
94
94
  stop Stop running instance(s)
95
95
  restart Stop and start the server
96
96
  status Show server status
97
+ update Check for and install updates
97
98
 
98
99
  OPTIONS:
99
100
  -p, --port Web server port (default: ${DEFAULT_PORT})
@@ -112,6 +113,7 @@ EXAMPLES:
112
113
  openchamber stop # Stop all running instances
113
114
  openchamber stop --port 3000 # Stop specific instance
114
115
  openchamber status # Check status
116
+ openchamber update # Update to latest version
115
117
  `);
116
118
  }
117
119
 
@@ -245,6 +247,12 @@ async function getPidFilePath(port) {
245
247
  return path.join(tmpDir, `openchamber-${port}.pid`);
246
248
  }
247
249
 
250
+ async function getInstanceFilePath(port) {
251
+ const os = await import('os');
252
+ const tmpDir = os.tmpdir();
253
+ return path.join(tmpDir, `openchamber-${port}.json`);
254
+ }
255
+
248
256
  function readPidFile(pidFilePath) {
249
257
  try {
250
258
  const content = fs.readFileSync(pidFilePath, 'utf8').trim();
@@ -276,6 +284,50 @@ function removePidFile(pidFilePath) {
276
284
  }
277
285
  }
278
286
 
287
+ /**
288
+ * Read stored instance options (port, daemon, uiPassword)
289
+ */
290
+ function readInstanceOptions(instanceFilePath) {
291
+ try {
292
+ const content = fs.readFileSync(instanceFilePath, 'utf8');
293
+ return JSON.parse(content);
294
+ } catch (error) {
295
+ return null;
296
+ }
297
+ }
298
+
299
+ /**
300
+ * Write instance options for restart/update to reuse
301
+ */
302
+ function writeInstanceOptions(instanceFilePath, options) {
303
+ try {
304
+ // Only store non-sensitive restart-relevant options
305
+ const toStore = {
306
+ port: options.port,
307
+ daemon: options.daemon || false,
308
+ // Store password existence but not value - will use env var
309
+ hasUiPassword: typeof options.uiPassword === 'string',
310
+ };
311
+ // For daemon mode, we need to store the password to restart properly
312
+ if (options.daemon && typeof options.uiPassword === 'string') {
313
+ toStore.uiPassword = options.uiPassword;
314
+ }
315
+ fs.writeFileSync(instanceFilePath, JSON.stringify(toStore, null, 2));
316
+ } catch (error) {
317
+ console.warn(`Warning: Could not write instance file: ${error.message}`);
318
+ }
319
+ }
320
+
321
+ function removeInstanceFile(instanceFilePath) {
322
+ try {
323
+ if (fs.existsSync(instanceFilePath)) {
324
+ fs.unlinkSync(instanceFilePath);
325
+ }
326
+ } catch (error) {
327
+ // Ignore
328
+ }
329
+ }
330
+
279
331
  function isProcessRunning(pid) {
280
332
  try {
281
333
  process.kill(pid, 0);
@@ -288,6 +340,7 @@ function isProcessRunning(pid) {
288
340
  const commands = {
289
341
  async serve(options) {
290
342
  const pidFilePath = await getPidFilePath(options.port);
343
+ const instanceFilePath = await getInstanceFilePath(options.port);
291
344
 
292
345
  const existingPid = readPidFile(pidFilePath);
293
346
  if (existingPid && isProcessRunning(existingPid)) {
@@ -323,6 +376,7 @@ const commands = {
323
376
  setTimeout(() => {
324
377
  if (isProcessRunning(child.pid)) {
325
378
  writePidFile(pidFilePath, child.pid);
379
+ writeInstanceOptions(instanceFilePath, options);
326
380
  console.log(`OpenChamber started in daemon mode on port ${options.port}`);
327
381
  console.log(`PID: ${child.pid}`);
328
382
  console.log(`Visit: http://localhost:${options.port}`);
@@ -338,6 +392,7 @@ const commands = {
338
392
  if (typeof options.uiPassword === 'string') {
339
393
  process.env.OPENCHAMBER_UI_PASSWORD = options.uiPassword;
340
394
  }
395
+ writeInstanceOptions(instanceFilePath, options);
341
396
  const { startWebUiServer } = await import(serverPath);
342
397
  await startWebUiServer({
343
398
  port: options.port,
@@ -365,10 +420,12 @@ const commands = {
365
420
  const pid = readPidFile(pidFilePath);
366
421
 
367
422
  if (pid && isProcessRunning(pid)) {
368
- runningInstances.push({ port, pid, pidFilePath });
423
+ const instanceFilePath = path.join(tmpDir, `openchamber-${port}.json`);
424
+ runningInstances.push({ port, pid, pidFilePath, instanceFilePath });
369
425
  } else {
370
426
 
371
427
  removePidFile(pidFilePath);
428
+ removeInstanceFile(path.join(tmpDir, `openchamber-${port}.json`));
372
429
  }
373
430
  }
374
431
  }
@@ -404,12 +461,14 @@ const commands = {
404
461
  if (!isProcessRunning(targetInstance.pid)) {
405
462
  clearInterval(checkShutdown);
406
463
  removePidFile(targetInstance.pidFilePath);
464
+ removeInstanceFile(targetInstance.instanceFilePath);
407
465
  console.log('OpenChamber stopped successfully');
408
466
  } else if (attempts >= maxAttempts) {
409
467
  clearInterval(checkShutdown);
410
468
  console.log('Force killing process...');
411
469
  process.kill(targetInstance.pid, 'SIGKILL');
412
470
  removePidFile(targetInstance.pidFilePath);
471
+ removeInstanceFile(targetInstance.instanceFilePath);
413
472
  console.log('OpenChamber force stopped');
414
473
  }
415
474
  }, 500);
@@ -437,6 +496,7 @@ const commands = {
437
496
  if (!isProcessRunning(instance.pid)) {
438
497
  clearInterval(checkShutdown);
439
498
  removePidFile(instance.pidFilePath);
499
+ removeInstanceFile(instance.instanceFilePath);
440
500
  console.log(` Port ${instance.port} stopped successfully`);
441
501
  resolve(true);
442
502
  } else if (attempts >= maxAttempts) {
@@ -445,6 +505,7 @@ const commands = {
445
505
  try {
446
506
  process.kill(instance.pid, 'SIGKILL');
447
507
  removePidFile(instance.pidFilePath);
508
+ removeInstanceFile(instance.instanceFilePath);
448
509
  console.log(` Port ${instance.port} force stopped`);
449
510
  } catch (e) {
450
511
 
@@ -464,11 +525,95 @@ const commands = {
464
525
  },
465
526
 
466
527
  async restart(options) {
467
- await commands.stop(options);
468
- await commands.serve(options);
528
+ const os = await import('os');
529
+ const tmpDir = os.tmpdir();
530
+
531
+ // Find running instances to get their stored options
532
+ let instancesToRestart = [];
533
+
534
+ try {
535
+ const files = fs.readdirSync(tmpDir);
536
+ const pidFiles = files.filter(file => file.startsWith('openchamber-') && file.endsWith('.pid'));
537
+
538
+ for (const file of pidFiles) {
539
+ const port = parseInt(file.replace('openchamber-', '').replace('.pid', ''));
540
+ if (!isNaN(port)) {
541
+ const pidFilePath = path.join(tmpDir, file);
542
+ const instanceFilePath = path.join(tmpDir, `openchamber-${port}.json`);
543
+ const pid = readPidFile(pidFilePath);
544
+
545
+ if (pid && isProcessRunning(pid)) {
546
+ const storedOptions = readInstanceOptions(instanceFilePath);
547
+ instancesToRestart.push({
548
+ port,
549
+ pid,
550
+ pidFilePath,
551
+ instanceFilePath,
552
+ storedOptions: storedOptions || { port, daemon: false },
553
+ });
554
+ }
555
+ }
556
+ }
557
+ } catch (error) {
558
+ // Ignore
559
+ }
560
+
561
+ const portWasSpecified = process.argv.includes('--port') || process.argv.includes('-p');
562
+
563
+ if (instancesToRestart.length === 0) {
564
+ console.log('No running OpenChamber instances to restart');
565
+ console.log('Use "openchamber serve" to start a new instance');
566
+ return;
567
+ }
568
+
569
+ if (portWasSpecified) {
570
+ // Restart specific instance
571
+ const target = instancesToRestart.find(inst => inst.port === options.port);
572
+ if (!target) {
573
+ console.log(`No OpenChamber instance found running on port ${options.port}`);
574
+ return;
575
+ }
576
+ instancesToRestart = [target];
577
+ }
578
+
579
+ for (const instance of instancesToRestart) {
580
+ console.log(`Restarting OpenChamber on port ${instance.port}...`);
581
+
582
+ // Merge stored options with any explicitly provided options
583
+ const restartOptions = {
584
+ ...instance.storedOptions,
585
+ // CLI-provided options override stored ones
586
+ ...(portWasSpecified ? { port: options.port } : {}),
587
+ ...(process.argv.includes('--daemon') || process.argv.includes('-d') ? { daemon: options.daemon } : {}),
588
+ ...(process.argv.includes('--ui-password') ? { uiPassword: options.uiPassword } : {}),
589
+ };
590
+
591
+ // Stop the instance
592
+ try {
593
+ process.kill(instance.pid, 'SIGTERM');
594
+ // Wait for it to stop
595
+ let attempts = 0;
596
+ while (isProcessRunning(instance.pid) && attempts < 20) {
597
+ await new Promise(resolve => setTimeout(resolve, 250));
598
+ attempts++;
599
+ }
600
+ if (isProcessRunning(instance.pid)) {
601
+ process.kill(instance.pid, 'SIGKILL');
602
+ }
603
+ removePidFile(instance.pidFilePath);
604
+ } catch (error) {
605
+ console.warn(`Warning: Could not stop instance: ${error.message}`);
606
+ }
607
+
608
+ // Small delay before restart
609
+ await new Promise(resolve => setTimeout(resolve, 500));
610
+
611
+ // Start with merged options
612
+ await commands.serve(restartOptions);
613
+ }
469
614
  },
470
615
 
471
- async status(options) {
616
+ async status() {
472
617
  const os = await import('os');
473
618
  const tmpDir = os.tmpdir();
474
619
 
@@ -527,6 +672,131 @@ const commands = {
527
672
  }
528
673
  },
529
674
 
675
+ async update() {
676
+ const os = await import('os');
677
+ const tmpDir = os.tmpdir();
678
+ const packageManagerPath = path.join(__dirname, '..', 'server', 'lib', 'package-manager.js');
679
+ const {
680
+ checkForUpdates,
681
+ executeUpdate,
682
+ detectPackageManager,
683
+ getCurrentVersion,
684
+ } = await import(packageManagerPath);
685
+
686
+ // Check for running instances before update
687
+ let runningInstances = [];
688
+ try {
689
+ const files = fs.readdirSync(tmpDir);
690
+ const pidFiles = files.filter(file => file.startsWith('openchamber-') && file.endsWith('.pid'));
691
+
692
+ for (const file of pidFiles) {
693
+ const port = parseInt(file.replace('openchamber-', '').replace('.pid', ''));
694
+ if (!isNaN(port)) {
695
+ const pidFilePath = path.join(tmpDir, file);
696
+ const instanceFilePath = path.join(tmpDir, `openchamber-${port}.json`);
697
+ const pid = readPidFile(pidFilePath);
698
+
699
+ if (pid && isProcessRunning(pid)) {
700
+ const storedOptions = readInstanceOptions(instanceFilePath);
701
+ runningInstances.push({
702
+ port,
703
+ pid,
704
+ pidFilePath,
705
+ instanceFilePath,
706
+ storedOptions: storedOptions || { port, daemon: true },
707
+ });
708
+ }
709
+ }
710
+ }
711
+ } catch (error) {
712
+ // Ignore
713
+ }
714
+
715
+ console.log('Checking for updates...');
716
+ console.log(`Current version: ${getCurrentVersion()}`);
717
+
718
+ const updateInfo = await checkForUpdates();
719
+
720
+ if (updateInfo.error) {
721
+ console.error(`Error: ${updateInfo.error}`);
722
+ process.exit(1);
723
+ }
724
+
725
+ if (!updateInfo.available) {
726
+ console.log('\nYou are running the latest version.');
727
+ return;
728
+ }
729
+
730
+ console.log(`\nNew version available: ${updateInfo.version}`);
731
+
732
+ if (updateInfo.body) {
733
+ console.log('\nChangelog:');
734
+ console.log('─'.repeat(40));
735
+ // Simple formatting for CLI
736
+ const formatted = updateInfo.body
737
+ .replace(/^## \[(\d+\.\d+\.\d+)\] - \d{4}-\d{2}-\d{2}/gm, '\nv$1')
738
+ .replace(/^### /gm, '\n')
739
+ .replace(/^- /gm, ' • ');
740
+ console.log(formatted);
741
+ console.log('─'.repeat(40));
742
+ }
743
+
744
+ // Stop running instances before update
745
+ if (runningInstances.length > 0) {
746
+ console.log(`\nStopping ${runningInstances.length} running instance(s) before update...`);
747
+ for (const instance of runningInstances) {
748
+ try {
749
+ process.kill(instance.pid, 'SIGTERM');
750
+ let attempts = 0;
751
+ while (isProcessRunning(instance.pid) && attempts < 20) {
752
+ await new Promise(resolve => setTimeout(resolve, 250));
753
+ attempts++;
754
+ }
755
+ if (isProcessRunning(instance.pid)) {
756
+ process.kill(instance.pid, 'SIGKILL');
757
+ }
758
+ removePidFile(instance.pidFilePath);
759
+ console.log(` Stopped instance on port ${instance.port}`);
760
+ } catch (error) {
761
+ console.warn(` Warning: Could not stop instance on port ${instance.port}`);
762
+ }
763
+ }
764
+ }
765
+
766
+ const pm = detectPackageManager();
767
+ console.log(`\nDetected package manager: ${pm}`);
768
+ console.log('Installing update...\n');
769
+
770
+ const result = executeUpdate(pm);
771
+
772
+ if (result.success) {
773
+ console.log('\nUpdate successful!');
774
+
775
+ // Restart previously running instances
776
+ if (runningInstances.length > 0) {
777
+ console.log(`\nRestarting ${runningInstances.length} instance(s)...`);
778
+ for (const instance of runningInstances) {
779
+ try {
780
+ // Force daemon mode for restart after update
781
+ const restartOptions = {
782
+ ...instance.storedOptions,
783
+ daemon: true,
784
+ };
785
+ await commands.serve(restartOptions);
786
+ console.log(` Restarted instance on port ${instance.port}`);
787
+ } catch (error) {
788
+ console.error(` Failed to restart instance on port ${instance.port}: ${error.message}`);
789
+ console.log(` Run manually: openchamber serve --port ${instance.port} --daemon`);
790
+ }
791
+ }
792
+ }
793
+ } else {
794
+ console.error('\nUpdate failed.');
795
+ console.error(`Exit code: ${result.exitCode}`);
796
+ process.exit(1);
797
+ }
798
+ },
799
+
530
800
  };
531
801
 
532
802
  async function main() {
@@ -1,5 +1,5 @@
1
- import{g as L,j as e,be as j,bs as g,ag as P,b0 as C,ar as T,b2 as w,Q as _,aR as z,aF as v,bp as D,bq as F,br as O,W as R}from"./vendor-.pnpm-Bax6Hn5Z.js";import{D as W,a as I,c as b,b as $,t as f,g as p,f as H,p as B,r as Q,d as V,e as E,h as A,S as G,i as q}from"./main-CjbXdQMY.js";import"./index-vvDNUcuS.js";const U=r=>{const o="h-3.5 w-3.5 flex-shrink-0",t=r.toLowerCase();return t==="reasoning"?e.jsx(P,{className:o}):t==="image-preview"?e.jsx(C,{className:o}):t==="edit"||t==="multiedit"||t==="str_replace"||t==="str_replace_based_edit_tool"?e.jsx(T,{className:o}):t==="write"||t==="create"||t==="file_write"?e.jsx(w,{className:o}):t==="read"||t==="view"||t==="file_read"||t==="cat"?e.jsx(w,{className:o}):t==="bash"||t==="shell"||t==="cmd"||t==="terminal"?e.jsx(_,{className:o}):t==="list"||t==="ls"||t==="dir"||t==="list_files"?e.jsx(z,{className:o}):t==="search"||t==="grep"||t==="find"||t==="ripgrep"?e.jsx(v,{className:o}):t==="glob"?e.jsx(D,{className:o}):t==="fetch"||t==="curl"||t==="wget"||t==="webfetch"?e.jsx(F,{className:o}):t==="web-search"||t==="websearch"||t==="search_web"||t==="google"||t==="bing"||t==="duckduckgo"?e.jsx(v,{className:o}):t==="todowrite"||t==="todoread"?e.jsx(O,{className:o}):t.startsWith("git")?e.jsx(R,{className:o}):e.jsx(j,{className:o})},X=({popup:r,onOpenChange:o,syntaxTheme:t,isMobile:u})=>{const[y,N]=L.useState(u?"unified":"side-by-side");return e.jsx(W,{open:r.open,onOpenChange:o,children:e.jsxs(I,{className:b("overflow-hidden flex flex-col min-h-0 pt-3 pb-4 px-4 gap-1","[&>button]:top-1.5",u?"w-[95vw] max-w-[95vw]":"max-w-5xl",u?"[&>button]:right-1":"[&>button]:top-2.5 [&>button]:right-4"),style:{maxHeight:"90vh"},children:[e.jsx("div",{className:"flex-shrink-0 pb-1",children:e.jsxs("div",{className:"flex items-start gap-2 text-foreground typography-ui-header font-semibold",children:[r.metadata?.tool?U(r.metadata.tool):e.jsx(j,{className:"h-3.5 w-3.5 text-foreground flex-shrink-0"}),e.jsx("span",{className:"break-words flex-1 leading-tight",children:r.title}),r.isDiff&&e.jsx($,{mode:y,onModeChange:N,className:"mr-8 flex-shrink-0"})]})}),e.jsx("div",{className:"flex-1 min-h-0 rounded-xl border border-border/30 bg-muted/10 overflow-hidden",children:e.jsxs("div",{className:"tool-output-surface h-full max-h-[75vh] overflow-y-auto px-3 pr-4",children:[r.metadata?.input&&typeof r.metadata.input=="object"&&Object.keys(r.metadata.input).length>0&&r.metadata?.tool!=="todowrite"&&r.metadata?.tool!=="todoread"?(()=>{const n=r.metadata,m=n.input,a=i=>{const s=m[i];return typeof s=="string"?s:typeof s=="number"?String(s):null};return e.jsxs("div",{className:"border-b border-border/20 p-4 -mx-3",children:[e.jsx("div",{className:"typography-markdown font-medium text-muted-foreground mb-2 px-3",children:n.tool==="bash"?"Command:":n.tool==="task"?"Task Details:":"Input:"}),n.tool==="bash"&&a("command")?e.jsx("div",{className:"tool-input-surface bg-transparent rounded-xl border border-border/20 mx-3",children:e.jsx(g,{style:t,language:"bash",PreTag:"div",customStyle:f.getPopupStyles(),codeTagProps:{style:{background:"transparent",backgroundColor:"transparent",fontSize:"inherit"}},wrapLongLines:!0,children:a("command")})}):n.tool==="task"&&a("prompt")?e.jsxs("div",{className:"tool-input-surface bg-transparent rounded-xl border border-border/20 font-mono whitespace-pre-wrap text-foreground/90 mx-3",style:f.getPopupStyles(),children:[a("description")?`Task: ${a("description")}
1
+ import{g as L,j as e,bg as v,bu as g,aj as P,b2 as C,au as T,b4 as w,Q as _,aT as z,aH as j,br as D,bs as O,bt as F,W}from"./vendor-.pnpm-Buk6Khtx.js";import{D as I,a as R,c as b,b as $,t as f,g as p,f as H,p as B,r as Q,d as V,e as E,h as A,S as G,i as U}from"./main-DI52tBPC.js";import"./index--hIzFLog.js";const q=r=>{const o="h-3.5 w-3.5 flex-shrink-0",t=r.toLowerCase();return t==="reasoning"?e.jsx(P,{className:o}):t==="image-preview"?e.jsx(C,{className:o}):t==="edit"||t==="multiedit"||t==="str_replace"||t==="str_replace_based_edit_tool"?e.jsx(T,{className:o}):t==="write"||t==="create"||t==="file_write"?e.jsx(w,{className:o}):t==="read"||t==="view"||t==="file_read"||t==="cat"?e.jsx(w,{className:o}):t==="bash"||t==="shell"||t==="cmd"||t==="terminal"?e.jsx(_,{className:o}):t==="list"||t==="ls"||t==="dir"||t==="list_files"?e.jsx(z,{className:o}):t==="search"||t==="grep"||t==="find"||t==="ripgrep"?e.jsx(j,{className:o}):t==="glob"?e.jsx(D,{className:o}):t==="fetch"||t==="curl"||t==="wget"||t==="webfetch"?e.jsx(O,{className:o}):t==="web-search"||t==="websearch"||t==="search_web"||t==="google"||t==="bing"||t==="duckduckgo"?e.jsx(j,{className:o}):t==="todowrite"||t==="todoread"?e.jsx(F,{className:o}):t.startsWith("git")?e.jsx(W,{className:o}):e.jsx(v,{className:o})},X=({popup:r,onOpenChange:o,syntaxTheme:t,isMobile:u})=>{const[y,N]=L.useState(u?"unified":"side-by-side");return e.jsx(I,{open:r.open,onOpenChange:o,children:e.jsxs(R,{className:b("overflow-hidden flex flex-col min-h-0 pt-3 pb-4 px-4 gap-1","[&>button]:top-1.5",u?"w-[95vw] max-w-[95vw]":"max-w-5xl",u?"[&>button]:right-1":"[&>button]:top-2.5 [&>button]:right-4"),style:{maxHeight:"90vh"},children:[e.jsx("div",{className:"flex-shrink-0 pb-1",children:e.jsxs("div",{className:"flex items-start gap-2 text-foreground typography-ui-header font-semibold",children:[r.metadata?.tool?q(r.metadata.tool):e.jsx(v,{className:"h-3.5 w-3.5 text-foreground flex-shrink-0"}),e.jsx("span",{className:"break-words flex-1 leading-tight",children:r.title}),r.isDiff&&e.jsx($,{mode:y,onModeChange:N,className:"mr-8 flex-shrink-0"})]})}),e.jsx("div",{className:"flex-1 min-h-0 rounded-xl border border-border/30 bg-muted/10 overflow-hidden",children:e.jsxs("div",{className:"tool-output-surface h-full max-h-[75vh] overflow-y-auto px-3 pr-4",children:[r.metadata?.input&&typeof r.metadata.input=="object"&&Object.keys(r.metadata.input).length>0&&r.metadata?.tool!=="todowrite"&&r.metadata?.tool!=="todoread"?(()=>{const n=r.metadata,m=n.input,a=i=>{const s=m[i];return typeof s=="string"?s:typeof s=="number"?String(s):null};return e.jsxs("div",{className:"border-b border-border/20 p-4 -mx-3",children:[e.jsx("div",{className:"typography-markdown font-medium text-muted-foreground mb-2 px-3",children:n.tool==="bash"?"Command:":n.tool==="task"?"Task Details:":"Input:"}),n.tool==="bash"&&a("command")?e.jsx("div",{className:"tool-input-surface bg-transparent rounded-xl border border-border/20 mx-3",children:e.jsx(g,{style:t,language:"bash",PreTag:"div",customStyle:f.getPopupStyles(),codeTagProps:{style:{background:"transparent",backgroundColor:"transparent",fontSize:"inherit"}},wrapLongLines:!0,children:a("command")})}):n.tool==="task"&&a("prompt")?e.jsxs("div",{className:"tool-input-surface bg-transparent rounded-xl border border-border/20 font-mono whitespace-pre-wrap text-foreground/90 mx-3",style:f.getPopupStyles(),children:[a("description")?`Task: ${a("description")}
2
2
  `:"",a("subagent_type")?`Agent Type: ${a("subagent_type")}
3
3
  `:"",`Instructions:
4
- ${a("prompt")}`]}):n.tool==="write"&&a("content")?e.jsx("div",{className:"tool-input-surface bg-transparent rounded-xl border border-border/20 mx-3",children:e.jsx(g,{style:t,language:p(a("filePath")||a("file_path")||"")||"text",PreTag:"div",customStyle:f.getPopupStyles(),codeTagProps:{style:{background:"transparent",backgroundColor:"transparent",fontSize:"inherit"}},wrapLongLines:!0,children:a("content")})}):e.jsx("div",{className:"tool-input-surface bg-transparent rounded-xl border border-border/20 font-mono whitespace-pre-wrap text-foreground/90 mx-3",style:f.getPopupStyles(),children:H(m,n.tool)})]})})():null,r.isDiff?y==="unified"?e.jsx("div",{className:"typography-code",children:B(r.content).map((n,m)=>e.jsxs("div",{className:"border-b border-border/20 last:border-b-0",children:[e.jsx("div",{className:b("bg-muted/20 px-3 py-2 font-medium text-muted-foreground border-b border-border/10 sticky top-0 z-10 break-words -mx-3",u?"typography-micro":"typography-markdown"),children:`${n.file} (line ${n.oldStart})`}),e.jsx("div",{children:n.lines.map((a,i)=>e.jsxs("div",{className:b("typography-code font-mono px-3 py-0.5 flex",a.type==="context"&&"bg-transparent",a.type==="removed"&&"bg-transparent",a.type==="added"&&"bg-transparent"),style:{lineHeight:"1.1",...a.type==="removed"?{backgroundColor:"var(--tools-edit-removed-bg)"}:a.type==="added"?{backgroundColor:"var(--tools-edit-added-bg)"}:{}},children:[e.jsx("span",{className:"text-muted-foreground/60 w-10 flex-shrink-0 text-right pr-3 self-start select-none",children:a.lineNumber||""}),e.jsx("div",{className:"flex-1 min-w-0",children:(()=>{const s=typeof r.metadata?.input=="object"&&r.metadata.input!==null?r.metadata.input.file_path||r.metadata.input.filePath:null,d=typeof s=="string"?s:"",l=typeof n=="object"&&n!==null&&"file"in n?n.file:null,h=d||(typeof l=="string"?l:"")||"";return e.jsx(g,{style:t,language:p(h)||"text",PreTag:"div",wrapLines:!0,wrapLongLines:!0,customStyle:{margin:0,padding:0,fontSize:"inherit",background:"transparent",backgroundColor:"transparent",borderRadius:0,overflow:"visible",whiteSpace:"pre-wrap",wordBreak:"break-all",overflowWrap:"anywhere"},codeTagProps:{style:{background:"transparent",backgroundColor:"transparent"}},children:a.content})})()})]},i))})]},m))}):r.diffHunks?e.jsx("div",{className:"typography-code",children:r.diffHunks.map((n,m)=>e.jsxs("div",{className:"border-b border-border/20 last:border-b-0",children:[e.jsx("div",{className:b("bg-muted/20 px-3 py-2 font-medium text-muted-foreground border-b border-border/10 sticky top-0 z-10 break-words -mx-3",u?"typography-micro":"typography-markdown"),children:`${n.file} (line ${n.oldStart})`}),e.jsx("div",{children:n.lines.map((a,i)=>e.jsxs("div",{className:"grid grid-cols-2 divide-x divide-border/20",children:[e.jsx("div",{className:b("typography-code font-mono px-3 py-0.5 overflow-hidden",a.leftLine.type==="context"&&"bg-transparent",a.leftLine.type==="empty"&&"bg-transparent"),style:{lineHeight:"1.1",...a.leftLine.type==="removed"?{backgroundColor:"var(--tools-edit-removed-bg)"}:{}},children:e.jsxs("div",{className:"flex",children:[e.jsx("span",{className:"text-muted-foreground/60 w-10 flex-shrink-0 text-right pr-3 self-start select-none",children:a.leftLine.lineNumber||""}),e.jsx("div",{className:"flex-1 min-w-0",children:a.leftLine.content&&e.jsx(g,{style:t,language:(()=>{const s=r.metadata?.input,d=typeof s=="object"&&s!==null?s:{},l=d.file_path||d.filePath,c=n.file;return p(typeof l=="string"?l:c)||"text"})(),PreTag:"div",wrapLines:!0,wrapLongLines:!0,customStyle:{margin:0,padding:0,fontSize:"inherit",background:"transparent",backgroundColor:"transparent",borderRadius:0,overflow:"visible",whiteSpace:"pre-wrap",wordBreak:"break-all",overflowWrap:"anywhere"},codeTagProps:{style:{background:"transparent",backgroundColor:"transparent"}},children:a.leftLine.content})})]})}),e.jsx("div",{className:b("typography-code font-mono px-3 py-0.5 overflow-hidden",a.rightLine.type==="context"&&"bg-transparent",a.rightLine.type==="empty"&&"bg-transparent"),style:{lineHeight:"1.1",...a.rightLine.type==="added"?{backgroundColor:"var(--tools-edit-added-bg)"}:{}},children:e.jsxs("div",{className:"flex",children:[e.jsx("span",{className:"text-muted-foreground/60 w-10 flex-shrink-0 text-right pr-3 self-start select-none",children:a.rightLine.lineNumber||""}),e.jsx("div",{className:"flex-1 min-w-0",children:a.rightLine.content&&e.jsx(g,{style:t,language:(()=>{const s=r.metadata?.input,d=typeof s=="object"&&s!==null?s:{},l=d.file_path||d.filePath,c=n.file;return p(typeof l=="string"?l:c)||"text"})(),PreTag:"div",wrapLines:!0,wrapLongLines:!0,customStyle:{margin:0,padding:0,fontSize:"inherit",background:"transparent",backgroundColor:"transparent",borderRadius:0,overflow:"visible",whiteSpace:"pre-wrap",wordBreak:"break-all",overflowWrap:"anywhere"},codeTagProps:{style:{background:"transparent",backgroundColor:"transparent"}},children:a.rightLine.content})})]})})]},i))})]},m))}):null:r.image?e.jsx("div",{className:"p-4",children:e.jsxs("div",{className:"flex flex-col items-center gap-3",children:[e.jsx("div",{className:"max-h-[70vh] overflow-hidden rounded-2xl border border-border/40 bg-muted/10",children:e.jsx("img",{src:r.image.url,alt:r.image.filename||r.title||"Image preview",className:"block h-full max-h-[70vh] w-auto max-w-full object-contain",loading:"lazy"})}),r.image.filename&&e.jsx("span",{className:"typography-meta text-muted-foreground text-center",children:r.image.filename})]})}):r.content?e.jsx("div",{className:"p-4",children:(()=>{const n=r.metadata?.tool;if(n==="todowrite"||n==="todoread")return Q(r.content)||e.jsx(g,{style:t,language:"json",PreTag:"div",wrapLongLines:!0,customStyle:f.getPopupContainerStyles(),codeTagProps:{style:{background:"transparent",backgroundColor:"transparent",fontSize:"inherit"}},children:r.content});if(n==="list")return V(r.content)||e.jsx("pre",{className:"typography-markdown bg-muted/30 p-2 rounded-xl border border-border/20 font-mono whitespace-pre-wrap",children:r.content});if(n==="grep")return E(r.content,u)||e.jsx("pre",{className:"typography-code bg-muted/30 p-2 rounded-xl border border-border/20 font-mono whitespace-pre-wrap",children:r.content});if(n==="glob")return A(r.content,u)||e.jsx("pre",{className:"typography-code bg-muted/30 p-2 rounded-xl border border-border/20 font-mono whitespace-pre-wrap",children:r.content});if(n==="task"||n==="reasoning")return e.jsx("div",{className:n==="reasoning"?"text-muted-foreground/70":"",children:e.jsx(G,{content:r.content,variant:"tool"})});if(n==="web-search"||n==="websearch"||n==="search_web")return q(r.content)||e.jsx(g,{style:t,language:"text",PreTag:"div",wrapLongLines:!0,customStyle:f.getPopupContainerStyles(),codeTagProps:{style:{background:"transparent",backgroundColor:"transparent",fontSize:"inherit"}},children:r.content});if(n==="read"){const m=r.content.split(`
4
+ ${a("prompt")}`]}):n.tool==="write"&&a("content")?e.jsx("div",{className:"tool-input-surface bg-transparent rounded-xl border border-border/20 mx-3",children:e.jsx(g,{style:t,language:p(a("filePath")||a("file_path")||"")||"text",PreTag:"div",customStyle:f.getPopupStyles(),codeTagProps:{style:{background:"transparent",backgroundColor:"transparent",fontSize:"inherit"}},wrapLongLines:!0,children:a("content")})}):e.jsx("div",{className:"tool-input-surface bg-transparent rounded-xl border border-border/20 font-mono whitespace-pre-wrap text-foreground/90 mx-3",style:f.getPopupStyles(),children:H(m,n.tool)})]})})():null,r.isDiff?y==="unified"?e.jsx("div",{className:"typography-code",children:B(r.content).map((n,m)=>e.jsxs("div",{className:"border-b border-border/20 last:border-b-0",children:[e.jsx("div",{className:b("bg-muted/20 px-3 py-2 font-medium text-muted-foreground border-b border-border/10 sticky top-0 z-10 break-words -mx-3",u?"typography-micro":"typography-markdown"),children:`${n.file} (line ${n.oldStart})`}),e.jsx("div",{children:n.lines.map((a,i)=>e.jsxs("div",{className:b("typography-code font-mono px-3 py-0.5 flex",a.type==="context"&&"bg-transparent",a.type==="removed"&&"bg-transparent",a.type==="added"&&"bg-transparent"),style:{lineHeight:"1.1",...a.type==="removed"?{backgroundColor:"var(--tools-edit-removed-bg)"}:a.type==="added"?{backgroundColor:"var(--tools-edit-added-bg)"}:{}},children:[e.jsx("span",{className:"text-muted-foreground/60 w-10 flex-shrink-0 text-right pr-3 self-start select-none",children:a.lineNumber||""}),e.jsx("div",{className:"flex-1 min-w-0",children:(()=>{const s=typeof r.metadata?.input=="object"&&r.metadata.input!==null?r.metadata.input.file_path||r.metadata.input.filePath:null,d=typeof s=="string"?s:"",l=typeof n=="object"&&n!==null&&"file"in n?n.file:null,h=d||(typeof l=="string"?l:"")||"";return e.jsx(g,{style:t,language:p(h)||"text",PreTag:"div",wrapLines:!0,wrapLongLines:!0,customStyle:{margin:0,padding:0,fontSize:"inherit",background:"transparent",backgroundColor:"transparent",borderRadius:0,overflow:"visible",whiteSpace:"pre-wrap",wordBreak:"break-all",overflowWrap:"anywhere"},codeTagProps:{style:{background:"transparent",backgroundColor:"transparent"}},children:a.content})})()})]},i))})]},m))}):r.diffHunks?e.jsx("div",{className:"typography-code",children:r.diffHunks.map((n,m)=>e.jsxs("div",{className:"border-b border-border/20 last:border-b-0",children:[e.jsx("div",{className:b("bg-muted/20 px-3 py-2 font-medium text-muted-foreground border-b border-border/10 sticky top-0 z-10 break-words -mx-3",u?"typography-micro":"typography-markdown"),children:`${n.file} (line ${n.oldStart})`}),e.jsx("div",{children:n.lines.map((a,i)=>e.jsxs("div",{className:"grid grid-cols-2 divide-x divide-border/20",children:[e.jsx("div",{className:b("typography-code font-mono px-3 py-0.5 overflow-hidden",a.leftLine.type==="context"&&"bg-transparent",a.leftLine.type==="empty"&&"bg-transparent"),style:{lineHeight:"1.1",...a.leftLine.type==="removed"?{backgroundColor:"var(--tools-edit-removed-bg)"}:{}},children:e.jsxs("div",{className:"flex",children:[e.jsx("span",{className:"text-muted-foreground/60 w-10 flex-shrink-0 text-right pr-3 self-start select-none",children:a.leftLine.lineNumber||""}),e.jsx("div",{className:"flex-1 min-w-0",children:a.leftLine.content&&e.jsx(g,{style:t,language:(()=>{const s=r.metadata?.input,d=typeof s=="object"&&s!==null?s:{},l=d.file_path||d.filePath,c=n.file;return p(typeof l=="string"?l:c)||"text"})(),PreTag:"div",wrapLines:!0,wrapLongLines:!0,customStyle:{margin:0,padding:0,fontSize:"inherit",background:"transparent",backgroundColor:"transparent",borderRadius:0,overflow:"visible",whiteSpace:"pre-wrap",wordBreak:"break-all",overflowWrap:"anywhere"},codeTagProps:{style:{background:"transparent",backgroundColor:"transparent"}},children:a.leftLine.content})})]})}),e.jsx("div",{className:b("typography-code font-mono px-3 py-0.5 overflow-hidden",a.rightLine.type==="context"&&"bg-transparent",a.rightLine.type==="empty"&&"bg-transparent"),style:{lineHeight:"1.1",...a.rightLine.type==="added"?{backgroundColor:"var(--tools-edit-added-bg)"}:{}},children:e.jsxs("div",{className:"flex",children:[e.jsx("span",{className:"text-muted-foreground/60 w-10 flex-shrink-0 text-right pr-3 self-start select-none",children:a.rightLine.lineNumber||""}),e.jsx("div",{className:"flex-1 min-w-0",children:a.rightLine.content&&e.jsx(g,{style:t,language:(()=>{const s=r.metadata?.input,d=typeof s=="object"&&s!==null?s:{},l=d.file_path||d.filePath,c=n.file;return p(typeof l=="string"?l:c)||"text"})(),PreTag:"div",wrapLines:!0,wrapLongLines:!0,customStyle:{margin:0,padding:0,fontSize:"inherit",background:"transparent",backgroundColor:"transparent",borderRadius:0,overflow:"visible",whiteSpace:"pre-wrap",wordBreak:"break-all",overflowWrap:"anywhere"},codeTagProps:{style:{background:"transparent",backgroundColor:"transparent"}},children:a.rightLine.content})})]})})]},i))})]},m))}):null:r.image?e.jsx("div",{className:"p-4",children:e.jsxs("div",{className:"flex flex-col items-center gap-3",children:[e.jsx("div",{className:"max-h-[70vh] overflow-hidden rounded-2xl border border-border/40 bg-muted/10",children:e.jsx("img",{src:r.image.url,alt:r.image.filename||r.title||"Image preview",className:"block h-full max-h-[70vh] w-auto max-w-full object-contain",loading:"lazy"})}),r.image.filename&&e.jsx("span",{className:"typography-meta text-muted-foreground text-center",children:r.image.filename})]})}):r.content?e.jsx("div",{className:"p-4",children:(()=>{const n=r.metadata?.tool;if(n==="todowrite"||n==="todoread")return Q(r.content)||e.jsx(g,{style:t,language:"json",PreTag:"div",wrapLongLines:!0,customStyle:f.getPopupContainerStyles(),codeTagProps:{style:{background:"transparent",backgroundColor:"transparent",fontSize:"inherit"}},children:r.content});if(n==="list")return V(r.content)||e.jsx("pre",{className:"typography-markdown bg-muted/30 p-2 rounded-xl border border-border/20 font-mono whitespace-pre-wrap",children:r.content});if(n==="grep")return E(r.content,u)||e.jsx("pre",{className:"typography-code bg-muted/30 p-2 rounded-xl border border-border/20 font-mono whitespace-pre-wrap",children:r.content});if(n==="glob")return A(r.content,u)||e.jsx("pre",{className:"typography-code bg-muted/30 p-2 rounded-xl border border-border/20 font-mono whitespace-pre-wrap",children:r.content});if(n==="task"||n==="reasoning")return e.jsx("div",{className:n==="reasoning"?"text-muted-foreground/70":"",children:e.jsx(G,{content:r.content,variant:"tool"})});if(n==="web-search"||n==="websearch"||n==="search_web")return U(r.content)||e.jsx(g,{style:t,language:"text",PreTag:"div",wrapLongLines:!0,customStyle:f.getPopupContainerStyles(),codeTagProps:{style:{background:"transparent",backgroundColor:"transparent",fontSize:"inherit"}},children:r.content});if(n==="read"){const m=r.content.split(`
5
5
  `),a=r.metadata?.input,i=typeof a=="object"&&a!==null?a:{},s=typeof i.offset=="number"?i.offset:0,d=typeof i.limit=="number"?i.limit:void 0,l=c=>c.trim().startsWith("(");return e.jsx("div",{children:m.map((c,h)=>{const x=l(c),k=s+h+1,S=!x&&(d===void 0||h<d);return e.jsxs("div",{className:`typography-code font-mono flex ${x?"text-muted-foreground/70 italic":""}`,children:[e.jsx("span",{className:"text-muted-foreground/60 w-10 flex-shrink-0 text-right pr-4 self-start select-none",children:S?k:""}),e.jsx("div",{className:"flex-1 min-w-0",children:x?e.jsx("div",{className:"whitespace-pre-wrap break-words",children:c}):e.jsx(g,{style:t,language:r.language||"text",PreTag:"div",wrapLines:!0,wrapLongLines:!0,customStyle:{margin:0,padding:0,fontSize:"inherit",background:"transparent",backgroundColor:"transparent",borderRadius:0,overflow:"visible",whiteSpace:"pre-wrap",wordBreak:"break-all",overflowWrap:"anywhere"},codeTagProps:{style:{background:"transparent",backgroundColor:"transparent",fontSize:"inherit"}},children:c})})]},h)})})}return e.jsx(g,{style:t,language:r.language||"text",PreTag:"div",wrapLongLines:!0,customStyle:f.getPopupContainerStyles(),codeTagProps:{style:{background:"transparent",backgroundColor:"transparent",fontSize:"inherit"}},children:r.content})})()}):e.jsxs("div",{className:"p-8 text-muted-foreground typography-ui-header",children:[e.jsx("div",{className:"mb-2",children:"Command completed successfully"}),e.jsx("div",{className:"typography-meta",children:"No output was produced"})]})]})})]})})};export{X as default};
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/main-CjbXdQMY.js","assets/vendor-.pnpm-Bax6Hn5Z.js","assets/vendor--B3aGWKBE.css","assets/main-BEJ2XliY.css"])))=>i.map(i=>d[i]);
2
- import{_ as P}from"./vendor-.pnpm-Bax6Hn5Z.js";(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))o(n);new MutationObserver(n=>{for(const a of n)if(a.type==="childList")for(const l of a.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&o(l)}).observe(document,{childList:!0,subtree:!0});function r(n){const a={};return n.integrity&&(a.integrity=n.integrity),n.referrerPolicy&&(a.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?a.credentials="include":n.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function o(n){if(n.ep)return;n.ep=!0;const a=r(n);fetch(n.href,a)}})();async function x(t){const e=await fetch("/api/terminal/create",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cwd:t.cwd,cols:t.cols||80,rows:t.rows||24})});if(!e.ok){const r=await e.json().catch(()=>({error:"Failed to create terminal"}));throw new Error(r.error||"Failed to create terminal session")}return e.json()}function $(t,e,r,o={}){const{maxRetries:n=3,initialRetryDelay:a=1e3,maxRetryDelay:l=8e3,connectionTimeout:F=1e4}=o;let c=null,d=0,p=null,y=null,m=!1,g=!1,h=!1;const T=()=>{p&&(clearTimeout(p),p=null),y&&(clearTimeout(y),y=null)},E=()=>{m=!0,T(),c&&(c.close(),c=null)},j=()=>{if(!(m||h)){if(c&&c.readyState!==EventSource.CLOSED){console.warn("Attempted to create duplicate EventSource, skipping");return}g=!1,c=new EventSource(`/api/terminal/${t}/stream`),y=setTimeout(()=>{!g&&c?.readyState!==EventSource.OPEN&&(console.error("Terminal connection timeout"),c?.close(),b(new Error("Connection timeout"),!1))},F),c.onopen=()=>{g||(g=!0,d=0,T(),e({type:"connected"}))},c.onmessage=u=>{try{const f=JSON.parse(u.data);f.type==="exit"&&(h=!0,E()),e(f)}catch(f){console.error("Failed to parse terminal event:",f),r?.(f,!1)}},c.onerror=u=>{console.error("Terminal stream error:",u,"readyState:",c?.readyState),T();const f=h||c?.readyState===EventSource.CLOSED;c?.close(),c=null,h||b(new Error("Terminal stream connection error"),f)}}},b=(u,f)=>{if(!(m||h))if(d<n&&!f){d++;const S=Math.min(a*Math.pow(2,d-1),l);console.log(`Reconnecting to terminal stream (attempt ${d}/${n}) in ${S}ms`),e({type:"reconnecting",attempt:d,maxAttempts:n}),p=setTimeout(()=>{!m&&!h&&j()},S)}else console.error(`Terminal connection failed after ${d} attempts`),r?.(u,!0),E()};return j(),E}async function C(t,e){const r=await fetch(`/api/terminal/${t}/input`,{method:"POST",headers:{"Content-Type":"text/plain"},body:e});if(!r.ok){const o=await r.json().catch(()=>({error:"Failed to send input"}));throw new Error(o.error||"Failed to send terminal input")}}async function N(t,e,r){const o=await fetch(`/api/terminal/${t}/resize`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cols:e,rows:r})});if(!o.ok){const n=await o.json().catch(()=>({error:"Failed to resize terminal"}));throw new Error(n.error||"Failed to resize terminal")}}async function G(t){const e=await fetch(`/api/terminal/${t}`,{method:"DELETE"});if(!e.ok){const r=await e.json().catch(()=>({error:"Failed to close terminal"}));throw new Error(r.error||"Failed to close terminal")}}async function I(t,e){const r=await fetch(`/api/terminal/${t}/restart`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cwd:e.cwd,cols:e.cols??80,rows:e.rows??24})});if(!r.ok){const o=await r.json().catch(()=>({error:"Failed to restart terminal"}));throw new Error(o.error||"Failed to restart terminal")}return r.json()}async function A(t){const e=await fetch("/api/terminal/force-kill",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!e.ok){const r=await e.json().catch(()=>({error:"Failed to force kill terminal"}));throw new Error(r.error||"Failed to force kill terminal")}}const v=t=>{const e=t?.retry;return{maxRetries:e?.maxRetries??3,initialRetryDelay:e?.initialDelayMs??1e3,maxRetryDelay:e?.maxDelayMs??8e3,connectionTimeout:t?.connectionTimeoutMs??1e4}},D=()=>({async createSession(t){return x(t)},connect(t,e,r){const o=$(t,e.onEvent,e.onError,v(r));return{close:()=>o()}},async sendInput(t,e){await C(t,e)},async resize(t){await N(t.sessionId,t.cols,t.rows)},async close(t){await G(t)},async restartSession(t,e){return I(t,{cwd:e.cwd??"",cols:e.cols,rows:e.rows})},async forceKill(t){await A(t)}}),J=()=>{if(typeof window>"u")return"";const t=window.__OPENCHAMBER_DESKTOP_SERVER__?.origin;return t||window.location.origin},s="/api/git";function i(t,e,r){const o=new URL(t,J());if(e&&o.searchParams.set("directory",e),r)for(const[n,a]of Object.entries(r))a!==void 0&&o.searchParams.set(n,String(a));return o.toString()}async function R(t){const e=await fetch(i(`${s}/check`,t));if(!e.ok)throw new Error(`Failed to check git repository: ${e.statusText}`);return(await e.json()).isGitRepository}async function _(t){const e=await fetch(i(`${s}/status`,t));if(!e.ok)throw new Error(`Failed to get git status: ${e.statusText}`);return e.json()}async function L(t,e){const{path:r,staged:o,contextLines:n}=e;if(!r)throw new Error("path is required to fetch git diff");const a=await fetch(i(`${s}/diff`,t,{path:r,staged:o?"true":void 0,context:n}));if(!a.ok)throw new Error(`Failed to get git diff: ${a.statusText}`);return a.json()}async function W(t,e){const{path:r,staged:o}=e;if(!r)throw new Error("path is required to fetch git file diff");const n=await fetch(i(`${s}/file-diff`,t,{path:r,staged:o?"true":void 0}));if(!n.ok)throw new Error(`Failed to get git file diff: ${n.statusText}`);return n.json()}async function B(t,e){if(!e)throw new Error("path is required to revert git changes");const r=await fetch(i(`${s}/revert`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e})});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to revert git changes")}}async function q(t){if(!t)return!1;const e=await fetch(i(`${s}/worktree-type`,t));if(!e.ok)throw new Error(`Failed to detect worktree type: ${e.statusText}`);return!!(await e.json()).linked}async function M(t){const e=await fetch(i(`${s}/branches`,t));if(!e.ok)throw new Error(`Failed to get branches: ${e.statusText}`);return e.json()}async function z(t,e){if(!e?.branch)throw new Error("branch is required to delete a branch");const r=await fetch(i(`${s}/branches`,t),{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to delete branch")}return r.json()}async function U(t,e){if(!e?.branch)throw new Error("branch is required to delete remote branch");const r=await fetch(i(`${s}/remote-branches`,t),{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to delete remote branch")}return r.json()}async function K(t,e){if(!Array.isArray(e)||e.length===0)throw new Error("No files provided to generate commit message");const r=await fetch(i(`${s}/commit-message`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({files:e})});if(!r.ok){const l=await r.json().catch(()=>({error:r.statusText}));throw new Error(l.error||"Failed to generate commit message")}const o=await r.json();if(!o?.message||typeof o.message!="object")throw new Error("Malformed commit generation response");const n=typeof o.message.subject=="string"&&o.message.subject.trim().length>0?o.message.subject.trim():"",a=Array.isArray(o.message.highlights)?o.message.highlights.filter(l=>typeof l=="string"&&l.trim().length>0).map(l=>l.trim()):[];return{message:{subject:n,highlights:a}}}async function V(t){const e=await fetch(i(`${s}/worktrees`,t));if(!e.ok){const r=await e.json().catch(()=>({error:e.statusText}));throw new Error(r.error||"Failed to list worktrees")}return e.json()}async function H(t,e){if(!e?.path||!e?.branch)throw new Error("path and branch are required to add a worktree");const r=await fetch(i(`${s}/worktrees`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to add worktree")}return r.json()}async function Q(t,e){if(!e?.path)throw new Error("path is required to remove a worktree");const r=await fetch(i(`${s}/worktrees`,t),{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to remove worktree")}return r.json()}async function X(t){const e=await fetch(i(`${s}/ignore-openchamber`,t),{method:"POST"});if(!e.ok){const r=await e.json().catch(()=>({error:e.statusText}));throw new Error(r.error||"Failed to update git ignore")}}async function Y(t,e,r={}){const o=await fetch(i(`${s}/commit`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:e,addAll:r.addAll??!1,files:r.files})});if(!o.ok){const n=await o.json().catch(()=>({error:o.statusText}));throw new Error(n.error||"Failed to create commit")}return o.json()}async function Z(t,e={}){const r=await fetch(i(`${s}/push`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to push")}return r.json()}async function ee(t,e={}){const r=await fetch(i(`${s}/pull`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to pull")}return r.json()}async function te(t,e={}){const r=await fetch(i(`${s}/fetch`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to fetch")}return r.json()}async function re(t,e){const r=await fetch(i(`${s}/checkout`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({branch:e})});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to checkout branch")}return r.json()}async function oe(t,e,r){const o=await fetch(i(`${s}/branches`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:e,startPoint:r})});if(!o.ok){const n=await o.json().catch(()=>({error:o.statusText}));throw new Error(n.error||"Failed to create branch")}return o.json()}async function ne(t,e={}){const r=await fetch(i(`${s}/log`,t,{maxCount:e.maxCount,from:e.from,to:e.to,file:e.file}));if(!r.ok)throw new Error(`Failed to get git log: ${r.statusText}`);return r.json()}async function se(t,e){const r=await fetch(i(`${s}/commit-files`,t,{hash:e}));if(!r.ok)throw new Error(`Failed to get commit files: ${r.statusText}`);return r.json()}async function ie(){const t=await fetch(i(`${s}/identities`,void 0));if(!t.ok)throw new Error(`Failed to get git identities: ${t.statusText}`);return t.json()}async function ae(t){const e=await fetch(i(`${s}/identities`,void 0),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!e.ok){const r=await e.json().catch(()=>({error:e.statusText}));throw new Error(r.error||"Failed to create git identity")}return e.json()}async function ce(t,e){const r=await fetch(i(`${s}/identities/${t}`,void 0),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to update git identity")}return r.json()}async function le(t){const e=await fetch(i(`${s}/identities/${t}`,void 0),{method:"DELETE"});if(!e.ok){const r=await e.json().catch(()=>({error:e.statusText}));throw new Error(r.error||"Failed to delete git identity")}}async function fe(t){if(!t)return null;const e=await fetch(i(`${s}/current-identity`,t));if(!e.ok)throw new Error(`Failed to get current git identity: ${e.statusText}`);const r=await e.json();return r?{userName:r.userName??null,userEmail:r.userEmail??null,sshCommand:r.sshCommand??null}:null}async function de(t,e){const r=await fetch(i(`${s}/set-identity`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({profileId:e})});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to set git identity")}return r.json()}const he=()=>({checkIsGitRepository:R,getGitStatus:_,getGitDiff:L,getGitFileDiff:W,revertGitFile:B,isLinkedWorktree:q,getGitBranches:M,deleteGitBranch:z,deleteRemoteBranch:U,generateCommitMessage:K,listGitWorktrees:V,addGitWorktree:H,removeGitWorktree:Q,ensureOpenChamberIgnored:X,createGitCommit(t,e,r){return Y(t,e,r)},gitPush:Z,gitPull:ee,gitFetch:te,checkoutBranch:re,createBranch:oe,getGitLog(t,e){return ne(t,e)},getCommitFiles:se,getCurrentGitIdentity:fe,setGitIdentity:de,getGitIdentities:ie,createGitIdentity:ae,updateGitIdentity:ce,deleteGitIdentity:le}),w=t=>t.replace(/\\/g,"/"),ue=()=>({async listDirectory(t){const e=w(t),r=await fetch("/api/fs/list",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e})});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to list directory")}return r.json()},async search(t){const e=await fetch("/api/fs/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({directory:w(t.directory),query:t.query,maxResults:t.maxResults})});if(!e.ok){const o=await e.json().catch(()=>({error:e.statusText}));throw new Error(o.error||"Failed to search files")}const r=await e.json();return Array.isArray(r)?r.filter(o=>!!o&&typeof o=="object"&&typeof o.path=="string").map(o=>({path:w(o.path),score:o.score,preview:o.preview})):[]},async createDirectory(t){const e=w(t),r=await fetch("/api/fs/mkdir",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e})});if(!r.ok){const n=await r.json().catch(()=>({error:r.statusText}));throw new Error(n.error||"Failed to create directory")}const o=await r.json();return{success:!!o?.success,path:typeof o?.path=="string"?w(o.path):e}}}),k="/api/config/settings",we="/api/config/reload",O=t=>!t||typeof t!="object"?{}:t,pe=()=>({async load(){const t=await fetch(k,{method:"GET",headers:{Accept:"application/json"}});if(!t.ok)throw new Error(`Failed to load settings: ${t.statusText}`);return{settings:O(await t.json().catch(()=>({}))),source:"web"}},async save(t){const e=await fetch(k,{method:"PUT",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(t)});if(!e.ok){const o=await e.json().catch(()=>({error:e.statusText}));throw new Error(o.error||"Failed to save settings")}return O(await e.json().catch(()=>({})))},async restartOpenCode(){const t=await fetch(we,{method:"POST"});if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to restart OpenCode")}return{restarted:!0}}}),ye=()=>({async requestDirectoryAccess(t){return{success:!0,path:t.path}},async startAccessingDirectory(t){return{success:!0}},async stopAccessingDirectory(t){return{success:!0}}}),me=async t=>{if(typeof Notification>"u")return console.info("Notifications not supported in this environment",t),!1;if(await Notification.requestPermission()!=="granted")return console.warn("Notification permission not granted"),!1;try{return new Notification(t?.title??"OpenChamber",{body:t?.body,tag:t?.tag}),!0}catch(r){return console.warn("Failed to send notification",r),!1}},ge=()=>({async notifyAgentCompletion(t){return me(t)},canNotify:()=>typeof Notification<"u"?Notification.permission==="granted":!1}),Te=()=>({async getAvailableTools(){const t=await fetch("/api/experimental/tool/ids");if(!t.ok)throw new Error(`Tools API returned ${t.status} ${t.statusText}`);const e=await t.json();if(!Array.isArray(e))throw new Error("Tools API returned invalid data format");return e.filter(r=>typeof r=="string"&&r!=="invalid").sort()}}),Ee=()=>({runtime:{platform:"web",isDesktop:!1,isVSCode:!1,label:"web"},terminal:D(),git:he(),files:ue(),settings:pe(),permissions:ye(),notifications:ge(),tools:Te()});window.__OPENCHAMBER_RUNTIME_APIS__=Ee();P(()=>import("./main-CjbXdQMY.js").then(t=>t.m),__vite__mapDeps([0,1,2,3]));export{U as a,le as b,R as c,z as d,ae as e,fe as f,_ as g,ie as h,X as i,Z as j,H as k,V as l,Q as r,ce as u};
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/main-DI52tBPC.js","assets/vendor-.pnpm-Buk6Khtx.js","assets/vendor--B3aGWKBE.css","assets/main-BEJ2XliY.css"])))=>i.map(i=>d[i]);
2
+ import{_ as P}from"./vendor-.pnpm-Buk6Khtx.js";(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))o(n);new MutationObserver(n=>{for(const a of n)if(a.type==="childList")for(const l of a.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&o(l)}).observe(document,{childList:!0,subtree:!0});function r(n){const a={};return n.integrity&&(a.integrity=n.integrity),n.referrerPolicy&&(a.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?a.credentials="include":n.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function o(n){if(n.ep)return;n.ep=!0;const a=r(n);fetch(n.href,a)}})();async function x(t){const e=await fetch("/api/terminal/create",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cwd:t.cwd,cols:t.cols||80,rows:t.rows||24})});if(!e.ok){const r=await e.json().catch(()=>({error:"Failed to create terminal"}));throw new Error(r.error||"Failed to create terminal session")}return e.json()}function $(t,e,r,o={}){const{maxRetries:n=3,initialRetryDelay:a=1e3,maxRetryDelay:l=8e3,connectionTimeout:F=1e4}=o;let c=null,d=0,p=null,y=null,m=!1,g=!1,h=!1;const T=()=>{p&&(clearTimeout(p),p=null),y&&(clearTimeout(y),y=null)},E=()=>{m=!0,T(),c&&(c.close(),c=null)},j=()=>{if(!(m||h)){if(c&&c.readyState!==EventSource.CLOSED){console.warn("Attempted to create duplicate EventSource, skipping");return}g=!1,c=new EventSource(`/api/terminal/${t}/stream`),y=setTimeout(()=>{!g&&c?.readyState!==EventSource.OPEN&&(console.error("Terminal connection timeout"),c?.close(),b(new Error("Connection timeout"),!1))},F),c.onopen=()=>{g||(g=!0,d=0,T(),e({type:"connected"}))},c.onmessage=u=>{try{const f=JSON.parse(u.data);f.type==="exit"&&(h=!0,E()),e(f)}catch(f){console.error("Failed to parse terminal event:",f),r?.(f,!1)}},c.onerror=u=>{console.error("Terminal stream error:",u,"readyState:",c?.readyState),T();const f=h||c?.readyState===EventSource.CLOSED;c?.close(),c=null,h||b(new Error("Terminal stream connection error"),f)}}},b=(u,f)=>{if(!(m||h))if(d<n&&!f){d++;const S=Math.min(a*Math.pow(2,d-1),l);console.log(`Reconnecting to terminal stream (attempt ${d}/${n}) in ${S}ms`),e({type:"reconnecting",attempt:d,maxAttempts:n}),p=setTimeout(()=>{!m&&!h&&j()},S)}else console.error(`Terminal connection failed after ${d} attempts`),r?.(u,!0),E()};return j(),E}async function C(t,e){const r=await fetch(`/api/terminal/${t}/input`,{method:"POST",headers:{"Content-Type":"text/plain"},body:e});if(!r.ok){const o=await r.json().catch(()=>({error:"Failed to send input"}));throw new Error(o.error||"Failed to send terminal input")}}async function N(t,e,r){const o=await fetch(`/api/terminal/${t}/resize`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cols:e,rows:r})});if(!o.ok){const n=await o.json().catch(()=>({error:"Failed to resize terminal"}));throw new Error(n.error||"Failed to resize terminal")}}async function G(t){const e=await fetch(`/api/terminal/${t}`,{method:"DELETE"});if(!e.ok){const r=await e.json().catch(()=>({error:"Failed to close terminal"}));throw new Error(r.error||"Failed to close terminal")}}async function I(t,e){const r=await fetch(`/api/terminal/${t}/restart`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cwd:e.cwd,cols:e.cols??80,rows:e.rows??24})});if(!r.ok){const o=await r.json().catch(()=>({error:"Failed to restart terminal"}));throw new Error(o.error||"Failed to restart terminal")}return r.json()}async function A(t){const e=await fetch("/api/terminal/force-kill",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!e.ok){const r=await e.json().catch(()=>({error:"Failed to force kill terminal"}));throw new Error(r.error||"Failed to force kill terminal")}}const v=t=>{const e=t?.retry;return{maxRetries:e?.maxRetries??3,initialRetryDelay:e?.initialDelayMs??1e3,maxRetryDelay:e?.maxDelayMs??8e3,connectionTimeout:t?.connectionTimeoutMs??1e4}},D=()=>({async createSession(t){return x(t)},connect(t,e,r){const o=$(t,e.onEvent,e.onError,v(r));return{close:()=>o()}},async sendInput(t,e){await C(t,e)},async resize(t){await N(t.sessionId,t.cols,t.rows)},async close(t){await G(t)},async restartSession(t,e){return I(t,{cwd:e.cwd??"",cols:e.cols,rows:e.rows})},async forceKill(t){await A(t)}}),J=()=>{if(typeof window>"u")return"";const t=window.__OPENCHAMBER_DESKTOP_SERVER__?.origin;return t||window.location.origin},s="/api/git";function i(t,e,r){const o=new URL(t,J());if(e&&o.searchParams.set("directory",e),r)for(const[n,a]of Object.entries(r))a!==void 0&&o.searchParams.set(n,String(a));return o.toString()}async function R(t){const e=await fetch(i(`${s}/check`,t));if(!e.ok)throw new Error(`Failed to check git repository: ${e.statusText}`);return(await e.json()).isGitRepository}async function _(t){const e=await fetch(i(`${s}/status`,t));if(!e.ok)throw new Error(`Failed to get git status: ${e.statusText}`);return e.json()}async function L(t,e){const{path:r,staged:o,contextLines:n}=e;if(!r)throw new Error("path is required to fetch git diff");const a=await fetch(i(`${s}/diff`,t,{path:r,staged:o?"true":void 0,context:n}));if(!a.ok)throw new Error(`Failed to get git diff: ${a.statusText}`);return a.json()}async function W(t,e){const{path:r,staged:o}=e;if(!r)throw new Error("path is required to fetch git file diff");const n=await fetch(i(`${s}/file-diff`,t,{path:r,staged:o?"true":void 0}));if(!n.ok)throw new Error(`Failed to get git file diff: ${n.statusText}`);return n.json()}async function B(t,e){if(!e)throw new Error("path is required to revert git changes");const r=await fetch(i(`${s}/revert`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e})});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to revert git changes")}}async function q(t){if(!t)return!1;const e=await fetch(i(`${s}/worktree-type`,t));if(!e.ok)throw new Error(`Failed to detect worktree type: ${e.statusText}`);return!!(await e.json()).linked}async function M(t){const e=await fetch(i(`${s}/branches`,t));if(!e.ok)throw new Error(`Failed to get branches: ${e.statusText}`);return e.json()}async function z(t,e){if(!e?.branch)throw new Error("branch is required to delete a branch");const r=await fetch(i(`${s}/branches`,t),{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to delete branch")}return r.json()}async function U(t,e){if(!e?.branch)throw new Error("branch is required to delete remote branch");const r=await fetch(i(`${s}/remote-branches`,t),{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to delete remote branch")}return r.json()}async function K(t,e){if(!Array.isArray(e)||e.length===0)throw new Error("No files provided to generate commit message");const r=await fetch(i(`${s}/commit-message`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({files:e})});if(!r.ok){const l=await r.json().catch(()=>({error:r.statusText}));throw new Error(l.error||"Failed to generate commit message")}const o=await r.json();if(!o?.message||typeof o.message!="object")throw new Error("Malformed commit generation response");const n=typeof o.message.subject=="string"&&o.message.subject.trim().length>0?o.message.subject.trim():"",a=Array.isArray(o.message.highlights)?o.message.highlights.filter(l=>typeof l=="string"&&l.trim().length>0).map(l=>l.trim()):[];return{message:{subject:n,highlights:a}}}async function V(t){const e=await fetch(i(`${s}/worktrees`,t));if(!e.ok){const r=await e.json().catch(()=>({error:e.statusText}));throw new Error(r.error||"Failed to list worktrees")}return e.json()}async function H(t,e){if(!e?.path||!e?.branch)throw new Error("path and branch are required to add a worktree");const r=await fetch(i(`${s}/worktrees`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to add worktree")}return r.json()}async function Q(t,e){if(!e?.path)throw new Error("path is required to remove a worktree");const r=await fetch(i(`${s}/worktrees`,t),{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to remove worktree")}return r.json()}async function X(t){const e=await fetch(i(`${s}/ignore-openchamber`,t),{method:"POST"});if(!e.ok){const r=await e.json().catch(()=>({error:e.statusText}));throw new Error(r.error||"Failed to update git ignore")}}async function Y(t,e,r={}){const o=await fetch(i(`${s}/commit`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:e,addAll:r.addAll??!1,files:r.files})});if(!o.ok){const n=await o.json().catch(()=>({error:o.statusText}));throw new Error(n.error||"Failed to create commit")}return o.json()}async function Z(t,e={}){const r=await fetch(i(`${s}/push`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to push")}return r.json()}async function ee(t,e={}){const r=await fetch(i(`${s}/pull`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to pull")}return r.json()}async function te(t,e={}){const r=await fetch(i(`${s}/fetch`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to fetch")}return r.json()}async function re(t,e){const r=await fetch(i(`${s}/checkout`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({branch:e})});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to checkout branch")}return r.json()}async function oe(t,e,r){const o=await fetch(i(`${s}/branches`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:e,startPoint:r})});if(!o.ok){const n=await o.json().catch(()=>({error:o.statusText}));throw new Error(n.error||"Failed to create branch")}return o.json()}async function ne(t,e={}){const r=await fetch(i(`${s}/log`,t,{maxCount:e.maxCount,from:e.from,to:e.to,file:e.file}));if(!r.ok)throw new Error(`Failed to get git log: ${r.statusText}`);return r.json()}async function se(t,e){const r=await fetch(i(`${s}/commit-files`,t,{hash:e}));if(!r.ok)throw new Error(`Failed to get commit files: ${r.statusText}`);return r.json()}async function ie(){const t=await fetch(i(`${s}/identities`,void 0));if(!t.ok)throw new Error(`Failed to get git identities: ${t.statusText}`);return t.json()}async function ae(t){const e=await fetch(i(`${s}/identities`,void 0),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!e.ok){const r=await e.json().catch(()=>({error:e.statusText}));throw new Error(r.error||"Failed to create git identity")}return e.json()}async function ce(t,e){const r=await fetch(i(`${s}/identities/${t}`,void 0),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to update git identity")}return r.json()}async function le(t){const e=await fetch(i(`${s}/identities/${t}`,void 0),{method:"DELETE"});if(!e.ok){const r=await e.json().catch(()=>({error:e.statusText}));throw new Error(r.error||"Failed to delete git identity")}}async function fe(t){if(!t)return null;const e=await fetch(i(`${s}/current-identity`,t));if(!e.ok)throw new Error(`Failed to get current git identity: ${e.statusText}`);const r=await e.json();return r?{userName:r.userName??null,userEmail:r.userEmail??null,sshCommand:r.sshCommand??null}:null}async function de(t,e){const r=await fetch(i(`${s}/set-identity`,t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({profileId:e})});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to set git identity")}return r.json()}const he=()=>({checkIsGitRepository:R,getGitStatus:_,getGitDiff:L,getGitFileDiff:W,revertGitFile:B,isLinkedWorktree:q,getGitBranches:M,deleteGitBranch:z,deleteRemoteBranch:U,generateCommitMessage:K,listGitWorktrees:V,addGitWorktree:H,removeGitWorktree:Q,ensureOpenChamberIgnored:X,createGitCommit(t,e,r){return Y(t,e,r)},gitPush:Z,gitPull:ee,gitFetch:te,checkoutBranch:re,createBranch:oe,getGitLog(t,e){return ne(t,e)},getCommitFiles:se,getCurrentGitIdentity:fe,setGitIdentity:de,getGitIdentities:ie,createGitIdentity:ae,updateGitIdentity:ce,deleteGitIdentity:le}),w=t=>t.replace(/\\/g,"/"),ue=()=>({async listDirectory(t){const e=w(t),r=await fetch("/api/fs/list",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e})});if(!r.ok){const o=await r.json().catch(()=>({error:r.statusText}));throw new Error(o.error||"Failed to list directory")}return r.json()},async search(t){const e=await fetch("/api/fs/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({directory:w(t.directory),query:t.query,maxResults:t.maxResults})});if(!e.ok){const o=await e.json().catch(()=>({error:e.statusText}));throw new Error(o.error||"Failed to search files")}const r=await e.json();return Array.isArray(r)?r.filter(o=>!!o&&typeof o=="object"&&typeof o.path=="string").map(o=>({path:w(o.path),score:o.score,preview:o.preview})):[]},async createDirectory(t){const e=w(t),r=await fetch("/api/fs/mkdir",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e})});if(!r.ok){const n=await r.json().catch(()=>({error:r.statusText}));throw new Error(n.error||"Failed to create directory")}const o=await r.json();return{success:!!o?.success,path:typeof o?.path=="string"?w(o.path):e}}}),k="/api/config/settings",we="/api/config/reload",O=t=>!t||typeof t!="object"?{}:t,pe=()=>({async load(){const t=await fetch(k,{method:"GET",headers:{Accept:"application/json"}});if(!t.ok)throw new Error(`Failed to load settings: ${t.statusText}`);return{settings:O(await t.json().catch(()=>({}))),source:"web"}},async save(t){const e=await fetch(k,{method:"PUT",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(t)});if(!e.ok){const o=await e.json().catch(()=>({error:e.statusText}));throw new Error(o.error||"Failed to save settings")}return O(await e.json().catch(()=>({})))},async restartOpenCode(){const t=await fetch(we,{method:"POST"});if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to restart OpenCode")}return{restarted:!0}}}),ye=()=>({async requestDirectoryAccess(t){return{success:!0,path:t.path}},async startAccessingDirectory(t){return{success:!0}},async stopAccessingDirectory(t){return{success:!0}}}),me=async t=>{if(typeof Notification>"u")return console.info("Notifications not supported in this environment",t),!1;if(await Notification.requestPermission()!=="granted")return console.warn("Notification permission not granted"),!1;try{return new Notification(t?.title??"OpenChamber",{body:t?.body,tag:t?.tag}),!0}catch(r){return console.warn("Failed to send notification",r),!1}},ge=()=>({async notifyAgentCompletion(t){return me(t)},canNotify:()=>typeof Notification<"u"?Notification.permission==="granted":!1}),Te=()=>({async getAvailableTools(){const t=await fetch("/api/experimental/tool/ids");if(!t.ok)throw new Error(`Tools API returned ${t.status} ${t.statusText}`);const e=await t.json();if(!Array.isArray(e))throw new Error("Tools API returned invalid data format");return e.filter(r=>typeof r=="string"&&r!=="invalid").sort()}}),Ee=()=>({runtime:{platform:"web",isDesktop:!1,isVSCode:!1,label:"web"},terminal:D(),git:he(),files:ue(),settings:pe(),permissions:ye(),notifications:ge(),tools:Te()});window.__OPENCHAMBER_RUNTIME_APIS__=Ee();P(()=>import("./main-DI52tBPC.js").then(t=>t.m),__vite__mapDeps([0,1,2,3]));export{U as a,le as b,R as c,z as d,ae as e,fe as f,_ as g,ie as h,X as i,Z as j,H as k,V as l,Q as r,ce as u};