@openchamber/web 1.3.9 → 1.4.1
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 +1 -0
- package/bin/cli.js +109 -15
- package/dist/assets/{ToolOutputDialog-BrFH3eLi.js → ToolOutputDialog-CBMeCbbW.js} +3 -3
- package/dist/assets/{index-CqiXpckC.js → index-CbGhBA-v.js} +2 -2
- package/dist/assets/index-Cx6NUrC-.css +1 -0
- package/dist/assets/main-BJvFwyGz.js +122 -0
- package/dist/assets/vendor--Jn2c0Clh.css +1 -0
- package/dist/assets/{vendor-.bun-B0k_58z8.js → vendor-.bun-CpaXrlrC.js} +630 -561
- package/dist/assets/{worker-Doc90iwx.js → worker-NULm4lOi.js} +18 -18
- package/dist/index.html +4 -4
- package/package.json +5 -5
- package/server/index.js +92 -32
- package/server/lib/cloudflare-tunnel.js +196 -0
- package/server/lib/git-service.js +120 -13
- package/dist/assets/index-Coco_yFR.css +0 -1
- package/dist/assets/main-DpLFDKL6.js +0 -119
- package/dist/assets/vendor--swUGvSZA.css +0 -1
package/README.md
CHANGED
|
@@ -41,6 +41,7 @@ openchamber update # Update to latest version
|
|
|
41
41
|
- Smart tool visualization (inline diffs, file trees, results highlighting)
|
|
42
42
|
- Rich permission cards with syntax-highlighted operation previews
|
|
43
43
|
- Per-agent permission modes (ask/allow/full) per session
|
|
44
|
+
- Multi-agent runs from a single prompt (isolated worktrees)
|
|
44
45
|
- Branchable conversations: start a new session from any assistant response
|
|
45
46
|
- Task tracker UI with live progress and tool summaries
|
|
46
47
|
- Model selection UX: favorites, recents, and configurable tool output density
|
package/bin/cli.js
CHANGED
|
@@ -11,10 +11,49 @@ const __dirname = path.dirname(__filename);
|
|
|
11
11
|
const DEFAULT_PORT = 3000;
|
|
12
12
|
const PACKAGE_JSON = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
|
|
13
13
|
|
|
14
|
+
function getBunBinary() {
|
|
15
|
+
if (typeof process.env.BUN_BINARY === 'string' && process.env.BUN_BINARY.trim().length > 0) {
|
|
16
|
+
return process.env.BUN_BINARY.trim();
|
|
17
|
+
}
|
|
18
|
+
if (typeof process.env.BUN_INSTALL === 'string' && process.env.BUN_INSTALL.trim().length > 0) {
|
|
19
|
+
return path.join(process.env.BUN_INSTALL.trim(), 'bin', 'bun');
|
|
20
|
+
}
|
|
21
|
+
return 'bun';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const BUN_BIN = getBunBinary();
|
|
25
|
+
|
|
26
|
+
function isBunRuntime() {
|
|
27
|
+
return typeof globalThis.Bun !== 'undefined';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function isBunInstalled() {
|
|
31
|
+
try {
|
|
32
|
+
const result = spawnSync(BUN_BIN, ['--version'], { stdio: 'ignore', env: process.env });
|
|
33
|
+
return result.status === 0;
|
|
34
|
+
} catch {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getPreferredServerRuntime() {
|
|
40
|
+
return isBunInstalled() ? 'bun' : 'node';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function generateRandomPassword(length = 16) {
|
|
44
|
+
const charset = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789';
|
|
45
|
+
let password = '';
|
|
46
|
+
for (let i = 0; i < length; i++) {
|
|
47
|
+
const randomIndex = Math.floor(Math.random() * charset.length);
|
|
48
|
+
password += charset[randomIndex];
|
|
49
|
+
}
|
|
50
|
+
return password;
|
|
51
|
+
}
|
|
52
|
+
|
|
14
53
|
function parseArgs() {
|
|
15
54
|
const args = process.argv.slice(2);
|
|
16
55
|
const envPassword = process.env.OPENCHAMBER_UI_PASSWORD || undefined;
|
|
17
|
-
const options = { port: DEFAULT_PORT, daemon: false, uiPassword: envPassword };
|
|
56
|
+
const options = { port: DEFAULT_PORT, daemon: false, uiPassword: envPassword, tryCfTunnel: false };
|
|
18
57
|
let command = 'serve';
|
|
19
58
|
|
|
20
59
|
const consumeValue = (currentIndex, inlineValue) => {
|
|
@@ -57,6 +96,9 @@ function parseArgs() {
|
|
|
57
96
|
case 'd':
|
|
58
97
|
options.daemon = true;
|
|
59
98
|
break;
|
|
99
|
+
case 'try-cf-tunnel':
|
|
100
|
+
options.tryCfTunnel = true;
|
|
101
|
+
break;
|
|
60
102
|
case 'ui-password': {
|
|
61
103
|
const { value, nextIndex } = consumeValue(i, inlineValue);
|
|
62
104
|
i = nextIndex;
|
|
@@ -97,11 +139,12 @@ COMMANDS:
|
|
|
97
139
|
update Check for and install updates
|
|
98
140
|
|
|
99
141
|
OPTIONS:
|
|
100
|
-
-p, --port
|
|
101
|
-
--ui-password
|
|
102
|
-
-
|
|
103
|
-
-
|
|
104
|
-
-
|
|
142
|
+
-p, --port Web server port (default: ${DEFAULT_PORT})
|
|
143
|
+
--ui-password Protect browser UI with single password
|
|
144
|
+
--try-cf-tunnel Create a Cloudflare Quick Tunnel for remote access
|
|
145
|
+
-d, --daemon Run in background (serve command)
|
|
146
|
+
-h, --help Show help
|
|
147
|
+
-v, --version Show version
|
|
105
148
|
|
|
106
149
|
ENVIRONMENT:
|
|
107
150
|
OPENCHAMBER_UI_PASSWORD Alternative to --ui-password flag
|
|
@@ -110,6 +153,7 @@ EXAMPLES:
|
|
|
110
153
|
openchamber # Start on default port 3000
|
|
111
154
|
openchamber --port 8080 # Start on port 8080
|
|
112
155
|
openchamber serve --daemon # Start in background
|
|
156
|
+
openchamber --try-cf-tunnel # Start with Cloudflare Quick Tunnel
|
|
113
157
|
openchamber stop # Stop all running instances
|
|
114
158
|
openchamber stop --port 3000 # Stop specific instance
|
|
115
159
|
openchamber status # Check status
|
|
@@ -353,21 +397,36 @@ const commands = {
|
|
|
353
397
|
|
|
354
398
|
const serverPath = path.join(__dirname, '..', 'server', 'index.js');
|
|
355
399
|
|
|
400
|
+
let effectiveUiPassword = options.uiPassword;
|
|
401
|
+
let showAutoGeneratedPassword = false;
|
|
402
|
+
|
|
403
|
+
if (options.tryCfTunnel && typeof effectiveUiPassword !== 'string') {
|
|
404
|
+
effectiveUiPassword = generateRandomPassword(16);
|
|
405
|
+
showAutoGeneratedPassword = true;
|
|
406
|
+
}
|
|
407
|
+
|
|
356
408
|
const serverArgs = [serverPath, '--port', options.port.toString()];
|
|
357
|
-
if (typeof
|
|
358
|
-
serverArgs.push('--ui-password',
|
|
409
|
+
if (typeof effectiveUiPassword === 'string') {
|
|
410
|
+
serverArgs.push('--ui-password', effectiveUiPassword);
|
|
359
411
|
}
|
|
412
|
+
if (options.tryCfTunnel) {
|
|
413
|
+
serverArgs.push('--try-cf-tunnel');
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
const preferredRuntime = getPreferredServerRuntime();
|
|
417
|
+
const runtimeBin = preferredRuntime === 'bun' ? BUN_BIN : process.execPath;
|
|
360
418
|
|
|
361
419
|
if (options.daemon) {
|
|
362
420
|
|
|
363
|
-
const child = spawn(
|
|
421
|
+
const child = spawn(runtimeBin, serverArgs, {
|
|
364
422
|
detached: true,
|
|
365
423
|
stdio: 'ignore',
|
|
366
424
|
env: {
|
|
367
425
|
...process.env,
|
|
368
426
|
OPENCHAMBER_PORT: options.port.toString(),
|
|
369
427
|
OPENCODE_BINARY: opencodeBinary,
|
|
370
|
-
...(typeof
|
|
428
|
+
...(typeof effectiveUiPassword === 'string' ? { OPENCHAMBER_UI_PASSWORD: effectiveUiPassword } : {}),
|
|
429
|
+
OPENCHAMBER_TRY_CF_TUNNEL: options.tryCfTunnel ? 'true' : 'false',
|
|
371
430
|
}
|
|
372
431
|
});
|
|
373
432
|
|
|
@@ -376,10 +435,14 @@ const commands = {
|
|
|
376
435
|
setTimeout(() => {
|
|
377
436
|
if (isProcessRunning(child.pid)) {
|
|
378
437
|
writePidFile(pidFilePath, child.pid);
|
|
379
|
-
writeInstanceOptions(instanceFilePath, options);
|
|
438
|
+
writeInstanceOptions(instanceFilePath, { ...options, uiPassword: effectiveUiPassword });
|
|
380
439
|
console.log(`OpenChamber started in daemon mode on port ${options.port}`);
|
|
381
440
|
console.log(`PID: ${child.pid}`);
|
|
382
441
|
console.log(`Visit: http://localhost:${options.port}`);
|
|
442
|
+
if (showAutoGeneratedPassword) {
|
|
443
|
+
console.log(`\n🔐 Auto-generated password: \x1b[92m${effectiveUiPassword}\x1b[0m`);
|
|
444
|
+
console.log('⚠️ Save this password - it won\'t be shown again!\n');
|
|
445
|
+
}
|
|
383
446
|
} else {
|
|
384
447
|
console.error('Failed to start server in daemon mode');
|
|
385
448
|
process.exit(1);
|
|
@@ -389,16 +452,47 @@ const commands = {
|
|
|
389
452
|
} else {
|
|
390
453
|
|
|
391
454
|
process.env.OPENCODE_BINARY = opencodeBinary;
|
|
392
|
-
if (typeof
|
|
393
|
-
process.env.OPENCHAMBER_UI_PASSWORD =
|
|
455
|
+
if (typeof effectiveUiPassword === 'string') {
|
|
456
|
+
process.env.OPENCHAMBER_UI_PASSWORD = effectiveUiPassword;
|
|
457
|
+
}
|
|
458
|
+
if (showAutoGeneratedPassword) {
|
|
459
|
+
console.log(`\n🔐 Auto-generated password: \x1b[92m${effectiveUiPassword}\x1b[0m`);
|
|
460
|
+
console.log('⚠️ Save this password - it won\'t be shown again!\n');
|
|
394
461
|
}
|
|
395
|
-
|
|
462
|
+
|
|
463
|
+
writeInstanceOptions(instanceFilePath, { ...options, uiPassword: effectiveUiPassword });
|
|
464
|
+
|
|
465
|
+
// Prefer bun when installed (much faster PTY). If CLI is running under Node,
|
|
466
|
+
// run the server in a child process so Node doesn't have to load bun-pty.
|
|
467
|
+
if (preferredRuntime === 'bun' && !isBunRuntime()) {
|
|
468
|
+
const child = spawn(runtimeBin, serverArgs, {
|
|
469
|
+
stdio: 'inherit',
|
|
470
|
+
env: {
|
|
471
|
+
...process.env,
|
|
472
|
+
OPENCHAMBER_PORT: options.port.toString(),
|
|
473
|
+
OPENCODE_BINARY: opencodeBinary,
|
|
474
|
+
...(typeof effectiveUiPassword === 'string' ? { OPENCHAMBER_UI_PASSWORD: effectiveUiPassword } : {}),
|
|
475
|
+
OPENCHAMBER_TRY_CF_TUNNEL: options.tryCfTunnel ? 'true' : 'false',
|
|
476
|
+
},
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
child.on('exit', (code) => {
|
|
480
|
+
process.exit(typeof code === 'number' ? code : 1);
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
|
|
396
486
|
const { startWebUiServer } = await import(serverPath);
|
|
397
487
|
await startWebUiServer({
|
|
398
488
|
port: options.port,
|
|
399
489
|
attachSignals: true,
|
|
400
490
|
exitOnShutdown: true,
|
|
401
|
-
uiPassword: typeof
|
|
491
|
+
uiPassword: typeof effectiveUiPassword === 'string' ? effectiveUiPassword : null,
|
|
492
|
+
tryCfTunnel: options.tryCfTunnel,
|
|
493
|
+
onTunnelReady: (url) => {
|
|
494
|
+
console.log(`\n🌐 Tunnel URL: \x1b[36m${url}\x1b[0m\n`);
|
|
495
|
+
},
|
|
402
496
|
});
|
|
403
497
|
}
|
|
404
498
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{g as L,j as e,
|
|
1
|
+
import{g as L,j as e,bf as j,bx as g,an as P,aY as C,aw as T,b2 as w,Q as _,aA as z,af as v,bt as D,bu as O,bv as F,W}from"./vendor-.bun-CpaXrlrC.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 A,h as E,S as G,i as K}from"./main-BJvFwyGz.js";import"./index-CbGhBA-v.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(O,{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(F,{className:o}):t.startsWith("git")?e.jsx(W,{className:o}):e.jsx(j,{className:o})},M=({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?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")}
|
|
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:
|
|
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,
|
|
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 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==="glob")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==="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 K(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
|
+
`),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{M as default};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/main-
|
|
2
|
-
import{_ as P}from"./vendor-.bun-B0k_58z8.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-DpLFDKL6.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-BJvFwyGz.js","assets/vendor-.bun-CpaXrlrC.js","assets/vendor--Jn2c0Clh.css","assets/main-C1GggQif.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{_ as P}from"./vendor-.bun-CpaXrlrC.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-BJvFwyGz.js").then(t=>t.m),__vite__mapDeps([0,1,2,3]));export{U as a,H as b,R as c,z as d,le as e,ae as f,_ as g,fe as h,ie as i,X as j,M as k,V as l,Q as r,ce as u};
|