junhost 0.2.2 → 0.2.5

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 (140) hide show
  1. package/dist/browser-mcp-server.js +1 -1
  2. package/dist/index.js +58 -59
  3. package/dist/mcp-server.js +11 -11
  4. package/package.json +1 -1
  5. package/ui-dist/assets/BrowserPage-BGBh4z-R.js +1 -0
  6. package/ui-dist/assets/DashboardPage-p5NKjE2b.js +1 -0
  7. package/ui-dist/assets/FilesPage-DhvtFQSF.js +64 -0
  8. package/ui-dist/assets/FormContext-CdQ9sDWR.js +1 -0
  9. package/ui-dist/assets/LogsPage-7aaauFsL.js +1 -0
  10. package/ui-dist/assets/McpPage-DtbL2uXL.js +1 -0
  11. package/ui-dist/assets/MemoriesPage-w0MWI88A.js +1 -0
  12. package/ui-dist/assets/{RunsPage-D0xR47tG.js → RunsPage-BNrvTKxB.js} +50 -50
  13. package/ui-dist/assets/SchedulesPage-BYsWhL4b.js +1 -0
  14. package/ui-dist/assets/SettingsPage-BVUtUDq9.js +1 -0
  15. package/ui-dist/assets/SkillsPage-C3SE9cvn.js +1 -0
  16. package/ui-dist/assets/api-DTaM-PBA.js +1 -0
  17. package/ui-dist/assets/architecture-7EHR7CIX-oae14Sjp.js +1 -0
  18. package/ui-dist/assets/{architectureDiagram-3BPJPVTR-k2gsD5OO.js → architectureDiagram-3BPJPVTR-CLvALvWH.js} +1 -1
  19. package/ui-dist/assets/badge-Czi0QcSt.js +1 -0
  20. package/ui-dist/assets/{blockDiagram-GPEHLZMM-DW56ELL9.js → blockDiagram-GPEHLZMM-agZaaW3b.js} +1 -1
  21. package/ui-dist/assets/button-C5SbvNQM.js +1 -0
  22. package/ui-dist/assets/{c4Diagram-AAUBKEIU-a19n5MC0.js → c4Diagram-AAUBKEIU-BtGNvFTN.js} +1 -1
  23. package/ui-dist/assets/channel-BJilWGHp.js +1 -0
  24. package/ui-dist/assets/checkbox-OXJcAFyD.js +1 -0
  25. package/ui-dist/assets/{chunk-2J33WTMH-Dq1oKvzF.js → chunk-2J33WTMH-Bz0Lx4CH.js} +1 -1
  26. package/ui-dist/assets/{chunk-3OPIFGDE-DOjepp5u.js → chunk-3OPIFGDE-DlqezFBL.js} +1 -1
  27. package/ui-dist/assets/{chunk-5ZQYHXKU-DQd7S-DN.js → chunk-5ZQYHXKU-06bRImiz.js} +1 -1
  28. package/ui-dist/assets/{chunk-727SXJPM-ZC51AjIP.js → chunk-727SXJPM-BACu39ui.js} +1 -1
  29. package/ui-dist/assets/{chunk-AQP2D5EJ-CWf39VtR.js → chunk-AQP2D5EJ-Chjw9I_j.js} +1 -1
  30. package/ui-dist/assets/{chunk-BO2N2NFS-HkysRQLG.js → chunk-BO2N2NFS-BH2X3sir.js} +4 -4
  31. package/ui-dist/assets/{chunk-CSCIHK7Q-Bbq9a-f4.js → chunk-CSCIHK7Q-cNr3wQ4T.js} +3 -3
  32. package/ui-dist/assets/{chunk-KSCS5N6A-BKp-kveo.js → chunk-KSCS5N6A-C0xPXGha.js} +1 -1
  33. package/ui-dist/assets/{chunk-L5ZTLDWV-C8BqtMre.js → chunk-L5ZTLDWV-CoUNWrar.js} +1 -1
  34. package/ui-dist/assets/{chunk-LZXEDZCA-Diyjko3L.js → chunk-LZXEDZCA-DPQ-Ldy1.js} +2 -2
  35. package/ui-dist/assets/{chunk-ND2GUHAM-BV6JTPNQ.js → chunk-ND2GUHAM-u6TfxADn.js} +1 -1
  36. package/ui-dist/assets/{chunk-NZK2D7GU-CB-RR-1q.js → chunk-NZK2D7GU-C1GtSkoM.js} +1 -1
  37. package/ui-dist/assets/{chunk-O5CBEL6O-Zyg3pbBu.js → chunk-O5CBEL6O-Di3YbCi3.js} +1 -1
  38. package/ui-dist/assets/{chunk-WU5MYG2G-CPYS59Yv.js → chunk-WU5MYG2G-C6fBWWCO.js} +1 -1
  39. package/ui-dist/assets/{circle-x-BSTd_gmE.js → circle-x-CAsSuVme.js} +1 -1
  40. package/ui-dist/assets/classDiagram-4FO5ZUOK-D9QMu2xp.js +1 -0
  41. package/ui-dist/assets/classDiagram-v2-Q7XG4LA2-D9QMu2xp.js +1 -0
  42. package/ui-dist/assets/collapsible-Dgd4Palj.js +1 -0
  43. package/ui-dist/assets/{dagre-BM42HDAG-B0nNmf3c.js → dagre-BM42HDAG-A8Y6yGN2.js} +1 -1
  44. package/ui-dist/assets/{diagram-2AECGRRQ-CmnP-Pwj.js → diagram-2AECGRRQ-CSy7jejs.js} +1 -1
  45. package/ui-dist/assets/{diagram-5GNKFQAL-DoplqwrH.js → diagram-5GNKFQAL-D00SleZk.js} +1 -1
  46. package/ui-dist/assets/{diagram-KO2AKTUF-C82yVEmF.js → diagram-KO2AKTUF-Bzkz5rYI.js} +1 -1
  47. package/ui-dist/assets/{diagram-LMA3HP47-CVf08v2e.js → diagram-LMA3HP47-C2enmWGa.js} +1 -1
  48. package/ui-dist/assets/{diagram-OG6HWLK6-GN7yiGuE.js → diagram-OG6HWLK6-SEm482Ky.js} +1 -1
  49. package/ui-dist/assets/dialog-BypJveGC.js +1 -0
  50. package/ui-dist/assets/{erDiagram-TEJ5UH35-1_XoHZAp.js → erDiagram-TEJ5UH35-D5-7flX_.js} +1 -1
  51. package/ui-dist/assets/eventmodeling-FCH6USID-Bxy3erui.js +1 -0
  52. package/ui-dist/assets/{external-link-DiZ5uX5z.js → external-link-DCXGJhiP.js} +1 -1
  53. package/ui-dist/assets/{flowDiagram-I6XJVG4X-c8jaDuzg.js → flowDiagram-I6XJVG4X-D6Kk1UFg.js} +1 -1
  54. package/ui-dist/assets/{ganttDiagram-6RSMTGT7-Ck7UsWeu.js → ganttDiagram-6RSMTGT7-SvRvoSwm.js} +1 -1
  55. package/ui-dist/assets/{gitGraph-WXDBUCRP-sFX7u0r_.js → gitGraph-WXDBUCRP-M4xvAR7q.js} +1 -1
  56. package/ui-dist/assets/{gitGraphDiagram-PVQCEYII-DSvNtio2.js → gitGraphDiagram-PVQCEYII-CsnXODOl.js} +1 -1
  57. package/ui-dist/assets/{highlighted-body-OFNGDK62-DesBT53i.js → highlighted-body-OFNGDK62-DHE0Z04J.js} +1 -1
  58. package/ui-dist/assets/index-BCipkFMc.js +12 -0
  59. package/ui-dist/assets/{index-CZzHSXB1.css → index-DEggNXsI.css} +1 -1
  60. package/ui-dist/assets/{info-J43DQDTF-Lf1TcbL5.js → info-J43DQDTF-DJfbaKer.js} +1 -1
  61. package/ui-dist/assets/{infoDiagram-5YYISTIA-CMVUnYwe.js → infoDiagram-5YYISTIA-ykgWzX2_.js} +1 -1
  62. package/ui-dist/assets/input-pcSINvE3.js +1 -0
  63. package/ui-dist/assets/{ishikawaDiagram-YF4QCWOH-8CQOcn5a.js → ishikawaDiagram-YF4QCWOH-CWlbevKa.js} +1 -1
  64. package/ui-dist/assets/{journeyDiagram-JHISSGLW-CrgcWtuA.js → journeyDiagram-JHISSGLW-Co9hkrSV.js} +1 -1
  65. package/ui-dist/assets/{kanban-definition-UN3LZRKU-DM4XwTkG.js → kanban-definition-UN3LZRKU-BqYnrzvT.js} +1 -1
  66. package/ui-dist/assets/katex-DzkW7LcA.js +1 -0
  67. package/ui-dist/assets/{key-round-D965pLEl.js → key-round-i_iJarVP.js} +1 -1
  68. package/ui-dist/assets/label-Bu19spuB.js +1 -0
  69. package/ui-dist/assets/{line-8DyrseaS.js → line-De084cjd.js} +1 -1
  70. package/ui-dist/assets/mermaid-GHXKKRXX-CD13uw1J.js +1 -0
  71. package/ui-dist/assets/{mermaid-parser.core-BflpgWAW.js → mermaid-parser.core-BgxY7hnP.js} +2 -2
  72. package/ui-dist/assets/{mindmap-definition-RKZ34NQL-Bjgr9zoF.js → mindmap-definition-RKZ34NQL-LkEZGFmn.js} +1 -1
  73. package/ui-dist/assets/{packet-YPE3B663-BhtAK3Ll.js → packet-YPE3B663-BkDiC9SL.js} +1 -1
  74. package/ui-dist/assets/{pause-h76ixDr5.js → pause-DhMeMeEd.js} +1 -1
  75. package/ui-dist/assets/{pie-LRSECV5Y-BsSRI3VF.js → pie-LRSECV5Y-C89oa4ep.js} +1 -1
  76. package/ui-dist/assets/{pieDiagram-4H26LBE5-Bp52danX.js → pieDiagram-4H26LBE5-dPB1x16f.js} +1 -1
  77. package/ui-dist/assets/play-D3mjFMmX.js +1 -0
  78. package/ui-dist/assets/{quadrantDiagram-W4KKPZXB-2-HXTKYE.js → quadrantDiagram-W4KKPZXB-C_mqMlKY.js} +1 -1
  79. package/ui-dist/assets/{radar-GUYGQ44K-jd5iouXS.js → radar-GUYGQ44K-DTBZ6zeL.js} +1 -1
  80. package/ui-dist/assets/{requirementDiagram-4Y6WPE33-BilSVdwW.js → requirementDiagram-4Y6WPE33-C02Lll9V.js} +1 -1
  81. package/ui-dist/assets/{rotate-cw-B1ZRM7VI.js → rotate-cw-BUTALXBe.js} +1 -1
  82. package/ui-dist/assets/{sankeyDiagram-5OEKKPKP-CoFgnJWS.js → sankeyDiagram-5OEKKPKP-BpCTN0fI.js} +1 -1
  83. package/ui-dist/assets/search-CKqhWG6h.js +1 -0
  84. package/ui-dist/assets/select-BPFroWD-.js +1 -0
  85. package/ui-dist/assets/{sequenceDiagram-3UESZ5HK-joTVEA7C.js → sequenceDiagram-3UESZ5HK-BSZzFC0b.js} +1 -1
  86. package/ui-dist/assets/square-COjZqkOL.js +1 -0
  87. package/ui-dist/assets/{stateDiagram-AJRCARHV-D79-k_XU.js → stateDiagram-AJRCARHV-sbrBtcyv.js} +1 -1
  88. package/ui-dist/assets/stateDiagram-v2-BHNVJYJU-Dvy9QnJ1.js +1 -0
  89. package/ui-dist/assets/tabs-RuXfAo0Q.js +1 -0
  90. package/ui-dist/assets/textarea-CwL3B5t5.js +1 -0
  91. package/ui-dist/assets/{timeline-definition-PNZ67QCA-D8MLBaMD.js → timeline-definition-PNZ67QCA-DerlFFtJ.js} +1 -1
  92. package/ui-dist/assets/{trash-2-D4CnL8wv.js → trash-2-D5W0vize.js} +1 -1
  93. package/ui-dist/assets/{treeView-BLDUP644-POJvg-dl.js → treeView-BLDUP644-CHplYEW1.js} +1 -1
  94. package/ui-dist/assets/{treemap-LRROVOQU-DS7TnyOD.js → treemap-LRROVOQU-DQciiAhX.js} +1 -1
  95. package/ui-dist/assets/useBaseUiId-DL38u1cQ.js +1 -0
  96. package/ui-dist/assets/useButton-kcIJA9wR.js +1 -0
  97. package/ui-dist/assets/useCompositeListItem-aicL7pEO.js +1 -0
  98. package/ui-dist/assets/useRegisterFieldControl-DOObtV36.js +1 -0
  99. package/ui-dist/assets/{vennDiagram-CIIHVFJN-D0EqM2aD.js → vennDiagram-CIIHVFJN-DItyMCJy.js} +1 -1
  100. package/ui-dist/assets/{wardley-L42UT6IY-ZBPaCQPM.js → wardley-L42UT6IY-rnuyIYo6.js} +1 -1
  101. package/ui-dist/assets/{wardleyDiagram-YWT4CUSO-CN9nmvW3.js → wardleyDiagram-YWT4CUSO-BfG0cbM-.js} +1 -1
  102. package/ui-dist/assets/{xychartDiagram-2RQKCTM6-CTV-CuX-.js → xychartDiagram-2RQKCTM6-DmzunUZx.js} +1 -1
  103. package/ui-dist/index.html +4 -4
  104. package/ui-dist/assets/BrowserPage-BwT5k8-s.js +0 -1
  105. package/ui-dist/assets/DashboardPage-BvxkAL6I.js +0 -1
  106. package/ui-dist/assets/FilesPage-Br3C0Pem.js +0 -64
  107. package/ui-dist/assets/FormContext-6Ydu-jal.js +0 -1
  108. package/ui-dist/assets/LogsPage-D7DXOEb9.js +0 -1
  109. package/ui-dist/assets/McpPage-CecHRhqq.js +0 -1
  110. package/ui-dist/assets/MemoriesPage-DBq4WGnc.js +0 -1
  111. package/ui-dist/assets/SchedulesPage-P4MkReA9.js +0 -1
  112. package/ui-dist/assets/SettingsPage-DCe6V1dk.js +0 -1
  113. package/ui-dist/assets/SkillsPage-CbJM3z7o.js +0 -1
  114. package/ui-dist/assets/architecture-7EHR7CIX-D_7WJiS2.js +0 -1
  115. package/ui-dist/assets/badge-DjyNiZCE.js +0 -1
  116. package/ui-dist/assets/button-Cg-0y2B2.js +0 -1
  117. package/ui-dist/assets/channel-D9Lx8ecr.js +0 -1
  118. package/ui-dist/assets/checkbox-Bwtgo2Iq.js +0 -1
  119. package/ui-dist/assets/classDiagram-4FO5ZUOK-DdMTKe_j.js +0 -1
  120. package/ui-dist/assets/classDiagram-v2-Q7XG4LA2-DdMTKe_j.js +0 -1
  121. package/ui-dist/assets/collapsible-BbFbh2zH.js +0 -1
  122. package/ui-dist/assets/dialog-BlNguSbT.js +0 -1
  123. package/ui-dist/assets/eventmodeling-FCH6USID-CYsRhu9T.js +0 -1
  124. package/ui-dist/assets/index-73cjKBdb.js +0 -12
  125. package/ui-dist/assets/input-DHLFV6Sc.js +0 -1
  126. package/ui-dist/assets/katex-9FE8ZsoR.js +0 -1
  127. package/ui-dist/assets/label-CxX4-RmK.js +0 -1
  128. package/ui-dist/assets/mermaid-GHXKKRXX-DBJCUbG7.js +0 -1
  129. package/ui-dist/assets/play-B4R5rXMZ.js +0 -1
  130. package/ui-dist/assets/search-09Pme-NO.js +0 -1
  131. package/ui-dist/assets/select-D9XYqRQR.js +0 -1
  132. package/ui-dist/assets/square-_9cV5Fet.js +0 -1
  133. package/ui-dist/assets/stateDiagram-v2-BHNVJYJU-BtJOy0q4.js +0 -1
  134. package/ui-dist/assets/tabs-DnAM3F1s.js +0 -1
  135. package/ui-dist/assets/textarea-5JHEEgU-.js +0 -1
  136. package/ui-dist/assets/useBaseUiId-dSIElxm7.js +0 -1
  137. package/ui-dist/assets/useButton-DKtiRcm8.js +0 -1
  138. package/ui-dist/assets/useCompositeListItem-C7NilwuX.js +0 -1
  139. package/ui-dist/assets/useRegisterFieldControl-CbOBCC3j.js +0 -1
  140. package/ui-dist/assets/utils-BX1Diber.js +0 -1
package/dist/index.js CHANGED
@@ -1,14 +1,13 @@
1
1
  // @bun
2
- var YY=Object.create;var{getPrototypeOf:WY,defineProperty:C0,getOwnPropertyNames:$Y}=Object;var GY=Object.prototype.hasOwnProperty;function UY(N){return this[N]}var QY,XY,J$=(N,H,Y)=>{var W=N!=null&&typeof N==="object";if(W){var $=H?QY??=new WeakMap:XY??=new WeakMap,G=$.get(N);if(G)return G}Y=N!=null?YY(WY(N)):{};let U=H||!N||!N.__esModule?C0(Y,"default",{value:N,enumerable:!0}):Y;for(let Q of $Y(N))if(!GY.call(U,Q))C0(U,Q,{get:UY.bind(N,Q),enumerable:!0});if(W)$.set(N,U);return U};var B$=(N,H)=>()=>(H||N((H={exports:{}}).exports,H),H.exports);var ZY=(N)=>N;function OY(N,H){this[N]=ZY.bind(null,H)}var A$=(N,H)=>{for(var Y in H)C0(N,Y,{get:H[Y],enumerable:!0,configurable:!0,set:OY.bind(H,Y)})};import{existsSync as e2,watch as O$}from"fs";import{stat as NY}from"fs/promises";import b from"path";import{promises as o}from"fs";import i from"path";import{existsSync as $1,renameSync as zY}from"fs";import G1 from"os";import S from"path";function q(N){return process.env[`JUN_${N}`]??process.env[`AGENTHOST_${N}`]}function FY(){let N=q("HOME");if(N)return N;let H=S.join(G1.homedir(),".jun"),Y=S.join(G1.homedir(),".agenthost");if(!$1(H)&&$1(Y))try{zY(Y,H),console.log("[paths] migrated data dir ~/.agenthost -> ~/.jun")}catch(W){return console.warn("[paths] could not migrate ~/.agenthost -> ~/.jun (files in use?) \u2014 using legacy dir:",W),Y}return H}var I=FY(),K="default",S0=q("HOST")??"127.0.0.1",iN=Number(q("PORT")??8787);function XN(){return S.join(I,"projects")}function NN(N=K){return S.join(XN(),N)}function a(){return S.join(I,"runs")}function B(N=K){return S.join(NN(N),"workspace")}function TN(){return S.join(I,"schedules")}function j(N=K){return S.join(NN(N),"codex-home")}function U1(N=K){return S.join(NN(N),"widgets")}function EN(N=K){return S.join(NN(N),"browser")}function pN(N){let H=S.resolve(XN()),Y=S.relative(H,S.resolve(N));if(!Y||Y.startsWith("..")||S.isAbsolute(Y))return null;return Y.split(S.sep)[0]||null}function u(N){return N.split(S.sep).join("/")}function T0(N){return i.join(NN(N),"project.json")}var VY=["files","reports","downloads","screenshots","artifacts",".agents/skills"],KY=["profile","downloads","screenshots","recordings"],LY={projectId:K,defaultModel:"gpt-5.4",defaultSandbox:"workspaceWrite",defaultApprovalPolicy:"onRequest",host:"127.0.0.1",port:8787,browserProvider:"agent-browser"},MY={version:1,pages:[{id:"home",title:"Home",widgets:[]}]},JY='# Jun workspace\n\nYou are running inside JunHost \u2014 a self-hosted dashboard that supervises you.\nThis directory is your workspace; write outputs here.\n\n## Browsing the web \u2014 use the `jun-browser` MCP tools\n\nA shared, visible browser session is already running \u2014 the same one the user\nwatches in the dashboard. Drive and inspect it through the **`jun-browser` MCP\nserver\'s tools**, NOT the `agent-browser` shell command:\n\n- `browser_status` \u2014 what URL/title is open RIGHT NOW + who has control. Use\n this to answer "what page is open" / "what am I logged in as" \u2014 it reflects\n exactly what the user sees.\n- `browser_navigate {url}` \u2014 go to a URL\n- `browser_snapshot {interactive}` \u2014 accessibility tree with @ref handles (decide what to click)\n- `browser_click {target}` \u2014 click an @ref or CSS selector\n- `browser_fill {target, text}` \u2014 fill an input\n- `browser_read {selector?}` \u2014 read page text\n- `browser_eval {expression}` \u2014 run JS in the page (read precise state)\n- `browser_screenshot` \u2014 capture to the workspace, returns a path to read\n\nWHY NOT the `agent-browser` CLI: your shell runs in a sandbox that can\'t reach\nthe shared session\'s socket and has no network, so `agent-browser \u2026` there\nfails ("Socket directory not writable" / "Daemon process exited") or silently\nopens a SEPARATE blank page \u2014 you\'d see `about:blank` while the user sees a real\nsite. The MCP tools run in the daemon (unsandboxed) and always act on the shared\npage. So to check a logged-in state, just call `browser_status` (or\n`browser_navigate` to the site, which keeps the user\'s cookies and loads signed\nin) \u2014 never shell out to `agent-browser`.\n\nPrefer snapshot \u2192 @ref actions over guessing selectors. Save extracted notes and\nscreenshots under `reports/` and `screenshots/`.\n\n## Output locations\n- `reports/` \u2014 summaries and findings\n- `screenshots/` \u2014 captured images\n- `downloads/` \u2014 downloaded files\n',BY=`# Codex configuration for this Jun project.
2
+ var dH=Object.create;var{getPrototypeOf:oH,defineProperty:A0,getOwnPropertyNames:nH}=Object;var aH=Object.prototype.hasOwnProperty;function sH(N){return this[N]}var tH,rH,WO=(N,U,H)=>{var Y=N!=null&&typeof N==="object";if(Y){var O=U?tH??=new WeakMap:rH??=new WeakMap,W=O.get(N);if(W)return W}H=N!=null?dH(oH(N)):{};let $=U||!N||!N.__esModule?A0(H,"default",{value:N,enumerable:!0}):H;for(let G of nH(N))if(!aH.call($,G))A0($,G,{get:sH.bind(N,G),enumerable:!0});if(Y)O.set(N,$);return $};var $O=(N,U)=>()=>(U||N((U={exports:{}}).exports,U),U.exports);var eH=(N)=>N;function NY(N,U){this[N]=eH.bind(null,U)}var GO=(N,U)=>{for(var H in U)A0(N,H,{get:U[H],enumerable:!0,configurable:!0,set:NY.bind(U,H)})};import{existsSync as pH,watch as r2}from"fs";import{stat as uH}from"fs/promises";import w from"path";import{promises as n}from"fs";import o from"path";import{existsSync as N1,renameSync as UY}from"fs";import U1 from"os";import h from"path";function x(N){return process.env[`JUN_${N}`]??process.env[`AGENTHOST_${N}`]}function HY(){let N=x("HOME");if(N)return N;let U=h.join(U1.homedir(),".jun"),H=h.join(U1.homedir(),".agenthost");if(!N1(U)&&N1(H))try{UY(H,U),console.log("[paths] migrated data dir ~/.agenthost -> ~/.jun")}catch(Y){return console.warn("[paths] could not migrate ~/.agenthost -> ~/.jun (files in use?) \u2014 using legacy dir:",Y),H}return U}var f=HY(),T0=x("HOST")??"127.0.0.1",mN=Number(x("PORT")??8787);function GN(){return h.join(f,"projects","default")}function d(){return h.join(f,"runs")}function M(){return h.join(GN(),"workspace")}function TN(){return h.join(f,"schedules")}function k(){return h.join(GN(),"codex-home")}function H1(){return h.join(GN(),"widgets")}function BN(){return h.join(GN(),"browser")}function l(N){return N.split(h.sep).join("/")}var YY=["files","reports","downloads","screenshots","artifacts",".agents/skills"],OY=["profile","downloads","screenshots","recordings"],WY={defaultModel:"gpt-5.4",defaultSandbox:"workspaceWrite",defaultApprovalPolicy:"onRequest",host:"127.0.0.1",port:8787,browserProvider:"agent-browser"},$Y={version:1,pages:[{id:"home",title:"Home",widgets:[]}]},GY='# Jun workspace\n\nYou are running inside JunHost \u2014 a self-hosted dashboard that supervises you.\nThis directory is your workspace; write outputs here.\n\n## Browsing the web \u2014 use the `jun-browser` MCP tools\n\nA shared, visible browser session is already running \u2014 the same one the user\nwatches in the dashboard. Drive and inspect it through the **`jun-browser` MCP\nserver\'s tools**, NOT the `agent-browser` shell command:\n\n- `browser_status` \u2014 what URL/title is open RIGHT NOW + who has control. Use\n this to answer "what page is open" / "what am I logged in as" \u2014 it reflects\n exactly what the user sees.\n- `browser_navigate {url}` \u2014 go to a URL\n- `browser_snapshot {interactive}` \u2014 accessibility tree with @ref handles (decide what to click)\n- `browser_click {target}` \u2014 click an @ref or CSS selector\n- `browser_fill {target, text}` \u2014 fill an input\n- `browser_read {selector?}` \u2014 read page text\n- `browser_eval {expression}` \u2014 run JS in the page (read precise state)\n- `browser_screenshot` \u2014 capture to the workspace, returns a path to read\n\nWHY NOT the `agent-browser` CLI: your shell runs in a sandbox that can\'t reach\nthe shared session\'s socket and has no network, so `agent-browser \u2026` there\nfails ("Socket directory not writable" / "Daemon process exited") or silently\nopens a SEPARATE blank page \u2014 you\'d see `about:blank` while the user sees a real\nsite. The MCP tools run in the daemon (unsandboxed) and always act on the shared\npage. So to check a logged-in state, just call `browser_status` (or\n`browser_navigate` to the site, which keeps the user\'s cookies and loads signed\nin) \u2014 never shell out to `agent-browser`.\n\nPrefer snapshot \u2192 @ref actions over guessing selectors. Save extracted notes and\nscreenshots under `reports/` and `screenshots/`.\n\n## Output locations\n- `reports/` \u2014 summaries and findings\n- `screenshots/` \u2014 captured images\n- `downloads/` \u2014 downloaded files\n',FY=`# Codex configuration for this Jun project.
3
3
  # MCP servers are configured here, e.g.:
4
4
  #
5
5
  # [mcp_servers.context7]
6
6
  # command = "npx"
7
7
  # args = ["-y", "@upstash/context7-mcp"]
8
- `;async function RN(N,H){try{await o.access(N)}catch{await o.mkdir(i.dirname(N),{recursive:!0}),await o.writeFile(N,H,"utf8")}}async function E0(N,H){let Y=B(N);for(let W of VY)await o.mkdir(i.join(Y,W),{recursive:!0});for(let W of KY)await o.mkdir(i.join(EN(N),W),{recursive:!0});await o.mkdir(U1(N),{recursive:!0}),await o.mkdir(i.join(j(N),"logs"),{recursive:!0}),await RN(T0(N),JSON.stringify({id:N,name:H??N,createdAt:new Date().toISOString()},null,2)+`
9
- `),await RN(i.join(NN(N),"dashboard.json"),JSON.stringify(MY,null,2)+`
10
- `),await RN(i.join(j(N),"config.toml"),BY),await RN(i.join(Y,"AGENTS.md"),JY)}async function Q1(){await o.mkdir(a(),{recursive:!0}),await RN(i.join(I,"config.json"),JSON.stringify(LY,null,2)+`
11
- `),await E0(K,"Default")}import{promises as KN}from"fs";import KW from"path";/*!
8
+ `;async function cN(N,U){try{await n.access(N)}catch{await n.mkdir(o.dirname(N),{recursive:!0}),await n.writeFile(N,U,"utf8")}}async function Y1(){await n.mkdir(d(),{recursive:!0}),await cN(o.join(f,"config.json"),JSON.stringify(WY,null,2)+`
9
+ `);let N=M();for(let U of YY)await n.mkdir(o.join(N,U),{recursive:!0});for(let U of OY)await n.mkdir(o.join(BN(),U),{recursive:!0});await n.mkdir(H1(),{recursive:!0}),await n.mkdir(o.join(k(),"logs"),{recursive:!0}),await cN(o.join(GN(),"dashboard.json"),JSON.stringify($Y,null,2)+`
10
+ `),await cN(o.join(k(),"config.toml"),FY),await cN(o.join(N,"AGENTS.md"),GY)}import{promises as LN}from"fs";import O2 from"path";/*!
12
11
  * Copyright (c) Squirrel Chat et al., All rights reserved.
13
12
  * SPDX-License-Identifier: BSD-3-Clause
14
13
  *
@@ -34,11 +33,11 @@ var YY=Object.create;var{getPrototypeOf:WY,defineProperty:C0,getOwnPropertyNames
34
33
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
35
34
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36
35
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
- */function AY(N,H){let Y=N.slice(0,H).split(/\r\n|\n|\r/g);return[Y.length,Y.pop().length+1]}function DY(N,H,Y){let W=N.split(/\r\n|\n|\r/g),$="",G=(Math.log10(H+1)|0)+1;for(let U=H-1;U<=H+1;U++){let Q=W[U-1];if(!Q)continue;if($+=U.toString().padEnd(G," "),$+=": ",$+=Q,$+=`
38
- `,U===H)$+=" ".repeat(G+Y+2),$+=`^
39
- `}return $}class L extends Error{line;column;codeblock;constructor(N,H){let[Y,W]=AY(H.toml,H.ptr),$=DY(H.toml,Y,W);super(`Invalid TOML document: ${N}
36
+ */function QY(N,U){let H=N.slice(0,U).split(/\r\n|\n|\r/g);return[H.length,H.pop().length+1]}function XY(N,U,H){let Y=N.split(/\r\n|\n|\r/g),O="",W=(Math.log10(U+1)|0)+1;for(let $=U-1;$<=U+1;$++){let G=Y[$-1];if(!G)continue;if(O+=$.toString().padEnd(W," "),O+=": ",O+=G,O+=`
37
+ `,$===U)O+=" ".repeat(W+H+2),O+=`^
38
+ `}return O}class D extends Error{line;column;codeblock;constructor(N,U){let[H,Y]=QY(U.toml,U.ptr),O=XY(U.toml,H,Y);super(`Invalid TOML document: ${N}
40
39
 
41
- ${$}`,H);this.line=Y,this.column=W,this.codeblock=$}}/*!
40
+ ${O}`,U);this.line=H,this.column=Y,this.codeblock=O}}/*!
42
41
  * Copyright (c) Squirrel Chat et al., All rights reserved.
43
42
  * SPDX-License-Identifier: BSD-3-Clause
44
43
  *
@@ -64,14 +63,14 @@ ${$}`,H);this.line=Y,this.column=W,this.codeblock=$}}/*!
64
63
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
65
64
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
66
65
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67
- */function CY(N,H){let Y=0;while(N[H-++Y]==="\\");return--Y&&Y%2}function nN(N,H=0,Y=N.length){let W=N.indexOf(`
68
- `,H);if(N[W-1]==="\r")W--;return W<=Y?W:-1}function ZN(N,H){for(let Y=H;Y<N.length;Y++){let W=N[Y];if(W===`
69
- `)return Y;if(W==="\r"&&N[Y+1]===`
70
- `)return Y+1;if(W<" "&&W!=="\t"||W==="\x7F")throw new L("control characters are not allowed in comments",{toml:N,ptr:H})}return N.length}function _(N,H,Y,W){let $;while(!0){while(($=N[H])===" "||$==="\t"||!Y&&($===`
71
- `||$==="\r"&&N[H+1]===`
72
- `))H++;if(W||$!=="#")break;H=ZN(N,H)}return H}function X1(N,H,Y,W,$=!1){if(!W)return H=nN(N,H),H<0?N.length:H;for(let G=H;G<N.length;G++){let U=N[G];if(U==="#")G=nN(N,G);else if(U===Y)return G+1;else if(U===W||$&&(U===`
73
- `||U==="\r"&&N[G+1]===`
74
- `))return G}throw new L("cannot find end of structure",{toml:N,ptr:H})}function dN(N,H){let Y=N[H],W=Y===N[H+1]&&N[H+1]===N[H+2]?N.slice(H,H+3):Y;H+=W.length-1;do H=N.indexOf(W,++H);while(H>-1&&Y!=="'"&&CY(N,H));if(H>-1){if(H+=W.length,W.length>1){if(N[H]===Y)H++;if(N[H]===Y)H++}}return H}/*!
66
+ */function ZY(N,U){let H=0;while(N[U-++H]==="\\");return--H&&H%2}function lN(N,U=0,H=N.length){let Y=N.indexOf(`
67
+ `,U);if(N[Y-1]==="\r")Y--;return Y<=H?Y:-1}function FN(N,U){for(let H=U;H<N.length;H++){let Y=N[H];if(Y===`
68
+ `)return H;if(Y==="\r"&&N[H+1]===`
69
+ `)return H+1;if(Y<" "&&Y!=="\t"||Y==="\x7F")throw new D("control characters are not allowed in comments",{toml:N,ptr:U})}return N.length}function S(N,U,H,Y){let O;while(!0){while((O=N[U])===" "||O==="\t"||!H&&(O===`
70
+ `||O==="\r"&&N[U+1]===`
71
+ `))U++;if(Y||O!=="#")break;U=FN(N,U)}return U}function O1(N,U,H,Y,O=!1){if(!Y)return U=lN(N,U),U<0?N.length:U;for(let W=U;W<N.length;W++){let $=N[W];if($==="#")W=lN(N,W);else if($===H)return W+1;else if($===Y||O&&($===`
72
+ `||$==="\r"&&N[W+1]===`
73
+ `))return W}throw new D("cannot find end of structure",{toml:N,ptr:U})}function pN(N,U){let H=N[U],Y=H===N[U+1]&&N[U+1]===N[U+2]?N.slice(U,U+3):H;U+=Y.length-1;do U=N.indexOf(Y,++U);while(U>-1&&H!=="'"&&ZY(N,U));if(U>-1){if(U+=Y.length,Y.length>1){if(N[U]===H)U++;if(N[U]===H)U++}}return U}/*!
75
74
  * Copyright (c) Squirrel Chat et al., All rights reserved.
76
75
  * SPDX-License-Identifier: BSD-3-Clause
77
76
  *
@@ -97,7 +96,7 @@ ${$}`,H);this.line=Y,this.column=W,this.codeblock=$}}/*!
97
96
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
98
97
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
99
98
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
100
- */var SY=/^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;class s extends Date{#H=!1;#Y=!1;#N=null;constructor(N){let H=!0,Y=!0,W="Z";if(typeof N==="string"){let $=N.match(SY);if($){if(!$[1])H=!1,N=`0000-01-01T${N}`;if(Y=!!$[2],Y&&N[10]===" "&&(N=N.replace(" ","T")),$[2]&&+$[2]>23)N="";else if(W=$[3]||null,N=N.toUpperCase(),!W&&Y)N+="Z"}else N=""}super(N);if(!isNaN(this.getTime()))this.#H=H,this.#Y=Y,this.#N=W}isDateTime(){return this.#H&&this.#Y}isLocal(){return!this.#H||!this.#Y||!this.#N}isDate(){return this.#H&&!this.#Y}isTime(){return this.#Y&&!this.#H}isValid(){return this.#H||this.#Y}toISOString(){let N=super.toISOString();if(this.isDate())return N.slice(0,10);if(this.isTime())return N.slice(11,23);if(this.#N===null)return N.slice(0,-1);if(this.#N==="Z")return N;let H=+this.#N.slice(1,3)*60+ +this.#N.slice(4,6);return H=this.#N[0]==="-"?H:-H,new Date(this.getTime()-H*60000).toISOString().slice(0,-1)+this.#N}static wrapAsOffsetDateTime(N,H="Z"){let Y=new s(N);return Y.#N=H,Y}static wrapAsLocalDateTime(N){let H=new s(N);return H.#N=null,H}static wrapAsLocalDate(N){let H=new s(N);return H.#Y=!1,H.#N=null,H}static wrapAsLocalTime(N){let H=new s(N);return H.#H=!1,H.#N=null,H}}/*!
99
+ */var LY=/^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;class a extends Date{#U=!1;#H=!1;#N=null;constructor(N){let U=!0,H=!0,Y="Z";if(typeof N==="string"){let O=N.match(LY);if(O){if(!O[1])U=!1,N=`0000-01-01T${N}`;if(H=!!O[2],H&&N[10]===" "&&(N=N.replace(" ","T")),O[2]&&+O[2]>23)N="";else if(Y=O[3]||null,N=N.toUpperCase(),!Y&&H)N+="Z"}else N=""}super(N);if(!isNaN(this.getTime()))this.#U=U,this.#H=H,this.#N=Y}isDateTime(){return this.#U&&this.#H}isLocal(){return!this.#U||!this.#H||!this.#N}isDate(){return this.#U&&!this.#H}isTime(){return this.#H&&!this.#U}isValid(){return this.#U||this.#H}toISOString(){let N=super.toISOString();if(this.isDate())return N.slice(0,10);if(this.isTime())return N.slice(11,23);if(this.#N===null)return N.slice(0,-1);if(this.#N==="Z")return N;let U=+this.#N.slice(1,3)*60+ +this.#N.slice(4,6);return U=this.#N[0]==="-"?U:-U,new Date(this.getTime()-U*60000).toISOString().slice(0,-1)+this.#N}static wrapAsOffsetDateTime(N,U="Z"){let H=new a(N);return H.#N=U,H}static wrapAsLocalDateTime(N){let U=new a(N);return U.#N=null,U}static wrapAsLocalDate(N){let U=new a(N);return U.#H=!1,U.#N=null,U}static wrapAsLocalTime(N){let U=new a(N);return U.#U=!1,U.#N=null,U}}/*!
101
100
  * Copyright (c) Squirrel Chat et al., All rights reserved.
102
101
  * SPDX-License-Identifier: BSD-3-Clause
103
102
  *
@@ -123,13 +122,13 @@ ${$}`,H);this.line=Y,this.column=W,this.codeblock=$}}/*!
123
122
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
124
123
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
125
124
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
126
- */var TY=/^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/,EY=/^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/,RY=/^[+-]?0[0-9_]/,wY=/^[0-9a-f]{2,8}$/i,Z1={b:"\b",t:"\t",n:`
127
- `,f:"\f",r:"\r",e:"\x1B",'"':'"',"\\":"\\"};function aN(N,H=0,Y=N.length){let W=N[H]==="'",$=N[H++]===N[H]&&N[H]===N[H+1];if($){if(Y-=2,N[H+=2]==="\r")H++;if(N[H]===`
128
- `)H++}let G=0,U,Q="",X=H;while(H<Y-1){let Z=N[H++];if(Z===`
129
- `||Z==="\r"&&N[H]===`
130
- `){if(!$)throw new L("newlines are not allowed in strings",{toml:N,ptr:H-1})}else if(Z<" "&&Z!=="\t"||Z==="\x7F")throw new L("control characters are not allowed in strings",{toml:N,ptr:H-1});if(U){if(U=!1,Z==="x"||Z==="u"||Z==="U"){let F=N.slice(H,H+=Z==="x"?2:Z==="u"?4:8);if(!wY.test(F))throw new L("invalid unicode escape",{toml:N,ptr:G});try{Q+=String.fromCodePoint(parseInt(F,16))}catch{throw new L("invalid unicode escape",{toml:N,ptr:G})}}else if($&&(Z===`
131
- `||Z===" "||Z==="\t"||Z==="\r")){if(H=_(N,H-1,!0),N[H]!==`
132
- `&&N[H]!=="\r")throw new L("invalid escape: only line-ending whitespace may be escaped",{toml:N,ptr:G});H=_(N,H)}else if(Z in Z1)Q+=Z1[Z];else throw new L("unrecognized escape sequence",{toml:N,ptr:G});X=H}else if(!W&&Z==="\\")G=H-1,U=!0,Q+=N.slice(X,G)}return Q+N.slice(X,Y-1)}function O1(N,H,Y,W){if(N==="true")return!0;if(N==="false")return!1;if(N==="-inf")return-1/0;if(N==="inf"||N==="+inf")return 1/0;if(N==="nan"||N==="+nan"||N==="-nan")return NaN;if(N==="-0")return W?0n:0;let $=TY.test(N);if($||EY.test(N)){if(RY.test(N))throw new L("leading zeroes are not allowed",{toml:H,ptr:Y});N=N.replace(/_/g,"");let U=+N;if(isNaN(U))throw new L("invalid number",{toml:H,ptr:Y});if($){if(($=!Number.isSafeInteger(U))&&!W)throw new L("integer value cannot be represented losslessly",{toml:H,ptr:Y});if($||W===!0)U=BigInt(N)}return U}let G=new s(N);if(!G.isValid())throw new L("invalid value",{toml:H,ptr:Y});return G}/*!
125
+ */var zY=/^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/,DY=/^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/,KY=/^[+-]?0[0-9_]/,VY=/^[0-9a-f]{2,8}$/i,W1={b:"\b",t:"\t",n:`
126
+ `,f:"\f",r:"\r",e:"\x1B",'"':'"',"\\":"\\"};function uN(N,U=0,H=N.length){let Y=N[U]==="'",O=N[U++]===N[U]&&N[U]===N[U+1];if(O){if(H-=2,N[U+=2]==="\r")U++;if(N[U]===`
127
+ `)U++}let W=0,$,G="",F=U;while(U<H-1){let Q=N[U++];if(Q===`
128
+ `||Q==="\r"&&N[U]===`
129
+ `){if(!O)throw new D("newlines are not allowed in strings",{toml:N,ptr:U-1})}else if(Q<" "&&Q!=="\t"||Q==="\x7F")throw new D("control characters are not allowed in strings",{toml:N,ptr:U-1});if($){if($=!1,Q==="x"||Q==="u"||Q==="U"){let L=N.slice(U,U+=Q==="x"?2:Q==="u"?4:8);if(!VY.test(L))throw new D("invalid unicode escape",{toml:N,ptr:W});try{G+=String.fromCodePoint(parseInt(L,16))}catch{throw new D("invalid unicode escape",{toml:N,ptr:W})}}else if(O&&(Q===`
130
+ `||Q===" "||Q==="\t"||Q==="\r")){if(U=S(N,U-1,!0),N[U]!==`
131
+ `&&N[U]!=="\r")throw new D("invalid escape: only line-ending whitespace may be escaped",{toml:N,ptr:W});U=S(N,U)}else if(Q in W1)G+=W1[Q];else throw new D("unrecognized escape sequence",{toml:N,ptr:W});F=U}else if(!Y&&Q==="\\")W=U-1,$=!0,G+=N.slice(F,W)}return G+N.slice(F,H-1)}function $1(N,U,H,Y){if(N==="true")return!0;if(N==="false")return!1;if(N==="-inf")return-1/0;if(N==="inf"||N==="+inf")return 1/0;if(N==="nan"||N==="+nan"||N==="-nan")return NaN;if(N==="-0")return Y?0n:0;let O=zY.test(N);if(O||DY.test(N)){if(KY.test(N))throw new D("leading zeroes are not allowed",{toml:U,ptr:H});N=N.replace(/_/g,"");let $=+N;if(isNaN($))throw new D("invalid number",{toml:U,ptr:H});if(O){if((O=!Number.isSafeInteger($))&&!Y)throw new D("integer value cannot be represented losslessly",{toml:U,ptr:H});if(O||Y===!0)$=BigInt(N)}return $}let W=new a(N);if(!W.isValid())throw new D("invalid value",{toml:U,ptr:H});return W}/*!
133
132
  * Copyright (c) Squirrel Chat et al., All rights reserved.
134
133
  * SPDX-License-Identifier: BSD-3-Clause
135
134
  *
@@ -155,8 +154,8 @@ ${$}`,H);this.line=Y,this.column=W,this.codeblock=$}}/*!
155
154
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
156
155
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
157
156
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
158
- */function _Y(N,H,Y){let W=N.slice(H,Y),$=W.indexOf("#");if($>-1)ZN(N,$),W=W.slice(0,$);return[W.trimEnd(),$]}function wN(N,H,Y,W,$){if(W===0)throw new L("document contains excessively nested structures. aborting.",{toml:N,ptr:H});let G=N[H];if(G==="["||G==="{"){let[X,Z]=G==="["?F1(N,H,W,$):z1(N,H,W,$);if(Y){if(Z=_(N,Z),N[Z]===",")Z++;else if(N[Z]!==Y)throw new L("expected comma or end of structure",{toml:N,ptr:Z})}return[X,Z]}let U;if(G==='"'||G==="'"){U=dN(N,H);let X=aN(N,H,U);if(Y){if(U=_(N,U),N[U]&&N[U]!==","&&N[U]!==Y&&N[U]!==`
159
- `&&N[U]!=="\r")throw new L("unexpected character encountered",{toml:N,ptr:U});U+=+(N[U]===",")}return[X,U]}U=X1(N,H,",",Y);let Q=_Y(N,H,U-+(N[U-1]===","));if(!Q[0])throw new L("incomplete key-value declaration: no value specified",{toml:N,ptr:H});if(Y&&Q[1]>-1)U=_(N,H+Q[1]),U+=+(N[U]===",");return[O1(Q[0],N,H,$),U]}/*!
157
+ */function MY(N,U,H){let Y=N.slice(U,H),O=Y.indexOf("#");if(O>-1)FN(N,O),Y=Y.slice(0,O);return[Y.trimEnd(),O]}function EN(N,U,H,Y,O){if(Y===0)throw new D("document contains excessively nested structures. aborting.",{toml:N,ptr:U});let W=N[U];if(W==="["||W==="{"){let[F,Q]=W==="["?F1(N,U,Y,O):G1(N,U,Y,O);if(H){if(Q=S(N,Q),N[Q]===",")Q++;else if(N[Q]!==H)throw new D("expected comma or end of structure",{toml:N,ptr:Q})}return[F,Q]}let $;if(W==='"'||W==="'"){$=pN(N,U);let F=uN(N,U,$);if(H){if($=S(N,$),N[$]&&N[$]!==","&&N[$]!==H&&N[$]!==`
158
+ `&&N[$]!=="\r")throw new D("unexpected character encountered",{toml:N,ptr:$});$+=+(N[$]===",")}return[F,$]}$=O1(N,U,",",H);let G=MY(N,U,$-+(N[$-1]===","));if(!G[0])throw new D("incomplete key-value declaration: no value specified",{toml:N,ptr:U});if(H&&G[1]>-1)$=S(N,U+G[1]),$+=+(N[$]===",");return[$1(G[0],N,U,O),$]}/*!
160
159
  * Copyright (c) Squirrel Chat et al., All rights reserved.
161
160
  * SPDX-License-Identifier: BSD-3-Clause
162
161
  *
@@ -182,9 +181,9 @@ ${$}`,H);this.line=Y,this.column=W,this.codeblock=$}}/*!
182
181
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
183
182
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
184
183
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
185
- */var PY=/^[a-zA-Z0-9-_]+[ \t]*$/;function oN(N,H,Y="="){let W=H-1,$=[],G=N.indexOf(Y,H);if(G<0)throw new L("incomplete key-value: cannot find end of key",{toml:N,ptr:H});do{let U=N[H=++W];if(U!==" "&&U!=="\t")if(U==='"'||U==="'"){if(U===N[H+1]&&U===N[H+2])throw new L("multiline strings are not allowed in keys",{toml:N,ptr:H});let Q=dN(N,H);if(Q<0)throw new L("unfinished string encountered",{toml:N,ptr:H});W=N.indexOf(".",Q);let X=N.slice(Q,W<0||W>G?G:W),Z=nN(X);if(Z>-1)throw new L("newlines are not allowed in keys",{toml:N,ptr:H+W+Z});if(X.trimStart())throw new L("found extra tokens after the string part",{toml:N,ptr:Q});if(G<Q){if(G=N.indexOf(Y,Q),G<0)throw new L("incomplete key-value: cannot find end of key",{toml:N,ptr:H})}$.push(aN(N,H,Q))}else{W=N.indexOf(".",H);let Q=N.slice(H,W<0||W>G?G:W);if(!PY.test(Q))throw new L("only letter, numbers, dashes and underscores are allowed in keys",{toml:N,ptr:H});$.push(Q.trimEnd())}}while(W+1&&W<G);return[$,_(N,G+1,!0,!0)]}function z1(N,H,Y,W){let $={},G=new Set,U;H++;while((U=N[H++])!=="}"&&U)if(U===",")throw new L("expected value, found comma",{toml:N,ptr:H-1});else if(U==="#")H=ZN(N,H);else if(U!==" "&&U!=="\t"&&U!==`
186
- `&&U!=="\r"){let Q,X=$,Z=!1,[F,M]=oN(N,H-1);for(let QN=0;QN<F.length;QN++){if(QN)X=Z?X[Q]:X[Q]={};if(Q=F[QN],(Z=Object.hasOwn(X,Q))&&(typeof X[Q]!=="object"||G.has(X[Q])))throw new L("trying to redefine an already defined value",{toml:N,ptr:H});if(!Z&&Q==="__proto__")Object.defineProperty(X,Q,{enumerable:!0,configurable:!0,writable:!0})}if(Z)throw new L("trying to redefine an already defined value",{toml:N,ptr:H});let[E,f]=wN(N,M,"}",Y-1,W);G.add(E),X[Q]=E,H=f}if(!U)throw new L("unfinished table encountered",{toml:N,ptr:H});return[$,H]}function F1(N,H,Y,W){let $=[],G;H++;while((G=N[H++])!=="]"&&G)if(G===",")throw new L("expected value, found comma",{toml:N,ptr:H-1});else if(G==="#")H=ZN(N,H);else if(G!==" "&&G!=="\t"&&G!==`
187
- `&&G!=="\r"){let U=wN(N,H-1,"]",Y-1,W);$.push(U[0]),H=U[1]}if(!G)throw new L("unfinished array encountered",{toml:N,ptr:H});return[$,H]}/*!
184
+ */var JY=/^[a-zA-Z0-9-_]+[ \t]*$/;function iN(N,U,H="="){let Y=U-1,O=[],W=N.indexOf(H,U);if(W<0)throw new D("incomplete key-value: cannot find end of key",{toml:N,ptr:U});do{let $=N[U=++Y];if($!==" "&&$!=="\t")if($==='"'||$==="'"){if($===N[U+1]&&$===N[U+2])throw new D("multiline strings are not allowed in keys",{toml:N,ptr:U});let G=pN(N,U);if(G<0)throw new D("unfinished string encountered",{toml:N,ptr:U});Y=N.indexOf(".",G);let F=N.slice(G,Y<0||Y>W?W:Y),Q=lN(F);if(Q>-1)throw new D("newlines are not allowed in keys",{toml:N,ptr:U+Y+Q});if(F.trimStart())throw new D("found extra tokens after the string part",{toml:N,ptr:G});if(W<G){if(W=N.indexOf(H,G),W<0)throw new D("incomplete key-value: cannot find end of key",{toml:N,ptr:U})}O.push(uN(N,U,G))}else{Y=N.indexOf(".",U);let G=N.slice(U,Y<0||Y>W?W:Y);if(!JY.test(G))throw new D("only letter, numbers, dashes and underscores are allowed in keys",{toml:N,ptr:U});O.push(G.trimEnd())}}while(Y+1&&Y<W);return[O,S(N,W+1,!0,!0)]}function G1(N,U,H,Y){let O={},W=new Set,$;U++;while(($=N[U++])!=="}"&&$)if($===",")throw new D("expected value, found comma",{toml:N,ptr:U-1});else if($==="#")U=FN(N,U);else if($!==" "&&$!=="\t"&&$!==`
185
+ `&&$!=="\r"){let G,F=O,Q=!1,[L,V]=iN(N,U-1);for(let $N=0;$N<L.length;$N++){if($N)F=Q?F[G]:F[G]={};if(G=L[$N],(Q=Object.hasOwn(F,G))&&(typeof F[G]!=="object"||W.has(F[G])))throw new D("trying to redefine an already defined value",{toml:N,ptr:U});if(!Q&&G==="__proto__")Object.defineProperty(F,G,{enumerable:!0,configurable:!0,writable:!0})}if(Q)throw new D("trying to redefine an already defined value",{toml:N,ptr:U});let[T,e]=EN(N,V,"}",H-1,Y);W.add(T),F[G]=T,U=e}if(!$)throw new D("unfinished table encountered",{toml:N,ptr:U});return[O,U]}function F1(N,U,H,Y){let O=[],W;U++;while((W=N[U++])!=="]"&&W)if(W===",")throw new D("expected value, found comma",{toml:N,ptr:U-1});else if(W==="#")U=FN(N,U);else if(W!==" "&&W!=="\t"&&W!==`
186
+ `&&W!=="\r"){let $=EN(N,U-1,"]",H-1,Y);O.push($[0]),U=$[1]}if(!W)throw new D("unfinished array encountered",{toml:N,ptr:U});return[O,U]}/*!
188
187
  * Copyright (c) Squirrel Chat et al., All rights reserved.
189
188
  * SPDX-License-Identifier: BSD-3-Clause
190
189
  *
@@ -210,8 +209,8 @@ ${$}`,H);this.line=Y,this.column=W,this.codeblock=$}}/*!
210
209
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
211
210
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
212
211
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
213
- */function V1(N,H,Y,W){let $=H,G=Y,U,Q=!1,X;for(let Z=0;Z<N.length;Z++){if(Z){if($=Q?$[U]:$[U]={},G=(X=G[U]).c,W===0&&(X.t===1||X.t===2))return null;if(X.t===2){let F=$.length-1;$=$[F],G=G[F].c}}if(U=N[Z],(Q=Object.hasOwn($,U))&&G[U]?.t===0&&G[U]?.d)return null;if(!Q){if(U==="__proto__")Object.defineProperty($,U,{enumerable:!0,configurable:!0,writable:!0}),Object.defineProperty(G,U,{enumerable:!0,configurable:!0,writable:!0});G[U]={t:Z<N.length-1&&W===2?3:W,d:!1,i:0,c:{}}}}if(X=G[U],X.t!==W&&!(W===1&&X.t===3))return null;if(W===2){if(!X.d)X.d=!0,$[U]=[];$[U].push($={}),X.c[X.i++]=X={t:1,d:!1,i:0,c:{}}}if(X.d)return null;if(X.d=!0,W===1)$=Q?$[U]:$[U]={};else if(W===0&&Q)return null;return[U,$,X.c]}function l(N,{maxDepth:H=1000,integersAsBigInt:Y}={}){let W={},$={},G=W,U=$;for(let Q=_(N,0);Q<N.length;){if(N[Q]==="["){let X=N[++Q]==="[",Z=oN(N,Q+=+X,"]");if(X){if(N[Z[1]-1]!=="]")throw new L("expected end of table declaration",{toml:N,ptr:Z[1]-1});Z[1]++}let F=V1(Z[0],W,$,X?2:1);if(!F)throw new L("trying to redefine an already defined table or value",{toml:N,ptr:Q});U=F[2],G=F[1],Q=Z[1]}else{let X=oN(N,Q),Z=V1(X[0],G,U,0);if(!Z)throw new L("trying to redefine an already defined table or value",{toml:N,ptr:Q});let F=wN(N,X[1],void 0,H,Y);Z[1][Z[0]]=F[0],Q=F[1]}if(Q=_(N,Q,!0),N[Q]&&N[Q]!==`
214
- `&&N[Q]!=="\r")throw new L("each key-value declaration must be followed by an end-of-line",{toml:N,ptr:Q});Q=_(N,Q)}return W}/*!
212
+ */function Q1(N,U,H,Y){let O=U,W=H,$,G=!1,F;for(let Q=0;Q<N.length;Q++){if(Q){if(O=G?O[$]:O[$]={},W=(F=W[$]).c,Y===0&&(F.t===1||F.t===2))return null;if(F.t===2){let L=O.length-1;O=O[L],W=W[L].c}}if($=N[Q],(G=Object.hasOwn(O,$))&&W[$]?.t===0&&W[$]?.d)return null;if(!G){if($==="__proto__")Object.defineProperty(O,$,{enumerable:!0,configurable:!0,writable:!0}),Object.defineProperty(W,$,{enumerable:!0,configurable:!0,writable:!0});W[$]={t:Q<N.length-1&&Y===2?3:Y,d:!1,i:0,c:{}}}}if(F=W[$],F.t!==Y&&!(Y===1&&F.t===3))return null;if(Y===2){if(!F.d)F.d=!0,O[$]=[];O[$].push(O={}),F.c[F.i++]=F={t:1,d:!1,i:0,c:{}}}if(F.d)return null;if(F.d=!0,Y===1)O=G?O[$]:O[$]={};else if(Y===0&&G)return null;return[$,O,F.c]}function m(N,{maxDepth:U=1000,integersAsBigInt:H}={}){let Y={},O={},W=Y,$=O;for(let G=S(N,0);G<N.length;){if(N[G]==="["){let F=N[++G]==="[",Q=iN(N,G+=+F,"]");if(F){if(N[Q[1]-1]!=="]")throw new D("expected end of table declaration",{toml:N,ptr:Q[1]-1});Q[1]++}let L=Q1(Q[0],Y,O,F?2:1);if(!L)throw new D("trying to redefine an already defined table or value",{toml:N,ptr:G});$=L[2],W=L[1],G=Q[1]}else{let F=iN(N,G),Q=Q1(F[0],W,$,0);if(!Q)throw new D("trying to redefine an already defined table or value",{toml:N,ptr:G});let L=EN(N,F[1],void 0,U,H);Q[1][Q[0]]=L[0],G=L[1]}if(G=S(N,G,!0),N[G]&&N[G]!==`
213
+ `&&N[G]!=="\r")throw new D("each key-value declaration must be followed by an end-of-line",{toml:N,ptr:G});G=S(N,G)}return Y}/*!
215
214
  * Copyright (c) Squirrel Chat et al., All rights reserved.
216
215
  * SPDX-License-Identifier: BSD-3-Clause
217
216
  *
@@ -237,16 +236,16 @@ ${$}`,H);this.line=Y,this.column=W,this.codeblock=$}}/*!
237
236
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
238
237
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
239
238
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
240
- */var K1=/^[a-z0-9-_]+$/i;function _N(N){let H=typeof N;if(H==="object"){if(Array.isArray(N))return"array";if(N instanceof Date)return"date"}return H}function xY(N){for(let H=0;H<N.length;H++)if(_N(N[H])!=="object")return!1;return N.length!=0}function R0(N){return JSON.stringify(N).replace(/\x7f/g,"\\u007f")}function w0(N,H,Y,W){if(Y===0)throw Error("Could not stringify the object: maximum object depth exceeded");if(H==="number"){if(isNaN(N))return"nan";if(N===1/0)return"inf";if(N===-1/0)return"-inf";if(W&&Number.isInteger(N))return N.toFixed(1);return N.toString()}if(H==="bigint"||H==="boolean")return N.toString();if(H==="string")return R0(N);if(H==="date"){if(isNaN(N.getTime()))throw TypeError("cannot serialize invalid date");return N.toISOString()}if(H==="object")return fY(N,Y,W);if(H==="array")return kY(N,Y,W)}function fY(N,H,Y){let W=Object.keys(N);if(W.length===0)return"{}";let $="{ ";for(let G=0;G<W.length;G++){let U=W[G];if(G)$+=", ";$+=K1.test(U)?U:R0(U),$+=" = ",$+=w0(N[U],_N(N[U]),H-1,Y)}return $+" }"}function kY(N,H,Y){if(N.length===0)return"[]";let W="[ ";for(let $=0;$<N.length;$++){if($)W+=", ";if(N[$]===null||N[$]===void 0)throw TypeError("arrays cannot contain null or undefined values");W+=w0(N[$],_N(N[$]),H-1,Y)}return W+" ]"}function yY(N,H,Y,W){if(Y===0)throw Error("Could not stringify the object: maximum object depth exceeded");let $="";for(let G=0;G<N.length;G++)$+=`${$&&`
241
- `}[[${H}]]
242
- `,$+=_0(0,N[G],H,Y,W);return $}function _0(N,H,Y,W,$){if(W===0)throw Error("Could not stringify the object: maximum object depth exceeded");let G="",U="",Q=Object.keys(H);for(let X=0;X<Q.length;X++){let Z=Q[X];if(H[Z]!==null&&H[Z]!==void 0){let F=_N(H[Z]);if(F==="symbol"||F==="function")throw TypeError(`cannot serialize values of type '${F}'`);let M=K1.test(Z)?Z:R0(Z);if(F==="array"&&xY(H[Z]))U+=(U&&`
243
- `)+yY(H[Z],Y?`${Y}.${M}`:M,W-1,$);else if(F==="object"){let E=Y?`${Y}.${M}`:M;U+=(U&&`
244
- `)+_0(E,H[Z],E,W-1,$)}else G+=M,G+=" = ",G+=w0(H[Z],F,W,$),G+=`
245
- `}}if(N&&(G||!U))G=G?`[${N}]
246
- ${G}`:`[${N}]`;return G&&U?`${G}
247
- ${U}`:G||U}function t(N,{maxDepth:H=1000,numbersAsFloat:Y=!1}={}){if(_N(N)!=="object")throw TypeError("stringify can only be called with an object");let W=_0(0,N,"",H,Y);if(W[W.length-1]!==`
248
- `)return W+`
249
- `;return W}/*!
239
+ */var X1=/^[a-z0-9-_]+$/i;function CN(N){let U=typeof N;if(U==="object"){if(Array.isArray(N))return"array";if(N instanceof Date)return"date"}return U}function AY(N){for(let U=0;U<N.length;U++)if(CN(N[U])!=="object")return!1;return N.length!=0}function B0(N){return JSON.stringify(N).replace(/\x7f/g,"\\u007f")}function E0(N,U,H,Y){if(H===0)throw Error("Could not stringify the object: maximum object depth exceeded");if(U==="number"){if(isNaN(N))return"nan";if(N===1/0)return"inf";if(N===-1/0)return"-inf";if(Y&&Number.isInteger(N))return N.toFixed(1);return N.toString()}if(U==="bigint"||U==="boolean")return N.toString();if(U==="string")return B0(N);if(U==="date"){if(isNaN(N.getTime()))throw TypeError("cannot serialize invalid date");return N.toISOString()}if(U==="object")return TY(N,H,Y);if(U==="array")return BY(N,H,Y)}function TY(N,U,H){let Y=Object.keys(N);if(Y.length===0)return"{}";let O="{ ";for(let W=0;W<Y.length;W++){let $=Y[W];if(W)O+=", ";O+=X1.test($)?$:B0($),O+=" = ",O+=E0(N[$],CN(N[$]),U-1,H)}return O+" }"}function BY(N,U,H){if(N.length===0)return"[]";let Y="[ ";for(let O=0;O<N.length;O++){if(O)Y+=", ";if(N[O]===null||N[O]===void 0)throw TypeError("arrays cannot contain null or undefined values");Y+=E0(N[O],CN(N[O]),U-1,H)}return Y+" ]"}function EY(N,U,H,Y){if(H===0)throw Error("Could not stringify the object: maximum object depth exceeded");let O="";for(let W=0;W<N.length;W++)O+=`${O&&`
240
+ `}[[${U}]]
241
+ `,O+=C0(0,N[W],U,H,Y);return O}function C0(N,U,H,Y,O){if(Y===0)throw Error("Could not stringify the object: maximum object depth exceeded");let W="",$="",G=Object.keys(U);for(let F=0;F<G.length;F++){let Q=G[F];if(U[Q]!==null&&U[Q]!==void 0){let L=CN(U[Q]);if(L==="symbol"||L==="function")throw TypeError(`cannot serialize values of type '${L}'`);let V=X1.test(Q)?Q:B0(Q);if(L==="array"&&AY(U[Q]))$+=($&&`
242
+ `)+EY(U[Q],H?`${H}.${V}`:V,Y-1,O);else if(L==="object"){let T=H?`${H}.${V}`:V;$+=($&&`
243
+ `)+C0(T,U[Q],T,Y-1,O)}else W+=V,W+=" = ",W+=E0(U[Q],L,Y,O),W+=`
244
+ `}}if(N&&(W||!$))W=W?`[${N}]
245
+ ${W}`:`[${N}]`;return W&&$?`${W}
246
+ ${$}`:W||$}function s(N,{maxDepth:U=1000,numbersAsFloat:H=!1}={}){if(CN(N)!=="object")throw TypeError("stringify can only be called with an object");let Y=C0(0,N,"",U,H);if(Y[Y.length-1]!==`
247
+ `)return Y+`
248
+ `;return Y}/*!
250
249
  * Copyright (c) Squirrel Chat et al., All rights reserved.
251
250
  * SPDX-License-Identifier: BSD-3-Clause
252
251
  *
@@ -272,13 +271,13 @@ ${U}`:G||U}function t(N,{maxDepth:H=1000,numbersAsFloat:Y=!1}={}){if(_N(N)!=="ob
272
271
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
273
272
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
274
273
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275
- */function O(N,H=200){return new Response(JSON.stringify(N),{status:H,headers:{"content-type":"application/json"}})}function z(N,H,Y){return O({error:H,detail:Y},N)}async function V(N){try{return await N.json()}catch{throw new A("Invalid JSON body")}}function J(N,H){if(typeof N!=="string"||N.length===0)throw new A(`Missing or invalid field: ${H}`);return N}class A extends Error{constructor(N){super(N);this.name="BadRequestError"}}import{promises as g}from"fs";import v from"path";import P0 from"path";function HN(N,H){let Y=P0.resolve(N),W=P0.resolve(Y,H||".");if(W!==Y&&!W.startsWith(Y+P0.sep))throw new sN(H);return W}class sN extends Error{constructor(N){super(`Path escapes workspace: ${N}`);this.name="PathEscapeError"}}var bY=2097152,qY=new Set([".png",".jpg",".jpeg",".gif",".webp",".svg",".bmp",".ico",".avif"]),IY=new Set([".zip",".tar",".gz",".7z",".exe",".dll",".so",".dylib",".pdf",".woff",".woff2",".ttf",".mp3",".mp4",".mov",".webm",".sqlite",".db",".bin"]);function jY(N){let H=v.extname(N).toLowerCase();if(H===".md"||H===".markdown")return"markdown";if(H===".json"||H===".jsonl")return"json";if(qY.has(H))return"image";if(IY.has(H))return"binary";return"text"}function r(N,H){return HN(B(H),N)}function x0(N,H){let Y=v.relative(B(H),N);return Y===""?".":u(Y)}async function L1(N,H){let Y=await g.stat(N),W={name:v.basename(N)||".",path:x0(N,H),type:Y.isDirectory()?"dir":"file",modifiedAt:Y.mtime.toISOString()};if(W.type==="file")return W.size=Y.size,W;let $=await g.readdir(N,{withFileTypes:!0}),G=await Promise.all($.map((U)=>L1(v.join(N,U.name),H)));return G.sort((U,Q)=>U.type!==Q.type?U.type==="dir"?-1:1:U.name.localeCompare(Q.name)),W.children=G,W}async function M1(N=".",H=K){return L1(r(N,H),H)}async function J1(N,H=K){let Y=r(N,H),W=await g.stat(Y);if(W.isDirectory())throw Error(`Not a file: ${N}`);let $=jY(Y),G={path:x0(Y,H),kind:$,size:W.size,modifiedAt:W.mtime.toISOString()};if($==="image"||$==="binary")return G;if(W.size>bY)throw Error(`File too large to open (${W.size} bytes): ${N}`);return G.content=await g.readFile(Y,"utf8"),G}async function B1(N,H,Y=K){let W=r(N,Y);await g.mkdir(v.dirname(W),{recursive:!0}),await g.writeFile(W,H,"utf8")}async function A1(N,H=K){await g.mkdir(r(N,H),{recursive:!0})}async function D1(N,H=K){let Y=r(N,H);if(Y===v.resolve(B(H)))throw Error("Cannot delete the workspace root");await g.rm(Y,{recursive:!0,force:!0})}async function C1(N,H,Y=K){let W=r(N,Y),$=r(H,Y);if(W===v.resolve(B(Y)))throw Error("Cannot rename the workspace root");await g.mkdir(v.dirname($),{recursive:!0}),await g.rename(W,$)}async function S1(N,H,Y,W=K){let $=v.basename(H);if(!$||$==="."||$==="..")throw Error(`Invalid file name: ${H}`);let G=HN(B(W),v.join(N||".",$));return await g.mkdir(v.dirname(G),{recursive:!0}),await Bun.write(G,Y),x0(G,W)}function tN(N,H=K){return r(N,H)}import{randomBytes as vY}from"crypto";function rN(N){return`${N}_${vY(6).toString("hex")}`}var f0=null;function E1(N){f0=N}function h(N,H){f0?.publish(N,JSON.stringify(H))}function R1(N,H){f0?.publish(N,H)}import{promises as PN}from"fs";import gY from"os";import k0 from"path";var e=new Map,w1=!1;function y0(N){return k0.join(a(),N,"meta.json")}var _1=k0.join(gY.homedir(),".agenthost");function P1(N){let H=JSON.parse(N);if(H.cwd?.startsWith(_1))H.cwd=I+H.cwd.slice(_1.length);return H}async function x1(N){await PN.mkdir(k0.join(a(),N.id),{recursive:!0}),await PN.writeFile(y0(N.id),JSON.stringify(N,null,2)+`
276
- `,"utf8")}async function hY(){if(w1)return;w1=!0;let N;try{N=await PN.readdir(a())}catch{return}for(let H of N){if(e.has(H))continue;try{let Y=await PN.readFile(y0(H),"utf8"),W=P1(Y);e.set(W.id,W)}catch{}}}async function f1(N){let H={id:rN("run"),projectId:N.projectId??K,prompt:N.prompt,status:"starting",startedAt:new Date().toISOString(),cwd:N.cwd,sandbox:N.sandbox,approvalPolicy:N.approvalPolicy,approvalsReviewer:N.approvalsReviewer,model:N.model,effort:N.effort,source:N.source,scheduleId:N.scheduleId,scheduleName:N.scheduleName};return e.set(H.id,H),await x1(H),H}async function YN(N,H){let Y=await D(N);if(!Y)return null;let W={...Y,...H};return e.set(N,W),await x1(W),W}async function D(N){if(e.has(N))return e.get(N);try{let H=await PN.readFile(y0(N),"utf8"),Y=P1(H);return e.set(N,Y),Y}catch{return null}}async function k1(N){await hY();let H=[...e.values()];return(N?H.filter((W)=>W.projectId===N):H).sort((W,$)=>$.startedAt.localeCompare(W.startedAt))}function m(N){return N==="queued"||N==="starting"||N==="running"||N==="waiting_approval"}import{promises as y1}from"fs";import mY from"path";function b1(N){return mY.join(a(),N,"events.jsonl")}async function q1(N){await y1.appendFile(b1(N.runId),JSON.stringify(N)+`
277
- `,"utf8")}var cY=/"type":\s*"run\.(started|resumed|steered)"/,lY=400;async function I1(N,H={}){let Y;try{Y=await y1.readFile(b1(N),"utf8")}catch{return{events:[],offset:0,total:0}}let W=Y.split(`
278
- `);if(W.length>0&&W[W.length-1]==="")W.pop();let $=W.length,G=Math.max(0,Math.min(H.before??$,$)),U=H.limit===void 0?0:Math.max(0,G-H.limit);if(U>0){for(let X=U;X>=Math.max(0,U-lY);X--)if(cY.test(W[X])){U=X;break}}let Q=[];for(let X=U;X<G;X++){let Z=W[X].trim();if(!Z)continue;try{Q.push(JSON.parse(Z))}catch{}}return{events:Q,offset:U,total:$}}import{promises as LH}from"fs";import $W from"os";import MH from"path";var v1={name:"junhost",version:"0.2.2",description:"Jun \u2014 a self-hosted dashboard that runs and supervises Codex as a 24/7 local/VPS agent: chat runs, workspace files, remote browser, skills, MCP, schedules.",type:"module",bin:{jun:"bin/jun.js"},files:["bin","dist","ui-dist","README.md"],engines:{bun:">=1.2.0"},keywords:["codex","agent","ai","dashboard","self-hosted","browser-automation","mcp"],license:"UNLICENSED",scripts:{dev:"bun --hot src/index.ts",start:"bun src/index.ts",build:"bun build src/index.ts src/mcp-server.ts src/browser-mcp-server.ts --target=bun --minify --outdir=dist",typecheck:"bunx tsc --noEmit"},dependencies:{"agent-browser":"^0.27.1",cloakbrowser:"^0.3.31"},devDependencies:{"@junhost/shared":"workspace:*","@modelcontextprotocol/sdk":"^1.29.0","@types/bun":"^1.2.0","smol-toml":"^1.6.1",typescript:"^5.6.3",zod:"3"}};var ON=v1.version;import dY from"os";import P from"path";import{existsSync as kN,readdirSync as aY}from"fs";import{mkdir as p1}from"fs/promises";import{randomUUID as oY}from"crypto";import{readFileSync as iY}from"fs";import{promises as pY}from"fs";import nY from"path";var g1=["browserProxy","browserNoProxy"];function h1(){return nY.join(I,"config.json")}var eN=null;function N0(){if(eN)return eN;let N={};try{N=JSON.parse(iY(h1(),"utf8"))}catch{}let H={};for(let Y of g1){let W=N[Y];if(typeof W==="string"&&W.length>0)H[Y]=W}return eN=H,H}async function m1(N){let H={...N0()};for(let Y of g1){if(!(Y in N))continue;let W=N[Y];if(typeof W==="string"&&W.trim().length>0)H[Y]=W.trim();else delete H[Y]}return await pY.writeFile(h1(),JSON.stringify(H,null,2)+`
279
- `,"utf8"),eN=H,H}var sY="jun",c1=200,n1=process.platform==="win32"?"agent-browser.exe":"agent-browser";function d1(){let N=import.meta.dir;for(let H=0;H<8;H++){let Y=P.join(N,"node_modules",".bin");if(kN(P.join(Y,n1)))return Y;let W=P.dirname(N);if(W===N)break;N=W}return null}function tY(N){let H=d1();if(H)return[P.join(H,n1),...N];return process.platform==="win32"?["cmd","/c","agent-browser",...N]:["agent-browser",...N]}var l1=Object.keys(process.env).find((N)=>N.toUpperCase()==="PATH")??"PATH",$0="agent",Y0=null,H0=[];function a1(){let N=q("CLOAK_PATH");if(N&&kN(N))return N;let H=P.join(dY.homedir(),".cloakbrowser"),Y;try{Y=aY(H).filter(($)=>$.startsWith("chromium-"))}catch{return null}Y.sort().reverse();let W=process.platform==="win32"?"chrome.exe":"chrome";for(let $ of Y){let G=P.join(H,$,W);if(kN(G))return G}return null}function rY(){let N=q("CHROME_PATH");if(N&&kN(N))return N;return(process.platform==="win32"?[`${process.env.ProgramFiles}\\Google\\Chrome\\Application\\chrome.exe`,`${process.env["ProgramFiles(x86)"]}\\Google\\Chrome\\Application\\chrome.exe`,`${process.env.LocalAppData}\\Google\\Chrome\\Application\\chrome.exe`]:process.platform==="darwin"?["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"]:["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/opt/google/chrome/chrome"]).find((Y)=>Y&&kN(Y))??null}function I0(){let N={AGENT_BROWSER_SESSION:sY,AGENT_BROWSER_PROFILE:P.join(EN(),"profile"),AGENT_BROWSER_DOWNLOAD_PATH:P.join(B(),"downloads"),AGENT_BROWSER_SCREENSHOT_DIR:P.join(B(),"screenshots"),AGENT_BROWSER_ARGS:"--disable-blink-features=AutomationControlled"},H=G0().value;if(H)N.AGENT_BROWSER_PROXY=H;let Y=U0().value;if(Y)N.AGENT_BROWSER_PROXY_BYPASS=Y;let W=d1();if(W)N[l1]=`${W}${P.delimiter}${process.env[l1]??""}`;let $=a1();if($)return N.AGENT_BROWSER_EXECUTABLE_PATH=$,N;let G=rY(),U=process.platform!=="linux"||Boolean(process.env.DISPLAY),Q=q("BROWSER_HEADED")!=="false"&&U;if(process.platform==="linux"&&!process.env.DISPLAY&&q("BROWSER_HEADED")!=="false")console.warn("[browser] No cloakbrowser engine and no DISPLAY \u2014 running HEADLESS. Edge "+"WAFs (Reddit/Fastly) will block headless. Install cloakbrowser (works headless) or set up Xvfb + Google Chrome with DISPLAY for a VPS.");if(G&&Q)N.AGENT_BROWSER_EXECUTABLE_PATH=G,N.AGENT_BROWSER_HEADED="true";else{if(G)N.AGENT_BROWSER_EXECUTABLE_PATH=G;N.AGENT_BROWSER_USER_AGENT="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36"}return N}function eY(){return{...process.env,...I0()}}function NW(){let N=G0().value;if(!N)return[];let H=["--proxy",N],Y=U0().value;if(Y)H.push("--proxy-bypass",Y);return H}function G0(){let N=N0().browserProxy;if(N)return{value:N,source:"settings"};let H=q("BROWSER_PROXY")?.trim();if(H)return{value:H,source:"env"};return{value:null,source:"none"}}function U0(){let N=N0().browserNoProxy;if(N)return{value:N,source:"settings"};let H=q("BROWSER_NO_PROXY")?.trim();if(H)return{value:H,source:"env"};return{value:null,source:"none"}}var q0=!1;function o1(N){if(q0)return;if(q("NO_CLOAK_DOWNLOAD")==="true")return;if(a1())return;q0=!0,console.log("[browser] cloakbrowser Stealth Chromium not found \u2014 downloading in background\u2026"),Bun.spawn([process.execPath,"x","cloakbrowser","install"],{cwd:N,stdout:"inherit",stderr:"inherit"}).exited.then((Y)=>{if(q0=!1,Y===0)console.log("[browser] cloakbrowser Stealth Chromium ready.");else console.warn(`[browser] cloakbrowser download exited with code ${Y}.`)})}async function u1(N,H,Y){if(!N)return"";let W=N.getReader(),$=new TextDecoder,G="",U=Date.now()+Y;try{while(Date.now()<U){let Q=Math.min(H,U-Date.now()),X=await Promise.race([W.read(),new Promise((Z)=>setTimeout(()=>Z("timeout"),Q))]);if(X==="timeout"||X.done)break;G+=$.decode(X.value,{stream:!0})}}finally{W.releaseLock()}return G}async function T(N,H={}){let Y=[...NW(),...N],W=H.json?[...Y,"--json"]:Y,$=Bun.spawn(tY(W),{env:eY(),stdout:"pipe",stderr:"pipe"}),G=setTimeout(()=>$.kill(),H.timeoutMs??120000),U=await $.exited;clearTimeout(G);let[Q,X]=await Promise.all([u1($.stdout,80,1500),u1($.stderr,60,300)]),Z,F;if(H.json)try{let M=JSON.parse(Q);if(Z=M.data??M,M.success===!1)F=typeof M.error==="string"?M.error:"command failed"}catch{}return{ok:U===0&&!F,stdout:Q,stderr:X,data:Z,error:F}}function p(N,H){if(H0.unshift({id:oY(),ts:new Date().toISOString(),kind:N,detail:H}),H0.length>c1)H0.length=c1}function s1(){return H0}function t1(){return $0}function r1(N){$0=N,p("control",N)}function e1(){return Y0}var NH=(N)=>typeof N==="object"&&N!==null?N:{};function W0(N){if(typeof N==="string")return N;let H=NH(N);for(let Y of["url","title","value","text","result"])if(typeof H[Y]==="string")return H[Y];return null}var HW=2500,fN=null,xN=null;function n(){fN=null}async function yN(){if(fN&&Date.now()-fN.at<HW)return{...fN.status,controller:$0};if(xN)return xN;return xN=YW().then((N)=>{return fN={at:Date.now(),status:N},N}).finally(()=>{xN=null}),xN}async function YW(){let N=await T(["stream","status"],{json:!0,timeoutMs:30000}),H=NH(N.data),Y=N.ok&&H.connected===!0,W=Y&&H.enabled===!0;Y0=W&&typeof H.port==="number"?H.port:null;let $=null,G=null;if(Y){let[U,Q]=await Promise.all([T(["get","url"],{json:!0,timeoutMs:30000}),T(["get","title"],{json:!0,timeoutMs:30000})]);$=U.ok?W0(U.data):null,G=Q.ok?W0(Q.data):null}return{running:Y,streaming:W,streamPort:Y0,url:$,title:G,controller:$0}}var i1={width:1280,height:720};async function j0(){await T(["set","viewport",String(i1.width),String(i1.height)],{timeoutMs:30000})}async function HH(){await Promise.all(["screenshots","downloads","reports"].map((N)=>p1(P.join(B(),N),{recursive:!0})))}async function YH(N){await HH(),await p1(P.join(EN(),"profile"),{recursive:!0});let H=await T(["open",N??"about:blank"],{timeoutMs:180000});if(!H.ok)throw Error(`agent-browser open failed: ${H.stderr||H.stdout}`);return await j0(),await T(["stream","enable"],{json:!0,timeoutMs:30000}),p("start",N??"about:blank"),n(),yN()}async function WH(){await T(["close"],{timeoutMs:30000}),Y0=null,n(),p("stop")}async function $H(N){let H=await T(["open",N],{timeoutMs:120000});if(!H.ok)throw Error(`Navigation failed: ${H.stderr||H.stdout}`);await j0(),n(),p("navigate",N)}async function GH(N){let H=await T([N],{timeoutMs:60000});if(!H.ok)throw Error(`${N} failed: ${H.stderr||H.stdout}`);await j0(),n(),p(N)}async function UH(N){let H=await T(["press",N],{timeoutMs:30000});if(!H.ok)throw Error(`Key press failed: ${H.stderr||H.stdout}`);n()}async function QH(){await HH();let N=`browser-${new Date().toISOString().replace(/[:.]/g,"-")}.png`,H=P.join(B(),"screenshots",N),Y=await T(["screenshot",H],{timeoutMs:60000});if(!Y.ok)throw Error(`Screenshot failed: ${Y.stderr||Y.stdout}`);return p("screenshot",`screenshots/${N}`),`screenshots/${N}`}async function XH(N=!0){let H=await T(["snapshot",...N?["-i"]:[]],{timeoutMs:60000});if(!H.ok)throw Error(`Snapshot failed: ${H.stderr||H.stdout}`);return H.stdout.trim()}async function ZH(N){let H=await T(["click",N],{timeoutMs:30000});if(!H.ok)throw Error(`Click failed: ${H.stderr||H.stdout}`);n(),p("click",N)}async function OH(N,H){let Y=await T(["fill",N,H],{timeoutMs:30000});if(!Y.ok)throw Error(`Fill failed: ${Y.stderr||Y.stdout}`);p("fill",N)}async function zH(N){let Y=await T(N?["get","text",N]:["get","text","body"],{json:!0,timeoutMs:30000});if(!Y.ok)throw Error(`Read failed: ${Y.stderr||Y.stdout}`);return W0(Y.data)??Y.stdout.trim()}async function FH(N){let H=await T(["eval",N],{json:!0,timeoutMs:30000});if(!H.ok)throw Error(`Eval failed: ${H.stderr||H.stdout}`);return W0(H.data)??H.stdout.trim()}async function VH(N,H={}){if(!Array.isArray(N)||N.length===0||!N.every((W)=>typeof W==="string"))throw Error("args must be a non-empty array of strings");if(N[0]==="close"||N[0]==="--all")throw Error("`close` is not allowed \u2014 the daemon owns the shared session's lifecycle");let Y=await T(N,{json:H.json,timeoutMs:H.timeoutMs??120000});return n(),p("exec",N.join(" ").slice(0,80)),{ok:Y.ok,stdout:Y.stdout,stderr:Y.stderr,error:Y.error}}class v0{send;handlers;nextId=1;pending=new Map;constructor(N,H){this.send=N;this.handlers=H}request(N,H){let Y=this.nextId++,W=new Promise(($,G)=>{this.pending.set(Y,{method:N,resolve:$,reject:G})});return this.send(JSON.stringify({jsonrpc:"2.0",id:Y,method:N,params:H})),W}notify(N,H){this.send(JSON.stringify({jsonrpc:"2.0",method:N,params:H}))}respond(N,H){this.send(JSON.stringify({jsonrpc:"2.0",id:N,result:H}))}respondError(N,H,Y){this.send(JSON.stringify({jsonrpc:"2.0",id:N,error:{code:H,message:Y}}))}handleLine(N){let H;try{H=JSON.parse(N)}catch{console.warn("[codex] non-JSON line on stdout:",N.slice(0,200));return}if(H.method!==void 0){if(H.id!==void 0)this.handlers.onServerRequest(H.id,H.method,H.params);else this.handlers.onNotification(H.method,H.params);return}if(H.id===void 0)return;let Y=this.pending.get(Number(H.id));if(!Y)return;if(this.pending.delete(Number(H.id)),H.error)Y.reject(Error(`${Y.method} failed: ${H.error.message} (${H.error.code})`));else Y.resolve(H.result)}failAll(N){for(let H of this.pending.values())H.reject(Error(`${H.method} failed: ${N}`));this.pending.clear()}}function KH(N){let H="",Y=new TextDecoder;return{push(W){H+=Y.decode(W,{stream:!0});let $;while(($=H.indexOf(`
280
- `))!==-1){let G=H.slice(0,$).replace(/\r$/,"");if(H=H.slice($+1),G.trim().length>0)N(G)}},flush(){let W=H.trim();if(H="",W.length>0)N(W)}}}var g0=60000,h0=5,JH=30000;class m0{handlers;proc=null;rpc=null;initialized=!1;exitTimes=[];backoffUntil=0;lastExitCode=null;constructor(N){this.handlers=N}get running(){return this.proc!==null}get health(){let N=Math.max(0,this.backoffUntil-Date.now());return{running:this.proc!==null,lastExitCode:this.lastExitCode,crashLooping:N>0,backoffMs:N}}async start(){if(this.proc)return;let N=this.backoffUntil-Date.now();if(N>0)throw Error(`codex app-server is crash-looping (${h0}+ exits in ${g0/1000}s) \u2014 `+`backing off, retry in ${Math.ceil(N/1000)}s. Run \`jun doctor\` to diagnose.`);await GW();let H=Bun.which("codex");if(!H)throw Error("codex binary not found in PATH. Install Codex CLI first.");let Y=/\.(cmd|bat)$/i.test(H)?["cmd","/c",H,"app-server"]:[H,"app-server"],W=Bun.spawn(Y,{cwd:B(),env:{...process.env,CODEX_HOME:j(),...I0()},stdin:"pipe",stdout:"pipe",stderr:"pipe",onExit:(G,U)=>{this.lastExitCode=U,this.rpc?.failAll(`codex app-server exited (code ${U})`),this.proc=null,this.rpc=null,this.initialized=!1;let Q=Date.now();if(this.exitTimes=this.exitTimes.filter((X)=>Q-X<g0),this.exitTimes.push(Q),this.exitTimes.length>=h0)this.backoffUntil=Q+JH,this.exitTimes=[],console.error(`[codex] app-server crash-looping (${h0} exits in ${g0/1000}s) \u2014 backing off ${JH/1000}s`);else console.log(`[codex] app-server exited (code ${U}) \u2014 will restart on next run`);this.handlers.onExit(U)}});this.proc=W,this.rpc=new v0((G)=>{W.stdin.write(G+`
281
- `),W.stdin.flush()},{onNotification:(G,U)=>this.handlers.onNotification(G,U),onServerRequest:(G,U,Q)=>this.handlers.onServerRequest(G,U,Q)});let $=this.rpc;(async()=>{let G=KH((U)=>$.handleLine(U));for await(let U of W.stdout)G.push(U);G.flush()})(),(async()=>{let G=new TextDecoder;for await(let U of W.stderr){let Q=G.decode(U).trimEnd();if(Q)console.error("[codex:stderr]",Q)}})()}async initializeOnce(){if(this.initialized)return;await this.requireRpc().request("initialize",{clientInfo:{name:"jun",title:"Jun",version:ON},capabilities:{experimentalApi:!0}}),this.requireRpc().notify("initialized",{}),this.initialized=!0}request(N,H){return this.requireRpc().request(N,H)}respond(N,H){this.requireRpc().respond(N,H)}respondError(N,H,Y){this.requireRpc().respondError(N,H,Y)}requireRpc(){if(!this.rpc)throw Error("codex app-server is not running");return this.rpc}}async function GW(){let N=MH.join(j(),"auth.json");try{await LH.access(N);return}catch{}let H=MH.join($W.homedir(),".codex","auth.json");try{await LH.copyFile(H,N),console.log("[codex] copied auth.json from ~/.codex into project codex-home")}catch{console.warn("[codex] no auth.json found in ~/.codex \u2014 runs may fail until `codex login` is run")}}var bN=null,Q0=null;function X0(){return bN}function BH(){return Q0}function AH(N){if(bN=N,N)Q0=null}function Z0(){bN=null,Q0=null}function DH(N){let H=N??{};if(Q0={success:H.success===!0,error:H.error??null,at:new Date().toISOString()},!H.loginId||bN?.loginId===H.loginId)bN=null}var UW={"thread/started":"codex.thread.started","turn/started":"codex.turn.started","turn/completed":"codex.turn.completed","item/started":"codex.item.started","item/completed":"codex.item.completed","item/agentMessage/delta":"codex.message.delta","item/reasoning/textDelta":"codex.reasoning.delta","item/reasoning/summaryTextDelta":"codex.reasoning.summary.delta","item/commandExecution/outputDelta":"codex.command.output","item/fileChange/patchUpdated":"codex.file_change.patch",error:"codex.error"},QW={"item/commandExecution/requestApproval":"codex.approval.command","item/fileChange/requestApproval":"codex.approval.file_change","item/permissions/requestApproval":"codex.approval.permissions","item/tool/requestUserInput":"codex.approval.user_input","mcpServer/elicitation/request":"codex.approval.elicitation"};function CH(N){return UW[N]??`codex.${N.split("/").join(".")}`}function SH(N){return QW[N]??null}function TH(N){return N==="item/commandExecution/requestApproval"||N==="item/fileChange/requestApproval"||N==="item/permissions/requestApproval"}function qN(N){if(typeof N!=="object"||N===null)return null;let H=N;if(typeof H.threadId==="string")return H.threadId;let Y=H.thread;if(typeof Y==="object"&&Y!==null){let W=Y.id;if(typeof W==="string")return W}return null}var EH={readOnly:"read-only",workspaceWrite:"workspace-write",dangerFullAccess:"danger-full-access"},RH={readOnly:{type:"readOnly"},workspaceWrite:{type:"workspaceWrite"},dangerFullAccess:{type:"dangerFullAccess"}},c0={never:"never",onRequest:"on-request",onFailure:"on-failure",untrusted:"untrusted"},O0=`# Who you are
274
+ */function Z(N,U=200){return new Response(JSON.stringify(N),{status:U,headers:{"content-type":"application/json"}})}function X(N,U,H){return Z({error:U,detail:H},N)}async function z(N){try{return await N.json()}catch{throw new J("Invalid JSON body")}}function K(N,U){if(typeof N!=="string"||N.length===0)throw new J(`Missing or invalid field: ${U}`);return N}class J extends Error{constructor(N){super(N);this.name="BadRequestError"}}import{promises as b}from"fs";import y from"path";import R0 from"path";function NN(N,U){let H=R0.resolve(N),Y=R0.resolve(H,U||".");if(Y!==H&&!Y.startsWith(H+R0.sep))throw new dN(U);return Y}class dN extends Error{constructor(N){super(`Path escapes workspace: ${N}`);this.name="PathEscapeError"}}var CY=2097152,RY=new Set([".png",".jpg",".jpeg",".gif",".webp",".svg",".bmp",".ico",".avif"]),SY=new Set([".zip",".tar",".gz",".7z",".exe",".dll",".so",".dylib",".pdf",".woff",".woff2",".ttf",".mp3",".mp4",".mov",".webm",".sqlite",".db",".bin"]);function _Y(N){let U=y.extname(N).toLowerCase();if(U===".md"||U===".markdown")return"markdown";if(U===".json"||U===".jsonl")return"json";if(RY.has(U))return"image";if(SY.has(U))return"binary";return"text"}function t(N){return NN(M(),N)}function S0(N){let U=y.relative(M(),N);return U===""?".":l(U)}async function Z1(N){let U=await b.stat(N),H={name:y.basename(N)||".",path:S0(N),type:U.isDirectory()?"dir":"file",modifiedAt:U.mtime.toISOString()};if(H.type==="file")return H.size=U.size,H;let Y=await b.readdir(N,{withFileTypes:!0}),O=await Promise.all(Y.map((W)=>Z1(y.join(N,W.name))));return O.sort((W,$)=>W.type!==$.type?W.type==="dir"?-1:1:W.name.localeCompare($.name)),H.children=O,H}async function L1(N="."){return Z1(t(N))}async function z1(N){let U=t(N),H=await b.stat(U);if(H.isDirectory())throw Error(`Not a file: ${N}`);let Y=_Y(U),O={path:S0(U),kind:Y,size:H.size,modifiedAt:H.mtime.toISOString()};if(Y==="image"||Y==="binary")return O;if(H.size>CY)throw Error(`File too large to open (${H.size} bytes): ${N}`);return O.content=await b.readFile(U,"utf8"),O}async function D1(N,U){let H=t(N);await b.mkdir(y.dirname(H),{recursive:!0}),await b.writeFile(H,U,"utf8")}async function K1(N){await b.mkdir(t(N),{recursive:!0})}async function V1(N){let U=t(N);if(U===y.resolve(M()))throw Error("Cannot delete the workspace root");await b.rm(U,{recursive:!0,force:!0})}async function M1(N,U){let H=t(N),Y=t(U);if(H===y.resolve(M()))throw Error("Cannot rename the workspace root");await b.mkdir(y.dirname(Y),{recursive:!0}),await b.rename(H,Y)}async function J1(N,U,H){let Y=y.basename(U);if(!Y||Y==="."||Y==="..")throw Error(`Invalid file name: ${U}`);let O=NN(M(),y.join(N||".",Y));return await b.mkdir(y.dirname(O),{recursive:!0}),await Bun.write(O,H),S0(O)}function oN(N){return t(N)}import{randomBytes as jY}from"crypto";function nN(N){return`${N}_${jY(6).toString("hex")}`}var _0=null;function T1(N){_0=N}function q(N,U){_0?.publish(N,JSON.stringify(U))}function B1(N,U){_0?.publish(N,U)}import{promises as RN}from"fs";import PY from"os";import j0 from"path";var r=new Map,E1=!1;function P0(N){return j0.join(d(),N,"meta.json")}var C1=j0.join(PY.homedir(),".agenthost");function R1(N){let U=JSON.parse(N);if(U.cwd?.startsWith(C1))U.cwd=f+U.cwd.slice(C1.length);return U}async function S1(N){await RN.mkdir(j0.join(d(),N.id),{recursive:!0}),await RN.writeFile(P0(N.id),JSON.stringify(N,null,2)+`
275
+ `,"utf8")}async function IY(){if(E1)return;E1=!0;let N;try{N=await RN.readdir(d())}catch{return}for(let U of N){if(r.has(U))continue;try{let H=await RN.readFile(P0(U),"utf8"),Y=R1(H);r.set(Y.id,Y)}catch{}}}async function _1(N){let U={id:nN("run"),prompt:N.prompt,status:"starting",startedAt:new Date().toISOString(),cwd:N.cwd,sandbox:N.sandbox,approvalPolicy:N.approvalPolicy,approvalsReviewer:N.approvalsReviewer,model:N.model,effort:N.effort,source:N.source,scheduleId:N.scheduleId,scheduleName:N.scheduleName};return r.set(U.id,U),await S1(U),U}async function UN(N,U){let H=await A(N);if(!H)return null;let Y={...H,...U};return r.set(N,Y),await S1(Y),Y}async function A(N){if(r.has(N))return r.get(N);try{let U=await RN.readFile(P0(N),"utf8"),H=R1(U);return r.set(N,H),H}catch{return null}}async function j1(){return await IY(),[...r.values()].sort((N,U)=>U.startedAt.localeCompare(N.startedAt))}function v(N){return N==="queued"||N==="starting"||N==="running"||N==="waiting_approval"}import{promises as P1}from"fs";import wY from"path";function I1(N){return wY.join(d(),N,"events.jsonl")}async function w1(N){await P1.appendFile(I1(N.runId),JSON.stringify(N)+`
276
+ `,"utf8")}var xY=/"type":\s*"run\.(started|resumed|steered)"/,fY=400;async function x1(N,U={}){let H;try{H=await P1.readFile(I1(N),"utf8")}catch{return{events:[],offset:0,total:0}}let Y=H.split(`
277
+ `);if(Y.length>0&&Y[Y.length-1]==="")Y.pop();let O=Y.length,W=Math.max(0,Math.min(U.before??O,O)),$=U.limit===void 0?0:Math.max(0,W-U.limit);if($>0){for(let F=$;F>=Math.max(0,$-fY);F--)if(xY.test(Y[F])){$=F;break}}let G=[];for(let F=$;F<W;F++){let Q=Y[F].trim();if(!Q)continue;try{G.push(JSON.parse(Q))}catch{}}return{events:G,offset:$,total:O}}import{promises as ZU}from"fs";import nY from"os";import LU from"path";var k1={name:"junhost",version:"0.2.5",description:"Jun \u2014 a self-hosted dashboard that runs and supervises Codex as a 24/7 local/VPS agent: chat runs, workspace files, remote browser, skills, MCP, schedules.",type:"module",bin:{jun:"bin/jun.js"},files:["bin","dist","ui-dist","README.md"],engines:{bun:">=1.2.0"},keywords:["codex","agent","ai","dashboard","self-hosted","browser-automation","mcp"],license:"UNLICENSED",scripts:{dev:"bun --hot src/index.ts",start:"bun src/index.ts",build:"bun build src/index.ts src/mcp-server.ts src/browser-mcp-server.ts --target=bun --minify --outdir=dist",typecheck:"bunx tsc --noEmit"},dependencies:{"agent-browser":"^0.27.1",cloakbrowser:"^0.3.31"},devDependencies:{"@junhost/shared":"workspace:*","@modelcontextprotocol/sdk":"^1.29.0","@types/bun":"^1.2.0","smol-toml":"^1.6.1",typescript:"^5.6.3",zod:"3"}};var c=k1.version;import vY from"os";import _ from"path";import{existsSync as jN,readdirSync as gY}from"fs";import{mkdir as c1}from"fs/promises";import{randomUUID as hY}from"crypto";import{readFileSync as yY}from"fs";import{promises as bY}from"fs";import qY from"path";var y1=["browserProxy","browserNoProxy"];function b1(){return qY.join(f,"config.json")}var aN=null;function sN(){if(aN)return aN;let N={};try{N=JSON.parse(yY(b1(),"utf8"))}catch{}let U={};for(let H of y1){let Y=N[H];if(typeof Y==="string"&&Y.length>0)U[H]=Y}return aN=U,U}async function q1(N){let U={...sN()};for(let H of y1){if(!(H in N))continue;let Y=N[H];if(typeof Y==="string"&&Y.trim().length>0)U[H]=Y.trim();else delete U[H]}return await bY.writeFile(b1(),JSON.stringify(U,null,2)+`
278
+ `,"utf8"),aN=U,U}var mY="jun",v1=200,l1=process.platform==="win32"?"agent-browser.exe":"agent-browser";function p1(){let N=import.meta.dir;for(let U=0;U<8;U++){let H=_.join(N,"node_modules",".bin");if(jN(_.join(H,l1)))return H;let Y=_.dirname(N);if(Y===N)break;N=Y}return null}function cY(N){let U=p1();if(U)return[_.join(U,l1),...N];return process.platform==="win32"?["cmd","/c","agent-browser",...N]:["agent-browser",...N]}var g1=Object.keys(process.env).find((N)=>N.toUpperCase()==="PATH")??"PATH",N0="agent",rN=null,tN=[];function u1(){let N=x("CLOAK_PATH");if(N&&jN(N))return N;let U=_.join(vY.homedir(),".cloakbrowser"),H;try{H=gY(U).filter((O)=>O.startsWith("chromium-"))}catch{return null}H.sort().reverse();let Y=process.platform==="win32"?"chrome.exe":"chrome";for(let O of H){let W=_.join(U,O,Y);if(jN(W))return W}return null}function lY(){let N=x("CHROME_PATH");if(N&&jN(N))return N;return(process.platform==="win32"?[`${process.env.ProgramFiles}\\Google\\Chrome\\Application\\chrome.exe`,`${process.env["ProgramFiles(x86)"]}\\Google\\Chrome\\Application\\chrome.exe`,`${process.env.LocalAppData}\\Google\\Chrome\\Application\\chrome.exe`]:process.platform==="darwin"?["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"]:["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/opt/google/chrome/chrome"]).find((H)=>H&&jN(H))??null}function x0(){let N={AGENT_BROWSER_SESSION:mY,AGENT_BROWSER_PROFILE:_.join(BN(),"profile"),AGENT_BROWSER_DOWNLOAD_PATH:_.join(M(),"downloads"),AGENT_BROWSER_SCREENSHOT_DIR:_.join(M(),"screenshots"),AGENT_BROWSER_ARGS:"--disable-blink-features=AutomationControlled"},U=U0().value;if(U)N.AGENT_BROWSER_PROXY=U;let H=H0().value;if(H)N.AGENT_BROWSER_PROXY_BYPASS=H;let Y=p1();if(Y)N[g1]=`${Y}${_.delimiter}${process.env[g1]??""}`;let O=u1();if(O)return N.AGENT_BROWSER_EXECUTABLE_PATH=O,N;let W=lY(),$=process.platform!=="linux"||Boolean(process.env.DISPLAY),G=x("BROWSER_HEADED")!=="false"&&$;if(process.platform==="linux"&&!process.env.DISPLAY&&x("BROWSER_HEADED")!=="false")console.warn("[browser] No cloakbrowser engine and no DISPLAY \u2014 running HEADLESS. Edge "+"WAFs (Reddit/Fastly) will block headless. Install cloakbrowser (works headless) or set up Xvfb + Google Chrome with DISPLAY for a VPS.");if(W&&G)N.AGENT_BROWSER_EXECUTABLE_PATH=W,N.AGENT_BROWSER_HEADED="true";else{if(W)N.AGENT_BROWSER_EXECUTABLE_PATH=W;N.AGENT_BROWSER_USER_AGENT="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36"}return N}function pY(){return{...process.env,...x0()}}function uY(){let N=U0().value;if(!N)return[];let U=["--proxy",N],H=H0().value;if(H)U.push("--proxy-bypass",H);return U}function U0(){let N=sN().browserProxy;if(N)return{value:N,source:"settings"};let U=x("BROWSER_PROXY")?.trim();if(U)return{value:U,source:"env"};return{value:null,source:"none"}}function H0(){let N=sN().browserNoProxy;if(N)return{value:N,source:"settings"};let U=x("BROWSER_NO_PROXY")?.trim();if(U)return{value:U,source:"env"};return{value:null,source:"none"}}var w0=!1;function i1(N){if(w0)return;if(x("NO_CLOAK_DOWNLOAD")==="true")return;if(u1())return;w0=!0,console.log("[browser] cloakbrowser Stealth Chromium not found \u2014 downloading in background\u2026"),Bun.spawn([process.execPath,"x","cloakbrowser","install"],{cwd:N,stdout:"inherit",stderr:"inherit"}).exited.then((H)=>{if(w0=!1,H===0)console.log("[browser] cloakbrowser Stealth Chromium ready.");else console.warn(`[browser] cloakbrowser download exited with code ${H}.`)})}async function h1(N,U,H){if(!N)return"";let Y=N.getReader(),O=new TextDecoder,W="",$=Date.now()+H;try{while(Date.now()<$){let G=Math.min(U,$-Date.now()),F=await Promise.race([Y.read(),new Promise((Q)=>setTimeout(()=>Q("timeout"),G))]);if(F==="timeout"||F.done)break;W+=O.decode(F.value,{stream:!0})}}finally{Y.releaseLock()}return W}async function E(N,U={}){let H=[...uY(),...N],Y=U.json?[...H,"--json"]:H,O=Bun.spawn(cY(Y),{env:pY(),stdout:"pipe",stderr:"pipe"}),W=setTimeout(()=>O.kill(),U.timeoutMs??120000),$=await O.exited;clearTimeout(W);let[G,F]=await Promise.all([h1(O.stdout,80,1500),h1(O.stderr,60,300)]),Q,L;if(U.json)try{let V=JSON.parse(G);if(Q=V.data??V,V.success===!1)L=typeof V.error==="string"?V.error:"command failed"}catch{}return{ok:$===0&&!L,stdout:G,stderr:F,data:Q,error:L}}function p(N,U){if(tN.unshift({id:hY(),ts:new Date().toISOString(),kind:N,detail:U}),tN.length>v1)tN.length=v1}function d1(){return tN}function o1(){return N0}function n1(N){N0=N,p("control",N)}function a1(){return rN}var s1=(N)=>typeof N==="object"&&N!==null?N:{};function eN(N){if(typeof N==="string")return N;let U=s1(N);for(let H of["url","title","value","text","result"])if(typeof U[H]==="string")return U[H];return null}var iY=2500,_N=null,SN=null;function u(){_N=null}async function PN(){if(_N&&Date.now()-_N.at<iY)return{..._N.status,controller:N0};if(SN)return SN;return SN=dY().then((N)=>{return _N={at:Date.now(),status:N},N}).finally(()=>{SN=null}),SN}async function dY(){let N=await E(["stream","status"],{json:!0,timeoutMs:30000}),U=s1(N.data),H=N.ok&&U.connected===!0,Y=H&&U.enabled===!0;rN=Y&&typeof U.port==="number"?U.port:null;let O=null,W=null;if(H){let[$,G]=await Promise.all([E(["get","url"],{json:!0,timeoutMs:30000}),E(["get","title"],{json:!0,timeoutMs:30000})]);O=$.ok?eN($.data):null,W=G.ok?eN(G.data):null}return{running:H,streaming:Y,streamPort:rN,url:O,title:W,controller:N0}}var m1={width:1280,height:720};async function f0(){await E(["set","viewport",String(m1.width),String(m1.height)],{timeoutMs:30000})}async function t1(){await Promise.all(["screenshots","downloads","reports"].map((N)=>c1(_.join(M(),N),{recursive:!0})))}async function r1(N){await t1(),await c1(_.join(BN(),"profile"),{recursive:!0});let U=await E(["open",N??"about:blank"],{timeoutMs:180000});if(!U.ok)throw Error(`agent-browser open failed: ${U.stderr||U.stdout}`);return await f0(),await E(["stream","enable"],{json:!0,timeoutMs:30000}),p("start",N??"about:blank"),u(),PN()}async function e1(){await E(["close"],{timeoutMs:30000}),rN=null,u(),p("stop")}async function NU(N){let U=await E(["open",N],{timeoutMs:120000});if(!U.ok)throw Error(`Navigation failed: ${U.stderr||U.stdout}`);await f0(),u(),p("navigate",N)}async function UU(N){let U=await E([N],{timeoutMs:60000});if(!U.ok)throw Error(`${N} failed: ${U.stderr||U.stdout}`);await f0(),u(),p(N)}async function HU(N){let U=await E(["press",N],{timeoutMs:30000});if(!U.ok)throw Error(`Key press failed: ${U.stderr||U.stdout}`);u()}async function YU(){await t1();let N=`browser-${new Date().toISOString().replace(/[:.]/g,"-")}.png`,U=_.join(M(),"screenshots",N),H=await E(["screenshot",U],{timeoutMs:60000});if(!H.ok)throw Error(`Screenshot failed: ${H.stderr||H.stdout}`);return p("screenshot",`screenshots/${N}`),`screenshots/${N}`}async function OU(N=!0){let U=await E(["snapshot",...N?["-i"]:[]],{timeoutMs:60000});if(!U.ok)throw Error(`Snapshot failed: ${U.stderr||U.stdout}`);return U.stdout.trim()}async function WU(N){let U=await E(["click",N],{timeoutMs:30000});if(!U.ok)throw Error(`Click failed: ${U.stderr||U.stdout}`);u(),p("click",N)}async function $U(N,U){let H=await E(["fill",N,U],{timeoutMs:30000});if(!H.ok)throw Error(`Fill failed: ${H.stderr||H.stdout}`);p("fill",N)}async function GU(N){let H=await E(N?["get","text",N]:["get","text","body"],{json:!0,timeoutMs:30000});if(!H.ok)throw Error(`Read failed: ${H.stderr||H.stdout}`);return eN(H.data)??H.stdout.trim()}async function FU(N){let U=await E(["eval",N],{json:!0,timeoutMs:30000});if(!U.ok)throw Error(`Eval failed: ${U.stderr||U.stdout}`);return eN(U.data)??U.stdout.trim()}async function QU(N,U={}){if(!Array.isArray(N)||N.length===0||!N.every((Y)=>typeof Y==="string"))throw Error("args must be a non-empty array of strings");if(N[0]==="close"||N[0]==="--all")throw Error("`close` is not allowed \u2014 the daemon owns the shared session's lifecycle");let H=await E(N,{json:U.json,timeoutMs:U.timeoutMs??120000});return u(),p("exec",N.join(" ").slice(0,80)),{ok:H.ok,stdout:H.stdout,stderr:H.stderr,error:H.error}}class k0{send;handlers;nextId=1;pending=new Map;constructor(N,U){this.send=N;this.handlers=U}request(N,U){let H=this.nextId++,Y=new Promise((O,W)=>{this.pending.set(H,{method:N,resolve:O,reject:W})});return this.send(JSON.stringify({jsonrpc:"2.0",id:H,method:N,params:U})),Y}notify(N,U){this.send(JSON.stringify({jsonrpc:"2.0",method:N,params:U}))}respond(N,U){this.send(JSON.stringify({jsonrpc:"2.0",id:N,result:U}))}respondError(N,U,H){this.send(JSON.stringify({jsonrpc:"2.0",id:N,error:{code:U,message:H}}))}handleLine(N){let U;try{U=JSON.parse(N)}catch{console.warn("[codex] non-JSON line on stdout:",N.slice(0,200));return}if(U.method!==void 0){if(U.id!==void 0)this.handlers.onServerRequest(U.id,U.method,U.params);else this.handlers.onNotification(U.method,U.params);return}if(U.id===void 0)return;let H=this.pending.get(Number(U.id));if(!H)return;if(this.pending.delete(Number(U.id)),U.error)H.reject(Error(`${H.method} failed: ${U.error.message} (${U.error.code})`));else H.resolve(U.result)}failAll(N){for(let U of this.pending.values())U.reject(Error(`${U.method} failed: ${N}`));this.pending.clear()}}function XU(N){let U="",H=new TextDecoder;return{push(Y){U+=H.decode(Y,{stream:!0});let O;while((O=U.indexOf(`
279
+ `))!==-1){let W=U.slice(0,O).replace(/\r$/,"");if(U=U.slice(O+1),W.trim().length>0)N(W)}},flush(){let Y=U.trim();if(U="",Y.length>0)N(Y)}}}var y0=60000,b0=5,zU=30000;class q0{handlers;proc=null;rpc=null;initialized=!1;exitTimes=[];backoffUntil=0;lastExitCode=null;constructor(N){this.handlers=N}get running(){return this.proc!==null}get health(){let N=Math.max(0,this.backoffUntil-Date.now());return{running:this.proc!==null,lastExitCode:this.lastExitCode,crashLooping:N>0,backoffMs:N}}async start(){if(this.proc)return;let N=this.backoffUntil-Date.now();if(N>0)throw Error(`codex app-server is crash-looping (${b0}+ exits in ${y0/1000}s) \u2014 `+`backing off, retry in ${Math.ceil(N/1000)}s. Run \`jun doctor\` to diagnose.`);await aY();let U=Bun.which("codex");if(!U)throw Error("codex binary not found in PATH. Install Codex CLI first.");let H=/\.(cmd|bat)$/i.test(U)?["cmd","/c",U,"app-server"]:[U,"app-server"],Y=Bun.spawn(H,{cwd:M(),env:{...process.env,CODEX_HOME:k(),...x0()},stdin:"pipe",stdout:"pipe",stderr:"pipe",onExit:(W,$)=>{this.lastExitCode=$,this.rpc?.failAll(`codex app-server exited (code ${$})`),this.proc=null,this.rpc=null,this.initialized=!1;let G=Date.now();if(this.exitTimes=this.exitTimes.filter((F)=>G-F<y0),this.exitTimes.push(G),this.exitTimes.length>=b0)this.backoffUntil=G+zU,this.exitTimes=[],console.error(`[codex] app-server crash-looping (${b0} exits in ${y0/1000}s) \u2014 backing off ${zU/1000}s`);else console.log(`[codex] app-server exited (code ${$}) \u2014 will restart on next run`);this.handlers.onExit($)}});this.proc=Y,this.rpc=new k0((W)=>{Y.stdin.write(W+`
280
+ `),Y.stdin.flush()},{onNotification:(W,$)=>this.handlers.onNotification(W,$),onServerRequest:(W,$,G)=>this.handlers.onServerRequest(W,$,G)});let O=this.rpc;(async()=>{let W=XU(($)=>O.handleLine($));for await(let $ of Y.stdout)W.push($);W.flush()})(),(async()=>{let W=new TextDecoder;for await(let $ of Y.stderr){let G=W.decode($).trimEnd();if(G)console.error("[codex:stderr]",G)}})()}async initializeOnce(){if(this.initialized)return;await this.requireRpc().request("initialize",{clientInfo:{name:"jun",title:"Jun",version:c},capabilities:{experimentalApi:!0}}),this.requireRpc().notify("initialized",{}),this.initialized=!0}request(N,U){return this.requireRpc().request(N,U)}respond(N,U){this.requireRpc().respond(N,U)}respondError(N,U,H){this.requireRpc().respondError(N,U,H)}requireRpc(){if(!this.rpc)throw Error("codex app-server is not running");return this.rpc}}async function aY(){let N=LU.join(k(),"auth.json");try{await ZU.access(N);return}catch{}let U=LU.join(nY.homedir(),".codex","auth.json");try{await ZU.copyFile(U,N),console.log("[codex] copied auth.json from ~/.codex into project codex-home")}catch{console.warn("[codex] no auth.json found in ~/.codex \u2014 runs may fail until `codex login` is run")}}var IN=null,Y0=null;function O0(){return IN}function DU(){return Y0}function KU(N){if(IN=N,N)Y0=null}function W0(){IN=null,Y0=null}function VU(N){let U=N??{};if(Y0={success:U.success===!0,error:U.error??null,at:new Date().toISOString()},!U.loginId||IN?.loginId===U.loginId)IN=null}var sY={"thread/started":"codex.thread.started","turn/started":"codex.turn.started","turn/completed":"codex.turn.completed","item/started":"codex.item.started","item/completed":"codex.item.completed","item/agentMessage/delta":"codex.message.delta","item/reasoning/textDelta":"codex.reasoning.delta","item/reasoning/summaryTextDelta":"codex.reasoning.summary.delta","item/commandExecution/outputDelta":"codex.command.output","item/fileChange/patchUpdated":"codex.file_change.patch",error:"codex.error"},tY={"item/commandExecution/requestApproval":"codex.approval.command","item/fileChange/requestApproval":"codex.approval.file_change","item/permissions/requestApproval":"codex.approval.permissions","item/tool/requestUserInput":"codex.approval.user_input","mcpServer/elicitation/request":"codex.approval.elicitation"};function MU(N){return sY[N]??`codex.${N.split("/").join(".")}`}function JU(N){return tY[N]??null}function AU(N){return N==="item/commandExecution/requestApproval"||N==="item/fileChange/requestApproval"||N==="item/permissions/requestApproval"}function wN(N){if(typeof N!=="object"||N===null)return null;let U=N;if(typeof U.threadId==="string")return U.threadId;let H=U.thread;if(typeof H==="object"&&H!==null){let Y=H.id;if(typeof Y==="string")return Y}return null}var TU={readOnly:"read-only",workspaceWrite:"workspace-write",dangerFullAccess:"danger-full-access"},BU={readOnly:{type:"readOnly"},workspaceWrite:{type:"workspaceWrite"},dangerFullAccess:{type:"dangerFullAccess"}},v0={never:"never",onRequest:"on-request",onFailure:"on-failure",untrusted:"untrusted"},$0=`# Who you are
282
281
 
283
282
  You are Jun. That's your name, use it if anyone asks. You live inside JunHost,
284
283
  your own self-hosted dashboard that runs you as a long-running local/VPS assistant, and
@@ -319,20 +318,20 @@ model powers you; you're just Jun.
319
318
  - Report outcomes honestly. If something failed, say so plainly with the actual
320
319
  error; don't dress up a partial result as done.
321
320
  - Per-workspace guidance lives in each workspace's AGENTS.md and takes
322
- precedence over this general guidance when they differ.`,WN=new Map,$N=new Map,IN=new Map,wH=new Set,jN=new Map,zN=new Map,l0="__default__";function XW(N){let H=N.error?.message;return typeof H==="string"&&H.includes("unsupported_parameter")&&H.includes("reasoning.summary")}async function _H(N,H,Y){if(wH.has(H))Y.summary="none";jN.set(N,Y),await k().request("turn/start",Y)}var vN=new Map,FN=null;function k(){if(!FN)FN=new m0({onNotification:ZW,onServerRequest:OW,onExit:zW});return FN}function PH(){return FN?.health??{running:!1,lastExitCode:null,crashLooping:!1,backoffMs:0}}async function R(N,H,Y,W){let $={id:rN("evt"),runId:N,ts:new Date().toISOString(),source:H,type:Y,payload:W};return await q1($),h(`run:${N}`,$),h("runs",{type:"run.event",runId:N,eventType:Y}),$}async function y(N,H){let Y={status:H};if(H==="completed"||H==="failed"||H==="stopped")Y.completedAt=new Date().toISOString();let W=await YN(N,Y);if(W)h("runs",{type:"run.updated",run:W})}function ZW(N,H){if(N==="account/login/completed"){DH(H);return}let Y=qN(H),W=Y?vN.get(Y):void 0;if(W){if(N==="item/completed"){let G=H.item;if(G?.type==="agentMessage"&&typeof G.text==="string")W.text=G.text}else if(N==="turn/completed"||N==="error")W.done(W.text);return}let $=Y?WN.get(Y):void 0;if(!$)return;(async()=>{if(await R($,"codex",CH(N),H),N==="turn/started"){let G=H.turn?.id;if(typeof G==="string")IN.set($,G)}else if(N==="turn/completed"){let G=H.turn?.id;if(typeof G==="string"&&zN.get($)===G){zN.delete($);return}zN.delete($),IN.delete($),jN.delete($);let U=await D($);if(U&&m(U.status))await y($,"completed");if($N.delete($),U&&!U.title)VW($)}else if(N==="error"){let G=H.turnId;IN.delete($);let U=await D($),Q=jN.get($);if(U&&Q&&Q.summary&&Q.summary!=="none"&&XW(H)){wH.add(U.model??l0);let X={...Q,summary:"none"};console.warn(`[runs] ${U.model??"default model"} rejects reasoning.summary \u2014 retrying with summaries disabled`);try{if(typeof G==="string")zN.set($,G);jN.set($,X),await k().request("turn/start",X);return}catch(Z){zN.delete($),console.warn(`[runs] summary-less retry failed for ${$}:`,Z)}}if(U&&m(U.status))await y($,"failed")}else if(N==="thread/name/updated"){let G=H.threadName;if(typeof G==="string"&&G.trim()){let U=await YN($,{title:G.trim()});if(U)h("runs",{type:"run.updated",run:U})}}})()}function OW(N,H,Y){let W=SH(H),$=qN(Y),G=$?WN.get($):void 0;if(!W||!G){if(console.warn(`[runs] auto-declining unroutable server request ${H} (id ${N})`),TH(H))k().respond(N,{decision:"decline"});else k().respondError(N,-32601,"Jun cannot handle this request yet");return}(async()=>{if(H==="mcpServer/elicitation/request"){let Q=await D(G);if(Q?.approvalPolicy==="never"||Q?.approvalsReviewer==="auto_review"){k().respond(N,{action:"accept"}),await R(G,"daemon","approval.resolved",{requestId:N,decision:"accept",auto:!0});return}}let U=$N.get(G)??[];U.push({requestId:N,method:H}),$N.set(G,U),await y(G,"waiting_approval"),await R(G,"codex",W,{requestId:N,method:H,params:Y})})()}function zW(N){for(let Y of vN.values())Y.done(Y.text);vN.clear();let H=[...WN.values()];WN.clear(),$N.clear(),IN.clear(),jN.clear(),zN.clear();for(let Y of H)(async()=>{let W=await D(Y);if(!W||!m(W.status))return;await R(Y,"daemon","run.failed",{reason:`codex app-server exited (code ${N})`}),await y(Y,"failed")})()}function u0(N,H,Y,W){let $=(Y??[]).filter((X)=>X.mediaType?.startsWith("image/")),G=(Y??[]).filter((X)=>!X.mediaType?.startsWith("image/")),U=H;if(G.length>0)U+=`
321
+ precedence over this general guidance when they differ.`,HN=new Map,YN=new Map,xN=new Map,EU=new Set,fN=new Map,QN=new Map,g0="__default__";function rY(N){let U=N.error?.message;return typeof U==="string"&&U.includes("unsupported_parameter")&&U.includes("reasoning.summary")}async function CU(N,U,H){if(EU.has(U))H.summary="none";fN.set(N,H),await P().request("turn/start",H)}var kN=new Map,XN=null;function P(){if(!XN)XN=new q0({onNotification:eY,onServerRequest:N2,onExit:U2});return XN}function RU(){return XN?.health??{running:!1,lastExitCode:null,crashLooping:!1,backoffMs:0}}async function C(N,U,H,Y){let O={id:nN("evt"),runId:N,ts:new Date().toISOString(),source:U,type:H,payload:Y};return await w1(O),q(`run:${N}`,O),q("runs",{type:"run.event",runId:N,eventType:H}),O}async function I(N,U){let H={status:U};if(U==="completed"||U==="failed"||U==="stopped")H.completedAt=new Date().toISOString();let Y=await UN(N,H);if(Y)q("runs",{type:"run.updated",run:Y})}function eY(N,U){if(N==="account/login/completed"){VU(U);return}let H=wN(U),Y=H?kN.get(H):void 0;if(Y){if(N==="item/completed"){let W=U.item;if(W?.type==="agentMessage"&&typeof W.text==="string")Y.text=W.text}else if(N==="turn/completed"||N==="error")Y.done(Y.text);return}let O=H?HN.get(H):void 0;if(!O)return;(async()=>{if(await C(O,"codex",MU(N),U),N==="turn/started"){let W=U.turn?.id;if(typeof W==="string")xN.set(O,W)}else if(N==="turn/completed"){let W=U.turn?.id;if(typeof W==="string"&&QN.get(O)===W){QN.delete(O);return}QN.delete(O),xN.delete(O),fN.delete(O);let $=await A(O);if($&&v($.status))await I(O,"completed");if(YN.delete(O),$&&!$.title)Y2(O)}else if(N==="error"){let W=U.turnId;xN.delete(O);let $=await A(O),G=fN.get(O);if($&&G&&G.summary&&G.summary!=="none"&&rY(U)){EU.add($.model??g0);let F={...G,summary:"none"};console.warn(`[runs] ${$.model??"default model"} rejects reasoning.summary \u2014 retrying with summaries disabled`);try{if(typeof W==="string")QN.set(O,W);fN.set(O,F),await P().request("turn/start",F);return}catch(Q){QN.delete(O),console.warn(`[runs] summary-less retry failed for ${O}:`,Q)}}if($&&v($.status))await I(O,"failed")}else if(N==="thread/name/updated"){let W=U.threadName;if(typeof W==="string"&&W.trim()){let $=await UN(O,{title:W.trim()});if($)q("runs",{type:"run.updated",run:$})}}})()}function N2(N,U,H){let Y=JU(U),O=wN(H),W=O?HN.get(O):void 0;if(!Y||!W){if(console.warn(`[runs] auto-declining unroutable server request ${U} (id ${N})`),AU(U))P().respond(N,{decision:"decline"});else P().respondError(N,-32601,"Jun cannot handle this request yet");return}(async()=>{if(U==="mcpServer/elicitation/request"){let G=await A(W);if(G?.approvalPolicy==="never"||G?.approvalsReviewer==="auto_review"){P().respond(N,{action:"accept"}),await C(W,"daemon","approval.resolved",{requestId:N,decision:"accept",auto:!0});return}}let $=YN.get(W)??[];$.push({requestId:N,method:U}),YN.set(W,$),await I(W,"waiting_approval"),await C(W,"codex",Y,{requestId:N,method:U,params:H})})()}function U2(N){for(let H of kN.values())H.done(H.text);kN.clear();let U=[...HN.values()];HN.clear(),YN.clear(),xN.clear(),fN.clear(),QN.clear();for(let H of U)(async()=>{let Y=await A(H);if(!Y||!v(Y.status))return;await C(H,"daemon","run.failed",{reason:`codex app-server exited (code ${N})`}),await I(H,"failed")})()}function h0(N,U,H){let Y=(U??[]).filter((G)=>G.mediaType?.startsWith("image/")),O=(U??[]).filter((G)=>!G.mediaType?.startsWith("image/")),W=N;if(O.length>0)W+=`
323
322
 
324
323
  Attached workspace files:
325
- `+G.map((X)=>`- ${X.path}`).join(`
326
- `);let Q=[{type:"text",text:U}];if(W)Q.push({type:"skill",name:W.name,path:W.path});for(let X of $)Q.push({type:"localImage",path:tN(X.path,N)});return Q}function FW(N){if(!N)return null;let H=N.split(`
327
- `)[0].replace(/^["'`#*\s]+|["'`*\s]+$/g,"").replace(/\s+/g," ").trim();if(!H)return null;return H.length>60?H.slice(0,57).trimEnd()+"\u2026":H}async function VW(N){let H=await D(N);if(!H||H.title||!H.codexThreadId)return;try{let Y=k(),W=await Y.request("thread/start",{cwd:H.cwd,ephemeral:!0,sandbox:"read-only",approvalPolicy:"never",serviceName:"jun"}),$=qN(W);if(!$)return;let G=await new Promise((X)=>{let Z=(M)=>{clearTimeout(F),vN.delete($),X(M)},F=setTimeout(()=>Z(null),30000);vN.set($,{text:null,done:Z}),Y.request("turn/start",{threadId:$,input:[{type:"text",text:`Reply with ONLY a short title (3-6 words, no quotes, no punctuation at the end) summarizing this conversation opener:
324
+ `+O.map((G)=>`- ${G.path}`).join(`
325
+ `);let $=[{type:"text",text:W}];if(H)$.push({type:"skill",name:H.name,path:H.path});for(let G of Y)$.push({type:"localImage",path:oN(G.path)});return $}function H2(N){if(!N)return null;let U=N.split(`
326
+ `)[0].replace(/^["'`#*\s]+|["'`*\s]+$/g,"").replace(/\s+/g," ").trim();if(!U)return null;return U.length>60?U.slice(0,57).trimEnd()+"\u2026":U}async function Y2(N){let U=await A(N);if(!U||U.title||!U.codexThreadId)return;try{let H=P(),Y=await H.request("thread/start",{cwd:U.cwd,ephemeral:!0,sandbox:"read-only",approvalPolicy:"never",serviceName:"jun"}),O=wN(Y);if(!O)return;let W=await new Promise((F)=>{let Q=(V)=>{clearTimeout(L),kN.delete(O),F(V)},L=setTimeout(()=>Q(null),30000);kN.set(O,{text:null,done:Q}),H.request("turn/start",{threadId:O,input:[{type:"text",text:`Reply with ONLY a short title (3-6 words, no quotes, no punctuation at the end) summarizing this conversation opener:
328
327
 
329
- `+H.prompt.slice(0,2000)}],effort:"low"}).catch(()=>Z(null))}),U=FW(G);if(!U)return;await Y.request("thread/name/set",{threadId:H.codexThreadId,name:U});let Q=await YN(N,{title:U});if(Q)h("runs",{type:"run.updated",run:Q})}catch(Y){console.warn(`[runs] title generation failed for ${N}:`,Y)}}async function C(N,H){let Y=k();return await Y.start(),await Y.initializeOnce(),Y.request(N,H)}async function VN(N){let H=N.projectId??"default",Y=N.cwd??B(H),W=await f1({prompt:N.prompt,cwd:Y,projectId:H,sandbox:N.sandbox??"workspaceWrite",approvalPolicy:N.approvalPolicy??"onRequest",approvalsReviewer:N.approvalsReviewer??"user",model:N.model,effort:N.effort??"medium",source:N.source,scheduleId:N.scheduleId,scheduleName:N.scheduleName});return h("runs",{type:"run.updated",run:W}),await R(W.id,"daemon","run.started",{prompt:N.prompt,cwd:Y,projectId:H,attachments:N.attachments??[]}),(async()=>{try{let $=k();await $.start(),await $.initializeOnce();let G=await $.request("thread/start",{cwd:Y,model:N.model??null,sandbox:EH[N.sandbox??"workspaceWrite"],approvalPolicy:c0[N.approvalPolicy??"onRequest"],...N.approvalsReviewer==="auto_review"?{approvalsReviewer:"auto_review"}:{},...O0?{developerInstructions:O0}:{},serviceName:"jun"}),U=qN(G)??(typeof G.threadId==="string"?G.threadId:null);if(!U)throw Error(`thread/start returned no thread id: ${JSON.stringify(G)}`);WN.set(U,W.id),await YN(W.id,{codexThreadId:U}),await y(W.id,"running"),await _H(W.id,N.model??l0,{threadId:U,input:u0(H,N.prompt,N.attachments,N.skill),summary:"detailed",effort:N.effort??"medium",sandboxPolicy:RH[N.sandbox??"workspaceWrite"]})}catch($){let G=$ instanceof Error?$.message:String($);await R(W.id,"daemon","run.failed",{reason:G}),await y(W.id,"failed")}})(),W}async function i0(N,H){let Y=k();if(await Y.start(),await Y.initializeOnce(),WN.has(H))return{server:Y,resumed:!1};let W=await D(N);return await Y.request("thread/resume",{threadId:H,...W?.approvalPolicy?{approvalPolicy:c0[W.approvalPolicy]}:{},...W?.approvalsReviewer==="auto_review"?{approvalsReviewer:"auto_review"}:{},...W?.model?{model:W.model}:{},...W?.sandbox?{sandbox:EH[W.sandbox]}:{},...O0?{developerInstructions:O0}:{}}),WN.set(H,N),{server:Y,resumed:!0}}async function z0(N,H,Y,W){let $=await D(N);if(!$)throw Error(`Run not found: ${N}`);if(m($.status))throw Error("Run is still active \u2014 wait for the current turn to finish");let G=$.codexThreadId;if(!G)throw Error("Run has no Codex thread to resume");let U={};if(W?.sandbox&&W.sandbox!==$.sandbox)U.sandbox=W.sandbox;if(W?.approvalPolicy&&W.approvalPolicy!==$.approvalPolicy)U.approvalPolicy=W.approvalPolicy;if(W?.approvalsReviewer&&W.approvalsReviewer!==$.approvalsReviewer)U.approvalsReviewer=W.approvalsReviewer;if(W?.model&&W.model!==$.model)U.model=W.model;if(W?.effort&&W.effort!==$.effort)U.effort=W.effort;if(Object.keys(U).length>0){let Q=await YN(N,U);if(Q)h("runs",{type:"run.updated",run:Q})}return await R(N,"daemon","run.resumed",{prompt:H,attachments:Y??[],...Object.keys(U).length>0?{modeChanges:U}:{}}),await y(N,"running"),(async()=>{try{await i0(N,G);let Q=U.sandbox??$.sandbox??"workspaceWrite",X=U.approvalPolicy??$.approvalPolicy??"onRequest",Z=U.approvalsReviewer??$.approvalsReviewer,F=U.model??$.model,M=(await D(N))?.serviceTier;await _H(N,F??l0,{threadId:G,input:u0($.projectId,H,Y),summary:"detailed",effort:U.effort??$.effort??"medium",sandboxPolicy:RH[Q],approvalPolicy:c0[X],...Z==="auto_review"?{approvalsReviewer:Z}:{},...F?{model:F}:{},...M?{serviceTier:M}:{}})}catch(Q){let X=Q instanceof Error?Q.message:String(Q);await R(N,"daemon","run.failed",{reason:X}),await y(N,"failed")}})(),await D(N)}async function xH(N,H,Y){let W=await D(N);if(!W)throw Error(`Run not found: ${N}`);if(!m(W.status))throw Error("Run is not active \u2014 send a follow-up message instead");let $=W.codexThreadId,G=IN.get(N);if(!$||!G)throw Error("No active turn to steer");await R(N,"daemon","run.steered",{prompt:H,attachments:Y??[]}),await k().request("turn/steer",{threadId:$,expectedTurnId:G,input:u0(W.projectId,H,Y)})}async function fH(N,H){let Y=await D(N);if(!Y)throw Error(`Run not found: ${N}`);if(H){let G=((await C("model/list",{})).data??[]).find((U)=>Y.model?U.model===Y.model:U.isDefault);if(!G?.serviceTiers?.some((U)=>U.id==="priority"))throw Error(`Model ${G?.model??Y.model??"unknown"} does not support fast mode`)}let W=await YN(N,{serviceTier:H?"priority":"standard"});if(W)h("runs",{type:"run.updated",run:W});return await R(N,"daemon","run.fast",{enabled:H}),W}async function kH(N){let H=await D(N);if(!H)throw Error(`Run not found: ${N}`);if(m(H.status))throw Error("Run is still active \u2014 wait for the current turn to finish");let Y=H.codexThreadId;if(!Y)throw Error("Run has no Codex thread");let{server:W}=await i0(N,Y);await R(N,"daemon","run.compact.started",{}),await W.request("thread/compact/start",{threadId:Y})}async function yH(N,H){let Y=await D(N);if(!Y)throw Error(`Run not found: ${N}`);if(m(Y.status))throw Error("Run is still active \u2014 wait for the current turn to finish");let W=Y.codexThreadId;if(!W)throw Error("Run has no Codex thread");let{server:$}=await i0(N,W),G=H?.trim();await R(N,"daemon","run.review.started",{instructions:G??null}),await y(N,"running");try{await $.request("review/start",{threadId:W,target:G?{type:"custom",instructions:G}:{type:"uncommittedChanges"},delivery:"inline"})}catch(U){let Q=U instanceof Error?U.message:String(U);throw await R(N,"daemon","run.failed",{reason:Q}),await y(N,"failed"),U}return await D(N)}async function bH(N){let H=await D(N);if(!H||!m(H.status))return!1;if(H.codexThreadId&&FN?.running)try{await FN.request("turn/interrupt",{threadId:H.codexThreadId})}catch(Y){console.warn(`[runs] turn/interrupt failed for ${N}:`,Y)}return $N.delete(N),await R(N,"daemon","run.stopped",{}),await y(N,"stopped"),!0}async function qH(N,H,Y){let W=$N.get(N)??[],$=W.findIndex((U)=>String(U.requestId)===String(H));if($===-1)return!1;let[G]=W.splice($,1);if(W.length===0)$N.delete(N);if(G.method==="mcpServer/elicitation/request"){let U=Y==="decline"||Y==="cancel"?Y:"accept";k().respond(G.requestId,{action:U})}else k().respond(G.requestId,{decision:Y});if(await R(N,"daemon","approval.resolved",{requestId:G.requestId,decision:Y}),W.length===0)await y(N,"running");return!0}function LN(){return KW.join(j(),"config.toml")}async function d(){try{return await KN.readFile(LN(),"utf8")}catch{return""}}async function jH(N){try{l(N)}catch(H){throw new A(`Invalid TOML: ${H instanceof Error?H.message:String(H)}`)}await KN.writeFile(LN(),N,"utf8")}function LW(N){if(!N.trim())return{};let Y=l(N).mcp_servers;if(typeof Y!=="object"||Y===null)return{};return Y}async function MW(){let N=new Map;try{let H=await C("mcpServerStatus/list",{detail:"full"});for(let Y of H.data??[]){let W=Object.entries(Y.tools??{}).map(([$,G])=>({name:$,description:G?.description}));N.set(Y.name,{startupState:Y.serverInfo?"ready":"starting",authStatus:Y.authStatus??null,tools:W})}}catch(H){console.warn("[mcp] mcpServerStatus/list failed:",H)}return N}async function vH(){let N=await d(),H=LW(N),Y=await MW();return{servers:Object.entries(H).map(([$,G])=>{let U=Y.get($);return{name:$,command:G.command,args:G.args,envKeys:G.env?Object.keys(G.env):void 0,url:G.url,enabled:G.enabled!==!1,startupState:U?.startupState??null,authStatus:U?.authStatus??null,tools:U?.tools??[],error:U?.error}})}}var JW=/^[A-Za-z0-9_-]+$/;async function gH(N){if(!JW.test(N.name))throw new A(`Invalid server name "${N.name}" \u2014 letters, digits, _ and - only`);if(!N.command&&!N.url)throw new A("Server needs either a command or a url");let H=await d(),Y=H.trim()?l(H):{},W=Y.mcp_servers??{},$={};if(N.command)$.command=N.command;if(N.args&&N.args.length>0)$.args=N.args;if(N.env&&Object.keys(N.env).length>0)$.env=N.env;if(N.url)$.url=N.url;if(N.enabled===!1)$.enabled=!1;W[N.name]=$,Y.mcp_servers=W,await KN.writeFile(LN(),t(Y),"utf8")}async function hH(N){let H=await d();if(!H.trim())return!1;let Y=l(H),W=Y.mcp_servers;if(!W||!(N in W))return!1;return delete W[N],await KN.writeFile(LN(),t(Y),"utf8"),!0}async function mH(N,H){let Y=await d(),W=l(Y||""),$=W.mcp_servers??{};if(!$[N])throw new A(`Server not found: ${N}`);$[N].enabled=H,W.mcp_servers=$,await KN.writeFile(LN(),t(W),"utf8")}async function cH(){await C("config/mcpServer/reload",{})}async function lH(N,H,Y,W){let $=await d(),G=$.trim()?l($):{},U=G.mcp_servers??{},Q={command:process.execPath,args:[H],env:{JUN_PORT:String(Y)}},X=U[N],Z=Boolean(W&&U[W]);if(X&&!Z&&X.command===Q.command&&JSON.stringify(X.args)===JSON.stringify(Q.args)&&X.env?.JUN_PORT===String(Y))return;if(W)delete U[W];U[N]=Q,G.mcp_servers=U,await KN.writeFile(LN(),t(G),"utf8")}var AW="https://registry.npmjs.org/junhost/latest",DW=7200000,CW=1800000,p0=null,uH=0,n0=!1,MN=null;async function iH(){try{let N=await fetch(AW,{signal:AbortSignal.timeout(5000)});if(!N.ok)throw Error(`registry ${N.status}`);let H=await N.json();p0=typeof H.version==="string"?H.version:null,n0=p0!==null}catch{n0=!1}finally{uH=Date.now(),MN=null}}function SW(){let N=n0?DW:CW;if(!MN&&Date.now()-uH>N)MN=iH();return p0}async function pH(){if(!MN)MN=iH();await MN}function TW(N,H){let Y=N.split(".").map(($)=>parseInt($,10)||0),W=H.split(".").map(($)=>parseInt($,10)||0);for(let $=0;$<Math.max(Y.length,W.length);$++){let G=Y[$]??0,U=W[$]??0;if(G!==U)return G>U}return!1}function nH(){let N=SW();return{latestVersion:N,updateAvailable:N!==null&&TW(N,ON)}}var EW=Date.now();function dH(){return O({ok:!0})}async function aH(N){if(N?.searchParams.get("refresh")==="1")await pH();let H={ok:!0,name:"jun",version:ON,...nH(),projectId:K,dataRoot:I,workspaceRoot:B(),uptimeSeconds:Math.round((Date.now()-EW)/1000),engine:PH()};return O(H)}import RW from"path";var F0={ok:!0};async function oH(N,H){let Y=H.pathname.slice(11),W=H.searchParams.get("path")??".",$=H.searchParams.get("project")??K;switch(`${N.method} ${Y}`){case"GET tree":return O(await M1(W,$));case"GET read":return O(await J1(W,$));case"GET download":{let G=tN(W,$),U=Bun.file(G);if(!await U.exists())return z(404,`File not found: ${W}`);return new Response(U,{headers:{"content-disposition":`attachment; filename="${encodeURIComponent(RW.basename(G))}"`}})}case"POST write":{let G=await V(N);return await B1(J(G.path,"path"),typeof G.content==="string"?G.content:"",$),O(F0)}case"POST mkdir":{let G=await V(N);return await A1(J(G.path,"path"),$),O(F0)}case"POST delete":{let G=await V(N);return await D1(J(G.path,"path"),$),O(F0)}case"POST rename":{let G=await V(N);return await C1(J(G.from,"from"),J(G.to,"to"),$),O(F0)}case"POST upload":{let G;try{G=await N.formData()}catch{throw new A("Expected multipart/form-data body")}let U=String(G.get("path")??"."),Q=G.getAll("file").filter((Z)=>Z instanceof File);if(Q.length===0)throw new A("No files in upload (field name: file)");let X=[];for(let Z of Q)X.push(await S1(U,Z.name,Z,$));return O({ok:!0,saved:X})}default:return z(404,`Unknown files endpoint: ${N.method} /api/files/${Y}`)}}import{promises as sH}from"fs";function wW(N){return N.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,48)}async function tH(N){try{let H=await sH.readFile(T0(N),"utf8"),Y=JSON.parse(H);return{id:Y.id??N,name:Y.name??N,createdAt:Y.createdAt??new Date(0).toISOString(),workspaceRoot:B(N)}}catch{return null}}async function rH(){let N;try{N=await sH.readdir(XN(),{withFileTypes:!0})}catch{return[]}let H=[];for(let Y of N){if(!Y.isDirectory())continue;let W=await tH(Y.name);if(W)H.push(W)}return H.sort((Y,W)=>{if(Y.id===K)return-1;if(W.id===K)return 1;return W.createdAt.localeCompare(Y.createdAt)}),H}async function gN(N){return tH(N)}async function eH(N){let H=N.trim();if(!H)throw Error("Project name is required");let Y=wW(H);if(!Y)throw Error("Project name must contain letters or numbers");if(await gN(Y))throw Error(`A project named "${Y}" already exists`);await E0(Y,H);let W=await gN(Y);if(!W)throw Error(`Failed to create project "${Y}"`);return W}async function JN(N){return await gN(N)!==null}async function N2(N,H){let W=H.pathname.split("/").filter(Boolean)[2];if(!W){if(N.method==="GET"){let $={projects:await rH()};return O($)}if(N.method==="POST"){let $=await V(N);J($.name,"name");try{let U={project:await eH($.name)};return O(U,201)}catch(G){let U=G instanceof Error?G.message:String(G),Q=U.includes("already exists")?409:400;return z(Q,U)}}return z(405,"Method not allowed")}if(N.method==="GET"){let $=await gN(W);return $?O({project:$}):z(404,`Project not found: ${W}`)}return z(405,"Method not allowed")}var _W=new Set(["accept","acceptForSession","decline","cancel"]);async function H2(N,H,Y){let W=H.pathname.split("/").filter(Boolean),$=W[2],G=W[3];if(!$){if(N.method==="GET"){let U=H.searchParams.get("project")??void 0,Q={runs:await k1(U)};return O(Q)}if(N.method==="POST"){let U=await V(N);J(U.prompt,"prompt");let X={run:await VN(U)};return O(X,201)}return z(405,"Method not allowed")}if(G==="events"){if(!await D($))return z(404,`Run not found: ${$}`);return Y.upgrade(N,{data:{channel:`run:${$}`}})?void 0:z(400,"WebSocket upgrade required")}if(!G&&N.method==="GET"){let U=await D($);if(!U)return z(404,`Run not found: ${$}`);let Q=Number(H.searchParams.get("tail")??NaN),X=Number(H.searchParams.get("before")??NaN),Z=await I1($,{limit:Number.isFinite(Q)&&Q>0?Q:void 0,before:Number.isFinite(X)&&X>=0?X:void 0}),F={run:U,events:Z.events,eventsOffset:Z.offset,totalEvents:Z.total};return O(F)}if(N.method!=="POST")return z(405,"Method not allowed");switch(G){case"stop":return await bH($)?O({ok:!0}):z(409,"Run is not active");case"resume":{let U=await V(N);J(U.prompt,"prompt");try{let Q=await z0($,U.prompt,Array.isArray(U.attachments)?U.attachments:void 0,{sandbox:U.sandbox,approvalPolicy:U.approvalPolicy,approvalsReviewer:U.approvalsReviewer,model:U.model,effort:U.effort});return O({run:Q})}catch(Q){let X=Q instanceof Error?Q.message:String(Q),Z=X.includes("not found")?404:X.includes("still active")?409:400;return z(Z,X)}}case"steer":{let U=await V(N);J(U.prompt,"prompt");try{return await xH($,U.prompt,Array.isArray(U.attachments)?U.attachments:void 0),O({ok:!0})}catch(Q){let X=Q instanceof Error?Q.message:String(Q),Z=X.includes("not found")?404:X.includes("not active")||X.includes("No active turn")?409:400;return z(Z,X)}}case"fast":{let U=await V(N);if(typeof U.enabled!=="boolean")return z(400,"Missing or invalid field: enabled");try{let Q=await fH($,U.enabled);return O({run:Q})}catch(Q){let X=Q instanceof Error?Q.message:String(Q),Z=X.includes("not found")?404:X.includes("does not support")?400:500;return z(Z,X)}}case"compact":try{return await kH($),O({ok:!0})}catch(U){let Q=U instanceof Error?U.message:String(U),X=Q.includes("not found")?404:Q.includes("still active")?409:400;return z(X,Q)}case"review":{let U=await V(N);try{let Q=await yH($,U.instructions);return O({run:Q})}catch(Q){let X=Q instanceof Error?Q.message:String(Q),Z=X.includes("not found")?404:X.includes("still active")?409:400;return z(Z,X)}}case"approve":{let U=await V(N);if(!_W.has(String(U.decision)))return z(400,`Invalid decision: ${String(U.decision)}`);if(U.requestId===void 0||U.requestId===null)return z(400,"Missing field: requestId");return await qH($,U.requestId,U.decision)?O({ok:!0}):z(404,"No matching pending approval")}default:return z(404,`Unknown runs endpoint: ${H.pathname}`)}}var GN="browser-stream",c=null,Y2=null,BN=0,AN=null,a0=null;function PW(N){if(c&&Y2===N&&c.readyState<=WebSocket.OPEN)return;c?.close(),Y2=N;let H=new WebSocket(`ws://127.0.0.1:${N}`);c=H,H.onmessage=(Y)=>{let W=String(Y.data);if(W.includes('"type":"frame"'))a0=W;R1(GN,W)},H.onclose=()=>{if(c===H)c=null,a0=null,W2()},H.onerror=()=>{}}function W2(){if(AN||BN===0)return;AN=setTimeout(()=>{AN=null,hN(!0)},2000)}async function hN(N=!1){if(BN===0)return;let H=N?null:e1();if(H===null){if(N)n();H=(await yN()).streamPort}if(H!==null)PW(H);else W2()}function $2(){BN+=1,hN()}function G2(){return a0}function U2(){if(BN=Math.max(0,BN-1),BN===0){if(c?.close(),c=null,AN)clearTimeout(AN),AN=null}}var xW=new Set(["input_mouse","input_keyboard","input_touch"]);function Q2(N){if(t1()!=="user")return;if(!c||c.readyState!==WebSocket.OPEN)return;let H=typeof N==="string"?N:N.toString("utf8");try{let Y=JSON.parse(H);if(typeof Y.type==="string"&&xW.has(Y.type))c.send(H)}catch{}}var fW=new Set(["user","agent","paused"]);async function X2(N,H,Y){let $=H.pathname.split("/").filter(Boolean)[2];if($==="stream")return Y.upgrade(N,{data:{channel:GN}})?void 0:z(400,"WebSocket upgrade required");if(N.method==="GET")switch($){case"status":{let G=await yN();if(G.streaming)hN();return O({status:G})}case"actions":{let G={actions:s1()};return O(G)}default:return z(404,`Unknown browser endpoint: ${H.pathname}`)}if(N.method!=="POST")return z(405,"Method not allowed");switch($){case"start":{let G=await V(N).catch(()=>({})),U=await YH(typeof G.url==="string"&&G.url.length>0?G.url:void 0);return hN(),O({status:U})}case"stop":return await WH(),O({ok:!0});case"navigate":{let G=await V(N);return J(G.url,"url"),await $H(G.url),O({ok:!0})}case"key":{let G=await V(N);return J(G.key,"key"),await UH(G.key),O({ok:!0})}case"back":case"forward":case"reload":return await GH($),O({ok:!0});case"screenshot":{let U={path:await QH()};return O(U)}case"snapshot":{let G=await V(N).catch(()=>({})),U=await XH(G.interactive??!0);return O({snapshot:U})}case"click":{let G=await V(N);return J(G.target,"target"),await ZH(G.target),O({ok:!0})}case"fill":{let G=await V(N);return J(G.target,"target"),J(G.text,"text"),await OH(G.target,G.text),O({ok:!0})}case"read":{let G=await V(N).catch(()=>({})),U=await zH(G.selector);return O({text:U})}case"eval":{let G=await V(N);J(G.expression,"expression");let U=await FH(G.expression);return O({result:U})}case"exec":{let G=await V(N);if(!Array.isArray(G.args)||G.args.length===0)return z(400,"args must be a non-empty array of strings");let U=await VH(G.args,{json:G.json});return O(U)}case"control":{let G=await V(N);if(!fW.has(String(G.controller)))return z(400,`Invalid controller: ${String(G.controller)}`);return r1(G.controller),O({ok:!0})}default:return z(404,`Unknown browser endpoint: ${H.pathname}`)}}import{promises as x}from"fs";import w from"path";var z2=".agents/skills";function DN(N){return w.join(B(N),z2)}var kW=/^[a-z0-9][a-z0-9-]*$/,yW=new Set(["registry","install"]);function CN(N,H){if(!kW.test(N))throw new A(`Invalid skill id "${N}" \u2014 use lowercase letters, digits and dashes`);return w.join(DN(H),N)}function Z2(N){return N.replace(/\x1b\[[0-9;?]*[A-Za-z]/g,"")}async function F2(N,H,Y=120000){let W=Bun.spawn([process.execPath,"x","skills",...N],{cwd:H,env:{...process.env,DISABLE_TELEMETRY:"1",DO_NOT_TRACK:"1"},stdout:"pipe",stderr:"pipe"}),$=setTimeout(()=>W.kill(),Y);try{let[G,U,Q]=await Promise.all([new Response(W.stdout).text(),new Response(W.stderr).text(),W.exited]);return{stdout:Z2(G),stderr:Z2(U),code:Q}}finally{clearTimeout($)}}function bW(N){let H=[],Y=null;for(let W of N.split(/\r?\n/)){let $=W.trim(),G=/^(\S+@\S+)\s+([\d.]+[KMB]?)\s+installs\b/.exec($);if(G){let Q=G[1],X=Q.indexOf("@");Y={source:Q,repo:Q.slice(0,X),name:Q.slice(X+1),installs:G[2]},H.push(Y);continue}let U=/^[\u2514\u2570]\s*(https?:\/\/\S+)/.exec($);if(U&&Y)Y.url=U[1],Y=null}return H}function qW(N){let H=[],Y=/^---\r?\n([\s\S]*?)\r?\n---/.exec(N.replace(/^\uFEFF/,""));if(!Y)return{errors:["Missing YAML frontmatter (--- name/description ---)"]};let W={};for(let $ of Y[1].split(/\r?\n/)){let G=/^([A-Za-z_][\w-]*):\s*(.*)$/.exec($);if(G)W[G[1].toLowerCase()]=G[2].trim().replace(/^["']|["']$/g,"")}if(!W.name)H.push("Frontmatter is missing required field: name");if(!W.description)H.push("Frontmatter is missing required field: description");return{name:W.name,description:W.description,errors:H}}var IW=15000,s0=new Map,o0=new Map;function mN(N){s0.delete(N)}async function jW(N){let H=s0.get(N);if(H&&Date.now()-H.at<IW)return H.view;let Y=o0.get(N);if(Y)return Y;let W=vW(N).then(($)=>{return s0.set(N,{at:Date.now(),view:$}),$}).finally(()=>{o0.delete(N)});return o0.set(N,W),W}async function vW(N){let H=new Map,Y=[];try{let W=await C("skills/list",{cwds:[B(N)],forceReload:!0});for(let $ of W.data??[]){for(let G of $.errors??[])Y.push(G);for(let G of $.skills??[]){let U=w.basename(w.dirname(G.path));H.set(U,G)}}}catch(W){console.warn("[skills] skills/list failed:",W)}return{byDir:H,errors:Y}}async function V0(N=K){await x.mkdir(DN(N),{recursive:!0});let Y=(await x.readdir(DN(N),{withFileTypes:!0})).filter((Q)=>Q.isDirectory()).map((Q)=>Q.name),{byDir:W,errors:$}=await jW(N),G=[];for(let Q of Y){let X=w.join(DN(N),Q,"SKILL.md"),Z=null;try{Z=await x.readFile(X,"utf8")}catch{G.push({id:Q,name:Q,description:"",enabled:!1,errors:["Missing SKILL.md"]});continue}let F=qW(Z),M=W.get(Q),E=$.filter((f)=>u(f.path).includes(`/${Q}/`)||w.basename(w.dirname(f.path))===Q).map((f)=>f.message);G.push({id:Q,name:M?.name??F.name??Q,description:M?.description??F.description??"",enabled:M?.enabled??!0,errors:[...new Set([...F.errors,...E])]})}let U=$.filter((Q)=>!Y.some((X)=>u(Q.path).includes(`/${X}/`)));return{skills:G,errors:U}}async function cN(N,H=K){let Y=CN(N,H),W;try{W=await x.readFile(w.join(Y,"SKILL.md"),"utf8")}catch{return null}let{skills:$}=await V0(H),G=$.find((X)=>X.id===N)??{id:N,name:N,description:"",enabled:!0,errors:[]},U=[],Q=async(X)=>{let Z=await x.readdir(w.join(Y,X),{withFileTypes:!0});for(let F of Z){let M=X?`${X}/${F.name}`:F.name;if(F.isDirectory())await Q(M);else if(M!=="SKILL.md")U.push(`${z2}/${N}/${M}`)}};return await Q(""),{info:G,content:W,files:U}}async function V2(N,H=K){let Y=N.name.trim().toLowerCase().replace(/\s+/g,"-");if(yW.has(Y))throw new A(`"${Y}" is a reserved name \u2014 pick another`);let W=CN(Y,H);try{throw await x.access(w.join(W,"SKILL.md")),new A(`Skill "${Y}" already exists`)}catch(G){if(G instanceof A)throw G}let $=`---
330
- name: ${Y}
328
+ `+U.prompt.slice(0,2000)}],effort:"low"}).catch(()=>Q(null))}),$=H2(W);if(!$)return;await H.request("thread/name/set",{threadId:U.codexThreadId,name:$});let G=await UN(N,{title:$});if(G)q("runs",{type:"run.updated",run:G})}catch(H){console.warn(`[runs] title generation failed for ${N}:`,H)}}async function B(N,U){let H=P();return await H.start(),await H.initializeOnce(),H.request(N,U)}async function ZN(N){let U=N.cwd??M(),H=await _1({prompt:N.prompt,cwd:U,sandbox:N.sandbox??"workspaceWrite",approvalPolicy:N.approvalPolicy??"onRequest",approvalsReviewer:N.approvalsReviewer??"user",model:N.model,effort:N.effort??"medium",source:N.source,scheduleId:N.scheduleId,scheduleName:N.scheduleName});return q("runs",{type:"run.updated",run:H}),await C(H.id,"daemon","run.started",{prompt:N.prompt,cwd:U,attachments:N.attachments??[]}),(async()=>{try{let Y=P();await Y.start(),await Y.initializeOnce();let O=await Y.request("thread/start",{cwd:U,model:N.model??null,sandbox:TU[N.sandbox??"workspaceWrite"],approvalPolicy:v0[N.approvalPolicy??"onRequest"],...N.approvalsReviewer==="auto_review"?{approvalsReviewer:"auto_review"}:{},...$0?{developerInstructions:$0}:{},serviceName:"jun"}),W=wN(O)??(typeof O.threadId==="string"?O.threadId:null);if(!W)throw Error(`thread/start returned no thread id: ${JSON.stringify(O)}`);HN.set(W,H.id),await UN(H.id,{codexThreadId:W}),await I(H.id,"running"),await CU(H.id,N.model??g0,{threadId:W,input:h0(N.prompt,N.attachments,N.skill),summary:"detailed",effort:N.effort??"medium",sandboxPolicy:BU[N.sandbox??"workspaceWrite"]})}catch(Y){let O=Y instanceof Error?Y.message:String(Y);await C(H.id,"daemon","run.failed",{reason:O}),await I(H.id,"failed")}})(),H}async function m0(N,U){let H=P();if(await H.start(),await H.initializeOnce(),HN.has(U))return{server:H,resumed:!1};let Y=await A(N);return await H.request("thread/resume",{threadId:U,...Y?.approvalPolicy?{approvalPolicy:v0[Y.approvalPolicy]}:{},...Y?.approvalsReviewer==="auto_review"?{approvalsReviewer:"auto_review"}:{},...Y?.model?{model:Y.model}:{},...Y?.sandbox?{sandbox:TU[Y.sandbox]}:{},...$0?{developerInstructions:$0}:{}}),HN.set(U,N),{server:H,resumed:!0}}async function G0(N,U,H,Y){let O=await A(N);if(!O)throw Error(`Run not found: ${N}`);if(v(O.status))throw Error("Run is still active \u2014 wait for the current turn to finish");let W=O.codexThreadId;if(!W)throw Error("Run has no Codex thread to resume");let $={};if(Y?.sandbox&&Y.sandbox!==O.sandbox)$.sandbox=Y.sandbox;if(Y?.approvalPolicy&&Y.approvalPolicy!==O.approvalPolicy)$.approvalPolicy=Y.approvalPolicy;if(Y?.approvalsReviewer&&Y.approvalsReviewer!==O.approvalsReviewer)$.approvalsReviewer=Y.approvalsReviewer;if(Y?.model&&Y.model!==O.model)$.model=Y.model;if(Y?.effort&&Y.effort!==O.effort)$.effort=Y.effort;if(Object.keys($).length>0){let G=await UN(N,$);if(G)q("runs",{type:"run.updated",run:G})}return await C(N,"daemon","run.resumed",{prompt:U,attachments:H??[],...Object.keys($).length>0?{modeChanges:$}:{}}),await I(N,"running"),(async()=>{try{await m0(N,W);let G=$.sandbox??O.sandbox??"workspaceWrite",F=$.approvalPolicy??O.approvalPolicy??"onRequest",Q=$.approvalsReviewer??O.approvalsReviewer,L=$.model??O.model,V=(await A(N))?.serviceTier;await CU(N,L??g0,{threadId:W,input:h0(U,H),summary:"detailed",effort:$.effort??O.effort??"medium",sandboxPolicy:BU[G],approvalPolicy:v0[F],...Q==="auto_review"?{approvalsReviewer:Q}:{},...L?{model:L}:{},...V?{serviceTier:V}:{}})}catch(G){let F=G instanceof Error?G.message:String(G);await C(N,"daemon","run.failed",{reason:F}),await I(N,"failed")}})(),await A(N)}async function SU(N,U,H){let Y=await A(N);if(!Y)throw Error(`Run not found: ${N}`);if(!v(Y.status))throw Error("Run is not active \u2014 send a follow-up message instead");let O=Y.codexThreadId,W=xN.get(N);if(!O||!W)throw Error("No active turn to steer");await C(N,"daemon","run.steered",{prompt:U,attachments:H??[]}),await P().request("turn/steer",{threadId:O,expectedTurnId:W,input:h0(U,H)})}async function _U(N,U){let H=await A(N);if(!H)throw Error(`Run not found: ${N}`);if(U){let W=((await B("model/list",{})).data??[]).find(($)=>H.model?$.model===H.model:$.isDefault);if(!W?.serviceTiers?.some(($)=>$.id==="priority"))throw Error(`Model ${W?.model??H.model??"unknown"} does not support fast mode`)}let Y=await UN(N,{serviceTier:U?"priority":"standard"});if(Y)q("runs",{type:"run.updated",run:Y});return await C(N,"daemon","run.fast",{enabled:U}),Y}async function jU(N){let U=await A(N);if(!U)throw Error(`Run not found: ${N}`);if(v(U.status))throw Error("Run is still active \u2014 wait for the current turn to finish");let H=U.codexThreadId;if(!H)throw Error("Run has no Codex thread");let{server:Y}=await m0(N,H);await C(N,"daemon","run.compact.started",{}),await Y.request("thread/compact/start",{threadId:H})}async function PU(N,U){let H=await A(N);if(!H)throw Error(`Run not found: ${N}`);if(v(H.status))throw Error("Run is still active \u2014 wait for the current turn to finish");let Y=H.codexThreadId;if(!Y)throw Error("Run has no Codex thread");let{server:O}=await m0(N,Y),W=U?.trim();await C(N,"daemon","run.review.started",{instructions:W??null}),await I(N,"running");try{await O.request("review/start",{threadId:Y,target:W?{type:"custom",instructions:W}:{type:"uncommittedChanges"},delivery:"inline"})}catch($){let G=$ instanceof Error?$.message:String($);throw await C(N,"daemon","run.failed",{reason:G}),await I(N,"failed"),$}return await A(N)}async function IU(N){let U=await A(N);if(!U||!v(U.status))return!1;if(U.codexThreadId&&XN?.running)try{await XN.request("turn/interrupt",{threadId:U.codexThreadId})}catch(H){console.warn(`[runs] turn/interrupt failed for ${N}:`,H)}return YN.delete(N),await C(N,"daemon","run.stopped",{}),await I(N,"stopped"),!0}async function wU(N,U,H){let Y=YN.get(N)??[],O=Y.findIndex(($)=>String($.requestId)===String(U));if(O===-1)return!1;let[W]=Y.splice(O,1);if(Y.length===0)YN.delete(N);if(W.method==="mcpServer/elicitation/request"){let $=H==="decline"||H==="cancel"?H:"accept";P().respond(W.requestId,{action:$})}else P().respond(W.requestId,{decision:H});if(await C(N,"daemon","approval.resolved",{requestId:W.requestId,decision:H}),Y.length===0)await I(N,"running");return!0}function zN(){return O2.join(k(),"config.toml")}async function i(){try{return await LN.readFile(zN(),"utf8")}catch{return""}}async function fU(N){try{m(N)}catch(U){throw new J(`Invalid TOML: ${U instanceof Error?U.message:String(U)}`)}await LN.writeFile(zN(),N,"utf8")}function W2(N){if(!N.trim())return{};let H=m(N).mcp_servers;if(typeof H!=="object"||H===null)return{};return H}async function $2(){let N=new Map;try{let U=await B("mcpServerStatus/list",{detail:"full"});for(let H of U.data??[]){let Y=Object.entries(H.tools??{}).map(([O,W])=>({name:O,description:W?.description}));N.set(H.name,{startupState:H.serverInfo?"ready":"starting",authStatus:H.authStatus??null,tools:Y})}}catch(U){console.warn("[mcp] mcpServerStatus/list failed:",U)}return N}async function kU(){let N=await i(),U=W2(N),H=await $2();return{servers:Object.entries(U).map(([O,W])=>{let $=H.get(O);return{name:O,command:W.command,args:W.args,envKeys:W.env?Object.keys(W.env):void 0,url:W.url,enabled:W.enabled!==!1,startupState:$?.startupState??null,authStatus:$?.authStatus??null,tools:$?.tools??[],error:$?.error}})}}var G2=/^[A-Za-z0-9_-]+$/;async function yU(N){if(!G2.test(N.name))throw new J(`Invalid server name "${N.name}" \u2014 letters, digits, _ and - only`);if(!N.command&&!N.url)throw new J("Server needs either a command or a url");let U=await i(),H=U.trim()?m(U):{},Y=H.mcp_servers??{},O={};if(N.command)O.command=N.command;if(N.args&&N.args.length>0)O.args=N.args;if(N.env&&Object.keys(N.env).length>0)O.env=N.env;if(N.url)O.url=N.url;if(N.enabled===!1)O.enabled=!1;Y[N.name]=O,H.mcp_servers=Y,await LN.writeFile(zN(),s(H),"utf8")}async function bU(N){let U=await i();if(!U.trim())return!1;let H=m(U),Y=H.mcp_servers;if(!Y||!(N in Y))return!1;return delete Y[N],await LN.writeFile(zN(),s(H),"utf8"),!0}async function qU(N,U){let H=await i(),Y=m(H||""),O=Y.mcp_servers??{};if(!O[N])throw new J(`Server not found: ${N}`);O[N].enabled=U,Y.mcp_servers=O,await LN.writeFile(zN(),s(Y),"utf8")}async function vU(){await B("config/mcpServer/reload",{})}async function gU(N,U,H,Y){let O=await i(),W=O.trim()?m(O):{},$=W.mcp_servers??{},G={command:process.execPath,args:[U],env:{JUN_PORT:String(H)}},F=$[N],Q=Boolean(Y&&$[Y]);if(F&&!Q&&F.command===G.command&&JSON.stringify(F.args)===JSON.stringify(G.args)&&F.env?.JUN_PORT===String(H))return;if(Y)delete $[Y];$[N]=G,W.mcp_servers=$,await LN.writeFile(zN(),s(W),"utf8")}var Q2="https://registry.npmjs.org/junhost/latest",X2=7200000,Z2=1800000,c0=null,hU=0,l0=!1,DN=null;async function mU(){try{let N=await fetch(Q2,{signal:AbortSignal.timeout(5000)});if(!N.ok)throw Error(`registry ${N.status}`);let U=await N.json();c0=typeof U.version==="string"?U.version:null,l0=c0!==null}catch{l0=!1}finally{hU=Date.now(),DN=null}}function p0(){let N=l0?X2:Z2;if(!DN&&Date.now()-hU>N)DN=mU();return c0}async function F0(){if(!DN)DN=mU();await DN}function u0(N,U){let H=N.split(".").map((O)=>parseInt(O,10)||0),Y=U.split(".").map((O)=>parseInt(O,10)||0);for(let O=0;O<Math.max(H.length,Y.length);O++){let W=H[O]??0,$=Y[O]??0;if(W!==$)return W>$}return!1}function cU(){let N=p0();return{latestVersion:N,updateAvailable:N!==null&&u0(N,c)}}var L2=Date.now();function lU(){return Z({ok:!0})}async function pU(N){if(N?.searchParams.get("refresh")==="1")await F0();let U={ok:!0,name:"jun",version:c,...cU(),dataRoot:f,workspaceRoot:M(),uptimeSeconds:Math.round((Date.now()-L2)/1000),engine:RU()};return Z(U)}import z2 from"path";var Q0={ok:!0};async function uU(N,U){let H=U.pathname.slice(11),Y=U.searchParams.get("path")??".";switch(`${N.method} ${H}`){case"GET tree":return Z(await L1(Y));case"GET read":return Z(await z1(Y));case"GET download":{let O=oN(Y),W=Bun.file(O);if(!await W.exists())return X(404,`File not found: ${Y}`);return new Response(W,{headers:{"content-disposition":`attachment; filename="${encodeURIComponent(z2.basename(O))}"`}})}case"POST write":{let O=await z(N);return await D1(K(O.path,"path"),typeof O.content==="string"?O.content:""),Z(Q0)}case"POST mkdir":{let O=await z(N);return await K1(K(O.path,"path")),Z(Q0)}case"POST delete":{let O=await z(N);return await V1(K(O.path,"path")),Z(Q0)}case"POST rename":{let O=await z(N);return await M1(K(O.from,"from"),K(O.to,"to")),Z(Q0)}case"POST upload":{let O;try{O=await N.formData()}catch{throw new J("Expected multipart/form-data body")}let W=String(O.get("path")??"."),$=O.getAll("file").filter((F)=>F instanceof File);if($.length===0)throw new J("No files in upload (field name: file)");let G=[];for(let F of $)G.push(await J1(W,F.name,F));return Z({ok:!0,saved:G})}default:return X(404,`Unknown files endpoint: ${N.method} /api/files/${H}`)}}var D2=new Set(["accept","acceptForSession","decline","cancel"]);async function iU(N,U,H){let Y=U.pathname.split("/").filter(Boolean),O=Y[2],W=Y[3];if(!O){if(N.method==="GET"){let $={runs:await j1()};return Z($)}if(N.method==="POST"){let $=await z(N);K($.prompt,"prompt");let F={run:await ZN($)};return Z(F,201)}return X(405,"Method not allowed")}if(W==="events"){if(!await A(O))return X(404,`Run not found: ${O}`);return H.upgrade(N,{data:{channel:`run:${O}`}})?void 0:X(400,"WebSocket upgrade required")}if(!W&&N.method==="GET"){let $=await A(O);if(!$)return X(404,`Run not found: ${O}`);let G=Number(U.searchParams.get("tail")??NaN),F=Number(U.searchParams.get("before")??NaN),Q=await x1(O,{limit:Number.isFinite(G)&&G>0?G:void 0,before:Number.isFinite(F)&&F>=0?F:void 0}),L={run:$,events:Q.events,eventsOffset:Q.offset,totalEvents:Q.total};return Z(L)}if(N.method!=="POST")return X(405,"Method not allowed");switch(W){case"stop":return await IU(O)?Z({ok:!0}):X(409,"Run is not active");case"resume":{let $=await z(N);K($.prompt,"prompt");try{let G=await G0(O,$.prompt,Array.isArray($.attachments)?$.attachments:void 0,{sandbox:$.sandbox,approvalPolicy:$.approvalPolicy,approvalsReviewer:$.approvalsReviewer,model:$.model,effort:$.effort});return Z({run:G})}catch(G){let F=G instanceof Error?G.message:String(G),Q=F.includes("not found")?404:F.includes("still active")?409:400;return X(Q,F)}}case"steer":{let $=await z(N);K($.prompt,"prompt");try{return await SU(O,$.prompt,Array.isArray($.attachments)?$.attachments:void 0),Z({ok:!0})}catch(G){let F=G instanceof Error?G.message:String(G),Q=F.includes("not found")?404:F.includes("not active")||F.includes("No active turn")?409:400;return X(Q,F)}}case"fast":{let $=await z(N);if(typeof $.enabled!=="boolean")return X(400,"Missing or invalid field: enabled");try{let G=await _U(O,$.enabled);return Z({run:G})}catch(G){let F=G instanceof Error?G.message:String(G),Q=F.includes("not found")?404:F.includes("does not support")?400:500;return X(Q,F)}}case"compact":try{return await jU(O),Z({ok:!0})}catch($){let G=$ instanceof Error?$.message:String($),F=G.includes("not found")?404:G.includes("still active")?409:400;return X(F,G)}case"review":{let $=await z(N);try{let G=await PU(O,$.instructions);return Z({run:G})}catch(G){let F=G instanceof Error?G.message:String(G),Q=F.includes("not found")?404:F.includes("still active")?409:400;return X(Q,F)}}case"approve":{let $=await z(N);if(!D2.has(String($.decision)))return X(400,`Invalid decision: ${String($.decision)}`);if($.requestId===void 0||$.requestId===null)return X(400,"Missing field: requestId");return await wU(O,$.requestId,$.decision)?Z({ok:!0}):X(404,"No matching pending approval")}default:return X(404,`Unknown runs endpoint: ${U.pathname}`)}}var ON="browser-stream",g=null,dU=null,KN=0,VN=null,i0=null;function K2(N){if(g&&dU===N&&g.readyState<=WebSocket.OPEN)return;g?.close(),dU=N;let U=new WebSocket(`ws://127.0.0.1:${N}`);g=U,U.onmessage=(H)=>{let Y=String(H.data);if(Y.includes('"type":"frame"'))i0=Y;B1(ON,Y)},U.onclose=()=>{if(g===U)g=null,i0=null,oU()},U.onerror=()=>{}}function oU(){if(VN||KN===0)return;VN=setTimeout(()=>{VN=null,yN(!0)},2000)}async function yN(N=!1){if(KN===0)return;let U=N?null:a1();if(U===null){if(N)u();U=(await PN()).streamPort}if(U!==null)K2(U);else oU()}function nU(){KN+=1,yN()}function aU(){return i0}function sU(){if(KN=Math.max(0,KN-1),KN===0){if(g?.close(),g=null,VN)clearTimeout(VN),VN=null}}var V2=new Set(["input_mouse","input_keyboard","input_touch"]);function tU(N){if(o1()!=="user")return;if(!g||g.readyState!==WebSocket.OPEN)return;let U=typeof N==="string"?N:N.toString("utf8");try{let H=JSON.parse(U);if(typeof H.type==="string"&&V2.has(H.type))g.send(U)}catch{}}var M2=new Set(["user","agent","paused"]);async function rU(N,U,H){let O=U.pathname.split("/").filter(Boolean)[2];if(O==="stream")return H.upgrade(N,{data:{channel:ON}})?void 0:X(400,"WebSocket upgrade required");if(N.method==="GET")switch(O){case"status":{let W=await PN();if(W.streaming)yN();return Z({status:W})}case"actions":{let W={actions:d1()};return Z(W)}default:return X(404,`Unknown browser endpoint: ${U.pathname}`)}if(N.method!=="POST")return X(405,"Method not allowed");switch(O){case"start":{let W=await z(N).catch(()=>({})),$=await r1(typeof W.url==="string"&&W.url.length>0?W.url:void 0);return yN(),Z({status:$})}case"stop":return await e1(),Z({ok:!0});case"navigate":{let W=await z(N);return K(W.url,"url"),await NU(W.url),Z({ok:!0})}case"key":{let W=await z(N);return K(W.key,"key"),await HU(W.key),Z({ok:!0})}case"back":case"forward":case"reload":return await UU(O),Z({ok:!0});case"screenshot":{let $={path:await YU()};return Z($)}case"snapshot":{let W=await z(N).catch(()=>({})),$=await OU(W.interactive??!0);return Z({snapshot:$})}case"click":{let W=await z(N);return K(W.target,"target"),await WU(W.target),Z({ok:!0})}case"fill":{let W=await z(N);return K(W.target,"target"),K(W.text,"text"),await $U(W.target,W.text),Z({ok:!0})}case"read":{let W=await z(N).catch(()=>({})),$=await GU(W.selector);return Z({text:$})}case"eval":{let W=await z(N);K(W.expression,"expression");let $=await FU(W.expression);return Z({result:$})}case"exec":{let W=await z(N);if(!Array.isArray(W.args)||W.args.length===0)return X(400,"args must be a non-empty array of strings");let $=await QU(W.args,{json:W.json});return Z($)}case"control":{let W=await z(N);if(!M2.has(String(W.controller)))return X(400,`Invalid controller: ${String(W.controller)}`);return n1(W.controller),Z({ok:!0})}default:return X(404,`Unknown browser endpoint: ${U.pathname}`)}}import{promises as j}from"fs";import R from"path";var UH=".agents/skills";function MN(){return R.join(M(),UH)}var J2=/^[a-z0-9][a-z0-9-]*$/,A2=new Set(["registry","install"]);function JN(N){if(!J2.test(N))throw new J(`Invalid skill id "${N}" \u2014 use lowercase letters, digits and dashes`);return R.join(MN(),N)}function eU(N){return N.replace(/\x1b\[[0-9;?]*[A-Za-z]/g,"")}async function HH(N,U,H=120000){let Y=Bun.spawn([process.execPath,"x","skills",...N],{cwd:U,env:{...process.env,DISABLE_TELEMETRY:"1",DO_NOT_TRACK:"1"},stdout:"pipe",stderr:"pipe"}),O=setTimeout(()=>Y.kill(),H);try{let[W,$,G]=await Promise.all([new Response(Y.stdout).text(),new Response(Y.stderr).text(),Y.exited]);return{stdout:eU(W),stderr:eU($),code:G}}finally{clearTimeout(O)}}function T2(N){let U=[],H=null;for(let Y of N.split(/\r?\n/)){let O=Y.trim(),W=/^(\S+@\S+)\s+([\d.]+[KMB]?)\s+installs\b/.exec(O);if(W){let G=W[1],F=G.indexOf("@");H={source:G,repo:G.slice(0,F),name:G.slice(F+1),installs:W[2]},U.push(H);continue}let $=/^[\u2514\u2570]\s*(https?:\/\/\S+)/.exec(O);if($&&H)H.url=$[1],H=null}return U}function B2(N){let U=[],H=/^---\r?\n([\s\S]*?)\r?\n---/.exec(N.replace(/^\uFEFF/,""));if(!H)return{errors:["Missing YAML frontmatter (--- name/description ---)"]};let Y={};for(let O of H[1].split(/\r?\n/)){let W=/^([A-Za-z_][\w-]*):\s*(.*)$/.exec(O);if(W)Y[W[1].toLowerCase()]=W[2].trim().replace(/^["']|["']$/g,"")}if(!Y.name)U.push("Frontmatter is missing required field: name");if(!Y.description)U.push("Frontmatter is missing required field: description");return{name:Y.name,description:Y.description,errors:U}}var E2=15000,bN=null,X0=null;function qN(){bN=null}async function C2(){if(bN&&Date.now()-bN.at<E2)return bN.view;if(X0)return X0;let N=R2().then((U)=>{return bN={at:Date.now(),view:U},U}).finally(()=>{X0=null});return X0=N,N}async function R2(){let N=new Map,U=[];try{let H=await B("skills/list",{cwds:[M()],forceReload:!0});for(let Y of H.data??[]){for(let O of Y.errors??[])U.push(O);for(let O of Y.skills??[]){let W=R.basename(R.dirname(O.path));N.set(W,O)}}}catch(H){console.warn("[skills] skills/list failed:",H)}return{byDir:N,errors:U}}async function Z0(){await j.mkdir(MN(),{recursive:!0});let U=(await j.readdir(MN(),{withFileTypes:!0})).filter(($)=>$.isDirectory()).map(($)=>$.name),{byDir:H,errors:Y}=await C2(),O=[];for(let $ of U){let G=R.join(MN(),$,"SKILL.md"),F=null;try{F=await j.readFile(G,"utf8")}catch{O.push({id:$,name:$,description:"",enabled:!1,errors:["Missing SKILL.md"]});continue}let Q=B2(F),L=H.get($),V=Y.filter((T)=>l(T.path).includes(`/${$}/`)||R.basename(R.dirname(T.path))===$).map((T)=>T.message);O.push({id:$,name:L?.name??Q.name??$,description:L?.description??Q.description??"",enabled:L?.enabled??!0,errors:[...new Set([...Q.errors,...V])]})}let W=Y.filter(($)=>!U.some((G)=>l($.path).includes(`/${G}/`)));return{skills:O,errors:W}}async function vN(N){let U=JN(N),H;try{H=await j.readFile(R.join(U,"SKILL.md"),"utf8")}catch{return null}let{skills:Y}=await Z0(),O=Y.find((G)=>G.id===N)??{id:N,name:N,description:"",enabled:!0,errors:[]},W=[],$=async(G)=>{let F=await j.readdir(R.join(U,G),{withFileTypes:!0});for(let Q of F){let L=G?`${G}/${Q.name}`:Q.name;if(Q.isDirectory())await $(L);else if(L!=="SKILL.md")W.push(`${UH}/${N}/${L}`)}};return await $(""),{info:O,content:H,files:W}}async function YH(N){let U=N.name.trim().toLowerCase().replace(/\s+/g,"-");if(A2.has(U))throw new J(`"${U}" is a reserved name \u2014 pick another`);let H=JN(U);try{throw await j.access(R.join(H,"SKILL.md")),new J(`Skill "${U}" already exists`)}catch(O){if(O instanceof J)throw O}let Y=`---
329
+ name: ${U}
331
330
  description: ${N.description.trim()}
332
331
  ---
333
332
 
334
333
  ${N.instructions?.trim()??"Describe when and how to use this skill."}
335
- `;return await x.mkdir(W,{recursive:!0}),await x.writeFile(w.join(W,"SKILL.md"),$,"utf8"),mN(H),await cN(Y,H)}async function K2(N,H,Y=K){let W=CN(N,Y);try{await x.access(W)}catch{throw new A(`Skill not found: ${N}`)}return await x.writeFile(w.join(W,"SKILL.md"),H,"utf8"),mN(Y),await cN(N,Y)}async function L2(N,H=K){let Y=CN(N,H);try{return await x.rm(Y,{recursive:!0,force:!1}),mN(H),!0}catch{return!1}}async function M2(N,H,Y=K){let W=w.join(CN(N,Y),"SKILL.md");await C("skills/config/write",{path:W,enabled:H,name:null}),mN(Y)}async function J2(N){let H=N.trim();if(!H)return[];let{stdout:Y}=await F2(["find",H],B(K),30000);return bW(Y)}async function O2(N){await x.mkdir(DN(N),{recursive:!0});let H=await x.readdir(DN(N),{withFileTypes:!0});return new Set(H.filter((Y)=>Y.isDirectory()).map((Y)=>Y.name))}async function B2(N,H=K){let Y=N.trim();if(!Y)throw new A("Missing skill source");if(/[\s;&|`$(){}<>]/.test(Y))throw new A("Invalid source \u2014 expected owner/repo[@skill] or a URL");let W=B(H),$=await O2(H),{stdout:G,stderr:U}=await F2(["add",Y,"-a","codex","--copy","-y"],W);mN(H);let X=[...await O2(H)].filter((F)=>!$.has(F));if(X.length===0){let F=[G,U].filter(Boolean).join(`
336
- `).trim();throw new A(`No skill installed from "${Y}".${F?`
337
- ${F}`:""}`)}let{skills:Z}=await V0(H);return{installed:X,skills:Z,log:[G,U].filter(Boolean).join(`
338
- `).trim()}}async function A2(N,H,Y=K){let W=await cN(N,Y);if(!W)throw new A(`Skill not found: ${N}`);let $={prompt:H?.trim()||`Use the "${W.info.name}" skill to demonstrate what it does. Follow its instructions and report the result.`,projectId:Y,skill:{name:W.info.name,path:w.join(CN(N,Y),"SKILL.md")}};return VN($)}async function hW(N){let H=N.searchParams.get("project");if(H)return H;let Y=N.searchParams.get("cwd");if(Y){let W=pN(Y);if(W&&await JN(W))return W}return K}async function D2(N,H){let Y=H.pathname.split("/").filter(Boolean),W=Y[2],$=Y[3],G=await hW(H);if(W==="registry"){if($==="search"&&N.method==="GET"){let U=H.searchParams.get("q")??"",Q=await J2(U);return O({results:Q})}if($==="install"&&N.method==="POST"){let U=await V(N);J(U.source,"source");let Q=await B2(U.source,G);return O(Q,201)}return z(404,`Unknown skills endpoint: ${H.pathname}`)}if(!W){if(N.method==="GET")return O(await V0(G));if(N.method==="POST"){let U=await V(N);J(U.name,"name"),J(U.description,"description");let Q=await V2(U,G);return O({skill:Q},201)}return z(405,"Method not allowed")}if(!$)switch(N.method){case"GET":{let U=await cN(W,G);return U?O({skill:U}):z(404,`Skill not found: ${W}`)}case"PUT":{let U=await V(N);J(U.content,"content");let Q=await K2(W,U.content,G);return O({skill:Q})}case"DELETE":return await L2(W,G)?O({ok:!0}):z(404,`Skill not found: ${W}`);default:return z(405,"Method not allowed")}if(N.method!=="POST")return z(405,"Method not allowed");switch($){case"enable":{let U=await V(N);if(typeof U.enabled!=="boolean")return z(400,"Missing or invalid field: enabled");return await M2(W,U.enabled,G),O({ok:!0})}case"test":{let U=await V(N).catch(()=>({})),Q=await A2(W,U.prompt,G);return O({run:Q},201)}default:return z(404,`Unknown skills endpoint: ${H.pathname}`)}}async function C2(N,H){let Y=H.pathname.split("/").filter(Boolean),W=Y[2];if(!W){if(N.method==="GET")return O(await vH());return z(405,"Method not allowed")}if(W==="config"){if(N.method==="GET"){let $={toml:await d()};return O($)}if(N.method==="PUT"){let $=await V(N);return J($.toml,"toml"),await jH($.toml),O({ok:!0})}return z(405,"Method not allowed")}if(W==="reload"&&N.method==="POST")return await cH(),O({ok:!0});if(W==="servers"){let $=Y[3];if(!$){if(N.method==="POST"){let U=await V(N);return J(U.name,"name"),await gH(U),O({ok:!0},201)}return z(405,"Method not allowed")}let G=Y[4];if(G==="enable"&&N.method==="POST"){let U=await V(N);if(typeof U.enabled!=="boolean")return z(400,"Missing or invalid field: enabled");return await mH($,U.enabled),O({ok:!0})}if(!G&&N.method==="DELETE")return await hH($)?O({ok:!0}):z(404,`Server not found: ${$}`);return z(405,"Method not allowed")}return z(404,`Unknown MCP endpoint: ${H.pathname}`)}import{promises as UN}from"fs";import lN from"path";function mW(){return lN.join(j(),"config.toml")}function L0(){return lN.join(j(),"memories")}async function S2(){let N=await d();return N.trim()?l(N):{}}function K0(N){return typeof N==="object"&&N!==null?N:{}}function cW(N){let H=K0(N.memories),Y={};if(typeof H.generate_memories==="boolean")Y.generateMemories=H.generate_memories;if(typeof H.use_memories==="boolean")Y.useMemories=H.use_memories;if(typeof H.disable_on_external_context==="boolean")Y.disableOnExternalContext=H.disable_on_external_context;if(typeof H.min_rate_limit_remaining_percent==="number")Y.minRateLimitRemainingPercent=H.min_rate_limit_remaining_percent;return Y}async function lW(){let N=L0(),H=[];async function Y(W){let $;try{$=await UN.readdir(W,{withFileTypes:!0})}catch{return}for(let G of $){let U=lN.join(W,G.name);if(G.isDirectory()){if(G.name===".git")continue;await Y(U)}else if(G.isFile()){let Q=await UN.stat(U);H.push({path:u(lN.relative(N,U)),name:G.name,size:Q.size,modifiedAt:Q.mtime.toISOString()})}}}return await Y(N),H.sort((W,$)=>$.modifiedAt.localeCompare(W.modifiedAt)),H}async function uW(){try{let H=((await C("experimentalFeature/list",{})).data??[]).find((Y)=>Y.name==="memories");return H?H.enabled:null}catch(N){return console.warn("[memories] experimentalFeature/list failed:",N),null}}async function T2(){let N=await S2();return{enabled:K0(N.features).memories===!0,liveEnabled:await uW(),settings:cW(N),files:await lW()}}async function E2(N){let H=await S2();if(typeof N.enabled==="boolean"){let Y=K0(H.features);Y.memories=N.enabled,H.features=Y}if(N.settings){let Y=K0(H.memories),W=N.settings;if(typeof W.generateMemories==="boolean")Y.generate_memories=W.generateMemories;if(typeof W.useMemories==="boolean")Y.use_memories=W.useMemories;if(typeof W.disableOnExternalContext==="boolean")Y.disable_on_external_context=W.disableOnExternalContext;if(typeof W.minRateLimitRemainingPercent==="number")Y.min_rate_limit_remaining_percent=W.minRateLimitRemainingPercent;H.memories=Y}if(await UN.writeFile(mW(),t(H),"utf8"),typeof N.enabled==="boolean")try{await C("experimentalFeature/enablement/set",{enablement:{memories:N.enabled}})}catch(Y){console.warn("[memories] live enablement/set failed (applies on restart):",Y)}}async function R2(N){let H=HN(L0(),N);return UN.readFile(H,"utf8")}async function w2(N,H){let Y=HN(L0(),N);await UN.mkdir(lN.dirname(Y),{recursive:!0}),await UN.writeFile(Y,H,"utf8")}async function _2(N){let H=HN(L0(),N);await UN.rm(H)}async function P2(N,H){let W=H.pathname.split("/").filter(Boolean)[2];if(!W){if(N.method==="GET")return O(await T2());return z(405,"Method not allowed")}if(W==="config"){if(N.method==="PUT"){let $=await V(N);if(typeof $.enabled!=="boolean"&&!$.settings)return z(400,"Nothing to update: pass enabled and/or settings");return await E2($),O({ok:!0})}return z(405,"Method not allowed")}if(W==="file"){if(N.method==="GET"){let $=J(H.searchParams.get("path"),"path"),G={path:$,content:await R2($)};return O(G)}if(N.method==="PUT"){let $=await V(N);if(J($.path,"path"),typeof $.content!=="string")return z(400,"Missing or invalid field: content");return await w2($.path,$.content),O({ok:!0})}if(N.method==="DELETE"){let $=J(H.searchParams.get("path"),"path");return await _2($),O({ok:!0})}return z(405,"Method not allowed")}return z(404,`Unknown memories endpoint: ${H.pathname}`)}var pW=300000,M0=null;async function x2(N){if(N.method!=="GET")return z(405,"Method not allowed");if(M0&&Date.now()-M0.at<pW)return O({models:M0.models});let Y=((await C("model/list",{})).data??[]).filter(($)=>!$.hidden).map(($)=>({id:$.id,model:$.model,displayName:$.displayName,description:$.description,isDefault:$.isDefault,defaultReasoningEffort:$.defaultReasoningEffort,supportedReasoningEfforts:$.supportedReasoningEfforts??[]}));return M0={at:Date.now(),models:Y},O({models:Y})}async function J0(){let N=await C("account/read",{});return{account:N.account??null,requiresOpenaiAuth:N.requiresOpenaiAuth,pendingLogin:X0(),lastLoginResult:BH()}}async function f2(N,H){if(H.pathname==="/api/account"){if(N.method!=="GET")return z(405,"Method not allowed");return O(await J0())}if(H.pathname==="/api/account/login"&&N.method==="POST"){let Y=await V(N),W;if(Y.type==="chatgpt"||Y.type==="chatgptDeviceCode")W={type:Y.type};else if(Y.type==="apiKey")W={type:"apiKey",apiKey:J(Y.apiKey,"apiKey")};else throw new A("type must be one of: chatgpt, chatgptDeviceCode, apiKey");let $=X0();if($)await C("account/login/cancel",{loginId:$.loginId}).catch(()=>{});Z0();let G=await C("account/login/start",W);if((G.type==="chatgpt"||G.type==="chatgptDeviceCode")&&G.loginId){let U={loginId:G.loginId,type:G.type,authUrl:G.authUrl,userCode:G.userCode,verificationUrl:G.verificationUrl,startedAt:new Date().toISOString()};AH(U)}return O(await J0())}if(H.pathname==="/api/account/login/cancel"&&N.method==="POST"){let Y=X0();if(Y)await C("account/login/cancel",{loginId:Y.loginId}).catch(()=>{});return Z0(),O(await J0())}if(H.pathname==="/api/account/logout"&&N.method==="POST")return await C("account/logout",{}),Z0(),O(await J0());return z(404,`Not found: ${H.pathname}`)}function nW(N){if(!N)return null;return N.replace(/^([a-z0-9+.-]+:\/\/[^:@/]+):[^@/]+@/i,"$1:\u2022\u2022\u2022\u2022@")}function k2(){let N=G0(),H=U0();return{browserProxy:{proxyUrl:nW(N.value),source:N.source,noProxy:H.value,noProxySource:H.source}}}async function y2(N,H){if(H.pathname==="/api/settings"&&N.method==="GET")return O(k2());if(H.pathname==="/api/settings/browser-proxy"&&N.method==="PUT"){let Y=await V(N);if(Y.proxyUrl!==void 0&&Y.proxyUrl!==null&&Y.proxyUrl.trim())try{if(!new URL(Y.proxyUrl.trim()).hostname)throw Error("missing host")}catch{return z(400,"Invalid proxy URL \u2014 expected e.g. http://user:pass@host:port")}return await m1({...Y.proxyUrl!==void 0?{browserProxy:Y.proxyUrl}:{},...Y.noProxy!==void 0?{browserNoProxy:Y.noProxy}:{}}),O(k2())}if(N.method!=="GET"&&N.method!=="PUT")return z(405,"Method not allowed");return z(404,`Unknown settings endpoint: ${H.pathname}`)}import{promises as SN}from"fs";import h2 from"path";import{randomUUID as eW}from"crypto";function uN(N,H,Y,W){let $=new Set,G=N.trim()!=="*";for(let U of N.split(",")){let Q=U.trim();if(!Q)throw Error(`Invalid ${W} field: empty term`);let X=Q,Z=1,F=Q.indexOf("/");if(F!==-1){if(X=Q.slice(0,F),Z=Number(Q.slice(F+1)),!Number.isInteger(Z)||Z<=0)throw Error(`Invalid step in ${W}: ${Q}`)}let M,E;if(X==="*")M=H,E=Y;else if(X.includes("-")){let[f,QN]=X.split("-");M=Number(f),E=Number(QN)}else M=Number(X),E=M;if(!Number.isInteger(M)||!Number.isInteger(E))throw Error(`Invalid ${W} value: ${Q}`);if(M<H||E>Y||M>E)throw Error(`${W} out of range (${H}-${Y}): ${Q}`);for(let f=M;f<=E;f+=Z)$.add(f)}return{set:$,restricted:G}}function I2(N){let H=N.trim().split(/\s+/);if(H.length!==5)throw Error(`Cron must have 5 fields (min hour dom month dow); got ${H.length}`);let Y=uN(H[0],0,59,"minute"),W=uN(H[1],0,23,"hour"),$=uN(H[2],1,31,"day-of-month"),G=uN(H[3],1,12,"month"),U=uN(H[4],0,7,"day-of-week"),Q=new Set;for(let X of U.set)Q.add(X===7?0:X);return{minute:Y.set,hour:W.set,dom:$.set,month:G.set,dow:Q,domRestricted:$.restricted,dowRestricted:U.restricted}}function j2(N){try{return I2(N),null}catch(H){return H instanceof Error?H.message:"Invalid cron expression"}}function dW(N){return new Intl.DateTimeFormat("en-US",{timeZone:N,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"})}function v2(N,H){if(!H)return{year:N.getFullYear(),month:N.getMonth()+1,day:N.getDate(),hour:N.getHours(),minute:N.getMinutes(),second:N.getSeconds()};let Y={};for(let W of dW(H).formatToParts(N))if(W.type!=="literal")Y[W.type]=Number(W.value);return{year:Y.year,month:Y.month,day:Y.day,hour:Y.hour,minute:Y.minute,second:Y.second}}function aW(N,H){return new Date(Date.UTC(N,H,0)).getUTCDate()}function oW(N){return new Date(Date.UTC(N.year,N.month-1,N.day)).getUTCDay()}function b2(N){if(N.minute++,N.minute<60)return;if(N.minute=0,N.hour++,N.hour<24)return;if(N.hour=0,N.day++,N.day<=aW(N.year,N.month))return;if(N.day=1,N.month++,N.month<=12)return;N.month=1,N.year++}function sW(N,H){if(!N.minute.has(H.minute))return!1;if(!N.hour.has(H.hour))return!1;if(!N.month.has(H.month))return!1;let Y=N.dom.has(H.day),W=N.dow.has(oW(H));if(N.domRestricted&&N.dowRestricted)return Y||W;if(N.domRestricted)return Y;if(N.dowRestricted)return W;return!0}function q2(N,H){let Y=v2(N,H);return Date.UTC(Y.year,Y.month-1,Y.day,Y.hour,Y.minute,Y.second)-N.getTime()}function tW(N,H){if(!H)return new Date(N.year,N.month-1,N.day,N.hour,N.minute,0,0);let Y=Date.UTC(N.year,N.month-1,N.day,N.hour,N.minute,0),W=q2(new Date(Y),H),$=Y-W,G=q2(new Date($),H);if(G!==W)$=Y-G;return new Date($)}var rW=4216320;function g2(N,H,Y){let W=I2(N),$=v2(H,Y),G={year:$.year,month:$.month,day:$.day,hour:$.hour,minute:$.minute};b2(G);for(let U=0;U<rW;U++){if(sW(W,G))return tW(G,Y);b2(G)}return null}var N$={sandbox:"workspaceWrite",approvalPolicy:"onRequest",approvalsReviewer:"auto_review",effort:"medium"};function H$(N){return N.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40)}function r0(N){return h2.join(TN(),`${N}.json`)}async function m2(){await SN.mkdir(TN(),{recursive:!0})}async function e0(N){await m2(),await SN.writeFile(r0(N.id),JSON.stringify(N,null,2),"utf8")}function N1(N,H){if(!N.enabled)return null;if(N.kind==="once"){if(!N.runAt)return null;let W=new Date(N.runAt);if(Number.isNaN(W.getTime()))return null;if(N.lastRunAt)return null;return W.toISOString()}if(!N.cron)return null;let Y=g2(N.cron,H,N.tz);return Y?Y.toISOString():null}function c2(N,H){if(H==="cron"){if(!N.cron)throw Error("cron expression is required for a cron schedule");let Y=j2(N.cron);if(Y)throw Error(`Invalid cron expression: ${Y}`)}else{if(!N.runAt)throw Error("runAt is required for a one-off schedule");if(Number.isNaN(new Date(N.runAt).getTime()))throw Error("runAt is not a valid datetime")}if(N.tz)try{new Intl.DateTimeFormat("en-US",{timeZone:N.tz})}catch{throw Error(`Unknown timezone: ${N.tz}`)}}async function H1(N){await m2();let H;try{H=await SN.readdir(TN())}catch{return[]}let Y=[];for(let W of H){if(!W.endsWith(".json"))continue;try{let $=await SN.readFile(h2.join(TN(),W),"utf8"),G=JSON.parse($);if(N&&G.projectId!==N)continue;Y.push(G)}catch{}}return Y.sort((W,$)=>$.createdAt.localeCompare(W.createdAt)),Y}async function B0(N){try{let H=await SN.readFile(r0(N),"utf8");return JSON.parse(H)}catch{return null}}async function l2(N){let H=N.name?.trim();if(!H)throw Error("Schedule name is required");if(!N.prompt?.trim())throw Error("Schedule prompt is required");let Y=N.projectId??"default";if(!await JN(Y))throw Error(`Unknown project: ${Y}`);let W=N.kind??"cron";c2(N,W);let $=`${H$(H)||"schedule"}-${eW().slice(0,8)}`,G=new Date,U={id:$,name:H,projectId:Y,prompt:N.prompt,kind:W,cron:W==="cron"?N.cron:void 0,runAt:W==="once"?new Date(N.runAt).toISOString():void 0,tz:N.tz,mode:{...N$,...N.mode??{}},resume:N.resume??!1,threadRunId:null,enabled:N.enabled??!0,createdAt:G.toISOString(),lastRunAt:null,lastRunId:null,lastError:null,nextRunAt:null};return U.nextRunAt=N1(U,G),await e0(U),U}async function u2(N,H){let Y=await B0(N);if(!Y)return null;let W=H.kind??Y.kind,$={...Y,name:H.name?.trim()||Y.name,prompt:H.prompt??Y.prompt,kind:W,cron:W==="cron"?H.cron??Y.cron:void 0,runAt:W==="once"?H.runAt?new Date(H.runAt).toISOString():Y.runAt:void 0,tz:H.tz!==void 0?H.tz||void 0:Y.tz,mode:H.mode?{...Y.mode,...H.mode}:Y.mode,resume:H.resume??Y.resume,enabled:H.enabled??Y.enabled};if(c2($,W),W==="once"&&H.runAt&&$.runAt!==Y.runAt)$.lastRunAt=null;return $.nextRunAt=N1($,new Date),await e0($),$}async function i2(N){try{return await SN.unlink(r0(N)),!0}catch{return!1}}function Y$(N){return{sandbox:N.sandbox,approvalPolicy:N.approvalPolicy,approvalsReviewer:N.approvalsReviewer,model:N.model,effort:N.effort}}async function Y1(N,H){let Y=N.lastRunId??null,W=null,$=N.threadRunId??null;try{let U=N.mode;if(N.resume&&$&&await D($)){let Q=await D($);if(Q&&m(Q.status))throw Error("previous run still active \u2014 skipped this fire");Y=(await z0($,N.prompt,[],Y$(U))).id}else{let Q=await VN({prompt:N.prompt,projectId:N.projectId,sandbox:U.sandbox,approvalPolicy:U.approvalPolicy,approvalsReviewer:U.approvalsReviewer,model:U.model,effort:U.effort,source:"schedule",scheduleId:N.id,scheduleName:N.name});if(Y=Q.id,N.resume)$=Q.id}}catch(U){W=U instanceof Error?U.message:String(U)}let G={...N,lastRunAt:H.toISOString(),lastRunId:Y,lastError:W,threadRunId:$};return G.nextRunAt=N1(G,H),await e0(G),G}var t0=!1;async function p2(N=new Date){if(t0)return;t0=!0;try{let H=await H1();for(let Y of H){if(!Y.enabled||!Y.nextRunAt)continue;let W=new Date(Y.nextRunAt);if(Number.isNaN(W.getTime())||W.getTime()>N.getTime())continue;try{await Y1(Y,N)}catch($){console.error(`[schedules] fire failed for ${Y.id}:`,$)}}}catch(H){console.error("[schedules] tick failed:",H)}finally{t0=!1}}async function n2(N){let H=N.searchParams.get("project");if(H)return H;let Y=N.searchParams.get("cwd");if(Y){let W=pN(Y);if(W&&await JN(W))return W;return K}return}async function d2(N,H){let Y=H.pathname.split("/").filter(Boolean),W=Y[2],$=Y[3];if(!W){if(N.method==="GET"){let G=await n2(H),U={schedules:await H1(G)};return O(U)}if(N.method==="POST"){let G=await V(N);if(!G.projectId){let U=await n2(H);if(U)G.projectId=U}try{let Q={schedule:await l2(G)};return O(Q,201)}catch(U){return z(400,U instanceof Error?U.message:String(U))}}return z(405,"Method not allowed")}if($==="run"&&N.method==="POST"){let G=await B0(W);if(!G)return z(404,`Schedule not found: ${W}`);let Q={schedule:await Y1(G,new Date)};return O(Q)}if($)return z(404,`Not found: ${H.pathname}`);if(N.method==="GET"){let G=await B0(W);return G?O({schedule:G}):z(404,`Schedule not found: ${W}`)}if(N.method==="PUT"){let G=await V(N);try{let U=await u2(W,G);return U?O({schedule:U}):z(404,`Schedule not found: ${W}`)}catch(U){return z(400,U instanceof Error?U.message:String(U))}}if(N.method==="DELETE")return await i2(W)?O({ok:!0}):z(404,`Schedule not found: ${W}`);return z(405,"Method not allowed")}var $$=2000,A0=[],G$=0,a2=!1,W1="logs";function U$(N){return N.map((H)=>{if(typeof H==="string")return H;if(H instanceof Error)return H.stack??H.message;try{return Bun.inspect(H,{colors:!1,depth:3})}catch{return String(H)}}).join(" ")}function Q$(N,H){let Y={seq:++G$,ts:new Date().toISOString(),level:N,text:U$(H)};if(A0.push(Y),A0.length>$$)A0.shift();h(W1,Y)}function o2(){if(a2)return;a2=!0;let N=(H,Y)=>{let W=console[H].bind(console);console[H]=(...$)=>{try{Q$(Y,$)}catch{}W(...$)}};N("log","info"),N("info","info"),N("warn","warn"),N("error","error")}function s2(N={}){let H={info:0,warn:1,error:2},Y=N.level?H[N.level]:0,W=N.query?.toLowerCase(),$=A0.filter((G)=>H[G.level]>=Y&&(!W||G.text.toLowerCase().includes(W)));if(N.limit&&$.length>N.limit)$=$.slice(-N.limit);return $}var X$=new Set(["info","warn","error"]);function t2(N,H,Y){if(H.pathname==="/api/logs/stream")return Y.upgrade(N,{data:{channel:W1}})?void 0:z(400,"WebSocket upgrade required");if(N.method!=="GET")return z(405,"Method not allowed");let W=Number(H.searchParams.get("limit")),$=H.searchParams.get("level"),G=$&&X$.has($)?$:void 0,U={logs:s2({limit:Number.isFinite(W)&&W>0?Math.min(W,2000):500,level:G,query:H.searchParams.get("q")??void 0})};return O(U)}async function r2(N,H){let Y=new URL(N.url);try{if(Y.pathname==="/api/health")return dH();if(Y.pathname==="/api/status")return await aH(Y);if(Y.pathname==="/api/files/watch")return H.upgrade(N,{data:{channel:"files"}})?void 0:z(400,"WebSocket upgrade required");if(Y.pathname.startsWith("/api/files/"))return await oH(N,Y);if(Y.pathname==="/api/projects"||Y.pathname.startsWith("/api/projects/"))return await N2(N,Y);if(Y.pathname==="/api/runs"||Y.pathname.startsWith("/api/runs/"))return await H2(N,Y,H);if(Y.pathname.startsWith("/api/browser/"))return await X2(N,Y,H);if(Y.pathname==="/api/skills"||Y.pathname.startsWith("/api/skills/"))return await D2(N,Y);if(Y.pathname==="/api/mcp"||Y.pathname.startsWith("/api/mcp/"))return await C2(N,Y);if(Y.pathname==="/api/memories"||Y.pathname.startsWith("/api/memories/"))return await P2(N,Y);if(Y.pathname==="/api/models")return await x2(N);if(Y.pathname==="/api/account"||Y.pathname.startsWith("/api/account/"))return await f2(N,Y);if(Y.pathname==="/api/settings"||Y.pathname.startsWith("/api/settings/"))return await y2(N,Y);if(Y.pathname==="/api/schedules"||Y.pathname.startsWith("/api/schedules/"))return await d2(N,Y);if(Y.pathname==="/api/logs"||Y.pathname.startsWith("/api/logs/"))return t2(N,Y,H);return z(404,`Not found: ${Y.pathname}`)}catch(W){if(W instanceof sN)return z(400,W.message);if(W instanceof A)return z(400,W.message);if(Z$(W))return z(404,`Not found: ${Y.searchParams.get("path")??Y.pathname}`);return console.error(`[api] ${N.method} ${Y.pathname} failed:`,W),z(500,W instanceof Error?W.message:"Internal error")}}function Z$(N){return typeof N==="object"&&N!==null&&"code"in N&&N.code==="ENOENT"}o2();await Q1();var D0=[b.resolve(import.meta.dir,"../ui-dist"),b.resolve(import.meta.dir,"../../ui/dist")].find((N)=>e2(b.join(N,"index.html")))??b.resolve(import.meta.dir,"../../ui/dist"),z$=(N)=>[`${N}.ts`,`${N}.js`].map((H)=>b.join(import.meta.dir,H)).find((H)=>e2(H));for(let[N,H,Y]of[["jun","mcp-server","agenthost"],["jun-browser","browser-mcp-server",void 0]])try{let W=z$(H);if(W)await lH(N,W,iN,Y);else console.warn(`[daemon] ${N} MCP server script (${H}) not found next to daemon`)}catch(W){console.warn(`[daemon] could not register ${N} MCP server:`,W)}o1(b.join(import.meta.dir,".."));var HY=Bun.serve({hostname:S0,port:iN,async fetch(N,H){let Y=new URL(N.url);if(Y.pathname.startsWith("/api/"))return r2(N,H);let W=await V$(Y.pathname);if(W)return W;return new Response("Jun daemon is running. Build the UI to enable the dashboard.",{status:200})},websocket:{idleTimeout:960,open(N){if(N.subscribe(N.data.channel),N.data.channel===GN){$2();let H=G2();if(H)N.send(H)}},message(N,H){if(N.data.channel===GN)Q2(H)},close(N){if(N.unsubscribe(N.data.channel),N.data.channel===GN)U2()}}});E1(HY);try{O$(XN(),{recursive:!0},(N,H)=>{let Y={type:"fs.changed",path:H?u(String(H)):null,ts:new Date().toISOString()};HY.publish("files",JSON.stringify(Y))})}catch(N){console.warn("[daemon] workspace watcher unavailable:",N)}var F$=30000;setInterval(()=>{p2()},F$);console.log(`Jun daemon running at http://${S0}:${iN}`);console.log(`Workspace: ${b.resolve(B())}`);async function V$(N){let H=b.join(D0,"index.html");if(!await K$(H))return null;let Y=b.normalize(decodeURIComponent(N)).replace(/^[/\\]+/,""),W=b.resolve(D0,Y||"index.html"),$=`${D0}${b.sep}`;if(W!==D0&&!W.startsWith($))return new Response("Not found",{status:404});if(await L$(W))return new Response(Bun.file(W),{headers:{"content-type":M$(W)}});return new Response(Bun.file(H),{headers:{"content-type":"text/html; charset=utf-8"}})}async function K$(N){try{return await NY(N),!0}catch{return!1}}async function L$(N){try{return(await NY(N)).isFile()}catch{return!1}}function M$(N){switch(b.extname(N)){case".css":return"text/css; charset=utf-8";case".html":return"text/html; charset=utf-8";case".js":return"text/javascript; charset=utf-8";case".json":return"application/json; charset=utf-8";case".svg":return"image/svg+xml";case".webp":return"image/webp";case".png":return"image/png";case".jpg":case".jpeg":return"image/jpeg";case".ico":return"image/x-icon";default:return"application/octet-stream"}}
334
+ `;return await j.mkdir(H,{recursive:!0}),await j.writeFile(R.join(H,"SKILL.md"),Y,"utf8"),qN(),await vN(U)}async function OH(N,U){let H=JN(N);try{await j.access(H)}catch{throw new J(`Skill not found: ${N}`)}return await j.writeFile(R.join(H,"SKILL.md"),U,"utf8"),qN(),await vN(N)}async function WH(N){let U=JN(N);try{return await j.rm(U,{recursive:!0,force:!1}),qN(),!0}catch{return!1}}async function $H(N,U){let H=R.join(JN(N),"SKILL.md");await B("skills/config/write",{path:H,enabled:U,name:null}),qN()}async function GH(N){let U=N.trim();if(!U)return[];let{stdout:H}=await HH(["find",U],M(),30000);return T2(H)}async function NH(){await j.mkdir(MN(),{recursive:!0});let N=await j.readdir(MN(),{withFileTypes:!0});return new Set(N.filter((U)=>U.isDirectory()).map((U)=>U.name))}async function FH(N){let U=N.trim();if(!U)throw new J("Missing skill source");if(/[\s;&|`$(){}<>]/.test(U))throw new J("Invalid source \u2014 expected owner/repo[@skill] or a URL");let H=M(),Y=await NH(),{stdout:O,stderr:W}=await HH(["add",U,"-a","codex","--copy","-y"],H);qN();let G=[...await NH()].filter((Q)=>!Y.has(Q));if(G.length===0){let Q=[O,W].filter(Boolean).join(`
335
+ `).trim();throw new J(`No skill installed from "${U}".${Q?`
336
+ ${Q}`:""}`)}let{skills:F}=await Z0();return{installed:G,skills:F,log:[O,W].filter(Boolean).join(`
337
+ `).trim()}}async function QH(N,U){let H=await vN(N);if(!H)throw new J(`Skill not found: ${N}`);let Y={prompt:U?.trim()||`Use the "${H.info.name}" skill to demonstrate what it does. Follow its instructions and report the result.`,skill:{name:H.info.name,path:R.join(JN(N),"SKILL.md")}};return ZN(Y)}async function XH(N,U){let H=U.pathname.split("/").filter(Boolean),Y=H[2],O=H[3];if(Y==="registry"){if(O==="search"&&N.method==="GET"){let W=U.searchParams.get("q")??"",$=await GH(W);return Z({results:$})}if(O==="install"&&N.method==="POST"){let W=await z(N);K(W.source,"source");let $=await FH(W.source);return Z($,201)}return X(404,`Unknown skills endpoint: ${U.pathname}`)}if(!Y){if(N.method==="GET")return Z(await Z0());if(N.method==="POST"){let W=await z(N);K(W.name,"name"),K(W.description,"description");let $=await YH(W);return Z({skill:$},201)}return X(405,"Method not allowed")}if(!O)switch(N.method){case"GET":{let W=await vN(Y);return W?Z({skill:W}):X(404,`Skill not found: ${Y}`)}case"PUT":{let W=await z(N);K(W.content,"content");let $=await OH(Y,W.content);return Z({skill:$})}case"DELETE":return await WH(Y)?Z({ok:!0}):X(404,`Skill not found: ${Y}`);default:return X(405,"Method not allowed")}if(N.method!=="POST")return X(405,"Method not allowed");switch(O){case"enable":{let W=await z(N);if(typeof W.enabled!=="boolean")return X(400,"Missing or invalid field: enabled");return await $H(Y,W.enabled),Z({ok:!0})}case"test":{let W=await z(N).catch(()=>({})),$=await QH(Y,W.prompt);return Z({run:$},201)}default:return X(404,`Unknown skills endpoint: ${U.pathname}`)}}async function ZH(N,U){let H=U.pathname.split("/").filter(Boolean),Y=H[2];if(!Y){if(N.method==="GET")return Z(await kU());return X(405,"Method not allowed")}if(Y==="config"){if(N.method==="GET"){let O={toml:await i()};return Z(O)}if(N.method==="PUT"){let O=await z(N);return K(O.toml,"toml"),await fU(O.toml),Z({ok:!0})}return X(405,"Method not allowed")}if(Y==="reload"&&N.method==="POST")return await vU(),Z({ok:!0});if(Y==="servers"){let O=H[3];if(!O){if(N.method==="POST"){let $=await z(N);return K($.name,"name"),await yU($),Z({ok:!0},201)}return X(405,"Method not allowed")}let W=H[4];if(W==="enable"&&N.method==="POST"){let $=await z(N);if(typeof $.enabled!=="boolean")return X(400,"Missing or invalid field: enabled");return await qU(O,$.enabled),Z({ok:!0})}if(!W&&N.method==="DELETE")return await bU(O)?Z({ok:!0}):X(404,`Server not found: ${O}`);return X(405,"Method not allowed")}return X(404,`Unknown MCP endpoint: ${U.pathname}`)}import{promises as WN}from"fs";import gN from"path";function _2(){return gN.join(k(),"config.toml")}function z0(){return gN.join(k(),"memories")}async function LH(){let N=await i();return N.trim()?m(N):{}}function L0(N){return typeof N==="object"&&N!==null?N:{}}function j2(N){let U=L0(N.memories),H={};if(typeof U.generate_memories==="boolean")H.generateMemories=U.generate_memories;if(typeof U.use_memories==="boolean")H.useMemories=U.use_memories;if(typeof U.disable_on_external_context==="boolean")H.disableOnExternalContext=U.disable_on_external_context;if(typeof U.min_rate_limit_remaining_percent==="number")H.minRateLimitRemainingPercent=U.min_rate_limit_remaining_percent;return H}async function P2(){let N=z0(),U=[];async function H(Y){let O;try{O=await WN.readdir(Y,{withFileTypes:!0})}catch{return}for(let W of O){let $=gN.join(Y,W.name);if(W.isDirectory()){if(W.name===".git")continue;await H($)}else if(W.isFile()){let G=await WN.stat($);U.push({path:l(gN.relative(N,$)),name:W.name,size:G.size,modifiedAt:G.mtime.toISOString()})}}}return await H(N),U.sort((Y,O)=>O.modifiedAt.localeCompare(Y.modifiedAt)),U}async function I2(){try{let U=((await B("experimentalFeature/list",{})).data??[]).find((H)=>H.name==="memories");return U?U.enabled:null}catch(N){return console.warn("[memories] experimentalFeature/list failed:",N),null}}async function zH(){let N=await LH();return{enabled:L0(N.features).memories===!0,liveEnabled:await I2(),settings:j2(N),files:await P2()}}async function DH(N){let U=await LH();if(typeof N.enabled==="boolean"){let H=L0(U.features);H.memories=N.enabled,U.features=H}if(N.settings){let H=L0(U.memories),Y=N.settings;if(typeof Y.generateMemories==="boolean")H.generate_memories=Y.generateMemories;if(typeof Y.useMemories==="boolean")H.use_memories=Y.useMemories;if(typeof Y.disableOnExternalContext==="boolean")H.disable_on_external_context=Y.disableOnExternalContext;if(typeof Y.minRateLimitRemainingPercent==="number")H.min_rate_limit_remaining_percent=Y.minRateLimitRemainingPercent;U.memories=H}if(await WN.writeFile(_2(),s(U),"utf8"),typeof N.enabled==="boolean")try{await B("experimentalFeature/enablement/set",{enablement:{memories:N.enabled}})}catch(H){console.warn("[memories] live enablement/set failed (applies on restart):",H)}}async function KH(N){let U=NN(z0(),N);return WN.readFile(U,"utf8")}async function VH(N,U){let H=NN(z0(),N);await WN.mkdir(gN.dirname(H),{recursive:!0}),await WN.writeFile(H,U,"utf8")}async function MH(N){let U=NN(z0(),N);await WN.rm(U)}async function JH(N,U){let Y=U.pathname.split("/").filter(Boolean)[2];if(!Y){if(N.method==="GET")return Z(await zH());return X(405,"Method not allowed")}if(Y==="config"){if(N.method==="PUT"){let O=await z(N);if(typeof O.enabled!=="boolean"&&!O.settings)return X(400,"Nothing to update: pass enabled and/or settings");return await DH(O),Z({ok:!0})}return X(405,"Method not allowed")}if(Y==="file"){if(N.method==="GET"){let O=K(U.searchParams.get("path"),"path"),W={path:O,content:await KH(O)};return Z(W)}if(N.method==="PUT"){let O=await z(N);if(K(O.path,"path"),typeof O.content!=="string")return X(400,"Missing or invalid field: content");return await VH(O.path,O.content),Z({ok:!0})}if(N.method==="DELETE"){let O=K(U.searchParams.get("path"),"path");return await MH(O),Z({ok:!0})}return X(405,"Method not allowed")}return X(404,`Unknown memories endpoint: ${U.pathname}`)}var x2=300000,D0=null;async function AH(N){if(N.method!=="GET")return X(405,"Method not allowed");if(D0&&Date.now()-D0.at<x2)return Z({models:D0.models});let H=((await B("model/list",{})).data??[]).filter((O)=>!O.hidden).map((O)=>({id:O.id,model:O.model,displayName:O.displayName,description:O.description,isDefault:O.isDefault,defaultReasoningEffort:O.defaultReasoningEffort,supportedReasoningEfforts:O.supportedReasoningEfforts??[]}));return D0={at:Date.now(),models:H},Z({models:H})}async function K0(){let N=await B("account/read",{});return{account:N.account??null,requiresOpenaiAuth:N.requiresOpenaiAuth,pendingLogin:O0(),lastLoginResult:DU()}}async function TH(N,U){if(U.pathname==="/api/account"){if(N.method!=="GET")return X(405,"Method not allowed");return Z(await K0())}if(U.pathname==="/api/account/login"&&N.method==="POST"){let H=await z(N),Y;if(H.type==="chatgpt"||H.type==="chatgptDeviceCode")Y={type:H.type};else if(H.type==="apiKey")Y={type:"apiKey",apiKey:K(H.apiKey,"apiKey")};else throw new J("type must be one of: chatgpt, chatgptDeviceCode, apiKey");let O=O0();if(O)await B("account/login/cancel",{loginId:O.loginId}).catch(()=>{});W0();let W=await B("account/login/start",Y);if((W.type==="chatgpt"||W.type==="chatgptDeviceCode")&&W.loginId){let $={loginId:W.loginId,type:W.type,authUrl:W.authUrl,userCode:W.userCode,verificationUrl:W.verificationUrl,startedAt:new Date().toISOString()};KU($)}return Z(await K0())}if(U.pathname==="/api/account/login/cancel"&&N.method==="POST"){let H=O0();if(H)await B("account/login/cancel",{loginId:H.loginId}).catch(()=>{});return W0(),Z(await K0())}if(U.pathname==="/api/account/logout"&&N.method==="POST")return await B("account/logout",{}),W0(),Z(await K0());return X(404,`Not found: ${U.pathname}`)}function f2(N){if(!N)return null;return N.replace(/^([a-z0-9+.-]+:\/\/[^:@/]+):[^@/]+@/i,"$1:\u2022\u2022\u2022\u2022@")}function BH(){let N=U0(),U=H0();return{browserProxy:{proxyUrl:f2(N.value),source:N.source,noProxy:U.value,noProxySource:U.source}}}async function EH(N,U){if(U.pathname==="/api/settings"&&N.method==="GET")return Z(BH());if(U.pathname==="/api/settings/browser-proxy"&&N.method==="PUT"){let H=await z(N);if(H.proxyUrl!==void 0&&H.proxyUrl!==null&&H.proxyUrl.trim())try{if(!new URL(H.proxyUrl.trim()).hostname)throw Error("missing host")}catch{return X(400,"Invalid proxy URL \u2014 expected e.g. http://user:pass@host:port")}return await q1({...H.proxyUrl!==void 0?{browserProxy:H.proxyUrl}:{},...H.noProxy!==void 0?{browserNoProxy:H.noProxy}:{}}),Z(BH())}if(N.method!=="GET"&&N.method!=="PUT")return X(405,"Method not allowed");return X(404,`Unknown settings endpoint: ${U.pathname}`)}import{promises as AN}from"fs";import IH from"path";import{randomUUID as h2}from"crypto";function hN(N,U,H,Y){let O=new Set,W=N.trim()!=="*";for(let $ of N.split(",")){let G=$.trim();if(!G)throw Error(`Invalid ${Y} field: empty term`);let F=G,Q=1,L=G.indexOf("/");if(L!==-1){if(F=G.slice(0,L),Q=Number(G.slice(L+1)),!Number.isInteger(Q)||Q<=0)throw Error(`Invalid step in ${Y}: ${G}`)}let V,T;if(F==="*")V=U,T=H;else if(F.includes("-")){let[e,$N]=F.split("-");V=Number(e),T=Number($N)}else V=Number(F),T=V;if(!Number.isInteger(V)||!Number.isInteger(T))throw Error(`Invalid ${Y} value: ${G}`);if(V<U||T>H||V>T)throw Error(`${Y} out of range (${U}-${H}): ${G}`);for(let e=V;e<=T;e+=Q)O.add(e)}return{set:O,restricted:W}}function SH(N){let U=N.trim().split(/\s+/);if(U.length!==5)throw Error(`Cron must have 5 fields (min hour dom month dow); got ${U.length}`);let H=hN(U[0],0,59,"minute"),Y=hN(U[1],0,23,"hour"),O=hN(U[2],1,31,"day-of-month"),W=hN(U[3],1,12,"month"),$=hN(U[4],0,7,"day-of-week"),G=new Set;for(let F of $.set)G.add(F===7?0:F);return{minute:H.set,hour:Y.set,dom:O.set,month:W.set,dow:G,domRestricted:O.restricted,dowRestricted:$.restricted}}function _H(N){try{return SH(N),null}catch(U){return U instanceof Error?U.message:"Invalid cron expression"}}function k2(N){return new Intl.DateTimeFormat("en-US",{timeZone:N,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"})}function jH(N,U){if(!U)return{year:N.getFullYear(),month:N.getMonth()+1,day:N.getDate(),hour:N.getHours(),minute:N.getMinutes(),second:N.getSeconds()};let H={};for(let Y of k2(U).formatToParts(N))if(Y.type!=="literal")H[Y.type]=Number(Y.value);return{year:H.year,month:H.month,day:H.day,hour:H.hour,minute:H.minute,second:H.second}}function y2(N,U){return new Date(Date.UTC(N,U,0)).getUTCDate()}function b2(N){return new Date(Date.UTC(N.year,N.month-1,N.day)).getUTCDay()}function CH(N){if(N.minute++,N.minute<60)return;if(N.minute=0,N.hour++,N.hour<24)return;if(N.hour=0,N.day++,N.day<=y2(N.year,N.month))return;if(N.day=1,N.month++,N.month<=12)return;N.month=1,N.year++}function q2(N,U){if(!N.minute.has(U.minute))return!1;if(!N.hour.has(U.hour))return!1;if(!N.month.has(U.month))return!1;let H=N.dom.has(U.day),Y=N.dow.has(b2(U));if(N.domRestricted&&N.dowRestricted)return H||Y;if(N.domRestricted)return H;if(N.dowRestricted)return Y;return!0}function RH(N,U){let H=jH(N,U);return Date.UTC(H.year,H.month-1,H.day,H.hour,H.minute,H.second)-N.getTime()}function v2(N,U){if(!U)return new Date(N.year,N.month-1,N.day,N.hour,N.minute,0,0);let H=Date.UTC(N.year,N.month-1,N.day,N.hour,N.minute,0),Y=RH(new Date(H),U),O=H-Y,W=RH(new Date(O),U);if(W!==Y)O=H-W;return new Date(O)}var g2=4216320;function PH(N,U,H){let Y=SH(N),O=jH(U,H),W={year:O.year,month:O.month,day:O.day,hour:O.hour,minute:O.minute};CH(W);for(let $=0;$<g2;$++){if(q2(Y,W))return v2(W,H);CH(W)}return null}var m2={sandbox:"workspaceWrite",approvalPolicy:"onRequest",approvalsReviewer:"auto_review",effort:"medium"};function c2(N){return N.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40)}function o0(N){return IH.join(TN(),`${N}.json`)}async function wH(){await AN.mkdir(TN(),{recursive:!0})}async function n0(N){await wH(),await AN.writeFile(o0(N.id),JSON.stringify(N,null,2),"utf8")}function a0(N,U){if(!N.enabled)return null;if(N.kind==="once"){if(!N.runAt)return null;let Y=new Date(N.runAt);if(Number.isNaN(Y.getTime()))return null;if(N.lastRunAt)return null;return Y.toISOString()}if(!N.cron)return null;let H=PH(N.cron,U,N.tz);return H?H.toISOString():null}function xH(N,U){if(U==="cron"){if(!N.cron)throw Error("cron expression is required for a cron schedule");let H=_H(N.cron);if(H)throw Error(`Invalid cron expression: ${H}`)}else{if(!N.runAt)throw Error("runAt is required for a one-off schedule");if(Number.isNaN(new Date(N.runAt).getTime()))throw Error("runAt is not a valid datetime")}if(N.tz)try{new Intl.DateTimeFormat("en-US",{timeZone:N.tz})}catch{throw Error(`Unknown timezone: ${N.tz}`)}}async function s0(){await wH();let N;try{N=await AN.readdir(TN())}catch{return[]}let U=[];for(let H of N){if(!H.endsWith(".json"))continue;try{let Y=await AN.readFile(IH.join(TN(),H),"utf8"),O=JSON.parse(Y);U.push(O)}catch{}}return U.sort((H,Y)=>Y.createdAt.localeCompare(H.createdAt)),U}async function V0(N){try{let U=await AN.readFile(o0(N),"utf8");return JSON.parse(U)}catch{return null}}async function fH(N){let U=N.name?.trim();if(!U)throw Error("Schedule name is required");if(!N.prompt?.trim())throw Error("Schedule prompt is required");let H=N.kind??"cron";xH(N,H);let Y=`${c2(U)||"schedule"}-${h2().slice(0,8)}`,O=new Date,W={id:Y,name:U,prompt:N.prompt,kind:H,cron:H==="cron"?N.cron:void 0,runAt:H==="once"?new Date(N.runAt).toISOString():void 0,tz:N.tz,mode:{...m2,...N.mode??{}},resume:N.resume??!1,threadRunId:null,enabled:N.enabled??!0,createdAt:O.toISOString(),lastRunAt:null,lastRunId:null,lastError:null,nextRunAt:null};return W.nextRunAt=a0(W,O),await n0(W),W}async function kH(N,U){let H=await V0(N);if(!H)return null;let Y=U.kind??H.kind,O={...H,name:U.name?.trim()||H.name,prompt:U.prompt??H.prompt,kind:Y,cron:Y==="cron"?U.cron??H.cron:void 0,runAt:Y==="once"?U.runAt?new Date(U.runAt).toISOString():H.runAt:void 0,tz:U.tz!==void 0?U.tz||void 0:H.tz,mode:U.mode?{...H.mode,...U.mode}:H.mode,resume:U.resume??H.resume,enabled:U.enabled??H.enabled};if(xH(O,Y),Y==="once"&&U.runAt&&O.runAt!==H.runAt)O.lastRunAt=null;return O.nextRunAt=a0(O,new Date),await n0(O),O}async function yH(N){try{return await AN.unlink(o0(N)),!0}catch{return!1}}function l2(N){return{sandbox:N.sandbox,approvalPolicy:N.approvalPolicy,approvalsReviewer:N.approvalsReviewer,model:N.model,effort:N.effort}}async function t0(N,U){let H=N.lastRunId??null,Y=null,O=N.threadRunId??null;try{let $=N.mode;if(N.resume&&O&&await A(O)){let G=await A(O);if(G&&v(G.status))throw Error("previous run still active \u2014 skipped this fire");H=(await G0(O,N.prompt,[],l2($))).id}else{let G=await ZN({prompt:N.prompt,sandbox:$.sandbox,approvalPolicy:$.approvalPolicy,approvalsReviewer:$.approvalsReviewer,model:$.model,effort:$.effort,source:"schedule",scheduleId:N.id,scheduleName:N.name});if(H=G.id,N.resume)O=G.id}}catch($){Y=$ instanceof Error?$.message:String($)}let W={...N,lastRunAt:U.toISOString(),lastRunId:H,lastError:Y,threadRunId:O};return W.nextRunAt=a0(W,U),await n0(W),W}var d0=!1;async function bH(N=new Date){if(d0)return;d0=!0;try{let U=await s0();for(let H of U){if(!H.enabled||!H.nextRunAt)continue;let Y=new Date(H.nextRunAt);if(Number.isNaN(Y.getTime())||Y.getTime()>N.getTime())continue;try{await t0(H,N)}catch(O){console.error(`[schedules] fire failed for ${H.id}:`,O)}}}catch(U){console.error("[schedules] tick failed:",U)}finally{d0=!1}}async function qH(N,U){let H=U.pathname.split("/").filter(Boolean),Y=H[2],O=H[3];if(!Y){if(N.method==="GET"){let W={schedules:await s0()};return Z(W)}if(N.method==="POST"){let W=await z(N);try{let G={schedule:await fH(W)};return Z(G,201)}catch($){return X(400,$ instanceof Error?$.message:String($))}}return X(405,"Method not allowed")}if(O==="run"&&N.method==="POST"){let W=await V0(Y);if(!W)return X(404,`Schedule not found: ${Y}`);let G={schedule:await t0(W,new Date)};return Z(G)}if(O)return X(404,`Not found: ${U.pathname}`);if(N.method==="GET"){let W=await V0(Y);return W?Z({schedule:W}):X(404,`Schedule not found: ${Y}`)}if(N.method==="PUT"){let W=await z(N);try{let $=await kH(Y,W);return $?Z({schedule:$}):X(404,`Schedule not found: ${Y}`)}catch($){return X(400,$ instanceof Error?$.message:String($))}}if(N.method==="DELETE")return await yH(Y)?Z({ok:!0}):X(404,`Schedule not found: ${Y}`);return X(405,"Method not allowed")}var u2=2000,M0=[],i2=0,vH=!1,r0="logs";function d2(N){return N.map((U)=>{if(typeof U==="string")return U;if(U instanceof Error)return U.stack??U.message;try{return Bun.inspect(U,{colors:!1,depth:3})}catch{return String(U)}}).join(" ")}function o2(N,U){let H={seq:++i2,ts:new Date().toISOString(),level:N,text:d2(U)};if(M0.push(H),M0.length>u2)M0.shift();q(r0,H)}function gH(){if(vH)return;vH=!0;let N=(U,H)=>{let Y=console[U].bind(console);console[U]=(...O)=>{try{o2(H,O)}catch{}Y(...O)}};N("log","info"),N("info","info"),N("warn","warn"),N("error","error")}function hH(N={}){let U={info:0,warn:1,error:2},H=N.level?U[N.level]:0,Y=N.query?.toLowerCase(),O=M0.filter((W)=>U[W.level]>=H&&(!Y||W.text.toLowerCase().includes(Y)));if(N.limit&&O.length>N.limit)O=O.slice(-N.limit);return O}var n2=new Set(["info","warn","error"]);function mH(N,U,H){if(U.pathname==="/api/logs/stream")return H.upgrade(N,{data:{channel:r0}})?void 0:X(400,"WebSocket upgrade required");if(N.method!=="GET")return X(405,"Method not allowed");let Y=Number(U.searchParams.get("limit")),O=U.searchParams.get("level"),W=O&&n2.has(O)?O:void 0,$={logs:hH({limit:Number.isFinite(Y)&&Y>0?Math.min(Y,2000):500,level:W,query:U.searchParams.get("q")??void 0})};return Z($)}var e0=!1;function a2(){return Boolean(process.env.INVOCATION_ID)}function s2(){return import.meta.url.endsWith(".js")}async function cH(N,U){if(U.pathname!=="/api/system/upgrade")return X(404,"Not found");if(N.method!=="POST")return X(405,"Method not allowed");if(!s2())return X(400,"Self-upgrade only works on an installed junhost package (running from source \u2014 use git pull)");if(e0)return X(409,"Upgrade already in progress");await F0();let H=p0();if(!H)return X(502,"Could not reach the npm registry to check the latest version");if(!u0(H,c))return X(400,`Already up to date (v${c})`);e0=!0;try{let Y=Bun.spawn([process.execPath,"install","-g","junhost@latest"],{stdout:"pipe",stderr:"pipe"}),O=setTimeout(()=>Y.kill(),300000),W=await Y.exited;if(clearTimeout(O),W!==0){let F=await new Response(Y.stderr).text();return X(500,`bun install failed (exit ${W}): ${F.slice(0,500)}`)}let $=a2();if($)setTimeout(()=>process.exit(0),750);return Z({ok:!0,from:c,to:H,restarting:$})}finally{e0=!1}}async function lH(N,U){let H=new URL(N.url);try{if(H.pathname==="/api/health")return lU();if(H.pathname==="/api/status")return await pU(H);if(H.pathname.startsWith("/api/system/"))return cH(N,H);if(H.pathname==="/api/files/watch")return U.upgrade(N,{data:{channel:"files"}})?void 0:X(400,"WebSocket upgrade required");if(H.pathname.startsWith("/api/files/"))return await uU(N,H);if(H.pathname==="/api/runs"||H.pathname.startsWith("/api/runs/"))return await iU(N,H,U);if(H.pathname.startsWith("/api/browser/"))return await rU(N,H,U);if(H.pathname==="/api/skills"||H.pathname.startsWith("/api/skills/"))return await XH(N,H);if(H.pathname==="/api/mcp"||H.pathname.startsWith("/api/mcp/"))return await ZH(N,H);if(H.pathname==="/api/memories"||H.pathname.startsWith("/api/memories/"))return await JH(N,H);if(H.pathname==="/api/models")return await AH(N);if(H.pathname==="/api/account"||H.pathname.startsWith("/api/account/"))return await TH(N,H);if(H.pathname==="/api/settings"||H.pathname.startsWith("/api/settings/"))return await EH(N,H);if(H.pathname==="/api/schedules"||H.pathname.startsWith("/api/schedules/"))return await qH(N,H);if(H.pathname==="/api/logs"||H.pathname.startsWith("/api/logs/"))return mH(N,H,U);return X(404,`Not found: ${H.pathname}`)}catch(Y){if(Y instanceof dN)return X(400,Y.message);if(Y instanceof J)return X(400,Y.message);if(t2(Y))return X(404,`Not found: ${H.searchParams.get("path")??H.pathname}`);return console.error(`[api] ${N.method} ${H.pathname} failed:`,Y),X(500,Y instanceof Error?Y.message:"Internal error")}}function t2(N){return typeof N==="object"&&N!==null&&"code"in N&&N.code==="ENOENT"}gH();await Y1();var J0=[w.resolve(import.meta.dir,"../ui-dist"),w.resolve(import.meta.dir,"../../ui/dist")].find((N)=>pH(w.join(N,"index.html")))??w.resolve(import.meta.dir,"../../ui/dist"),e2=(N)=>[`${N}.ts`,`${N}.js`].map((U)=>w.join(import.meta.dir,U)).find((U)=>pH(U));for(let[N,U,H]of[["jun","mcp-server","agenthost"],["jun-browser","browser-mcp-server",void 0]])try{let Y=e2(U);if(Y)await gU(N,Y,mN,H);else console.warn(`[daemon] ${N} MCP server script (${U}) not found next to daemon`)}catch(Y){console.warn(`[daemon] could not register ${N} MCP server:`,Y)}i1(w.join(import.meta.dir,".."));var iH=Bun.serve({hostname:T0,port:mN,async fetch(N,U){let H=new URL(N.url);if(H.pathname.startsWith("/api/"))return lH(N,U);let Y=await UO(H.pathname);if(Y)return Y;return new Response("Jun daemon is running. Build the UI to enable the dashboard.",{status:200})},websocket:{idleTimeout:960,open(N){if(N.subscribe(N.data.channel),N.data.channel===ON){nU();let U=aU();if(U)N.send(U)}},message(N,U){if(N.data.channel===ON)tU(U)},close(N){if(N.unsubscribe(N.data.channel),N.data.channel===ON)sU()}}});T1(iH);try{r2(M(),{recursive:!0},(N,U)=>{let H={type:"fs.changed",path:U?l(String(U)):null,ts:new Date().toISOString()};iH.publish("files",JSON.stringify(H))})}catch(N){console.warn("[daemon] workspace watcher unavailable:",N)}var NO=30000;setInterval(()=>{bH()},NO);console.log(`Jun daemon running at http://${T0}:${mN}`);console.log(`Workspace: ${w.resolve(M())}`);async function UO(N){let U=w.join(J0,"index.html");if(!await HO(U))return null;let H=w.normalize(decodeURIComponent(N)).replace(/^[/\\]+/,""),Y=w.resolve(J0,H||"index.html"),O=`${J0}${w.sep}`;if(Y!==J0&&!Y.startsWith(O))return new Response("Not found",{status:404});if(await YO(Y))return new Response(Bun.file(Y),{headers:{"content-type":OO(Y)}});return new Response(Bun.file(U),{headers:{"content-type":"text/html; charset=utf-8"}})}async function HO(N){try{return await uH(N),!0}catch{return!1}}async function YO(N){try{return(await uH(N)).isFile()}catch{return!1}}function OO(N){switch(w.extname(N)){case".css":return"text/css; charset=utf-8";case".html":return"text/html; charset=utf-8";case".js":return"text/javascript; charset=utf-8";case".json":return"application/json; charset=utf-8";case".svg":return"image/svg+xml";case".webp":return"image/webp";case".png":return"image/png";case".jpg":case".jpeg":return"image/jpeg";case".ico":return"image/x-icon";default:return"application/octet-stream"}}