@openchamber/web 1.11.0 → 1.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/assets/{JsonTreeView-CUIfrcFf.js → JsonTreeView-9F0tH9yA.js} +1 -1
  2. package/dist/assets/{MarkdownRendererImpl-Bma9y3dD.js → MarkdownRendererImpl-C3QofAGm.js} +2 -2
  3. package/dist/assets/{MultiRunWindow-Cwc0x7fs.js → MultiRunWindow-wnUGv0Dl.js} +1 -1
  4. package/dist/assets/{OnboardingScreen-BhozUlcE.js → OnboardingScreen-17dAs0NH.js} +2 -2
  5. package/dist/assets/{SettingsWindow-B4B2bn0C.js → SettingsWindow-BgyVY5gz.js} +1 -1
  6. package/dist/assets/{TerminalView-BpoHWJj6.js → TerminalView-D11XIZuz.js} +1 -1
  7. package/dist/assets/{ToolOutputDialog-7U42lN20.js → ToolOutputDialog-DFG7ANVw.js} +6 -6
  8. package/dist/assets/es-Chl2Hu6K.js +15 -0
  9. package/dist/assets/index-0bVkxg-Z.css +1 -0
  10. package/dist/assets/{index-B2ztI3pp.js → index-BV2XTsJJ.js} +1 -1
  11. package/dist/assets/ko-BSrH3F9n.js +15 -0
  12. package/dist/assets/{main-rHOaDqOy.js → main-BHkNwOz1.js} +2 -2
  13. package/dist/assets/main-Bqf4fXgq.js +225 -0
  14. package/dist/assets/miniChat-BmB-E5xo.js +2 -0
  15. package/dist/assets/{modelPrefsAutoSave-D5z_F_WP.js → modelPrefsAutoSave-2uwW8uD9.js} +104 -96
  16. package/dist/assets/pl-YlGvPmFg.js +15 -0
  17. package/dist/assets/pt-BR-BonIMDN_.js +15 -0
  18. package/dist/assets/renderElectronMiniChatApp-B_qrXCU2.js +2 -0
  19. package/dist/assets/uk-lPqA3MHn.js +15 -0
  20. package/dist/assets/{vendor-.bun-BFTPeDgG.js → vendor-.bun-Boz6Tqcq.js} +20 -20
  21. package/dist/assets/zh-CN-C5nQQsUL.js +15 -0
  22. package/dist/index.html +4 -4
  23. package/dist/mini-chat.html +4 -4
  24. package/package.json +1 -1
  25. package/server/lib/git/DOCUMENTATION.md +1 -0
  26. package/server/lib/git/routes.js +26 -0
  27. package/server/lib/git/service.js +96 -10
  28. package/server/lib/git/service.test.js +39 -0
  29. package/server/lib/opencode/settings-helpers.js +10 -1
  30. package/server/lib/opencode/settings-helpers.test.js +35 -0
  31. package/server/lib/opencode/skill-routes.js +43 -49
  32. package/server/lib/opencode/skills.js +78 -10
  33. package/server/lib/preview/proxy-runtime.js +43 -3
  34. package/dist/assets/es-DLzL0vVb.js +0 -15
  35. package/dist/assets/index-D5TVqnib.css +0 -1
  36. package/dist/assets/ko-apnbnEuD.js +0 -15
  37. package/dist/assets/main-ClS4RVxe.js +0 -217
  38. package/dist/assets/miniChat-Cx8YK32Y.js +0 -2
  39. package/dist/assets/pl-DUKUujvh.js +0 -15
  40. package/dist/assets/pt-BR-D0UPeIZC.js +0 -15
  41. package/dist/assets/renderElectronMiniChatApp-zbukf-1g.js +0 -2
  42. package/dist/assets/uk-CaTe2At9.js +0 -15
  43. package/dist/assets/zh-CN-D-oQmPdK.js +0 -15
@@ -1 +1 @@
1
- (function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))o(n);new MutationObserver(n=>{for(const s of n)if(s.type==="childList")for(const c of s.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&o(c)}).observe(document,{childList:!0,subtree:!0});function e(n){const s={};return n.integrity&&(s.integrity=n.integrity),n.referrerPolicy&&(s.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?s.credentials="include":n.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function o(n){if(n.ep)return;n.ep=!0;const s=e(n);fetch(n.href,s)}})();const Y=1,f=1,j=0,V="/api/terminal/ws",tt=1200,et=250,rt=2e4,ot=5e3,P="__openchamberTerminalTransportState",nt=new TextEncoder,J=new TextDecoder,N=r=>{if(/^wss?:\/\//i.test(r))return r;if(/^https?:\/\//i.test(r)){const o=new URL(r);return o.protocol=o.protocol==="https:"?"wss:":"ws:",o.toString()}if(typeof window>"u")return"";const t=r.startsWith("/")?r:`/${r}`;return`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}${t}`},I=r=>{const t=nt.encode(JSON.stringify(r)),e=new Uint8Array(t.length+1);return e[0]=Y,e.set(t,1),e},E=r=>r?((r.transports??[]).includes("ws")||r.preferred==="ws")&&typeof r.ws?.path=="string"&&r.ws.path.length>0:!1,A=r=>r.streamCapability?.ws?.path??r.inputCapability?.ws?.path??V,st=r=>{switch(r){case"SESSION_NOT_FOUND":return new Error("Terminal session not found");case"NOT_BOUND":return new Error("Terminal session is not bound");case"WRITE_FAIL":return new Error("Failed to write to terminal");case"RATE_LIMIT":return new Error("Terminal websocket is rate limited");case"BAD_FRAME":return new Error("Terminal websocket protocol violation");default:return new Error("Terminal websocket error")}};class it{socket=null;socketUrl="";boundSessionId=null;requestedSessionId=null;openPromise=null;reconnectTimeout=null;keepaliveInterval=null;closed=!1;subscriptions=new Map;activeSubscriptionToken=null;configure(t){if(t){if(this.socketUrl===t){this.closed=!1,this.isConnectedOrConnecting()||this.ensureConnected();return}this.socketUrl=t,this.closed=!1,this.resetConnection(),this.ensureConnected()}}subscribe(t,e,o,n){const s=Symbol(t),c={token:s,sessionId:t,onEvent:e,onError:o,maxRetries:n?.maxRetries??3,initialRetryDelay:n?.initialRetryDelay??1e3,maxRetryDelay:n?.maxRetryDelay??8e3,connectionTimeout:n?.connectionTimeout??1e4,retryCount:0,connected:!1,connectionTimeoutId:null};return this.subscriptions.set(s,c),this.activeSubscriptionToken=s,this.boundSessionId=null,this.requestedSessionId=t,this.ensureConnected(),this.startConnectionTimeout(c),this.bindActiveSession(),()=>{this.clearConnectionTimeout(c),this.subscriptions.delete(s),this.activeSubscriptionToken===s&&(this.activeSubscriptionToken=null),this.boundSessionId===t&&(this.boundSessionId=null),this.requestedSessionId===t&&(this.requestedSessionId=null),this.subscriptions.size===0&&(this.clearReconnectTimeout(),this.resetConnection())}}async sendInput(t,e){if(!t||!e||this.closed||!this.socketUrl)return!1;const o=await this.getOpenSocket(tt);if(!o||o.readyState!==f)return!1;try{return this.boundSessionId!==t&&(this.requestedSessionId=t,o.send(I({t:"b",s:t,v:2}))),o.send(e),!0}catch{return this.handleSocketFailure(new Error("Terminal websocket send failed")),!1}}unbindSession(t){t&&(this.boundSessionId===t&&(this.boundSessionId=null),this.requestedSessionId===t&&(this.requestedSessionId=null))}close(){this.closed=!0,this.clearReconnectTimeout();for(const t of this.subscriptions.values())this.clearConnectionTimeout(t);this.resetConnection(),this.socketUrl="",this.subscriptions.clear(),this.activeSubscriptionToken=null}prime(){this.closed||!this.socketUrl||this.isConnectedOrConnecting()||this.ensureConnected()}isConnectedOrConnecting(t){return this.closed||t&&this.socketUrl!==t?!1:this.socket&&(this.socket.readyState===f||this.socket.readyState===j)?!0:this.openPromise!==null}getActiveSubscription(){return this.activeSubscriptionToken?this.subscriptions.get(this.activeSubscriptionToken)??null:null}startConnectionTimeout(t){this.clearConnectionTimeout(t),t.connectionTimeoutId=setTimeout(()=>{this.getActiveSubscription()?.token!==t.token||t.connected||this.handleSocketFailure(new Error("Connection timeout"))},t.connectionTimeout)}clearConnectionTimeout(t){t.connectionTimeoutId&&(clearTimeout(t.connectionTimeoutId),t.connectionTimeoutId=null)}async getOpenSocket(t){if(this.socket&&this.socket.readyState===f)return this.socket;if(this.ensureConnected(),this.socket&&this.socket.readyState===f)return this.socket;const e=await Promise.race([this.openPromise??Promise.resolve(null),new Promise(o=>{setTimeout(()=>o(null),t)})]);return e&&e.readyState===f?e:this.socket&&this.socket.readyState===f?this.socket:null}ensureConnected(){this.closed||!this.socketUrl||this.socket&&(this.socket.readyState===f||this.socket.readyState===j)||this.openPromise||(this.clearReconnectTimeout(),this.openPromise=new Promise(t=>{let e=!1,o=null;const n=s=>{e||(e=!0,o&&(clearTimeout(o),o=null),this.openPromise=null,t(s))};try{const s=new WebSocket(this.socketUrl);s.binaryType="arraybuffer",s.onopen=()=>{this.socket=s,this.startKeepalive(),n(s)},s.onmessage=c=>{this.handleSocketMessage(c.data)},s.onerror=()=>{!this.closed&&!this.getActiveSubscription()&&this.scheduleReconnect(new Error("Terminal websocket error"))},s.onclose=()=>{this.socket===s&&(this.socket=null,this.boundSessionId=null,this.stopKeepalive(),this.closed||this.scheduleReconnect(new Error("Terminal stream connection error"))),n(null)},this.socket=s,o=setTimeout(()=>{s.readyState===j&&(s.close(),n(null))},ot)}catch{n(null),this.closed||this.scheduleReconnect(new Error("Terminal websocket open failed"))}}))}bindActiveSession(){const t=this.getActiveSubscription();if(!(!t||!this.socket||this.socket.readyState!==f)){this.requestedSessionId=t.sessionId;try{this.socket.send(I({t:"b",s:t.sessionId,v:2}))}catch{this.handleSocketFailure(new Error("Terminal websocket bind failed"))}}}scheduleReconnect(t){if(this.closed||!this.socketUrl||this.reconnectTimeout)return;const e=this.getActiveSubscription();if(!e)return;const o=e.retryCount+1,n=e.initialRetryDelay,s=e.maxRetryDelay,c=e.maxRetries;if(o>c){this.clearConnectionTimeout(e),e.onError?.(t,!0);return}e.retryCount=o,e.connected=!1,e.onEvent({type:"reconnecting",attempt:o,maxAttempts:c}),this.startConnectionTimeout(e);const p=Math.min(n*Math.pow(2,Math.max(o-1,0)),s),l=Math.floor(Math.random()*et),h=p+l;this.reconnectTimeout=setTimeout(()=>{this.reconnectTimeout=null,this.ensureConnected(),this.bindActiveSession()},h)}clearReconnectTimeout(){this.reconnectTimeout&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=null)}sendControl(t){if(!this.socket||this.socket.readyState!==f)return!1;try{return this.socket.send(I(t)),!0}catch{return this.handleSocketFailure(new Error("Terminal websocket control send failed")),!1}}startKeepalive(){this.stopKeepalive(),this.keepaliveInterval=setInterval(()=>{this.closed||this.sendControl({t:"p",v:2})},rt)}stopKeepalive(){this.keepaliveInterval&&(clearInterval(this.keepaliveInterval),this.keepaliveInterval=null)}async handleSocketMessage(t){const e=await this.asUint8Array(t);if(e&&e.length>0&&e[0]===Y){this.handleControlMessage(e);return}const o=await this.asText(t);if(!o)return;const n=this.getActiveSubscription();n&&n.onEvent({type:"data",data:o})}handleControlMessage(t){if(t.length<2)return;let e;try{e=JSON.parse(J.decode(t.subarray(1)))}catch{this.handleSocketFailure(new Error("Terminal websocket control parse failed"));return}const o=this.getActiveSubscription();switch(e.t){case"ok":this.bindActiveSession();return;case"po":return;case"bok":{if(this.boundSessionId=e.s??this.requestedSessionId,!o)return;o.retryCount=0,o.connected=!0,this.clearConnectionTimeout(o),o.onEvent({type:"connected",runtime:e.runtime,ptyBackend:e.ptyBackend});return}case"x":{if(!o){this.boundSessionId=null;return}if(e.s&&e.s!==o.sessionId)return;o.connected=!1,this.clearConnectionTimeout(o),this.boundSessionId=null,this.requestedSessionId=null,o.onEvent({type:"exit",exitCode:e.exitCode,signal:e.signal??null});return}case"e":{const n=st(e.c),s=e.f===!0||e.c==="SESSION_NOT_FOUND";(e.c==="NOT_BOUND"||e.c==="SESSION_NOT_FOUND")&&(this.boundSessionId=null),o&&(o.connected=!1,s&&this.clearConnectionTimeout(o),o.onError?.(n,s)),e.f===!0&&this.handleSocketFailure(n);return}default:return}}async asUint8Array(t){if(t instanceof ArrayBuffer)return new Uint8Array(t);if(t instanceof Uint8Array)return t;if(typeof Blob<"u"&&t instanceof Blob){const e=await t.arrayBuffer();return new Uint8Array(e)}return null}async asText(t){if(typeof t=="string")return t;const e=await this.asUint8Array(t);return e?J.decode(e):""}handleSocketFailure(t){this.boundSessionId=null,this.requestedSessionId=null,this.resetConnection(),this.scheduleReconnect(t)}resetConnection(){if(this.openPromise=null,this.stopKeepalive(),this.socket){const t=this.socket;this.socket=null,t.onopen=null,t.onmessage=null,t.onerror=null,t.onclose=null,(t.readyState===f||t.readyState===j)&&t.close()}this.boundSessionId=null}}const y=()=>{const r=globalThis;return r[P]||(r[P]={inputCapability:null,streamCapability:null,manager:null}),r[P]},$=()=>{const r=y();return r.manager||(r.manager=new it),r.manager},Q=r=>{const t=y();if(t.inputCapability=r?.input??null,t.streamCapability=r?.stream??null,!E(t.inputCapability)&&!E(t.streamCapability)){t.manager?.close(),t.manager=null;return}const e=N(A(t));if(!e)return;$().configure(e)},at=async(r,t)=>{const e=await fetch(`/api/terminal/${r}/input`,{method:"POST",headers:{"Content-Type":"text/plain"},body:t});if(!e.ok){const o=await e.json().catch(()=>({error:"Failed to send terminal input"}));throw new Error(o.error||"Failed to send terminal input")}};async function ct(r){const t=await fetch("/api/terminal/create",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cwd:r.cwd,cols:r.cols??80,rows:r.rows??24})});if(!t.ok){const o=await t.json().catch(()=>({error:"Failed to create terminal"}));throw new Error(o.error||"Failed to create terminal session")}const e=await t.json();return Q(e.capabilities),e}const M=(r,t,e,o={})=>{const n=o.maxRetries??3,s=o.initialRetryDelay??1e3,c=o.maxRetryDelay??8e3,p=o.connectionTimeout??1e4;let l=null,h=0,w=null,T=null,m=!1,g=!1;const x=()=>{w&&(clearTimeout(w),w=null),T&&(clearTimeout(T),T=null)},F=()=>{m||(m=!0,x(),l&&(l.close(),l=null))},_=(S,k)=>{if(!(m||g)){if(h<n&&!k){h+=1;const b=Math.min(s*Math.pow(2,h-1),c);t({type:"reconnecting",attempt:h,maxAttempts:n}),w=setTimeout(()=>{!m&&!g&&D()},b);return}e?.(S,!0),F()}},D=()=>{if(m||g||l&&l.readyState!==EventSource.CLOSED)return;l=new EventSource(`/api/terminal/${r}/stream`);let S=!1;T=setTimeout(()=>{!S&&l?.readyState!==EventSource.OPEN&&(l?.close(),_(new Error("Connection timeout"),!1))},p),l.onopen=()=>{S||(S=!0,h=0,x(),t({type:"connected"}))},l.onmessage=k=>{try{const b=JSON.parse(k.data);b.type==="exit"&&(y().manager?.unbindSession(r),g=!0,F()),t(b)}catch(b){e?.(b,!1)}},l.onerror=()=>{x();const k=g||l?.readyState===EventSource.CLOSED;l?.close(),l=null,g||_(new Error("Terminal stream connection error"),k)}};return D(),F};function lt(r,t,e,o={}){const n=y();if(!E(n.streamCapability))return M(r,t,e,o);const s=$(),c=N(A(n));return c?(s.configure(c),s.subscribe(r,t,e,o)):M(r,t,e,o)}async function ut(r,t){const e=y();e.manager&&await e.manager.sendInput(r,t)||await at(r,t)}async function ht(r,t,e){const o=await fetch(`/api/terminal/${r}/resize`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cols:t,rows:e})});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 dt(r){y().manager?.unbindSession(r);const t=await fetch(`/api/terminal/${r}`,{method:"DELETE"});if(!t.ok){const e=await t.json().catch(()=>({error:"Failed to close terminal"}));throw new Error(e.error||"Failed to close terminal")}}async function pt(r,t){y().manager?.unbindSession(r);const e=await fetch(`/api/terminal/${r}/restart`,{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 n=await e.json().catch(()=>({error:"Failed to restart terminal"}));throw new Error(n.error||"Failed to restart terminal")}const o=await e.json();return Q(o.capabilities),o}async function ft(r){const t=await fetch("/api/terminal/force-kill",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});if(!t.ok){const e=await t.json().catch(()=>({error:"Failed to force kill terminal"}));throw new Error(e.error||"Failed to force kill terminal")}r.sessionId&&y().manager?.unbindSession(r.sessionId)}function Ce(){const r=y();if(r.inputCapability&&r.streamCapability&&!E(r.inputCapability)&&!E(r.streamCapability))return;const t=A(r)||V,e=N(t);if(!e)return;const o=$();o.isConnectedOrConnecting(e)||(o.configure(e),o.prime())}const wt=r=>{const t=r?.retry;return{maxRetries:t?.maxRetries??3,initialRetryDelay:t?.initialDelayMs??1e3,maxRetryDelay:t?.maxDelayMs??8e3,connectionTimeout:r?.connectionTimeoutMs??1e4}},yt=()=>({async createSession(r){return ct(r)},connect(r,t,e){const o=lt(r,t.onEvent,t.onError,wt(e));return{close:()=>o()}},async sendInput(r,t){await ut(r,t)},async resize(r){await ht(r.sessionId,r.cols,r.rows)},async close(r){await dt(r)},async restartSession(r,t){return pt(r,{cwd:t.cwd??"",cols:t.cols,rows:t.rows})},async forceKill(r){await ft(r)}}),mt=()=>{if(typeof window>"u")return"";const r=window.__OPENCHAMBER_DESKTOP_SERVER__?.origin;return r||window.location.origin},i="/api/git",gt=1200,Tt=5e3,U=new Map,C=new Map,W=new Map,O=new Map,R=r=>r.trim();function a(r,t,e){const o=new URL(r,mt());if(t&&o.searchParams.set("directory",t),e)for(const[n,s]of Object.entries(e))s!==void 0&&o.searchParams.set(n,String(s));return o.toString()}async function bt(r){const t=R(r),e=Date.now(),o=W.get(t);if(o&&o.expiresAt>e)return o.value;const n=O.get(t);if(n)return n;const s=(async()=>{const c=await fetch(a(`${i}/check`,r));if(!c.ok)throw new Error(`Failed to check git repository: ${c.statusText}`);const l=!!(await c.json()).isGitRepository;return W.set(t,{value:l,expiresAt:Date.now()+Tt}),l})();O.set(t,s);try{return await s}finally{O.get(t)===s&&O.delete(t)}}async function St(r,t){const e=t?.mode,o=e==="light"?`${R(r)}::light`:R(r),n=Date.now(),s=U.get(o);if(s&&s.expiresAt>n)return s.value;const c=C.get(o);if(c)return c;const p=(async()=>{const l=await fetch(a(`${i}/status`,r,e?{mode:e}:void 0));if(!l.ok)throw new Error(`Failed to get git status: ${l.statusText}`);const h=await l.json();return U.set(o,{value:h,expiresAt:Date.now()+gt}),h})();C.set(o,p);try{return await p}finally{C.get(o)===p&&C.delete(o)}}async function kt(r,t){const{path:e,staged:o,contextLines:n}=t;if(!e)throw new Error("path is required to fetch git diff");const s=await fetch(a(`${i}/diff`,r,{path:e,staged:o?"true":void 0,context:n}));if(!s.ok)throw new Error(`Failed to get git diff: ${s.statusText}`);return s.json()}async function Et(r,t){const{path:e,staged:o}=t;if(!e)throw new Error("path is required to fetch git file diff");const n=await fetch(a(`${i}/file-diff`,r,{path:e,staged:o?"true":void 0}));if(!n.ok)throw new Error(`Failed to get git file diff: ${n.statusText}`);return n.json()}async function jt(r,t){if(!t)throw new Error("path is required to revert git changes");const e=await fetch(a(`${i}/revert`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t})});if(!e.ok){const o=await e.json().catch(()=>({error:e.statusText}));throw new Error(o.error||"Failed to revert git changes")}}async function Ct(r){if(!r)return!1;const t=await fetch(a(`${i}/worktree-type`,r));if(!t.ok)throw new Error(`Failed to detect worktree type: ${t.statusText}`);return!!(await t.json()).linked}async function Ot(r){const t=await fetch(a(`${i}/branches`,r));if(!t.ok)throw new Error(`Failed to get branches: ${t.statusText}`);return t.json()}async function vt(r,t){if(!t?.branch)throw new Error("branch is required to delete a branch");const e=await fetch(a(`${i}/branches`,r),{method:"DELETE",headers:{"Content-Type":"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 delete branch")}return e.json()}async function xt(r,t){if(!t?.branch)throw new Error("branch is required to delete remote branch");const e=await fetch(a(`${i}/remote-branches`,r),{method:"DELETE",headers:{"Content-Type":"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 delete remote branch")}return e.json()}async function Ft(r,t){const e=t?.remote?.trim();if(!e)throw new Error("remote is required to remove a remote");const o=await fetch(a(`${i}/remotes`,r),{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({remote:e})});if(!o.ok){const n=await o.json().catch(()=>({error:o.statusText}));throw new Error(n.error||"Failed to remove remote")}return o.json()}async function Pt(r,t,e){if(!Array.isArray(t)||t.length===0)throw new Error("No files provided to generate commit message");const o={files:t};e?.zenModel&&(o.zenModel=e.zenModel),e?.providerId&&(o.providerId=e.providerId),e?.modelId&&(o.modelId=e.modelId);const n=await fetch(a(`${i}/commit-message`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o)});if(!n.ok){const l=await n.json().catch(()=>({error:n.statusText}));console.error("[git-generation][browser] http error",{status:n.status,statusText:n.statusText,error:l});const h=typeof l?.traceId=="string"&&l.traceId?` (traceId: ${l.traceId})`:"";throw new Error(`${l.error||"Failed to generate commit message"}${h}`)}const s=await n.json();if(!s?.message||typeof s.message!="object")throw new Error("Malformed commit generation response");const c=typeof s.message.subject=="string"&&s.message.subject.trim().length>0?s.message.subject.trim():"",p=Array.isArray(s.message.highlights)?s.message.highlights.filter(l=>typeof l=="string"&&l.trim().length>0).map(l=>l.trim()):[];return{message:{subject:c,highlights:p}}}async function It(r,t){const{base:e,head:o,context:n,zenModel:s,providerId:c,modelId:p}=t;if(!e||!o)throw new Error("base and head are required");const l={base:e,head:o};n?.trim()&&(l.context=n.trim()),s&&(l.zenModel=s),c&&(l.providerId=c),p&&(l.modelId=p);const h=await fetch(a(`${i}/pr-description`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)});if(!h.ok){const g=await h.json().catch(()=>({error:h.statusText}));throw new Error(g.error||"Failed to generate PR description")}const w=await h.json().catch(()=>null),T=typeof w?.title=="string"?w.title:"",m=typeof w?.body=="string"?w.body:"";if(!T&&!m)throw new Error("Malformed PR description response");return{title:T,body:m}}async function L(r){const t=await fetch(a(`${i}/worktrees`,r));if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to list worktrees")}return t.json()}async function B(r,t){const e=await fetch(a(`${i}/worktrees/validate`,r),{method:"POST",headers:{"Content-Type":"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 validate worktree")}return e.json()}async function Oe(r){const t=await fetch(a(`${i}/worktrees/bootstrap-status`,r));if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to get worktree bootstrap status")}return t.json()}async function ve(r,t){const e=await fetch(a(`${i}/worktrees/preview`,r),{method:"POST",headers:{"Content-Type":"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 preview worktree")}return e.json()}async function q(r,t){const e=await fetch(a(`${i}/worktrees`,r),{method:"POST",headers:{"Content-Type":"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 create worktree")}return e.json()}async function z(r,t){const e=await fetch(a(`${i}/worktrees`,r),{method:"DELETE",headers:{"Content-Type":"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 delete worktree")}return e.json()}async function Rt(r,t,e={}){const o=await fetch(a(`${i}/commit`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:t,addAll:e.addAll??!1,files:e.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 Nt(r,t={}){const e=await fetch(a(`${i}/push`,r),{method:"POST",headers:{"Content-Type":"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 push")}return e.json()}async function At(r,t={}){const e=await fetch(a(`${i}/pull`,r),{method:"POST",headers:{"Content-Type":"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 pull")}return e.json()}async function $t(r,t={}){const e=await fetch(a(`${i}/fetch`,r),{method:"POST",headers:{"Content-Type":"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 fetch")}return e.json()}async function Gt(r){const t=await fetch(a(`${i}/stashes`,r));if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to list stashes")}return t.json()}async function _t(r,t){const e=await fetch(a(`${i}/stashes/file-counts`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refs:t})});if(!e.ok){const o=await e.json().catch(()=>({error:e.statusText}));throw new Error(o.error||"Failed to count stash files")}return e.json()}async function X(r,t={}){const e=await fetch(a(`${i}/stash`,r),{method:"POST",headers:{"Content-Type":"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 stash changes")}return e.json()}const G=async(r,t,e)=>{const o=await fetch(a(`${i}/${t}`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!o.ok){const n=await o.json().catch(()=>({error:o.statusText}));throw new Error(n.error||`Failed to ${t}`)}return o.json()},Dt=(r,t)=>G(r,"stash/apply",t),Z=(r,t)=>G(r,"stash/pop",t),Jt=(r,t)=>G(r,"stash/drop",t);async function Mt(r,t){const e=await fetch(a(`${i}/checkout`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({branch:t})});if(!e.ok){const o=await e.json().catch(()=>({error:e.statusText}));throw new Error(o.error||"Failed to checkout branch")}return e.json()}async function Ut(r,t,e){const o=await fetch(a(`${i}/branches`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:t,startPoint:e})});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 Wt(r,t,e){const o=await fetch(a(`${i}/branches/rename`,r),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({oldName:t,newName:e})});if(!o.ok){const n=await o.json().catch(()=>({error:o.statusText}));throw new Error(n.error||"Failed to rename branch")}return o.json()}async function Lt(r,t={}){const e=await fetch(a(`${i}/log`,r,{maxCount:t.maxCount,from:t.from,to:t.to,file:t.file}));if(!e.ok)throw new Error(`Failed to get git log: ${e.statusText}`);return e.json()}async function Bt(r,t){const e=await fetch(a(`${i}/commit-files`,r,{hash:t}));if(!e.ok)throw new Error(`Failed to get commit files: ${e.statusText}`);return e.json()}async function qt(){const r=await fetch(a(`${i}/identities`,void 0));if(!r.ok)throw new Error(`Failed to get git identities: ${r.statusText}`);return r.json()}async function zt(r){const t=await fetch(a(`${i}/identities`,void 0),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to create git identity")}return t.json()}async function Kt(r,t){const e=await fetch(a(`${i}/identities/${r}`,void 0),{method:"PUT",headers:{"Content-Type":"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 update git identity")}return e.json()}async function Ht(r){const t=await fetch(a(`${i}/identities/${r}`,void 0),{method:"DELETE"});if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to delete git identity")}}async function Yt(r){if(!r)return null;const t=await fetch(a(`${i}/current-identity`,r));if(!t.ok)throw new Error(`Failed to get current git identity: ${t.statusText}`);const e=await t.json();return e?{userName:e.userName??null,userEmail:e.userEmail??null,sshCommand:e.sshCommand??null}:null}async function Vt(r){if(!r)return!1;const t=await fetch(a(`${i}/has-local-identity`,r));if(!t.ok)throw new Error(`Failed to check local identity: ${t.statusText}`);return(await t.json().catch(()=>null))?.hasLocalIdentity===!0}async function xe(){const r=await fetch(a(`${i}/global-identity`,void 0));if(!r.ok)throw new Error(`Failed to get global git identity: ${r.statusText}`);const t=await r.json();return!t||!t.userName&&!t.userEmail?null:{userName:t.userName??null,userEmail:t.userEmail??null,sshCommand:t.sshCommand??null}}async function Qt(r,t){const e=await fetch(a(`${i}/set-identity`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({profileId:t})});if(!e.ok){const o=await e.json().catch(()=>({error:e.statusText}));throw new Error(o.error||"Failed to set git identity")}return e.json()}async function Fe(){const r=await fetch(a(`${i}/discover-credentials`,void 0));if(!r.ok)throw new Error(`Failed to discover git credentials: ${r.statusText}`);return r.json()}async function Pe(r,t){if(!r)return null;const e=await fetch(a(`${i}/remote-url`,r,{remote:t}));return e.ok?(await e.json()).url??null:null}async function Xt(r){const t=await fetch(a(`${i}/remotes`,r));if(!t.ok)throw new Error(`Failed to get remotes: ${t.statusText}`);return t.json()}async function Zt(r,t){const e=await fetch(a(`${i}/rebase`,r),{method:"POST",headers:{"Content-Type":"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 rebase")}return e.json()}async function te(r){const t=await fetch(a(`${i}/rebase/abort`,r),{method:"POST"});if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to abort rebase")}return t.json()}async function ee(r,t){const e=await fetch(a(`${i}/merge`,r),{method:"POST",headers:{"Content-Type":"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 merge")}return e.json()}async function re(r){const t=await fetch(a(`${i}/merge/abort`,r),{method:"POST"});if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to abort merge")}return t.json()}async function oe(r){const t=await fetch(a(`${i}/rebase/continue`,r),{method:"POST"});if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to continue rebase")}return t.json()}async function ne(r){const t=await fetch(a(`${i}/merge/continue`,r),{method:"POST"});if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to continue merge")}return t.json()}async function se(r,t){return await X(r,{message:t?.message}),{success:!0}}async function ie(r){return await Z(r,{ref:"stash@{0}"}),{success:!0}}async function ae(r){const t=await fetch(a(`${i}/conflict-details`,r));if(!t.ok)throw new Error(`Failed to get conflict details: ${t.statusText}`);return t.json()}async function ce(r,t){const e=await fetch(`${i}/validate-directory`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({directory:r,worktreeRoot:t})});if(!e.ok)throw new Error(`Failed to validate worktree directory: ${e.statusText}`);return e.json()}async function le(r){const t=await fetch(`${i}/canonicalize-worktree-state`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({directory:r})});if(!t.ok)throw new Error(`Failed to canonicalize worktree state: ${t.statusText}`);return t.json()}const ue=()=>({checkIsGitRepository:bt,getGitStatus:St,getGitDiff:kt,getGitFileDiff:Et,revertGitFile:jt,isLinkedWorktree:Ct,getGitBranches:Ot,deleteGitBranch:vt,deleteRemoteBranch:xt,removeRemote:Ft,generateCommitMessage:Pt,generatePullRequestDescription:It,listGitWorktrees:L,validateGitWorktree:B,createGitWorktree:q,deleteGitWorktree:z,validateWorktreeDirectory:ce,canonicalizeWorktreeState:le,createGitCommit(r,t,e){return Rt(r,t,e)},gitPush:Nt,gitPull:At,gitFetch:$t,listGitStashes:Gt,countGitStashFiles:_t,stashGitChanges:X,applyGitStash:Dt,popGitStash:Z,dropGitStash:Jt,checkoutBranch:Mt,createBranch:Ut,renameBranch:Wt,getGitLog(r,t){return Lt(r,t)},getCommitFiles:Bt,getCurrentGitIdentity:Yt,hasLocalIdentity:Vt,setGitIdentity:Qt,getGitIdentities:qt,createGitIdentity:zt,updateGitIdentity:Kt,deleteGitIdentity:Ht,getRemotes:Xt,rebase:Zt,abortRebase:te,continueRebase:oe,merge:ee,abortMerge:re,continueMerge:ne,stash:se,stashPop:ie,getConflictDetails:ae,worktree:{list:L,validate:B,create:q,remove:z}}),d=r=>r.replace(/\\/g,"/"),he=(r,t)=>{const e=d(t?.directory||t?.path||r),o=Array.isArray(t?.entries)?t.entries:[];return{directory:e,entries:o.filter(n=>!!(n&&typeof n.name=="string"&&typeof n.path=="string")).map(n=>({name:n.name,path:d(n.path),isDirectory:!!n.isDirectory}))}},de=()=>({async listDirectory(r){const t=d(r),e=new URLSearchParams;t&&e.set("path",t);const o=await fetch(`/api/fs/list${e.toString()?`?${e.toString()}`:""}`);if(!o.ok){const s=await o.json().catch(()=>({error:o.statusText}));throw new Error(s.error||"Failed to list directory")}const n=await o.json();return he(t,n)},async search(r){const t=new URLSearchParams,e=d(r.directory);e&&t.set("directory",e),t.set("query",r.query),t.set("dirs","false"),t.set("type","file"),typeof r.maxResults=="number"&&Number.isFinite(r.maxResults)&&t.set("limit",String(r.maxResults));const o=await fetch(`/api/find/file?${t.toString()}`);if(!o.ok){const c=await o.json().catch(()=>({error:o.statusText}));throw new Error(c.error||"Failed to search files")}const n=await o.json();return(Array.isArray(n)?n:[]).map(c=>({path:d(`${e}/${c}`),preview:[d(c)]}))},async createDirectory(r){const t=d(r),e=await fetch("/api/fs/mkdir",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t})});if(!e.ok){const n=await e.json().catch(()=>({error:e.statusText}));throw new Error(n.error||"Failed to create directory")}const o=await e.json();return{success:!!o?.success,path:typeof o?.path=="string"?d(o.path):t}},async statFile(r,t){const e=d(r),o=new URLSearchParams({path:e});t?.allowOutsideWorkspace&&o.set("allowOutsideWorkspace","true");const n=await fetch(`/api/fs/stat?${o.toString()}`);if(!n.ok){const c=await n.json().catch(()=>({error:n.statusText}));throw new Error(c.error||"Failed to stat file")}const s=await n.json().catch(()=>({}));return{path:typeof s.path=="string"?d(s.path):e,isFile:!!s.isFile,size:typeof s.size=="number"?s.size:0,mtimeMs:typeof s.mtimeMs=="number"?s.mtimeMs:void 0}},async readFile(r,t){const e=d(r),o=new URLSearchParams({path:e});t?.allowOutsideWorkspace&&o.set("allowOutsideWorkspace","true"),t?.optional&&o.set("optional","true");const n=await fetch(`/api/fs/read?${o.toString()}`,{cache:t?.optional?"no-store":"default"});if(!n.ok){const c=await n.json().catch(()=>({error:n.statusText}));throw new Error(c.error||"Failed to read file")}return{content:await n.text(),path:e}},async writeFile(r,t){const e=d(r),o=await fetch("/api/fs/write",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e,content:t})});if(!o.ok){const s=await o.json().catch(()=>({error:o.statusText}));throw new Error(s.error||"Failed to write file")}const n=await o.json().catch(()=>({}));return{success:!!n.success,path:typeof n.path=="string"?d(n.path):e}},async delete(r){const t=d(r),e=await fetch("/api/fs/delete",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t})});if(!e.ok){const n=await e.json().catch(()=>({error:e.statusText}));throw new Error(n.error||"Failed to delete file")}return{success:!!(await e.json().catch(()=>({}))).success}},async rename(r,t){const e=await fetch("/api/fs/rename",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({oldPath:r,newPath:t})});if(!e.ok){const n=await e.json().catch(()=>({error:e.statusText}));throw new Error(n.error||"Failed to rename file")}const o=await e.json().catch(()=>({}));return{success:!!o.success,path:typeof o.path=="string"?d(o.path):t}},async revealPath(r){const t=await fetch("/api/fs/reveal",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:d(r)})});if(!t.ok){const o=await t.json().catch(()=>({error:t.statusText}));throw new Error(o.error||"Failed to reveal path")}return{success:!!(await t.json().catch(()=>({}))).success}},async downloadFile(r){const t=d(r),e=`/api/fs/raw?path=${encodeURIComponent(t)}&download=true`,o=document.createElement("a");o.href=e,o.download=t.split("/").pop()||"file",document.body.appendChild(o),o.click(),document.body.removeChild(o)}}),K="/api/config/settings",pe="/api/config/reload",H=r=>!r||typeof r!="object"?{}:r,fe=()=>({async load(){const r=await fetch(K,{method:"GET",headers:{Accept:"application/json"}});if(!r.ok)throw new Error(`Failed to load settings: ${r.statusText}`);return{settings:H(await r.json().catch(()=>({}))),source:"web"}},async save(r){const t=await fetch(K,{method:"PUT",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(r)});if(!t.ok){const o=await t.json().catch(()=>({error:t.statusText}));throw new Error(o.error||"Failed to save settings")}return H(await t.json().catch(()=>({})))},async restartOpenCode(){const r=await fetch(pe,{method:"POST"});if(!r.ok){const t=await r.json().catch(()=>({error:r.statusText}));throw new Error(t.error||"Failed to restart OpenCode")}return{restarted:!0}}}),we=()=>({async requestDirectoryAccess(r){return{success:!0,path:r.path}},async startAccessingDirectory(r){return{success:!0}},async stopAccessingDirectory(r){return{success:!0}}}),ye=1500,me=async()=>{if(typeof navigator>"u"||!("serviceWorker"in navigator))return null;let r=null;try{r=await navigator.serviceWorker.getRegistration()??null}catch{r=null}if(r?.active)return r;if(!r)return null;try{return await Promise.race([navigator.serviceWorker.ready,new Promise(e=>{setTimeout(()=>e(null),ye)})])??r}catch{return r}},ge=async r=>{const t=await me();if(!t||typeof t.showNotification!="function")return!1;try{return await t.showNotification(r?.title??"OpenChamber",{body:r?.body,tag:r?.tag}),!0}catch(e){return console.warn("Failed to send notification via service worker",e),!1}},Te=async r=>{if(typeof Notification>"u")return console.info("Notifications not supported in this environment",r),!1;if(Notification.permission==="default"&&await Notification.requestPermission()!=="granted"||Notification.permission!=="granted")return console.warn("Notification permission not granted"),!1;try{return await ge(r)||new Notification(r?.title??"OpenChamber",{body:r?.body,tag:r?.tag}),!0}catch(t){return console.warn("Failed to send notification",t),!1}},be=async r=>{if(typeof window>"u")return!1;const t=window.__TAURI__;if(!t?.core?.invoke)return!1;try{return await t.core.invoke("desktop_notify",{payload:{title:r?.title,body:r?.body,tag:r?.tag}}),!0}catch(e){return console.warn("Failed to send native notification (tauri)",e),!1}},Se=()=>({async notifyAgentCompletion(r){return await be(r)||await Te(r)},canNotify:()=>typeof window<"u"&&window.__TAURI__?.core?.invoke?!0:typeof Notification<"u"?Notification.permission==="granted":!1}),ke=()=>({async getAvailableTools(){const r=await fetch("/api/experimental/tool/ids");if(!r.ok)throw new Error(`Tools API returned ${r.status} ${r.statusText}`);const t=await r.json();if(!Array.isArray(t))throw new Error("Tools API returned invalid data format");return t.filter(e=>typeof e=="string"&&e!=="invalid").sort()}}),v=async(r,t)=>{try{const e=await fetch(r,{...t,credentials:"include",headers:{Accept:"application/json",...t?.headers??{}}});return e.ok?await e.json():null}catch{return null}},Ee=()=>({async getVapidPublicKey(){return v("/api/push/vapid-public-key")},async subscribe(r){return v("/api/push/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)})},async unsubscribe(r){return v("/api/push/subscribe",{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)})},async setVisibility(r){return v("/api/push/visibility",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),keepalive:!0})}}),u=async r=>await r.json().catch(()=>null),je=()=>({async authStatus(){const r=await fetch("/api/github/auth/status",{method:"GET",headers:{Accept:"application/json"}}),t=await u(r);if(!r.ok||!t)throw new Error(t?.error||r.statusText||"Failed to load GitHub status");return t},async authStart(){const r=await fetch("/api/github/auth/start",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({})}),t=await u(r);if(!r.ok||!t||!("deviceCode"in t))throw new Error(t?.error||r.statusText||"Failed to start GitHub auth");return t},async authComplete(r){const t=await fetch("/api/github/auth/complete",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({deviceCode:r})}),e=await u(t);if(!t.ok||!e)throw new Error(e?.error||t.statusText||"Failed to complete GitHub auth");return e},async authDisconnect(){const r=await fetch("/api/github/auth",{method:"DELETE",headers:{Accept:"application/json"}}),t=await u(r);if(!r.ok)throw new Error(t?.error||r.statusText||"Failed to disconnect GitHub");return{removed:!!t?.removed}},async authActivate(r){const t=await fetch("/api/github/auth/activate",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({accountId:r})}),e=await u(t);if(!t.ok||!e)throw new Error(e?.error||t.statusText||"Failed to activate GitHub account");return e},async me(){const r=await fetch("/api/github/me",{method:"GET",headers:{Accept:"application/json"}}),t=await u(r);if(!r.ok||!t)throw new Error(t?.error||r.statusText||"Failed to fetch GitHub user");return t},async prStatus(r,t,e,o){const n=new URLSearchParams({directory:r,branch:t,...e?{remote:e}:{},...o?.force?{force:"true"}:{}}),s=await fetch(`/api/github/pr/status?${n.toString()}`,{method:"GET",headers:{Accept:"application/json"}}),c=await u(s);if(!s.ok||!c)throw new Error(c?.error||s.statusText||"Failed to load PR status");return c},async prCreate(r){const t=await fetch("/api/github/pr/create",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(r)}),e=await u(t);if(!t.ok||!e)throw new Error(e?.error||t.statusText||"Failed to create PR");return e},async prUpdate(r){const t=await fetch("/api/github/pr/update",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(r)}),e=await u(t);if(!t.ok||!e)throw new Error(e?.error||t.statusText||"Failed to update PR");return e},async prMerge(r){const t=await fetch("/api/github/pr/merge",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(r)}),e=await u(t);if(!t.ok||!e)throw new Error(e?.error||t.statusText||"Failed to merge PR");return e},async prReady(r){const t=await fetch("/api/github/pr/ready",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(r)}),e=await u(t);if(!t.ok||!e)throw new Error(e?.error||t.statusText||"Failed to mark PR ready");return e},async repoUpstream(r){const t=await fetch(`/api/github/repo/upstream?directory=${encodeURIComponent(r)}`,{method:"GET",headers:{Accept:"application/json"}}),e=await u(t);if(!t.ok||!e)throw new Error(e?.error||t.statusText||"Failed to detect upstream repo");return e},async repoBranches(r,t){const e=await fetch(`/api/github/repo/branches?owner=${encodeURIComponent(r)}&repo=${encodeURIComponent(t)}`,{method:"GET",headers:{Accept:"application/json"}}),o=await u(e);if(!e.ok||!o)throw new Error(o?.error||e.statusText||"Failed to fetch repo branches");return o.branches??[]},async prsList(r,t){const e=t?.page??1,o=await fetch(`/api/github/pulls/list?directory=${encodeURIComponent(r)}&page=${encodeURIComponent(String(e))}`,{method:"GET",headers:{Accept:"application/json"}}),n=await u(o);if(!o.ok||!n)throw new Error(n?.error||o.statusText||"Failed to load pull requests");return n},async prContext(r,t,e){const o=new URL("/api/github/pulls/context",window.location.origin);o.searchParams.set("directory",r),o.searchParams.set("number",String(t)),e?.includeDiff&&o.searchParams.set("diff","1"),e?.includeCheckDetails&&o.searchParams.set("checkDetails","1"),e?.sourceRepo?.owner&&e.sourceRepo.repo&&(o.searchParams.set("owner",e.sourceRepo.owner),o.searchParams.set("repo",e.sourceRepo.repo));const n=await fetch(o.toString(),{method:"GET",headers:{Accept:"application/json"}}),s=await u(n);if(!n.ok||!s)throw new Error(s?.error||n.statusText||"Failed to load pull request context");return s},async issuesList(r,t){const e=t?.page??1,o=await fetch(`/api/github/issues/list?directory=${encodeURIComponent(r)}&page=${encodeURIComponent(String(e))}`,{method:"GET",headers:{Accept:"application/json"}}),n=await u(o);if(!o.ok||!n)throw new Error(n?.error||o.statusText||"Failed to load issues");return n},async issueGet(r,t,e){const o=new URL("/api/github/issues/get",window.location.origin);o.searchParams.set("directory",r),o.searchParams.set("number",String(t)),e?.sourceRepo?.owner&&e.sourceRepo.repo&&(o.searchParams.set("owner",e.sourceRepo.owner),o.searchParams.set("repo",e.sourceRepo.repo));const n=await fetch(o.toString(),{method:"GET",headers:{Accept:"application/json"}}),s=await u(n);if(!n.ok||!s)throw new Error(s?.error||n.statusText||"Failed to load issue");return s},async issueComments(r,t,e){const o=new URL("/api/github/issues/comments",window.location.origin);o.searchParams.set("directory",r),o.searchParams.set("number",String(t)),e?.sourceRepo?.owner&&e.sourceRepo.repo&&(o.searchParams.set("owner",e.sourceRepo.owner),o.searchParams.set("repo",e.sourceRepo.repo));const n=await fetch(o.toString(),{method:"GET",headers:{Accept:"application/json"}}),s=await u(n);if(!n.ok||!s)throw new Error(s?.error||n.statusText||"Failed to load issue comments");return s}}),Ie=()=>({runtime:{platform:"web",isDesktop:!1,isVSCode:!1,label:"web"},terminal:yt(),git:ue(),files:de(),settings:fe(),permissions:we(),notifications:Se(),github:je(),push:Ee(),tools:ke()});export{se as $,oe as A,_t as B,Ut as C,Rt as D,vt as E,Jt as F,Bt as G,ae as H,Yt as I,kt as J,Et as K,Lt as L,Pe as M,Xt as N,$t as O,At as P,Nt as Q,Vt as R,Ct as S,Gt as T,ee as U,Z as V,Zt as W,Ft as X,Wt as Y,jt as Z,Qt as _,dt as a,X as a0,ie as a1,ce as a2,Ce as a3,lt as b,Ie as c,Ht as d,zt as e,ft as f,Oe as g,Fe as h,xe as i,qt as j,bt as k,St as l,Ot as m,q as n,z as o,L as p,ve as q,xt as r,re as s,te as t,Kt as u,B as v,Dt as w,le as x,Mt as y,ne as z};
1
+ (function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))o(n);new MutationObserver(n=>{for(const s of n)if(s.type==="childList")for(const c of s.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&o(c)}).observe(document,{childList:!0,subtree:!0});function e(n){const s={};return n.integrity&&(s.integrity=n.integrity),n.referrerPolicy&&(s.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?s.credentials="include":n.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function o(n){if(n.ep)return;n.ep=!0;const s=e(n);fetch(n.href,s)}})();const Y=1,f=1,j=0,V="/api/terminal/ws",tt=1200,et=250,rt=2e4,ot=5e3,P="__openchamberTerminalTransportState",nt=new TextEncoder,J=new TextDecoder,N=r=>{if(/^wss?:\/\//i.test(r))return r;if(/^https?:\/\//i.test(r)){const o=new URL(r);return o.protocol=o.protocol==="https:"?"wss:":"ws:",o.toString()}if(typeof window>"u")return"";const t=r.startsWith("/")?r:`/${r}`;return`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}${t}`},I=r=>{const t=nt.encode(JSON.stringify(r)),e=new Uint8Array(t.length+1);return e[0]=Y,e.set(t,1),e},E=r=>r?((r.transports??[]).includes("ws")||r.preferred==="ws")&&typeof r.ws?.path=="string"&&r.ws.path.length>0:!1,A=r=>r.streamCapability?.ws?.path??r.inputCapability?.ws?.path??V,st=r=>{switch(r){case"SESSION_NOT_FOUND":return new Error("Terminal session not found");case"NOT_BOUND":return new Error("Terminal session is not bound");case"WRITE_FAIL":return new Error("Failed to write to terminal");case"RATE_LIMIT":return new Error("Terminal websocket is rate limited");case"BAD_FRAME":return new Error("Terminal websocket protocol violation");default:return new Error("Terminal websocket error")}};class it{socket=null;socketUrl="";boundSessionId=null;requestedSessionId=null;openPromise=null;reconnectTimeout=null;keepaliveInterval=null;closed=!1;subscriptions=new Map;activeSubscriptionToken=null;configure(t){if(t){if(this.socketUrl===t){this.closed=!1,this.isConnectedOrConnecting()||this.ensureConnected();return}this.socketUrl=t,this.closed=!1,this.resetConnection(),this.ensureConnected()}}subscribe(t,e,o,n){const s=Symbol(t),c={token:s,sessionId:t,onEvent:e,onError:o,maxRetries:n?.maxRetries??3,initialRetryDelay:n?.initialRetryDelay??1e3,maxRetryDelay:n?.maxRetryDelay??8e3,connectionTimeout:n?.connectionTimeout??1e4,retryCount:0,connected:!1,connectionTimeoutId:null};return this.subscriptions.set(s,c),this.activeSubscriptionToken=s,this.boundSessionId=null,this.requestedSessionId=t,this.ensureConnected(),this.startConnectionTimeout(c),this.bindActiveSession(),()=>{this.clearConnectionTimeout(c),this.subscriptions.delete(s),this.activeSubscriptionToken===s&&(this.activeSubscriptionToken=null),this.boundSessionId===t&&(this.boundSessionId=null),this.requestedSessionId===t&&(this.requestedSessionId=null),this.subscriptions.size===0&&(this.clearReconnectTimeout(),this.resetConnection())}}async sendInput(t,e){if(!t||!e||this.closed||!this.socketUrl)return!1;const o=await this.getOpenSocket(tt);if(!o||o.readyState!==f)return!1;try{return this.boundSessionId!==t&&(this.requestedSessionId=t,o.send(I({t:"b",s:t,v:2}))),o.send(e),!0}catch{return this.handleSocketFailure(new Error("Terminal websocket send failed")),!1}}unbindSession(t){t&&(this.boundSessionId===t&&(this.boundSessionId=null),this.requestedSessionId===t&&(this.requestedSessionId=null))}close(){this.closed=!0,this.clearReconnectTimeout();for(const t of this.subscriptions.values())this.clearConnectionTimeout(t);this.resetConnection(),this.socketUrl="",this.subscriptions.clear(),this.activeSubscriptionToken=null}prime(){this.closed||!this.socketUrl||this.isConnectedOrConnecting()||this.ensureConnected()}isConnectedOrConnecting(t){return this.closed||t&&this.socketUrl!==t?!1:this.socket&&(this.socket.readyState===f||this.socket.readyState===j)?!0:this.openPromise!==null}getActiveSubscription(){return this.activeSubscriptionToken?this.subscriptions.get(this.activeSubscriptionToken)??null:null}startConnectionTimeout(t){this.clearConnectionTimeout(t),t.connectionTimeoutId=setTimeout(()=>{this.getActiveSubscription()?.token!==t.token||t.connected||this.handleSocketFailure(new Error("Connection timeout"))},t.connectionTimeout)}clearConnectionTimeout(t){t.connectionTimeoutId&&(clearTimeout(t.connectionTimeoutId),t.connectionTimeoutId=null)}async getOpenSocket(t){if(this.socket&&this.socket.readyState===f)return this.socket;if(this.ensureConnected(),this.socket&&this.socket.readyState===f)return this.socket;const e=await Promise.race([this.openPromise??Promise.resolve(null),new Promise(o=>{setTimeout(()=>o(null),t)})]);return e&&e.readyState===f?e:this.socket&&this.socket.readyState===f?this.socket:null}ensureConnected(){this.closed||!this.socketUrl||this.socket&&(this.socket.readyState===f||this.socket.readyState===j)||this.openPromise||(this.clearReconnectTimeout(),this.openPromise=new Promise(t=>{let e=!1,o=null;const n=s=>{e||(e=!0,o&&(clearTimeout(o),o=null),this.openPromise=null,t(s))};try{const s=new WebSocket(this.socketUrl);s.binaryType="arraybuffer",s.onopen=()=>{this.socket=s,this.startKeepalive(),n(s)},s.onmessage=c=>{this.handleSocketMessage(c.data)},s.onerror=()=>{!this.closed&&!this.getActiveSubscription()&&this.scheduleReconnect(new Error("Terminal websocket error"))},s.onclose=()=>{this.socket===s&&(this.socket=null,this.boundSessionId=null,this.stopKeepalive(),this.closed||this.scheduleReconnect(new Error("Terminal stream connection error"))),n(null)},this.socket=s,o=setTimeout(()=>{s.readyState===j&&(s.close(),n(null))},ot)}catch{n(null),this.closed||this.scheduleReconnect(new Error("Terminal websocket open failed"))}}))}bindActiveSession(){const t=this.getActiveSubscription();if(!(!t||!this.socket||this.socket.readyState!==f)){this.requestedSessionId=t.sessionId;try{this.socket.send(I({t:"b",s:t.sessionId,v:2}))}catch{this.handleSocketFailure(new Error("Terminal websocket bind failed"))}}}scheduleReconnect(t){if(this.closed||!this.socketUrl||this.reconnectTimeout)return;const e=this.getActiveSubscription();if(!e)return;const o=e.retryCount+1,n=e.initialRetryDelay,s=e.maxRetryDelay,c=e.maxRetries;if(o>c){this.clearConnectionTimeout(e),e.onError?.(t,!0);return}e.retryCount=o,e.connected=!1,e.onEvent({type:"reconnecting",attempt:o,maxAttempts:c}),this.startConnectionTimeout(e);const p=Math.min(n*Math.pow(2,Math.max(o-1,0)),s),l=Math.floor(Math.random()*et),h=p+l;this.reconnectTimeout=setTimeout(()=>{this.reconnectTimeout=null,this.ensureConnected(),this.bindActiveSession()},h)}clearReconnectTimeout(){this.reconnectTimeout&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=null)}sendControl(t){if(!this.socket||this.socket.readyState!==f)return!1;try{return this.socket.send(I(t)),!0}catch{return this.handleSocketFailure(new Error("Terminal websocket control send failed")),!1}}startKeepalive(){this.stopKeepalive(),this.keepaliveInterval=setInterval(()=>{this.closed||this.sendControl({t:"p",v:2})},rt)}stopKeepalive(){this.keepaliveInterval&&(clearInterval(this.keepaliveInterval),this.keepaliveInterval=null)}async handleSocketMessage(t){const e=await this.asUint8Array(t);if(e&&e.length>0&&e[0]===Y){this.handleControlMessage(e);return}const o=await this.asText(t);if(!o)return;const n=this.getActiveSubscription();n&&n.onEvent({type:"data",data:o})}handleControlMessage(t){if(t.length<2)return;let e;try{e=JSON.parse(J.decode(t.subarray(1)))}catch{this.handleSocketFailure(new Error("Terminal websocket control parse failed"));return}const o=this.getActiveSubscription();switch(e.t){case"ok":this.bindActiveSession();return;case"po":return;case"bok":{if(this.boundSessionId=e.s??this.requestedSessionId,!o)return;o.retryCount=0,o.connected=!0,this.clearConnectionTimeout(o),o.onEvent({type:"connected",runtime:e.runtime,ptyBackend:e.ptyBackend});return}case"x":{if(!o){this.boundSessionId=null;return}if(e.s&&e.s!==o.sessionId)return;o.connected=!1,this.clearConnectionTimeout(o),this.boundSessionId=null,this.requestedSessionId=null,o.onEvent({type:"exit",exitCode:e.exitCode,signal:e.signal??null});return}case"e":{const n=st(e.c),s=e.f===!0||e.c==="SESSION_NOT_FOUND";(e.c==="NOT_BOUND"||e.c==="SESSION_NOT_FOUND")&&(this.boundSessionId=null),o&&(o.connected=!1,s&&this.clearConnectionTimeout(o),o.onError?.(n,s)),e.f===!0&&this.handleSocketFailure(n);return}default:return}}async asUint8Array(t){if(t instanceof ArrayBuffer)return new Uint8Array(t);if(t instanceof Uint8Array)return t;if(typeof Blob<"u"&&t instanceof Blob){const e=await t.arrayBuffer();return new Uint8Array(e)}return null}async asText(t){if(typeof t=="string")return t;const e=await this.asUint8Array(t);return e?J.decode(e):""}handleSocketFailure(t){this.boundSessionId=null,this.requestedSessionId=null,this.resetConnection(),this.scheduleReconnect(t)}resetConnection(){if(this.openPromise=null,this.stopKeepalive(),this.socket){const t=this.socket;this.socket=null,t.onopen=null,t.onmessage=null,t.onerror=null,t.onclose=null,(t.readyState===f||t.readyState===j)&&t.close()}this.boundSessionId=null}}const y=()=>{const r=globalThis;return r[P]||(r[P]={inputCapability:null,streamCapability:null,manager:null}),r[P]},$=()=>{const r=y();return r.manager||(r.manager=new it),r.manager},Q=r=>{const t=y();if(t.inputCapability=r?.input??null,t.streamCapability=r?.stream??null,!E(t.inputCapability)&&!E(t.streamCapability)){t.manager?.close(),t.manager=null;return}const e=N(A(t));if(!e)return;$().configure(e)},at=async(r,t)=>{const e=await fetch(`/api/terminal/${r}/input`,{method:"POST",headers:{"Content-Type":"text/plain"},body:t});if(!e.ok){const o=await e.json().catch(()=>({error:"Failed to send terminal input"}));throw new Error(o.error||"Failed to send terminal input")}};async function ct(r){const t=await fetch("/api/terminal/create",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cwd:r.cwd,cols:r.cols??80,rows:r.rows??24})});if(!t.ok){const o=await t.json().catch(()=>({error:"Failed to create terminal"}));throw new Error(o.error||"Failed to create terminal session")}const e=await t.json();return Q(e.capabilities),e}const M=(r,t,e,o={})=>{const n=o.maxRetries??3,s=o.initialRetryDelay??1e3,c=o.maxRetryDelay??8e3,p=o.connectionTimeout??1e4;let l=null,h=0,w=null,T=null,m=!1,g=!1;const v=()=>{w&&(clearTimeout(w),w=null),T&&(clearTimeout(T),T=null)},F=()=>{m||(m=!0,v(),l&&(l.close(),l=null))},_=(S,k)=>{if(!(m||g)){if(h<n&&!k){h+=1;const b=Math.min(s*Math.pow(2,h-1),c);t({type:"reconnecting",attempt:h,maxAttempts:n}),w=setTimeout(()=>{!m&&!g&&D()},b);return}e?.(S,!0),F()}},D=()=>{if(m||g||l&&l.readyState!==EventSource.CLOSED)return;l=new EventSource(`/api/terminal/${r}/stream`);let S=!1;T=setTimeout(()=>{!S&&l?.readyState!==EventSource.OPEN&&(l?.close(),_(new Error("Connection timeout"),!1))},p),l.onopen=()=>{S||(S=!0,h=0,v(),t({type:"connected"}))},l.onmessage=k=>{try{const b=JSON.parse(k.data);b.type==="exit"&&(y().manager?.unbindSession(r),g=!0,F()),t(b)}catch(b){e?.(b,!1)}},l.onerror=()=>{v();const k=g||l?.readyState===EventSource.CLOSED;l?.close(),l=null,g||_(new Error("Terminal stream connection error"),k)}};return D(),F};function lt(r,t,e,o={}){const n=y();if(!E(n.streamCapability))return M(r,t,e,o);const s=$(),c=N(A(n));return c?(s.configure(c),s.subscribe(r,t,e,o)):M(r,t,e,o)}async function ut(r,t){const e=y();e.manager&&await e.manager.sendInput(r,t)||await at(r,t)}async function ht(r,t,e){const o=await fetch(`/api/terminal/${r}/resize`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cols:t,rows:e})});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 dt(r){y().manager?.unbindSession(r);const t=await fetch(`/api/terminal/${r}`,{method:"DELETE"});if(!t.ok){const e=await t.json().catch(()=>({error:"Failed to close terminal"}));throw new Error(e.error||"Failed to close terminal")}}async function pt(r,t){y().manager?.unbindSession(r);const e=await fetch(`/api/terminal/${r}/restart`,{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 n=await e.json().catch(()=>({error:"Failed to restart terminal"}));throw new Error(n.error||"Failed to restart terminal")}const o=await e.json();return Q(o.capabilities),o}async function ft(r){const t=await fetch("/api/terminal/force-kill",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});if(!t.ok){const e=await t.json().catch(()=>({error:"Failed to force kill terminal"}));throw new Error(e.error||"Failed to force kill terminal")}r.sessionId&&y().manager?.unbindSession(r.sessionId)}function Ce(){const r=y();if(r.inputCapability&&r.streamCapability&&!E(r.inputCapability)&&!E(r.streamCapability))return;const t=A(r)||V,e=N(t);if(!e)return;const o=$();o.isConnectedOrConnecting(e)||(o.configure(e),o.prime())}const wt=r=>{const t=r?.retry;return{maxRetries:t?.maxRetries??3,initialRetryDelay:t?.initialDelayMs??1e3,maxRetryDelay:t?.maxDelayMs??8e3,connectionTimeout:r?.connectionTimeoutMs??1e4}},yt=()=>({async createSession(r){return ct(r)},connect(r,t,e){const o=lt(r,t.onEvent,t.onError,wt(e));return{close:()=>o()}},async sendInput(r,t){await ut(r,t)},async resize(r){await ht(r.sessionId,r.cols,r.rows)},async close(r){await dt(r)},async restartSession(r,t){return pt(r,{cwd:t.cwd??"",cols:t.cols,rows:t.rows})},async forceKill(r){await ft(r)}}),mt=()=>{if(typeof window>"u")return"";const r=window.__OPENCHAMBER_DESKTOP_SERVER__?.origin;return r||window.location.origin},i="/api/git",gt=1200,Tt=5e3,U=new Map,C=new Map,W=new Map,O=new Map,R=r=>r.trim();function a(r,t,e){const o=new URL(r,mt());if(t&&o.searchParams.set("directory",t),e)for(const[n,s]of Object.entries(e))s!==void 0&&o.searchParams.set(n,String(s));return o.toString()}async function bt(r){const t=R(r),e=Date.now(),o=W.get(t);if(o&&o.expiresAt>e)return o.value;const n=O.get(t);if(n)return n;const s=(async()=>{const c=await fetch(a(`${i}/check`,r));if(!c.ok)throw new Error(`Failed to check git repository: ${c.statusText}`);const l=!!(await c.json()).isGitRepository;return W.set(t,{value:l,expiresAt:Date.now()+Tt}),l})();O.set(t,s);try{return await s}finally{O.get(t)===s&&O.delete(t)}}async function St(r,t){const e=t?.mode,o=e==="light"?`${R(r)}::light`:R(r),n=Date.now(),s=U.get(o);if(s&&s.expiresAt>n)return s.value;const c=C.get(o);if(c)return c;const p=(async()=>{const l=await fetch(a(`${i}/status`,r,e?{mode:e}:void 0));if(!l.ok)throw new Error(`Failed to get git status: ${l.statusText}`);const h=await l.json();return U.set(o,{value:h,expiresAt:Date.now()+gt}),h})();C.set(o,p);try{return await p}finally{C.get(o)===p&&C.delete(o)}}async function kt(r,t){const{path:e,staged:o,contextLines:n}=t;if(!e)throw new Error("path is required to fetch git diff");const s=await fetch(a(`${i}/diff`,r,{path:e,staged:o?"true":void 0,context:n}));if(!s.ok)throw new Error(`Failed to get git diff: ${s.statusText}`);return s.json()}async function Et(r,t){const{path:e,staged:o}=t;if(!e)throw new Error("path is required to fetch git file diff");const n=await fetch(a(`${i}/file-diff`,r,{path:e,staged:o?"true":void 0}));if(!n.ok)throw new Error(`Failed to get git file diff: ${n.statusText}`);return n.json()}async function jt(r,t){if(!t)throw new Error("path is required to revert git changes");const e=await fetch(a(`${i}/revert`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t})});if(!e.ok){const o=await e.json().catch(()=>({error:e.statusText}));throw new Error(o.error||"Failed to revert git changes")}}async function Ct(r){if(!r)return!1;const t=await fetch(a(`${i}/worktree-type`,r));if(!t.ok)throw new Error(`Failed to detect worktree type: ${t.statusText}`);return!!(await t.json()).linked}async function Ot(r){const t=await fetch(a(`${i}/branches`,r));if(!t.ok)throw new Error(`Failed to get branches: ${t.statusText}`);return t.json()}async function xt(r,t){if(!t?.branch)throw new Error("branch is required to delete a branch");const e=await fetch(a(`${i}/branches`,r),{method:"DELETE",headers:{"Content-Type":"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 delete branch")}return e.json()}async function vt(r,t){if(!t?.branch)throw new Error("branch is required to delete remote branch");const e=await fetch(a(`${i}/remote-branches`,r),{method:"DELETE",headers:{"Content-Type":"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 delete remote branch")}return e.json()}async function Ft(r,t){const e=t?.remote?.trim();if(!e)throw new Error("remote is required to remove a remote");const o=await fetch(a(`${i}/remotes`,r),{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({remote:e})});if(!o.ok){const n=await o.json().catch(()=>({error:o.statusText}));throw new Error(n.error||"Failed to remove remote")}return o.json()}async function Pt(r,t,e){if(!Array.isArray(t)||t.length===0)throw new Error("No files provided to generate commit message");const o={files:t};e?.zenModel&&(o.zenModel=e.zenModel),e?.providerId&&(o.providerId=e.providerId),e?.modelId&&(o.modelId=e.modelId);const n=await fetch(a(`${i}/commit-message`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o)});if(!n.ok){const l=await n.json().catch(()=>({error:n.statusText}));console.error("[git-generation][browser] http error",{status:n.status,statusText:n.statusText,error:l});const h=typeof l?.traceId=="string"&&l.traceId?` (traceId: ${l.traceId})`:"";throw new Error(`${l.error||"Failed to generate commit message"}${h}`)}const s=await n.json();if(!s?.message||typeof s.message!="object")throw new Error("Malformed commit generation response");const c=typeof s.message.subject=="string"&&s.message.subject.trim().length>0?s.message.subject.trim():"",p=Array.isArray(s.message.highlights)?s.message.highlights.filter(l=>typeof l=="string"&&l.trim().length>0).map(l=>l.trim()):[];return{message:{subject:c,highlights:p}}}async function It(r,t){const{base:e,head:o,context:n,zenModel:s,providerId:c,modelId:p}=t;if(!e||!o)throw new Error("base and head are required");const l={base:e,head:o};n?.trim()&&(l.context=n.trim()),s&&(l.zenModel=s),c&&(l.providerId=c),p&&(l.modelId=p);const h=await fetch(a(`${i}/pr-description`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)});if(!h.ok){const g=await h.json().catch(()=>({error:h.statusText}));throw new Error(g.error||"Failed to generate PR description")}const w=await h.json().catch(()=>null),T=typeof w?.title=="string"?w.title:"",m=typeof w?.body=="string"?w.body:"";if(!T&&!m)throw new Error("Malformed PR description response");return{title:T,body:m}}async function L(r){const t=await fetch(a(`${i}/worktrees`,r));if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to list worktrees")}return t.json()}async function B(r,t){const e=await fetch(a(`${i}/worktrees/validate`,r),{method:"POST",headers:{"Content-Type":"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 validate worktree")}return e.json()}async function Oe(r){const t=await fetch(a(`${i}/worktrees/bootstrap-status`,r));if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to get worktree bootstrap status")}return t.json()}async function xe(r,t){const e=await fetch(a(`${i}/worktrees/preview`,r),{method:"POST",headers:{"Content-Type":"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 preview worktree")}return e.json()}async function q(r,t){const e=await fetch(a(`${i}/worktrees`,r),{method:"POST",headers:{"Content-Type":"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 create worktree")}return e.json()}async function z(r,t){const e=await fetch(a(`${i}/worktrees`,r),{method:"DELETE",headers:{"Content-Type":"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 delete worktree")}return e.json()}async function Rt(r,t,e={}){const o=await fetch(a(`${i}/commit`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:t,addAll:e.addAll??!1,files:e.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 Nt(r,t={}){const e=await fetch(a(`${i}/push`,r),{method:"POST",headers:{"Content-Type":"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 push")}return e.json()}async function At(r,t={}){const e=await fetch(a(`${i}/pull`,r),{method:"POST",headers:{"Content-Type":"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 pull")}return e.json()}async function $t(r,t={}){const e=await fetch(a(`${i}/fetch`,r),{method:"POST",headers:{"Content-Type":"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 fetch")}return e.json()}async function Gt(r){const t=await fetch(a(`${i}/stashes`,r));if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to list stashes")}return t.json()}async function _t(r,t){const e=await fetch(a(`${i}/stashes/file-counts`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refs:t})});if(!e.ok){const o=await e.json().catch(()=>({error:e.statusText}));throw new Error(o.error||"Failed to count stash files")}return e.json()}async function X(r,t={}){const e=await fetch(a(`${i}/stash`,r),{method:"POST",headers:{"Content-Type":"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 stash changes")}return e.json()}const G=async(r,t,e)=>{const o=await fetch(a(`${i}/${t}`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!o.ok){const n=await o.json().catch(()=>({error:o.statusText}));throw new Error(n.error||`Failed to ${t}`)}return o.json()},Dt=(r,t)=>G(r,"stash/apply",t),Z=(r,t)=>G(r,"stash/pop",t),Jt=(r,t)=>G(r,"stash/drop",t);async function Mt(r,t){const e=await fetch(a(`${i}/checkout`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({branch:t})});if(!e.ok){const o=await e.json().catch(()=>({error:e.statusText}));throw new Error(o.error||"Failed to checkout branch")}return e.json()}async function Ut(r,t,e){const o=await fetch(a(`${i}/branches`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:t,startPoint:e})});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 Wt(r,t,e){const o=await fetch(a(`${i}/branches/rename`,r),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({oldName:t,newName:e})});if(!o.ok){const n=await o.json().catch(()=>({error:o.statusText}));throw new Error(n.error||"Failed to rename branch")}return o.json()}async function Lt(r,t={}){const e=await fetch(a(`${i}/log`,r,{maxCount:t.maxCount,from:t.from,to:t.to,file:t.file}));if(!e.ok){const o=await e.json().catch(()=>({error:e.statusText}));throw new Error(`Failed to get git log: ${o.error||e.statusText}`)}return e.json()}async function Bt(r,t){const e=await fetch(a(`${i}/commit-files`,r,{hash:t}));if(!e.ok)throw new Error(`Failed to get commit files: ${e.statusText}`);return e.json()}async function ve(r,t,e,o){const n=await fetch(a(`${i}/commit-file-diff`,r,{hash:t,path:e,binary:o?"true":void 0}));if(!n.ok)throw new Error(`Failed to get commit file diff: ${n.statusText}`);return n.json()}async function qt(){const r=await fetch(a(`${i}/identities`,void 0));if(!r.ok)throw new Error(`Failed to get git identities: ${r.statusText}`);return r.json()}async function zt(r){const t=await fetch(a(`${i}/identities`,void 0),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to create git identity")}return t.json()}async function Kt(r,t){const e=await fetch(a(`${i}/identities/${r}`,void 0),{method:"PUT",headers:{"Content-Type":"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 update git identity")}return e.json()}async function Ht(r){const t=await fetch(a(`${i}/identities/${r}`,void 0),{method:"DELETE"});if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to delete git identity")}}async function Yt(r){if(!r)return null;const t=await fetch(a(`${i}/current-identity`,r));if(!t.ok)throw new Error(`Failed to get current git identity: ${t.statusText}`);const e=await t.json();return e?{userName:e.userName??null,userEmail:e.userEmail??null,sshCommand:e.sshCommand??null}:null}async function Vt(r){if(!r)return!1;const t=await fetch(a(`${i}/has-local-identity`,r));if(!t.ok)throw new Error(`Failed to check local identity: ${t.statusText}`);return(await t.json().catch(()=>null))?.hasLocalIdentity===!0}async function Fe(){const r=await fetch(a(`${i}/global-identity`,void 0));if(!r.ok)throw new Error(`Failed to get global git identity: ${r.statusText}`);const t=await r.json();return!t||!t.userName&&!t.userEmail?null:{userName:t.userName??null,userEmail:t.userEmail??null,sshCommand:t.sshCommand??null}}async function Qt(r,t){const e=await fetch(a(`${i}/set-identity`,r),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({profileId:t})});if(!e.ok){const o=await e.json().catch(()=>({error:e.statusText}));throw new Error(o.error||"Failed to set git identity")}return e.json()}async function Pe(){const r=await fetch(a(`${i}/discover-credentials`,void 0));if(!r.ok)throw new Error(`Failed to discover git credentials: ${r.statusText}`);return r.json()}async function Ie(r,t){if(!r)return null;const e=await fetch(a(`${i}/remote-url`,r,{remote:t}));return e.ok?(await e.json()).url??null:null}async function Xt(r){const t=await fetch(a(`${i}/remotes`,r));if(!t.ok)throw new Error(`Failed to get remotes: ${t.statusText}`);return t.json()}async function Zt(r,t){const e=await fetch(a(`${i}/rebase`,r),{method:"POST",headers:{"Content-Type":"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 rebase")}return e.json()}async function te(r){const t=await fetch(a(`${i}/rebase/abort`,r),{method:"POST"});if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to abort rebase")}return t.json()}async function ee(r,t){const e=await fetch(a(`${i}/merge`,r),{method:"POST",headers:{"Content-Type":"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 merge")}return e.json()}async function re(r){const t=await fetch(a(`${i}/merge/abort`,r),{method:"POST"});if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to abort merge")}return t.json()}async function oe(r){const t=await fetch(a(`${i}/rebase/continue`,r),{method:"POST"});if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to continue rebase")}return t.json()}async function ne(r){const t=await fetch(a(`${i}/merge/continue`,r),{method:"POST"});if(!t.ok){const e=await t.json().catch(()=>({error:t.statusText}));throw new Error(e.error||"Failed to continue merge")}return t.json()}async function se(r,t){return await X(r,{message:t?.message}),{success:!0}}async function ie(r){return await Z(r,{ref:"stash@{0}"}),{success:!0}}async function ae(r){const t=await fetch(a(`${i}/conflict-details`,r));if(!t.ok)throw new Error(`Failed to get conflict details: ${t.statusText}`);return t.json()}async function ce(r,t){const e=await fetch(`${i}/validate-directory`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({directory:r,worktreeRoot:t})});if(!e.ok)throw new Error(`Failed to validate worktree directory: ${e.statusText}`);return e.json()}async function le(r){const t=await fetch(`${i}/canonicalize-worktree-state`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({directory:r})});if(!t.ok)throw new Error(`Failed to canonicalize worktree state: ${t.statusText}`);return t.json()}const ue=()=>({checkIsGitRepository:bt,getGitStatus:St,getGitDiff:kt,getGitFileDiff:Et,revertGitFile:jt,isLinkedWorktree:Ct,getGitBranches:Ot,deleteGitBranch:xt,deleteRemoteBranch:vt,removeRemote:Ft,generateCommitMessage:Pt,generatePullRequestDescription:It,listGitWorktrees:L,validateGitWorktree:B,createGitWorktree:q,deleteGitWorktree:z,validateWorktreeDirectory:ce,canonicalizeWorktreeState:le,createGitCommit(r,t,e){return Rt(r,t,e)},gitPush:Nt,gitPull:At,gitFetch:$t,listGitStashes:Gt,countGitStashFiles:_t,stashGitChanges:X,applyGitStash:Dt,popGitStash:Z,dropGitStash:Jt,checkoutBranch:Mt,createBranch:Ut,renameBranch:Wt,getGitLog(r,t){return Lt(r,t)},getCommitFiles:Bt,getCurrentGitIdentity:Yt,hasLocalIdentity:Vt,setGitIdentity:Qt,getGitIdentities:qt,createGitIdentity:zt,updateGitIdentity:Kt,deleteGitIdentity:Ht,getRemotes:Xt,rebase:Zt,abortRebase:te,continueRebase:oe,merge:ee,abortMerge:re,continueMerge:ne,stash:se,stashPop:ie,getConflictDetails:ae,worktree:{list:L,validate:B,create:q,remove:z}}),d=r=>r.replace(/\\/g,"/"),he=(r,t)=>{const e=d(t?.directory||t?.path||r),o=Array.isArray(t?.entries)?t.entries:[];return{directory:e,entries:o.filter(n=>!!(n&&typeof n.name=="string"&&typeof n.path=="string")).map(n=>({name:n.name,path:d(n.path),isDirectory:!!n.isDirectory}))}},de=()=>({async listDirectory(r){const t=d(r),e=new URLSearchParams;t&&e.set("path",t);const o=await fetch(`/api/fs/list${e.toString()?`?${e.toString()}`:""}`);if(!o.ok){const s=await o.json().catch(()=>({error:o.statusText}));throw new Error(s.error||"Failed to list directory")}const n=await o.json();return he(t,n)},async search(r){const t=new URLSearchParams,e=d(r.directory);e&&t.set("directory",e),t.set("query",r.query),t.set("dirs","false"),t.set("type","file"),typeof r.maxResults=="number"&&Number.isFinite(r.maxResults)&&t.set("limit",String(r.maxResults));const o=await fetch(`/api/find/file?${t.toString()}`);if(!o.ok){const c=await o.json().catch(()=>({error:o.statusText}));throw new Error(c.error||"Failed to search files")}const n=await o.json();return(Array.isArray(n)?n:[]).map(c=>({path:d(`${e}/${c}`),preview:[d(c)]}))},async createDirectory(r){const t=d(r),e=await fetch("/api/fs/mkdir",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t})});if(!e.ok){const n=await e.json().catch(()=>({error:e.statusText}));throw new Error(n.error||"Failed to create directory")}const o=await e.json();return{success:!!o?.success,path:typeof o?.path=="string"?d(o.path):t}},async statFile(r,t){const e=d(r),o=new URLSearchParams({path:e});t?.allowOutsideWorkspace&&o.set("allowOutsideWorkspace","true");const n=await fetch(`/api/fs/stat?${o.toString()}`);if(!n.ok){const c=await n.json().catch(()=>({error:n.statusText}));throw new Error(c.error||"Failed to stat file")}const s=await n.json().catch(()=>({}));return{path:typeof s.path=="string"?d(s.path):e,isFile:!!s.isFile,size:typeof s.size=="number"?s.size:0,mtimeMs:typeof s.mtimeMs=="number"?s.mtimeMs:void 0}},async readFile(r,t){const e=d(r),o=new URLSearchParams({path:e});t?.allowOutsideWorkspace&&o.set("allowOutsideWorkspace","true"),t?.optional&&o.set("optional","true");const n=await fetch(`/api/fs/read?${o.toString()}`,{cache:t?.optional?"no-store":"default"});if(!n.ok){const c=await n.json().catch(()=>({error:n.statusText}));throw new Error(c.error||"Failed to read file")}return{content:await n.text(),path:e}},async writeFile(r,t){const e=d(r),o=await fetch("/api/fs/write",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e,content:t})});if(!o.ok){const s=await o.json().catch(()=>({error:o.statusText}));throw new Error(s.error||"Failed to write file")}const n=await o.json().catch(()=>({}));return{success:!!n.success,path:typeof n.path=="string"?d(n.path):e}},async delete(r){const t=d(r),e=await fetch("/api/fs/delete",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t})});if(!e.ok){const n=await e.json().catch(()=>({error:e.statusText}));throw new Error(n.error||"Failed to delete file")}return{success:!!(await e.json().catch(()=>({}))).success}},async rename(r,t){const e=await fetch("/api/fs/rename",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({oldPath:r,newPath:t})});if(!e.ok){const n=await e.json().catch(()=>({error:e.statusText}));throw new Error(n.error||"Failed to rename file")}const o=await e.json().catch(()=>({}));return{success:!!o.success,path:typeof o.path=="string"?d(o.path):t}},async revealPath(r){const t=await fetch("/api/fs/reveal",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:d(r)})});if(!t.ok){const o=await t.json().catch(()=>({error:t.statusText}));throw new Error(o.error||"Failed to reveal path")}return{success:!!(await t.json().catch(()=>({}))).success}},async downloadFile(r){const t=d(r),e=`/api/fs/raw?path=${encodeURIComponent(t)}&download=true`,o=document.createElement("a");o.href=e,o.download=t.split("/").pop()||"file",document.body.appendChild(o),o.click(),document.body.removeChild(o)}}),K="/api/config/settings",pe="/api/config/reload",H=r=>!r||typeof r!="object"?{}:r,fe=()=>({async load(){const r=await fetch(K,{method:"GET",headers:{Accept:"application/json"}});if(!r.ok)throw new Error(`Failed to load settings: ${r.statusText}`);return{settings:H(await r.json().catch(()=>({}))),source:"web"}},async save(r){const t=await fetch(K,{method:"PUT",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(r)});if(!t.ok){const o=await t.json().catch(()=>({error:t.statusText}));throw new Error(o.error||"Failed to save settings")}return H(await t.json().catch(()=>({})))},async restartOpenCode(){const r=await fetch(pe,{method:"POST"});if(!r.ok){const t=await r.json().catch(()=>({error:r.statusText}));throw new Error(t.error||"Failed to restart OpenCode")}return{restarted:!0}}}),we=()=>({async requestDirectoryAccess(r){return{success:!0,path:r.path}},async startAccessingDirectory(r){return{success:!0}},async stopAccessingDirectory(r){return{success:!0}}}),ye=1500,me=async()=>{if(typeof navigator>"u"||!("serviceWorker"in navigator))return null;let r=null;try{r=await navigator.serviceWorker.getRegistration()??null}catch{r=null}if(r?.active)return r;if(!r)return null;try{return await Promise.race([navigator.serviceWorker.ready,new Promise(e=>{setTimeout(()=>e(null),ye)})])??r}catch{return r}},ge=async r=>{const t=await me();if(!t||typeof t.showNotification!="function")return!1;try{return await t.showNotification(r?.title??"OpenChamber",{body:r?.body,tag:r?.tag}),!0}catch(e){return console.warn("Failed to send notification via service worker",e),!1}},Te=async r=>{if(typeof Notification>"u")return console.info("Notifications not supported in this environment",r),!1;if(Notification.permission==="default"&&await Notification.requestPermission()!=="granted"||Notification.permission!=="granted")return console.warn("Notification permission not granted"),!1;try{return await ge(r)||new Notification(r?.title??"OpenChamber",{body:r?.body,tag:r?.tag}),!0}catch(t){return console.warn("Failed to send notification",t),!1}},be=async r=>{if(typeof window>"u")return!1;const t=window.__TAURI__;if(!t?.core?.invoke)return!1;try{return await t.core.invoke("desktop_notify",{payload:{title:r?.title,body:r?.body,tag:r?.tag}}),!0}catch(e){return console.warn("Failed to send native notification (tauri)",e),!1}},Se=()=>({async notifyAgentCompletion(r){return await be(r)||await Te(r)},canNotify:()=>typeof window<"u"&&window.__TAURI__?.core?.invoke?!0:typeof Notification<"u"?Notification.permission==="granted":!1}),ke=()=>({async getAvailableTools(){const r=await fetch("/api/experimental/tool/ids");if(!r.ok)throw new Error(`Tools API returned ${r.status} ${r.statusText}`);const t=await r.json();if(!Array.isArray(t))throw new Error("Tools API returned invalid data format");return t.filter(e=>typeof e=="string"&&e!=="invalid").sort()}}),x=async(r,t)=>{try{const e=await fetch(r,{...t,credentials:"include",headers:{Accept:"application/json",...t?.headers??{}}});return e.ok?await e.json():null}catch{return null}},Ee=()=>({async getVapidPublicKey(){return x("/api/push/vapid-public-key")},async subscribe(r){return x("/api/push/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)})},async unsubscribe(r){return x("/api/push/subscribe",{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)})},async setVisibility(r){return x("/api/push/visibility",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),keepalive:!0})}}),u=async r=>await r.json().catch(()=>null),je=()=>({async authStatus(){const r=await fetch("/api/github/auth/status",{method:"GET",headers:{Accept:"application/json"}}),t=await u(r);if(!r.ok||!t)throw new Error(t?.error||r.statusText||"Failed to load GitHub status");return t},async authStart(){const r=await fetch("/api/github/auth/start",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({})}),t=await u(r);if(!r.ok||!t||!("deviceCode"in t))throw new Error(t?.error||r.statusText||"Failed to start GitHub auth");return t},async authComplete(r){const t=await fetch("/api/github/auth/complete",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({deviceCode:r})}),e=await u(t);if(!t.ok||!e)throw new Error(e?.error||t.statusText||"Failed to complete GitHub auth");return e},async authDisconnect(){const r=await fetch("/api/github/auth",{method:"DELETE",headers:{Accept:"application/json"}}),t=await u(r);if(!r.ok)throw new Error(t?.error||r.statusText||"Failed to disconnect GitHub");return{removed:!!t?.removed}},async authActivate(r){const t=await fetch("/api/github/auth/activate",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({accountId:r})}),e=await u(t);if(!t.ok||!e)throw new Error(e?.error||t.statusText||"Failed to activate GitHub account");return e},async me(){const r=await fetch("/api/github/me",{method:"GET",headers:{Accept:"application/json"}}),t=await u(r);if(!r.ok||!t)throw new Error(t?.error||r.statusText||"Failed to fetch GitHub user");return t},async prStatus(r,t,e,o){const n=new URLSearchParams({directory:r,branch:t,...e?{remote:e}:{},...o?.force?{force:"true"}:{}}),s=await fetch(`/api/github/pr/status?${n.toString()}`,{method:"GET",headers:{Accept:"application/json"}}),c=await u(s);if(!s.ok||!c)throw new Error(c?.error||s.statusText||"Failed to load PR status");return c},async prCreate(r){const t=await fetch("/api/github/pr/create",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(r)}),e=await u(t);if(!t.ok||!e)throw new Error(e?.error||t.statusText||"Failed to create PR");return e},async prUpdate(r){const t=await fetch("/api/github/pr/update",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(r)}),e=await u(t);if(!t.ok||!e)throw new Error(e?.error||t.statusText||"Failed to update PR");return e},async prMerge(r){const t=await fetch("/api/github/pr/merge",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(r)}),e=await u(t);if(!t.ok||!e)throw new Error(e?.error||t.statusText||"Failed to merge PR");return e},async prReady(r){const t=await fetch("/api/github/pr/ready",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(r)}),e=await u(t);if(!t.ok||!e)throw new Error(e?.error||t.statusText||"Failed to mark PR ready");return e},async repoUpstream(r){const t=await fetch(`/api/github/repo/upstream?directory=${encodeURIComponent(r)}`,{method:"GET",headers:{Accept:"application/json"}}),e=await u(t);if(!t.ok||!e)throw new Error(e?.error||t.statusText||"Failed to detect upstream repo");return e},async repoBranches(r,t){const e=await fetch(`/api/github/repo/branches?owner=${encodeURIComponent(r)}&repo=${encodeURIComponent(t)}`,{method:"GET",headers:{Accept:"application/json"}}),o=await u(e);if(!e.ok||!o)throw new Error(o?.error||e.statusText||"Failed to fetch repo branches");return o.branches??[]},async prsList(r,t){const e=t?.page??1,o=await fetch(`/api/github/pulls/list?directory=${encodeURIComponent(r)}&page=${encodeURIComponent(String(e))}`,{method:"GET",headers:{Accept:"application/json"}}),n=await u(o);if(!o.ok||!n)throw new Error(n?.error||o.statusText||"Failed to load pull requests");return n},async prContext(r,t,e){const o=new URL("/api/github/pulls/context",window.location.origin);o.searchParams.set("directory",r),o.searchParams.set("number",String(t)),e?.includeDiff&&o.searchParams.set("diff","1"),e?.includeCheckDetails&&o.searchParams.set("checkDetails","1"),e?.sourceRepo?.owner&&e.sourceRepo.repo&&(o.searchParams.set("owner",e.sourceRepo.owner),o.searchParams.set("repo",e.sourceRepo.repo));const n=await fetch(o.toString(),{method:"GET",headers:{Accept:"application/json"}}),s=await u(n);if(!n.ok||!s)throw new Error(s?.error||n.statusText||"Failed to load pull request context");return s},async issuesList(r,t){const e=t?.page??1,o=await fetch(`/api/github/issues/list?directory=${encodeURIComponent(r)}&page=${encodeURIComponent(String(e))}`,{method:"GET",headers:{Accept:"application/json"}}),n=await u(o);if(!o.ok||!n)throw new Error(n?.error||o.statusText||"Failed to load issues");return n},async issueGet(r,t,e){const o=new URL("/api/github/issues/get",window.location.origin);o.searchParams.set("directory",r),o.searchParams.set("number",String(t)),e?.sourceRepo?.owner&&e.sourceRepo.repo&&(o.searchParams.set("owner",e.sourceRepo.owner),o.searchParams.set("repo",e.sourceRepo.repo));const n=await fetch(o.toString(),{method:"GET",headers:{Accept:"application/json"}}),s=await u(n);if(!n.ok||!s)throw new Error(s?.error||n.statusText||"Failed to load issue");return s},async issueComments(r,t,e){const o=new URL("/api/github/issues/comments",window.location.origin);o.searchParams.set("directory",r),o.searchParams.set("number",String(t)),e?.sourceRepo?.owner&&e.sourceRepo.repo&&(o.searchParams.set("owner",e.sourceRepo.owner),o.searchParams.set("repo",e.sourceRepo.repo));const n=await fetch(o.toString(),{method:"GET",headers:{Accept:"application/json"}}),s=await u(n);if(!n.ok||!s)throw new Error(s?.error||n.statusText||"Failed to load issue comments");return s}}),Re=()=>({runtime:{platform:"web",isDesktop:!1,isVSCode:!1,label:"web"},terminal:yt(),git:ue(),files:de(),settings:fe(),permissions:we(),notifications:Se(),github:je(),push:Ee(),tools:ke()});export{Qt as $,oe as A,_t as B,Ut as C,Rt as D,xt as E,Jt as F,ve as G,Bt as H,ae as I,Yt as J,kt as K,Et as L,Lt as M,Ie as N,Xt as O,$t as P,At as Q,Nt as R,Vt as S,Ct as T,Gt as U,ee as V,Z as W,Zt as X,Ft as Y,Wt as Z,jt as _,dt as a,se as a0,X as a1,ie as a2,ce as a3,Ce as a4,lt as b,Re as c,Ht as d,zt as e,ft as f,Oe as g,Pe as h,Fe as i,qt as j,bt as k,St as l,Ot as m,q as n,z as o,L as p,xe as q,vt as r,re as s,te as t,Kt as u,B as v,Dt as w,le as x,Mt as y,ne as z};