junhost 0.3.0 → 0.3.4

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 (93) hide show
  1. package/dist/browser-mcp-server.js +1 -1
  2. package/dist/index.js +46 -46
  3. package/dist/mcp-server.js +1 -1
  4. package/package.json +1 -1
  5. package/ui-dist/assets/{BrowserPage-DHyQHcXA.js → BrowserPage-9gVeSQwJ.js} +2 -1
  6. package/ui-dist/assets/{DashboardPage-CUuPkg6v.js → DashboardPage-DpUFKefL.js} +1 -1
  7. package/ui-dist/assets/{FilesPage-4pIFdyDG.js → FilesPage-DcAROlEl.js} +1 -1
  8. package/ui-dist/assets/{LogsPage-BMnY04x1.js → LogsPage-Cjy1u4mi.js} +1 -1
  9. package/ui-dist/assets/{McpPage-DjJyOTby.js → McpPage-CbF1n-r9.js} +1 -1
  10. package/ui-dist/assets/{MemoriesPage-bCrf5Euh.js → MemoriesPage-CZ0Djv0N.js} +1 -1
  11. package/ui-dist/assets/{RunsPage-DmL6kxm4.js → RunsPage-CoBKmzka.js} +5 -5
  12. package/ui-dist/assets/{SchedulesPage-DiEX_BG2.js → SchedulesPage-Do5nDZ-J.js} +1 -1
  13. package/ui-dist/assets/{SettingsPage-fztdWEUq.js → SettingsPage-B26G7vPS.js} +1 -1
  14. package/ui-dist/assets/{SkillsPage-Ba0OFfGe.js → SkillsPage-AkyZ2EQZ.js} +1 -1
  15. package/ui-dist/assets/architecture-7EHR7CIX-cCzS06Gh.js +1 -0
  16. package/ui-dist/assets/{architectureDiagram-3BPJPVTR-CTkJZekp.js → architectureDiagram-3BPJPVTR-DfC6sLNc.js} +1 -1
  17. package/ui-dist/assets/{blockDiagram-GPEHLZMM-DkKeuF3p.js → blockDiagram-GPEHLZMM-BS8EGcCG.js} +1 -1
  18. package/ui-dist/assets/{c4Diagram-AAUBKEIU-DCIXqWKO.js → c4Diagram-AAUBKEIU-CJkaD3Jx.js} +1 -1
  19. package/ui-dist/assets/channel-kSqogUuL.js +1 -0
  20. package/ui-dist/assets/{checkbox-C-XQQq3C.js → checkbox-vUBksx1q.js} +1 -1
  21. package/ui-dist/assets/{chunk-2J33WTMH-C_Do0fzJ.js → chunk-2J33WTMH-mhbuj50G.js} +1 -1
  22. package/ui-dist/assets/{chunk-3OPIFGDE-Dnq2pibd.js → chunk-3OPIFGDE-DY3vh1Nq.js} +1 -1
  23. package/ui-dist/assets/{chunk-5ZQYHXKU--3ftGxeU.js → chunk-5ZQYHXKU-CjgZVK38.js} +1 -1
  24. package/ui-dist/assets/{chunk-727SXJPM-CE9UFsBc.js → chunk-727SXJPM-BQTDUHRj.js} +1 -1
  25. package/ui-dist/assets/{chunk-AQP2D5EJ-IlAT6iTc.js → chunk-AQP2D5EJ-Sy1xPTv6.js} +1 -1
  26. package/ui-dist/assets/{chunk-BO2N2NFS-Bck0jxRI.js → chunk-BO2N2NFS-Bgx9ri0_.js} +4 -4
  27. package/ui-dist/assets/{chunk-CSCIHK7Q-DlysIzUR.js → chunk-CSCIHK7Q-BSHQXS7Y.js} +3 -3
  28. package/ui-dist/assets/{chunk-KSCS5N6A-DCPxMCgc.js → chunk-KSCS5N6A-eLYuhWcU.js} +1 -1
  29. package/ui-dist/assets/{chunk-L5ZTLDWV-Cj9_jpoi.js → chunk-L5ZTLDWV-BmpG0Ewi.js} +1 -1
  30. package/ui-dist/assets/{chunk-LZXEDZCA-GAi6scJw.js → chunk-LZXEDZCA-wjYpyGTZ.js} +2 -2
  31. package/ui-dist/assets/{chunk-ND2GUHAM-CC2nvwpG.js → chunk-ND2GUHAM-BkvdHoNV.js} +1 -1
  32. package/ui-dist/assets/{chunk-NZK2D7GU-CGITkLyN.js → chunk-NZK2D7GU-DD7-1aWi.js} +1 -1
  33. package/ui-dist/assets/{chunk-O5CBEL6O-BxDX-s5O.js → chunk-O5CBEL6O-cv64tuEA.js} +1 -1
  34. package/ui-dist/assets/{chunk-WU5MYG2G-BNy8p0ko.js → chunk-WU5MYG2G-DA1LQa1D.js} +1 -1
  35. package/ui-dist/assets/classDiagram-4FO5ZUOK-DIN_soal.js +1 -0
  36. package/ui-dist/assets/classDiagram-v2-Q7XG4LA2-DIN_soal.js +1 -0
  37. package/ui-dist/assets/{collapsible-DL1Pa5At.js → collapsible-WgEfcx9l.js} +1 -1
  38. package/ui-dist/assets/{dagre-BM42HDAG-B-A8sAyD.js → dagre-BM42HDAG-BQ_Gt3C1.js} +1 -1
  39. package/ui-dist/assets/{diagram-2AECGRRQ-BlkmoJab.js → diagram-2AECGRRQ-DegViS8Q.js} +1 -1
  40. package/ui-dist/assets/{diagram-5GNKFQAL-DLurH93Z.js → diagram-5GNKFQAL-INLXoEGU.js} +1 -1
  41. package/ui-dist/assets/{diagram-KO2AKTUF-sXtOf-O5.js → diagram-KO2AKTUF-Bav-apee.js} +1 -1
  42. package/ui-dist/assets/{diagram-LMA3HP47-CVJgaCxQ.js → diagram-LMA3HP47-DetmV1XF.js} +1 -1
  43. package/ui-dist/assets/{diagram-OG6HWLK6-DlSJEniK.js → diagram-OG6HWLK6-DxSK26S7.js} +1 -1
  44. package/ui-dist/assets/{dialog-CYLeVyM-.js → dialog-BTcyz3qf.js} +1 -1
  45. package/ui-dist/assets/{erDiagram-TEJ5UH35-DXCrI6I5.js → erDiagram-TEJ5UH35-LZjEp26F.js} +1 -1
  46. package/ui-dist/assets/eventmodeling-FCH6USID-LEdFjPoC.js +1 -0
  47. package/ui-dist/assets/{flowDiagram-I6XJVG4X-DuXHlm5x.js → flowDiagram-I6XJVG4X-DQf-PrHy.js} +1 -1
  48. package/ui-dist/assets/{ganttDiagram-6RSMTGT7-9X5KI_9q.js → ganttDiagram-6RSMTGT7-DeK_z-Js.js} +1 -1
  49. package/ui-dist/assets/{gitGraph-WXDBUCRP-4lP61HuT.js → gitGraph-WXDBUCRP-BFMrYnF5.js} +1 -1
  50. package/ui-dist/assets/{gitGraphDiagram-PVQCEYII-DS7sOc3V.js → gitGraphDiagram-PVQCEYII-CIUYCNZd.js} +1 -1
  51. package/ui-dist/assets/{highlighted-body-OFNGDK62-DC-eZj7U.js → highlighted-body-OFNGDK62-CJEeWNGR.js} +1 -1
  52. package/ui-dist/assets/{index-N-aJPrjP.js → index-BV4eUtAp.js} +2 -2
  53. package/ui-dist/assets/{index-D3Qn6btz.css → index-BdtKSgW5.css} +1 -1
  54. package/ui-dist/assets/{info-J43DQDTF-BPA_aNjl.js → info-J43DQDTF-llmEniUV.js} +1 -1
  55. package/ui-dist/assets/{infoDiagram-5YYISTIA-DnVSGlrV.js → infoDiagram-5YYISTIA-BGI2mOhY.js} +1 -1
  56. package/ui-dist/assets/{input-F0nzOm5c.js → input-S0ZdxSeo.js} +1 -1
  57. package/ui-dist/assets/{ishikawaDiagram-YF4QCWOH-DsmzrCMt.js → ishikawaDiagram-YF4QCWOH-BkQI6c7Q.js} +1 -1
  58. package/ui-dist/assets/{journeyDiagram-JHISSGLW-CRuM8UdX.js → journeyDiagram-JHISSGLW-Coq6JWX7.js} +1 -1
  59. package/ui-dist/assets/{kanban-definition-UN3LZRKU-uSoN0lnh.js → kanban-definition-UN3LZRKU-CjxplmXf.js} +1 -1
  60. package/ui-dist/assets/katex-BI2iw9tJ.js +1 -0
  61. package/ui-dist/assets/{line-DBlKTrex.js → line-BEtII_LR.js} +1 -1
  62. package/ui-dist/assets/mermaid-GHXKKRXX-CfVWhIeR.js +1 -0
  63. package/ui-dist/assets/{mermaid-parser.core-CPYQHkLW.js → mermaid-parser.core-DaFgcYuk.js} +2 -2
  64. package/ui-dist/assets/{mindmap-definition-RKZ34NQL-CQAbVdBK.js → mindmap-definition-RKZ34NQL-B3J8wqEL.js} +1 -1
  65. package/ui-dist/assets/{packet-YPE3B663-B_jxDJ78.js → packet-YPE3B663-CfmL0nS0.js} +1 -1
  66. package/ui-dist/assets/{pie-LRSECV5Y-DdzUETNE.js → pie-LRSECV5Y-0q2SlDUq.js} +1 -1
  67. package/ui-dist/assets/{pieDiagram-4H26LBE5-eWkLmgTA.js → pieDiagram-4H26LBE5-D5MF1SI0.js} +1 -1
  68. package/ui-dist/assets/{quadrantDiagram-W4KKPZXB-SNBNPkHE.js → quadrantDiagram-W4KKPZXB-g6p42sLr.js} +1 -1
  69. package/ui-dist/assets/{radar-GUYGQ44K-CVFtMDrf.js → radar-GUYGQ44K-BmaImLTH.js} +1 -1
  70. package/ui-dist/assets/{requirementDiagram-4Y6WPE33-CDrbqGdB.js → requirementDiagram-4Y6WPE33-u0DaPOqm.js} +1 -1
  71. package/ui-dist/assets/{sankeyDiagram-5OEKKPKP-DjpIDQlh.js → sankeyDiagram-5OEKKPKP-D9pDA_0Q.js} +1 -1
  72. package/ui-dist/assets/{select-CyfVacuL.js → select-j1Z7DzXz.js} +1 -1
  73. package/ui-dist/assets/{sequenceDiagram-3UESZ5HK-43oP0nrT.js → sequenceDiagram-3UESZ5HK-K18mGDHD.js} +1 -1
  74. package/ui-dist/assets/{stateDiagram-AJRCARHV-BbNa4W6Z.js → stateDiagram-AJRCARHV-UcpM53Ws.js} +1 -1
  75. package/ui-dist/assets/stateDiagram-v2-BHNVJYJU-J2d5S8Su.js +1 -0
  76. package/ui-dist/assets/{tabs-CMZKIx3J.js → tabs-A13Rxj36.js} +1 -1
  77. package/ui-dist/assets/{timeline-definition-PNZ67QCA-YzIE7mGL.js → timeline-definition-PNZ67QCA-CeeEL7tt.js} +1 -1
  78. package/ui-dist/assets/{treeView-BLDUP644-BZteZrd-.js → treeView-BLDUP644-hNdF1f8d.js} +1 -1
  79. package/ui-dist/assets/{treemap-LRROVOQU-CAzPGyTN.js → treemap-LRROVOQU-CdkcNxzK.js} +1 -1
  80. package/ui-dist/assets/{useOpenInteractionType-0pVIpVIn.js → useOpenInteractionType-Bq3-ALUl.js} +1 -1
  81. package/ui-dist/assets/{vennDiagram-CIIHVFJN-4KTFUlxw.js → vennDiagram-CIIHVFJN-DrvJRdOf.js} +1 -1
  82. package/ui-dist/assets/{wardley-L42UT6IY-Bkw1e9Ke.js → wardley-L42UT6IY-DlkMLhw2.js} +1 -1
  83. package/ui-dist/assets/{wardleyDiagram-YWT4CUSO-D0_SJSEO.js → wardleyDiagram-YWT4CUSO-sOLJdABg.js} +1 -1
  84. package/ui-dist/assets/{xychartDiagram-2RQKCTM6-PXl7Msmq.js → xychartDiagram-2RQKCTM6-BdoTJvuh.js} +1 -1
  85. package/ui-dist/index.html +2 -2
  86. package/ui-dist/assets/architecture-7EHR7CIX-B-lLNHMj.js +0 -1
  87. package/ui-dist/assets/channel-Da_creZX.js +0 -1
  88. package/ui-dist/assets/classDiagram-4FO5ZUOK-Bn-f2je0.js +0 -1
  89. package/ui-dist/assets/classDiagram-v2-Q7XG4LA2-Bn-f2je0.js +0 -1
  90. package/ui-dist/assets/eventmodeling-FCH6USID-m81sQw35.js +0 -1
  91. package/ui-dist/assets/katex-CO1WTfq9.js +0 -1
  92. package/ui-dist/assets/mermaid-GHXKKRXX-DdkJOHN3.js +0 -1
  93. package/ui-dist/assets/stateDiagram-v2-BHNVJYJU-CIh0Hr2o.js +0 -1
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  // @bun
2
- var oH=Object.create;var{getPrototypeOf:nH,defineProperty:A0,getOwnPropertyNames:aH}=Object;var sH=Object.prototype.hasOwnProperty;function tH(N){return this[N]}var rH,eH,QW=(N,U,H)=>{var Y=N!=null&&typeof N==="object";if(Y){var W=U?rH??=new WeakMap:eH??=new WeakMap,$=W.get(N);if($)return $}H=N!=null?oH(nH(N)):{};let O=U||!N||!N.__esModule?A0(H,"default",{value:N,enumerable:!0}):H;for(let G of aH(N))if(!sH.call(O,G))A0(O,G,{get:tH.bind(N,G),enumerable:!0});if(Y)W.set(N,O);return O};var FW=(N,U)=>()=>(U||N((U={exports:{}}).exports,U),U.exports);var NY=(N)=>N;function UY(N,U){this[N]=NY.bind(null,U)}var XW=(N,U)=>{for(var H in U)A0(N,H,{get:U[H],enumerable:!0,configurable:!0,set:UY.bind(U,H)})};import{existsSync as uH,watch as UW}from"fs";import{stat as iH}from"fs/promises";import w from"path";import{promises as n}from"fs";import o from"path";import{existsSync as N1,renameSync as HY}from"fs";import U1 from"os";import h from"path";function x(N){return process.env[`JUN_${N}`]??process.env[`AGENTHOST_${N}`]}function YY(){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{HY(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=YY(),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 u(N){return N.split(h.sep).join("/")}var WY=["files","reports","downloads","screenshots","artifacts",".agents/skills"],OY=["profile","downloads","screenshots","recordings"],$Y={defaultModel:"gpt-5.4",defaultSandbox:"workspaceWrite",defaultApprovalPolicy:"onRequest",host:"127.0.0.1",port:8787,browserProvider:"agent-browser"},GY={version:1,pages:[{id:"home",title:"Home",widgets:[]}]},QY='# 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.
2
+ var nH=Object.create;var{getPrototypeOf:aH,defineProperty:A0,getOwnPropertyNames:sH}=Object;var tH=Object.prototype.hasOwnProperty;function rH(N){return this[N]}var eH,NY,FW=(N,U,H)=>{var Y=N!=null&&typeof N==="object";if(Y){var W=U?eH??=new WeakMap:NY??=new WeakMap,G=W.get(N);if(G)return G}H=N!=null?nH(aH(N)):{};let $=U||!N||!N.__esModule?A0(H,"default",{value:N,enumerable:!0}):H;for(let O of sH(N))if(!tH.call($,O))A0($,O,{get:rH.bind(N,O),enumerable:!0});if(Y)W.set(N,$);return $};var XW=(N,U)=>()=>(U||N((U={exports:{}}).exports,U),U.exports);var UY=(N)=>N;function HY(N,U){this[N]=UY.bind(null,U)}var ZW=(N,U)=>{for(var H in U)A0(N,H,{get:U[H],enumerable:!0,configurable:!0,set:HY.bind(U,H)})};import{existsSync as iH,watch as HW}from"fs";import{stat as dH}from"fs/promises";import x from"path";import{promises as a}from"fs";import n from"path";import{existsSync as N1,renameSync as YY}from"fs";import U1 from"os";import m from"path";function k(N){return process.env[`JUN_${N}`]??process.env[`AGENTHOST_${N}`]}function WY(){let N=k("HOME");if(N)return N;let U=m.join(U1.homedir(),".jun"),H=m.join(U1.homedir(),".agenthost");if(!N1(U)&&N1(H))try{YY(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 y=WY(),T0=k("HOST")??"127.0.0.1",mN=Number(k("PORT")??8787);function ON(){return m.join(y,"projects","default")}function o(){return m.join(y,"runs")}function M(){return m.join(ON(),"workspace")}function TN(){return m.join(y,"schedules")}function b(){return m.join(ON(),"codex-home")}function H1(){return m.join(ON(),"widgets")}function BN(){return m.join(ON(),"browser")}function i(N){return N.split(m.sep).join("/")}var $Y=["files","reports","downloads","screenshots","artifacts",".agents/skills"],GY=["profile","downloads","screenshots","recordings"],OY={defaultModel:"gpt-5.4",defaultSandbox:"workspaceWrite",defaultApprovalPolicy:"onRequest",host:"127.0.0.1",port:8787,browserProvider:"agent-browser"},QY={version:1,pages:[{id:"home",title:"Home",widgets:[]}]},FY='# 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',XY=`# 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 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($Y,null,2)+`
9
- `);let N=M();for(let U of WY)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(GY,null,2)+`
10
- `),await cN(o.join(k(),"config.toml"),FY),await cN(o.join(N,"AGENTS.md"),QY)}import{promises as LN}from"fs";import G2 from"path";/*!
8
+ `;async function cN(N,U){try{await a.access(N)}catch{await a.mkdir(n.dirname(N),{recursive:!0}),await a.writeFile(N,U,"utf8")}}async function Y1(){await a.mkdir(o(),{recursive:!0}),await cN(n.join(y,"config.json"),JSON.stringify(OY,null,2)+`
9
+ `);let N=M();for(let U of $Y)await a.mkdir(n.join(N,U),{recursive:!0});for(let U of GY)await a.mkdir(n.join(BN(),U),{recursive:!0});await a.mkdir(H1(),{recursive:!0}),await a.mkdir(n.join(b(),"logs"),{recursive:!0}),await cN(n.join(ON(),"dashboard.json"),JSON.stringify(QY,null,2)+`
10
+ `),await cN(n.join(b(),"config.toml"),XY),await cN(n.join(N,"AGENTS.md"),FY)}import{promises as LN}from"fs";import Q2 from"path";/*!
11
11
  * Copyright (c) Squirrel Chat et al., All rights reserved.
12
12
  * SPDX-License-Identifier: BSD-3-Clause
13
13
  *
@@ -33,9 +33,9 @@ var oH=Object.create;var{getPrototypeOf:nH,defineProperty:A0,getOwnPropertyNames
33
33
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34
34
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
35
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
- */function XY(N,U){let H=N.slice(0,U).split(/\r\n|\n|\r/g);return[H.length,H.pop().length+1]}function ZY(N,U,H){let Y=N.split(/\r\n|\n|\r/g),W="",$=(Math.log10(U+1)|0)+1;for(let O=U-1;O<=U+1;O++){let G=Y[O-1];if(!G)continue;if(W+=O.toString().padEnd($," "),W+=": ",W+=G,W+=`
37
- `,O===U)W+=" ".repeat($+H+2),W+=`^
38
- `}return W}class D extends Error{line;column;codeblock;constructor(N,U){let[H,Y]=XY(U.toml,U.ptr),W=ZY(U.toml,H,Y);super(`Invalid TOML document: ${N}
36
+ */function ZY(N,U){let H=N.slice(0,U).split(/\r\n|\n|\r/g);return[H.length,H.pop().length+1]}function LY(N,U,H){let Y=N.split(/\r\n|\n|\r/g),W="",G=(Math.log10(U+1)|0)+1;for(let $=U-1;$<=U+1;$++){let O=Y[$-1];if(!O)continue;if(W+=$.toString().padEnd(G," "),W+=": ",W+=O,W+=`
37
+ `,$===U)W+=" ".repeat(G+H+2),W+=`^
38
+ `}return W}class D extends Error{line;column;codeblock;constructor(N,U){let[H,Y]=ZY(U.toml,U.ptr),W=LY(U.toml,H,Y);super(`Invalid TOML document: ${N}
39
39
 
40
40
  ${W}`,U);this.line=H,this.column=Y,this.codeblock=W}}/*!
41
41
  * Copyright (c) Squirrel Chat et al., All rights reserved.
@@ -63,14 +63,14 @@ ${W}`,U);this.line=H,this.column=Y,this.codeblock=W}}/*!
63
63
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
64
64
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
65
65
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
66
- */function LY(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(`
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
67
  `,U);if(N[Y-1]==="\r")Y--;return Y<=H?Y:-1}function QN(N,U){for(let H=U;H<N.length;H++){let Y=N[H];if(Y===`
68
68
  `)return H;if(Y==="\r"&&N[H+1]===`
69
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 _(N,U,H,Y){let W;while(!0){while((W=N[U])===" "||W==="\t"||!H&&(W===`
70
70
  `||W==="\r"&&N[U+1]===`
71
- `))U++;if(Y||W!=="#")break;U=QN(N,U)}return U}function W1(N,U,H,Y,W=!1){if(!Y)return U=lN(N,U),U<0?N.length:U;for(let $=U;$<N.length;$++){let O=N[$];if(O==="#")$=lN(N,$);else if(O===H)return $+1;else if(O===Y||W&&(O===`
72
- `||O==="\r"&&N[$+1]===`
73
- `))return $}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!=="'"&&LY(N,U));if(U>-1){if(U+=Y.length,Y.length>1){if(N[U]===H)U++;if(N[U]===H)U++}}return U}/*!
71
+ `))U++;if(Y||W!=="#")break;U=QN(N,U)}return U}function W1(N,U,H,Y,W=!1){if(!Y)return U=lN(N,U),U<0?N.length:U;for(let G=U;G<N.length;G++){let $=N[G];if($==="#")G=lN(N,G);else if($===H)return G+1;else if($===Y||W&&($===`
72
+ `||$==="\r"&&N[G+1]===`
73
+ `))return G}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}/*!
74
74
  * Copyright (c) Squirrel Chat et al., All rights reserved.
75
75
  * SPDX-License-Identifier: BSD-3-Clause
76
76
  *
@@ -96,7 +96,7 @@ ${W}`,U);this.line=H,this.column=Y,this.codeblock=W}}/*!
96
96
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
97
97
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
98
98
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
99
- */var zY=/^(\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 W=N.match(zY);if(W){if(!W[1])U=!1,N=`0000-01-01T${N}`;if(H=!!W[2],H&&N[10]===" "&&(N=N.replace(" ","T")),W[2]&&+W[2]>23)N="";else if(Y=W[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}}/*!
99
+ */var DY=/^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;class s extends Date{#U=!1;#H=!1;#N=null;constructor(N){let U=!0,H=!0,Y="Z";if(typeof N==="string"){let W=N.match(DY);if(W){if(!W[1])U=!1,N=`0000-01-01T${N}`;if(H=!!W[2],H&&N[10]===" "&&(N=N.replace(" ","T")),W[2]&&+W[2]>23)N="";else if(Y=W[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 s(N);return H.#N=U,H}static wrapAsLocalDateTime(N){let U=new s(N);return U.#N=null,U}static wrapAsLocalDate(N){let U=new s(N);return U.#H=!1,U.#N=null,U}static wrapAsLocalTime(N){let U=new s(N);return U.#U=!1,U.#N=null,U}}/*!
100
100
  * Copyright (c) Squirrel Chat et al., All rights reserved.
101
101
  * SPDX-License-Identifier: BSD-3-Clause
102
102
  *
@@ -122,13 +122,13 @@ ${W}`,U);this.line=H,this.column=Y,this.codeblock=W}}/*!
122
122
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
123
123
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
124
124
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
125
- */var DY=/^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/,KY=/^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/,VY=/^[+-]?0[0-9_]/,MY=/^[0-9a-f]{2,8}$/i,O1={b:"\b",t:"\t",n:`
125
+ */var KY=/^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/,VY=/^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/,MY=/^[+-]?0[0-9_]/,JY=/^[0-9a-f]{2,8}$/i,$1={b:"\b",t:"\t",n:`
126
126
  `,f:"\f",r:"\r",e:"\x1B",'"':'"',"\\":"\\"};function uN(N,U=0,H=N.length){let Y=N[U]==="'",W=N[U++]===N[U]&&N[U]===N[U+1];if(W){if(H-=2,N[U+=2]==="\r")U++;if(N[U]===`
127
- `)U++}let $=0,O,G="",Q=U;while(U<H-1){let F=N[U++];if(F===`
127
+ `)U++}let G=0,$,O="",Q=U;while(U<H-1){let F=N[U++];if(F===`
128
128
  `||F==="\r"&&N[U]===`
129
- `){if(!W)throw new D("newlines are not allowed in strings",{toml:N,ptr:U-1})}else if(F<" "&&F!=="\t"||F==="\x7F")throw new D("control characters are not allowed in strings",{toml:N,ptr:U-1});if(O){if(O=!1,F==="x"||F==="u"||F==="U"){let L=N.slice(U,U+=F==="x"?2:F==="u"?4:8);if(!MY.test(L))throw new D("invalid unicode escape",{toml:N,ptr:$});try{G+=String.fromCodePoint(parseInt(L,16))}catch{throw new D("invalid unicode escape",{toml:N,ptr:$})}}else if(W&&(F===`
129
+ `){if(!W)throw new D("newlines are not allowed in strings",{toml:N,ptr:U-1})}else if(F<" "&&F!=="\t"||F==="\x7F")throw new D("control characters are not allowed in strings",{toml:N,ptr:U-1});if($){if($=!1,F==="x"||F==="u"||F==="U"){let L=N.slice(U,U+=F==="x"?2:F==="u"?4:8);if(!JY.test(L))throw new D("invalid unicode escape",{toml:N,ptr:G});try{O+=String.fromCodePoint(parseInt(L,16))}catch{throw new D("invalid unicode escape",{toml:N,ptr:G})}}else if(W&&(F===`
130
130
  `||F===" "||F==="\t"||F==="\r")){if(U=_(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:$});U=_(N,U)}else if(F in O1)G+=O1[F];else throw new D("unrecognized escape sequence",{toml:N,ptr:$});Q=U}else if(!Y&&F==="\\")$=U-1,O=!0,G+=N.slice(Q,$)}return G+N.slice(Q,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 W=DY.test(N);if(W||KY.test(N)){if(VY.test(N))throw new D("leading zeroes are not allowed",{toml:U,ptr:H});N=N.replace(/_/g,"");let O=+N;if(isNaN(O))throw new D("invalid number",{toml:U,ptr:H});if(W){if((W=!Number.isSafeInteger(O))&&!Y)throw new D("integer value cannot be represented losslessly",{toml:U,ptr:H});if(W||Y===!0)O=BigInt(N)}return O}let $=new a(N);if(!$.isValid())throw new D("invalid value",{toml:U,ptr:H});return $}/*!
131
+ `&&N[U]!=="\r")throw new D("invalid escape: only line-ending whitespace may be escaped",{toml:N,ptr:G});U=_(N,U)}else if(F in $1)O+=$1[F];else throw new D("unrecognized escape sequence",{toml:N,ptr:G});Q=U}else if(!Y&&F==="\\")G=U-1,$=!0,O+=N.slice(Q,G)}return O+N.slice(Q,H-1)}function G1(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 W=KY.test(N);if(W||VY.test(N)){if(MY.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(W){if((W=!Number.isSafeInteger($))&&!Y)throw new D("integer value cannot be represented losslessly",{toml:U,ptr:H});if(W||Y===!0)$=BigInt(N)}return $}let G=new s(N);if(!G.isValid())throw new D("invalid value",{toml:U,ptr:H});return G}/*!
132
132
  * Copyright (c) Squirrel Chat et al., All rights reserved.
133
133
  * SPDX-License-Identifier: BSD-3-Clause
134
134
  *
@@ -154,8 +154,8 @@ ${W}`,U);this.line=H,this.column=Y,this.codeblock=W}}/*!
154
154
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
155
155
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
156
156
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
157
- */function JY(N,U,H){let Y=N.slice(U,H),W=Y.indexOf("#");if(W>-1)QN(N,W),Y=Y.slice(0,W);return[Y.trimEnd(),W]}function EN(N,U,H,Y,W){if(Y===0)throw new D("document contains excessively nested structures. aborting.",{toml:N,ptr:U});let $=N[U];if($==="["||$==="{"){let[Q,F]=$==="["?Q1(N,U,Y,W):G1(N,U,Y,W);if(H){if(F=_(N,F),N[F]===",")F++;else if(N[F]!==H)throw new D("expected comma or end of structure",{toml:N,ptr:F})}return[Q,F]}let O;if($==='"'||$==="'"){O=pN(N,U);let Q=uN(N,U,O);if(H){if(O=_(N,O),N[O]&&N[O]!==","&&N[O]!==H&&N[O]!==`
158
- `&&N[O]!=="\r")throw new D("unexpected character encountered",{toml:N,ptr:O});O+=+(N[O]===",")}return[Q,O]}O=W1(N,U,",",H);let G=JY(N,U,O-+(N[O-1]===","));if(!G[0])throw new D("incomplete key-value declaration: no value specified",{toml:N,ptr:U});if(H&&G[1]>-1)O=_(N,U+G[1]),O+=+(N[O]===",");return[$1(G[0],N,U,W),O]}/*!
157
+ */function AY(N,U,H){let Y=N.slice(U,H),W=Y.indexOf("#");if(W>-1)QN(N,W),Y=Y.slice(0,W);return[Y.trimEnd(),W]}function CN(N,U,H,Y,W){if(Y===0)throw new D("document contains excessively nested structures. aborting.",{toml:N,ptr:U});let G=N[U];if(G==="["||G==="{"){let[Q,F]=G==="["?Q1(N,U,Y,W):O1(N,U,Y,W);if(H){if(F=_(N,F),N[F]===",")F++;else if(N[F]!==H)throw new D("expected comma or end of structure",{toml:N,ptr:F})}return[Q,F]}let $;if(G==='"'||G==="'"){$=pN(N,U);let Q=uN(N,U,$);if(H){if($=_(N,$),N[$]&&N[$]!==","&&N[$]!==H&&N[$]!==`
158
+ `&&N[$]!=="\r")throw new D("unexpected character encountered",{toml:N,ptr:$});$+=+(N[$]===",")}return[Q,$]}$=W1(N,U,",",H);let O=AY(N,U,$-+(N[$-1]===","));if(!O[0])throw new D("incomplete key-value declaration: no value specified",{toml:N,ptr:U});if(H&&O[1]>-1)$=_(N,U+O[1]),$+=+(N[$]===",");return[G1(O[0],N,U,W),$]}/*!
159
159
  * Copyright (c) Squirrel Chat et al., All rights reserved.
160
160
  * SPDX-License-Identifier: BSD-3-Clause
161
161
  *
@@ -181,9 +181,9 @@ ${W}`,U);this.line=H,this.column=Y,this.codeblock=W}}/*!
181
181
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
182
182
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
183
183
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
184
- */var AY=/^[a-zA-Z0-9-_]+[ \t]*$/;function iN(N,U,H="="){let Y=U-1,W=[],$=N.indexOf(H,U);if($<0)throw new D("incomplete key-value: cannot find end of key",{toml:N,ptr:U});do{let O=N[U=++Y];if(O!==" "&&O!=="\t")if(O==='"'||O==="'"){if(O===N[U+1]&&O===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 Q=N.slice(G,Y<0||Y>$?$:Y),F=lN(Q);if(F>-1)throw new D("newlines are not allowed in keys",{toml:N,ptr:U+Y+F});if(Q.trimStart())throw new D("found extra tokens after the string part",{toml:N,ptr:G});if($<G){if($=N.indexOf(H,G),$<0)throw new D("incomplete key-value: cannot find end of key",{toml:N,ptr:U})}W.push(uN(N,U,G))}else{Y=N.indexOf(".",U);let G=N.slice(U,Y<0||Y>$?$:Y);if(!AY.test(G))throw new D("only letter, numbers, dashes and underscores are allowed in keys",{toml:N,ptr:U});W.push(G.trimEnd())}}while(Y+1&&Y<$);return[W,_(N,$+1,!0,!0)]}function G1(N,U,H,Y){let W={},$=new Set,O;U++;while((O=N[U++])!=="}"&&O)if(O===",")throw new D("expected value, found comma",{toml:N,ptr:U-1});else if(O==="#")U=QN(N,U);else if(O!==" "&&O!=="\t"&&O!==`
185
- `&&O!=="\r"){let G,Q=W,F=!1,[L,K]=iN(N,U-1);for(let $N=0;$N<L.length;$N++){if($N)Q=F?Q[G]:Q[G]={};if(G=L[$N],(F=Object.hasOwn(Q,G))&&(typeof Q[G]!=="object"||$.has(Q[G])))throw new D("trying to redefine an already defined value",{toml:N,ptr:U});if(!F&&G==="__proto__")Object.defineProperty(Q,G,{enumerable:!0,configurable:!0,writable:!0})}if(F)throw new D("trying to redefine an already defined value",{toml:N,ptr:U});let[A,e]=EN(N,K,"}",H-1,Y);$.add(A),Q[G]=A,U=e}if(!O)throw new D("unfinished table encountered",{toml:N,ptr:U});return[W,U]}function Q1(N,U,H,Y){let W=[],$;U++;while(($=N[U++])!=="]"&&$)if($===",")throw new D("expected value, found comma",{toml:N,ptr:U-1});else if($==="#")U=QN(N,U);else if($!==" "&&$!=="\t"&&$!==`
186
- `&&$!=="\r"){let O=EN(N,U-1,"]",H-1,Y);W.push(O[0]),U=O[1]}if(!$)throw new D("unfinished array encountered",{toml:N,ptr:U});return[W,U]}/*!
184
+ */var TY=/^[a-zA-Z0-9-_]+[ \t]*$/;function iN(N,U,H="="){let Y=U-1,W=[],G=N.indexOf(H,U);if(G<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 O=pN(N,U);if(O<0)throw new D("unfinished string encountered",{toml:N,ptr:U});Y=N.indexOf(".",O);let Q=N.slice(O,Y<0||Y>G?G:Y),F=lN(Q);if(F>-1)throw new D("newlines are not allowed in keys",{toml:N,ptr:U+Y+F});if(Q.trimStart())throw new D("found extra tokens after the string part",{toml:N,ptr:O});if(G<O){if(G=N.indexOf(H,O),G<0)throw new D("incomplete key-value: cannot find end of key",{toml:N,ptr:U})}W.push(uN(N,U,O))}else{Y=N.indexOf(".",U);let O=N.slice(U,Y<0||Y>G?G:Y);if(!TY.test(O))throw new D("only letter, numbers, dashes and underscores are allowed in keys",{toml:N,ptr:U});W.push(O.trimEnd())}}while(Y+1&&Y<G);return[W,_(N,G+1,!0,!0)]}function O1(N,U,H,Y){let W={},G=new Set,$;U++;while(($=N[U++])!=="}"&&$)if($===",")throw new D("expected value, found comma",{toml:N,ptr:U-1});else if($==="#")U=QN(N,U);else if($!==" "&&$!=="\t"&&$!==`
185
+ `&&$!=="\r"){let O,Q=W,F=!1,[L,K]=iN(N,U-1);for(let GN=0;GN<L.length;GN++){if(GN)Q=F?Q[O]:Q[O]={};if(O=L[GN],(F=Object.hasOwn(Q,O))&&(typeof Q[O]!=="object"||G.has(Q[O])))throw new D("trying to redefine an already defined value",{toml:N,ptr:U});if(!F&&O==="__proto__")Object.defineProperty(Q,O,{enumerable:!0,configurable:!0,writable:!0})}if(F)throw new D("trying to redefine an already defined value",{toml:N,ptr:U});let[J,f]=CN(N,K,"}",H-1,Y);G.add(J),Q[O]=J,U=f}if(!$)throw new D("unfinished table encountered",{toml:N,ptr:U});return[W,U]}function Q1(N,U,H,Y){let W=[],G;U++;while((G=N[U++])!=="]"&&G)if(G===",")throw new D("expected value, found comma",{toml:N,ptr:U-1});else if(G==="#")U=QN(N,U);else if(G!==" "&&G!=="\t"&&G!==`
186
+ `&&G!=="\r"){let $=CN(N,U-1,"]",H-1,Y);W.push($[0]),U=$[1]}if(!G)throw new D("unfinished array encountered",{toml:N,ptr:U});return[W,U]}/*!
187
187
  * Copyright (c) Squirrel Chat et al., All rights reserved.
188
188
  * SPDX-License-Identifier: BSD-3-Clause
189
189
  *
@@ -209,8 +209,8 @@ ${W}`,U);this.line=H,this.column=Y,this.codeblock=W}}/*!
209
209
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
210
210
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
211
211
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
212
- */function F1(N,U,H,Y){let W=U,$=H,O,G=!1,Q;for(let F=0;F<N.length;F++){if(F){if(W=G?W[O]:W[O]={},$=(Q=$[O]).c,Y===0&&(Q.t===1||Q.t===2))return null;if(Q.t===2){let L=W.length-1;W=W[L],$=$[L].c}}if(O=N[F],(G=Object.hasOwn(W,O))&&$[O]?.t===0&&$[O]?.d)return null;if(!G){if(O==="__proto__")Object.defineProperty(W,O,{enumerable:!0,configurable:!0,writable:!0}),Object.defineProperty($,O,{enumerable:!0,configurable:!0,writable:!0});$[O]={t:F<N.length-1&&Y===2?3:Y,d:!1,i:0,c:{}}}}if(Q=$[O],Q.t!==Y&&!(Y===1&&Q.t===3))return null;if(Y===2){if(!Q.d)Q.d=!0,W[O]=[];W[O].push(W={}),Q.c[Q.i++]=Q={t:1,d:!1,i:0,c:{}}}if(Q.d)return null;if(Q.d=!0,Y===1)W=G?W[O]:W[O]={};else if(Y===0&&G)return null;return[O,W,Q.c]}function m(N,{maxDepth:U=1000,integersAsBigInt:H}={}){let Y={},W={},$=Y,O=W;for(let G=_(N,0);G<N.length;){if(N[G]==="["){let Q=N[++G]==="[",F=iN(N,G+=+Q,"]");if(Q){if(N[F[1]-1]!=="]")throw new D("expected end of table declaration",{toml:N,ptr:F[1]-1});F[1]++}let L=F1(F[0],Y,W,Q?2:1);if(!L)throw new D("trying to redefine an already defined table or value",{toml:N,ptr:G});O=L[2],$=L[1],G=F[1]}else{let Q=iN(N,G),F=F1(Q[0],$,O,0);if(!F)throw new D("trying to redefine an already defined table or value",{toml:N,ptr:G});let L=EN(N,Q[1],void 0,U,H);F[1][F[0]]=L[0],G=L[1]}if(G=_(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=_(N,G)}return Y}/*!
212
+ */function F1(N,U,H,Y){let W=U,G=H,$,O=!1,Q;for(let F=0;F<N.length;F++){if(F){if(W=O?W[$]:W[$]={},G=(Q=G[$]).c,Y===0&&(Q.t===1||Q.t===2))return null;if(Q.t===2){let L=W.length-1;W=W[L],G=G[L].c}}if($=N[F],(O=Object.hasOwn(W,$))&&G[$]?.t===0&&G[$]?.d)return null;if(!O){if($==="__proto__")Object.defineProperty(W,$,{enumerable:!0,configurable:!0,writable:!0}),Object.defineProperty(G,$,{enumerable:!0,configurable:!0,writable:!0});G[$]={t:F<N.length-1&&Y===2?3:Y,d:!1,i:0,c:{}}}}if(Q=G[$],Q.t!==Y&&!(Y===1&&Q.t===3))return null;if(Y===2){if(!Q.d)Q.d=!0,W[$]=[];W[$].push(W={}),Q.c[Q.i++]=Q={t:1,d:!1,i:0,c:{}}}if(Q.d)return null;if(Q.d=!0,Y===1)W=O?W[$]:W[$]={};else if(Y===0&&O)return null;return[$,W,Q.c]}function c(N,{maxDepth:U=1000,integersAsBigInt:H}={}){let Y={},W={},G=Y,$=W;for(let O=_(N,0);O<N.length;){if(N[O]==="["){let Q=N[++O]==="[",F=iN(N,O+=+Q,"]");if(Q){if(N[F[1]-1]!=="]")throw new D("expected end of table declaration",{toml:N,ptr:F[1]-1});F[1]++}let L=F1(F[0],Y,W,Q?2:1);if(!L)throw new D("trying to redefine an already defined table or value",{toml:N,ptr:O});$=L[2],G=L[1],O=F[1]}else{let Q=iN(N,O),F=F1(Q[0],G,$,0);if(!F)throw new D("trying to redefine an already defined table or value",{toml:N,ptr:O});let L=CN(N,Q[1],void 0,U,H);F[1][F[0]]=L[0],O=L[1]}if(O=_(N,O,!0),N[O]&&N[O]!==`
213
+ `&&N[O]!=="\r")throw new D("each key-value declaration must be followed by an end-of-line",{toml:N,ptr:O});O=_(N,O)}return Y}/*!
214
214
  * Copyright (c) Squirrel Chat et al., All rights reserved.
215
215
  * SPDX-License-Identifier: BSD-3-Clause
216
216
  *
@@ -236,14 +236,14 @@ ${W}`,U);this.line=H,this.column=Y,this.codeblock=W}}/*!
236
236
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
237
237
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238
238
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 TY(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 BY(N,H,Y);if(U==="array")return EY(N,H,Y)}function BY(N,U,H){let Y=Object.keys(N);if(Y.length===0)return"{}";let W="{ ";for(let $=0;$<Y.length;$++){let O=Y[$];if($)W+=", ";W+=X1.test(O)?O:B0(O),W+=" = ",W+=E0(N[O],CN(N[O]),U-1,H)}return W+" }"}function EY(N,U,H){if(N.length===0)return"[]";let Y="[ ";for(let W=0;W<N.length;W++){if(W)Y+=", ";if(N[W]===null||N[W]===void 0)throw TypeError("arrays cannot contain null or undefined values");Y+=E0(N[W],CN(N[W]),U-1,H)}return Y+" ]"}function CY(N,U,H,Y){if(H===0)throw Error("Could not stringify the object: maximum object depth exceeded");let W="";for(let $=0;$<N.length;$++)W+=`${W&&`
239
+ */var X1=/^[a-z0-9-_]+$/i;function EN(N){let U=typeof N;if(U==="object"){if(Array.isArray(N))return"array";if(N instanceof Date)return"date"}return U}function BY(N){for(let U=0;U<N.length;U++)if(EN(N[U])!=="object")return!1;return N.length!=0}function B0(N){return JSON.stringify(N).replace(/\x7f/g,"\\u007f")}function C0(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 CY(N,H,Y);if(U==="array")return EY(N,H,Y)}function CY(N,U,H){let Y=Object.keys(N);if(Y.length===0)return"{}";let W="{ ";for(let G=0;G<Y.length;G++){let $=Y[G];if(G)W+=", ";W+=X1.test($)?$:B0($),W+=" = ",W+=C0(N[$],EN(N[$]),U-1,H)}return W+" }"}function EY(N,U,H){if(N.length===0)return"[]";let Y="[ ";for(let W=0;W<N.length;W++){if(W)Y+=", ";if(N[W]===null||N[W]===void 0)throw TypeError("arrays cannot contain null or undefined values");Y+=C0(N[W],EN(N[W]),U-1,H)}return Y+" ]"}function RY(N,U,H,Y){if(H===0)throw Error("Could not stringify the object: maximum object depth exceeded");let W="";for(let G=0;G<N.length;G++)W+=`${W&&`
240
240
  `}[[${U}]]
241
- `,W+=C0(0,N[$],U,H,Y);return W}function C0(N,U,H,Y,W){if(Y===0)throw Error("Could not stringify the object: maximum object depth exceeded");let $="",O="",G=Object.keys(U);for(let Q=0;Q<G.length;Q++){let F=G[Q];if(U[F]!==null&&U[F]!==void 0){let L=CN(U[F]);if(L==="symbol"||L==="function")throw TypeError(`cannot serialize values of type '${L}'`);let K=X1.test(F)?F:B0(F);if(L==="array"&&TY(U[F]))O+=(O&&`
242
- `)+CY(U[F],H?`${H}.${K}`:K,Y-1,W);else if(L==="object"){let A=H?`${H}.${K}`:K;O+=(O&&`
243
- `)+C0(A,U[F],A,Y-1,W)}else $+=K,$+=" = ",$+=E0(U[F],L,Y,W),$+=`
244
- `}}if(N&&($||!O))$=$?`[${N}]
245
- ${$}`:`[${N}]`;return $&&O?`${$}
246
- ${O}`:$||O}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]!==`
241
+ `,W+=E0(0,N[G],U,H,Y);return W}function E0(N,U,H,Y,W){if(Y===0)throw Error("Could not stringify the object: maximum object depth exceeded");let G="",$="",O=Object.keys(U);for(let Q=0;Q<O.length;Q++){let F=O[Q];if(U[F]!==null&&U[F]!==void 0){let L=EN(U[F]);if(L==="symbol"||L==="function")throw TypeError(`cannot serialize values of type '${L}'`);let K=X1.test(F)?F:B0(F);if(L==="array"&&BY(U[F]))$+=($&&`
242
+ `)+RY(U[F],H?`${H}.${K}`:K,Y-1,W);else if(L==="object"){let J=H?`${H}.${K}`:K;$+=($&&`
243
+ `)+E0(J,U[F],J,Y-1,W)}else G+=K,G+=" = ",G+=C0(U[F],L,Y,W),G+=`
244
+ `}}if(N&&(G||!$))G=G?`[${N}]
245
+ ${G}`:`[${N}]`;return G&&$?`${G}
246
+ ${$}`:G||$}function t(N,{maxDepth:U=1000,numbersAsFloat:H=!1}={}){if(EN(N)!=="object")throw TypeError("stringify can only be called with an object");let Y=E0(0,N,"",U,H);if(Y[Y.length-1]!==`
247
247
  `)return Y+`
248
248
  `;return Y}/*!
249
249
  * Copyright (c) Squirrel Chat et al., All rights reserved.
@@ -271,13 +271,13 @@ ${O}`:$||O}function s(N,{maxDepth:U=1000,numbersAsFloat:H=!1}={}){if(CN(N)!=="ob
271
271
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
272
272
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
273
273
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 V(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 RY=2097152,_Y=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 jY(N){let U=y.extname(N).toLowerCase();if(U===".md"||U===".markdown")return"markdown";if(U===".json"||U===".jsonl")return"json";if(_Y.has(U))return"image";if(SY.has(U))return"binary";return"text"}function t(N){return NN(M(),N)}function _0(N){let U=y.relative(M(),N);return U===""?".":u(U)}async function Z1(N){let U=await b.stat(N),H={name:y.basename(N)||".",path:_0(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}),W=await Promise.all(Y.map(($)=>Z1(y.join(N,$.name))));return W.sort(($,O)=>$.type!==O.type?$.type==="dir"?-1:1:$.name.localeCompare(O.name)),H.children=W,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=jY(U),W={path:_0(U),kind:Y,size:H.size,modifiedAt:H.mtime.toISOString()};if(Y==="image"||Y==="binary")return W;if(H.size>RY)throw Error(`File too large to open (${H.size} bytes): ${N}`);return W.content=await b.readFile(U,"utf8"),W}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 W=NN(M(),y.join(N||".",Y));return await b.mkdir(y.dirname(W),{recursive:!0}),await Bun.write(W,H),_0(W)}function oN(N){return t(N)}import{randomBytes as PY}from"crypto";function nN(N){return`${N}_${PY(6).toString("hex")}`}var S0=null;function T1(N){S0=N}function q(N,U){S0?.publish(N,JSON.stringify(U))}function B1(N,U){S0?.publish(N,U)}import{promises as RN}from"fs";import IY 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(IY.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 _1(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 wY(){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 S1(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 _1(U),U}async function UN(N,U){let H=await T(N);if(!H)return null;let Y={...H,...U};return r.set(N,Y),await _1(Y),Y}async function T(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 wY(),[...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 xY from"path";function I1(N){return xY.join(d(),N,"events.jsonl")}async function w1(N){await P1.appendFile(I1(N.runId),JSON.stringify(N)+`
276
- `,"utf8")}var fY=/"type":\s*"run\.(started|resumed|steered)"/,kY=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 W=Y.length,$=Math.max(0,Math.min(U.before??W,W)),O=U.limit===void 0?0:Math.max(0,$-U.limit);if(O>0){for(let Q=O;Q>=Math.max(0,O-kY);Q--)if(fY.test(Y[Q])){O=Q;break}}let G=[];for(let Q=O;Q<$;Q++){let F=Y[Q].trim();if(!F)continue;try{G.push(JSON.parse(F))}catch{}}return{events:G,offset:O,total:W}}import{promises as LU}from"fs";import tY from"os";import zU from"path";var k1={name:"junhost",version:"0.3.0",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 gY from"os";import S from"path";import{existsSync as jN,readdirSync as hY}from"fs";import{mkdir as c1}from"fs/promises";import{randomUUID as mY}from"crypto";import{readFileSync as bY}from"fs";import{promises as qY}from"fs";import vY from"path";var y1=["browserProxy","browserNoProxy"];function b1(){return vY.join(f,"config.json")}var aN=null;function sN(){if(aN)return aN;let N={};try{N=JSON.parse(bY(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 qY.writeFile(b1(),JSON.stringify(U,null,2)+`
278
- `,"utf8"),aN=U,U}var cY="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=S.join(N,"node_modules",".bin");if(jN(S.join(H,l1)))return H;let Y=S.dirname(N);if(Y===N)break;N=Y}return null}function lY(N){let U=p1();if(U)return[S.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=S.join(gY.homedir(),".cloakbrowser"),H;try{H=hY(U).filter((W)=>W.startsWith("chromium-"))}catch{return null}H.sort().reverse();let Y=process.platform==="win32"?"chrome.exe":"chrome";for(let W of H){let $=S.join(U,W,Y);if(jN($))return $}return null}function pY(){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:cY,AGENT_BROWSER_PROFILE:S.join(BN(),"profile"),AGENT_BROWSER_DOWNLOAD_PATH:S.join(M(),"downloads"),AGENT_BROWSER_SCREENSHOT_DIR:S.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}${S.delimiter}${process.env[g1]??""}`;let W=u1();if(W)return N.AGENT_BROWSER_EXECUTABLE_PATH=W,N;let $=pY(),O=process.platform!=="linux"||Boolean(process.env.DISPLAY),G=x("BROWSER_HEADED")!=="false"&&O;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($&&G)N.AGENT_BROWSER_EXECUTABLE_PATH=$,N.AGENT_BROWSER_HEADED="true";else{if($)N.AGENT_BROWSER_EXECUTABLE_PATH=$;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 uY(){return{...process.env,...x0()}}function iY(){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(),W=new TextDecoder,$="",O=Date.now()+H;try{while(Date.now()<O){let G=Math.min(U,O-Date.now()),Q=await Promise.race([Y.read(),new Promise((F)=>setTimeout(()=>F("timeout"),G))]);if(Q==="timeout"||Q.done)break;$+=W.decode(Q.value,{stream:!0})}}finally{Y.releaseLock()}return $}async function B(N,U={}){let H=[...iY(),...N],Y=U.json?[...H,"--json"]:H,W=Bun.spawn(lY(Y),{env:uY(),stdout:"pipe",stderr:"pipe"}),$=setTimeout(()=>W.kill(),U.timeoutMs??120000),O=await W.exited;clearTimeout($);let[G,Q]=await Promise.all([h1(W.stdout,80,1500),h1(W.stderr,60,300)]),F,L;if(U.json)try{let K=JSON.parse(G);if(F=K.data??K,K.success===!1)L=typeof K.error==="string"?K.error:"command failed"}catch{}return{ok:O===0&&!L,stdout:G,stderr:Q,data:F,error:L}}function l(N,U){if(tN.unshift({id:mY(),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,l("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 dY=2500,SN=null,_N=null;function p(){SN=null}async function PN(){if(SN&&Date.now()-SN.at<dY)return{...SN.status,controller:N0};if(_N)return _N;return _N=oY().then((N)=>{return SN={at:Date.now(),status:N},N}).finally(()=>{_N=null}),_N}async function oY(){let N=await B(["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 W=null,$=null;if(H){let[O,G]=await Promise.all([B(["get","url"],{json:!0,timeoutMs:30000}),B(["get","title"],{json:!0,timeoutMs:30000})]);W=O.ok?eN(O.data):null,$=G.ok?eN(G.data):null}return{running:H,streaming:Y,streamPort:rN,url:W,title:$,controller:N0}}var m1={width:1280,height:720};async function f0(){await B(["set","viewport",String(m1.width),String(m1.height)],{timeoutMs:30000})}async function t1(){await Promise.all(["screenshots","downloads","reports"].map((N)=>c1(S.join(M(),N),{recursive:!0})))}async function r1(N){await t1(),await c1(S.join(BN(),"profile"),{recursive:!0});let U=await B(["open",N??"about:blank"],{timeoutMs:180000});if(!U.ok)throw Error(`agent-browser open failed: ${U.stderr||U.stdout}`);return await f0(),await B(["stream","enable"],{json:!0,timeoutMs:30000}),l("start",N??"about:blank"),p(),PN()}async function e1(){await B(["close"],{timeoutMs:30000}),rN=null,p(),l("stop")}async function NU(N){let U=await B(["open",N],{timeoutMs:120000});if(!U.ok)throw Error(`Navigation failed: ${U.stderr||U.stdout}`);await f0(),p(),l("navigate",N)}async function UU(N){let U=await B([N],{timeoutMs:60000});if(!U.ok)throw Error(`${N} failed: ${U.stderr||U.stdout}`);await f0(),p(),l(N)}async function HU(N){let U=await B(["press",N],{timeoutMs:30000});if(!U.ok)throw Error(`Key press failed: ${U.stderr||U.stdout}`);p()}async function YU(){await t1();let N=`browser-${new Date().toISOString().replace(/[:.]/g,"-")}.png`,U=S.join(M(),"screenshots",N),H=await B(["screenshot",U],{timeoutMs:60000});if(!H.ok)throw Error(`Screenshot failed: ${H.stderr||H.stdout}`);return l("screenshot",`screenshots/${N}`),`screenshots/${N}`}async function WU(N=!0){let U=await B(["snapshot",...N?["-i"]:[]],{timeoutMs:60000});if(!U.ok)throw Error(`Snapshot failed: ${U.stderr||U.stdout}`);return U.stdout.trim()}async function OU(N){let U=await B(["click",N],{timeoutMs:30000});if(!U.ok)throw Error(`Click failed: ${U.stderr||U.stdout}`);p(),l("click",N)}async function $U(N,U){let H=await B(["fill",N,U],{timeoutMs:30000});if(!H.ok)throw Error(`Fill failed: ${H.stderr||H.stdout}`);l("fill",N)}async function GU(N){let H=await B(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 QU(N){let U=await B(["eval",N],{json:!0,timeoutMs:30000});if(!U.ok)throw Error(`Eval failed: ${U.stderr||U.stdout}`);return eN(U.data)??U.stdout.trim()}var nY=31536000;function aY(N){if(typeof N!=="string")return null;let U=N.toLowerCase();if(U==="strict")return"Strict";if(U==="lax")return"Lax";if(U==="none"||U==="no_restriction")return"None";return null}async function FU(N){if(!Array.isArray(N)||N.length===0)throw Error("No cookies provided");let U=[],H=0,Y=Math.floor(Date.now()/1000)+nY;for(let W of N){let $=typeof W?.name==="string"?W.name:"",O=typeof W?.value==="string"?W.value:"";if(!$){U.push({name:"(unnamed)",error:"missing name"});continue}let G=["cookies","set",$,O],Q=typeof W.domain==="string"?W.domain.trim():"";if(Q)G.push("--domain",Q),G.push("--url",`https://${Q.replace(/^\./,"")}/`);if(typeof W.path==="string"&&W.path)G.push("--path",W.path);if(W.httpOnly)G.push("--httpOnly");let F=aY(W.sameSite);if(W.secure||F==="None")G.push("--secure");if(F)G.push("--sameSite",F);let L=typeof W.expirationDate==="number"?W.expirationDate:typeof W.expires==="number"?W.expires:null,K=L&&L>0?Math.floor(L):Y;G.push("--expires",String(K));let A=await B(G,{timeoutMs:30000});if(A.ok)H+=1;else U.push({name:$,error:(A.error||A.stderr||A.stdout||"failed").trim().slice(0,200)})}return p(),l("cookies import",`${H}/${N.length} set`),{total:N.length,set:H,failed:U}}async function XU(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 B(N,{json:U.json,timeoutMs:U.timeoutMs??120000});return p(),l("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((W,$)=>{this.pending.set(H,{method:N,resolve:W,reject:$})});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 ZU(N){let U="",H=new TextDecoder;return{push(Y){U+=H.decode(Y,{stream:!0});let W;while((W=U.indexOf(`
279
- `))!==-1){let $=U.slice(0,W).replace(/\r$/,"");if(U=U.slice(W+1),$.trim().length>0)N($)}},flush(){let Y=U.trim();if(U="",Y.length>0)N(Y)}}}var y0=60000,b0=5,DU=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 rY();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:($,O)=>{this.lastExitCode=O,this.rpc?.failAll(`codex app-server exited (code ${O})`),this.proc=null,this.rpc=null,this.initialized=!1;let G=Date.now();if(this.exitTimes=this.exitTimes.filter((Q)=>G-Q<y0),this.exitTimes.push(G),this.exitTimes.length>=b0)this.backoffUntil=G+DU,this.exitTimes=[],console.error(`[codex] app-server crash-looping (${b0} exits in ${y0/1000}s) \u2014 backing off ${DU/1000}s`);else console.log(`[codex] app-server exited (code ${O}) \u2014 will restart on next run`);this.handlers.onExit(O)}});this.proc=Y,this.rpc=new k0(($)=>{Y.stdin.write($+`
280
- `),Y.stdin.flush()},{onNotification:($,O)=>this.handlers.onNotification($,O),onServerRequest:($,O,G)=>this.handlers.onServerRequest($,O,G)});let W=this.rpc;(async()=>{let $=ZU((O)=>W.handleLine(O));for await(let O of Y.stdout)$.push(O);$.flush()})(),(async()=>{let $=new TextDecoder;for await(let O of Y.stderr){let G=$.decode(O).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 rY(){let N=zU.join(k(),"auth.json");try{await LU.access(N);return}catch{}let U=zU.join(tY.homedir(),".codex","auth.json");try{await LU.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 W0(){return IN}function KU(){return Y0}function VU(N){if(IN=N,N)Y0=null}function O0(){IN=null,Y0=null}function MU(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 eY={"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"},N2={"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 JU(N){return eY[N]??`codex.${N.split("/").join(".")}`}function AU(N){return N2[N]??null}function TU(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 BU={readOnly:"read-only",workspaceWrite:"workspace-write",dangerFullAccess:"danger-full-access"},EU={readOnly:{type:"readOnly"},workspaceWrite:{type:"workspaceWrite"},dangerFullAccess:{type:"dangerFullAccess"}},v0={never:"never",onRequest:"on-request",onFailure:"on-failure",untrusted:"untrusted"},$0=`# 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 A("Invalid JSON body")}}function V(N,U){if(typeof N!=="string"||N.length===0)throw new A(`Missing or invalid field: ${U}`);return N}class A extends Error{constructor(N){super(N);this.name="BadRequestError"}}import{promises as v}from"fs";import q 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 _Y=2097152,SY=new Set([".png",".jpg",".jpeg",".gif",".webp",".svg",".bmp",".ico",".avif"]),jY=new Set([".zip",".tar",".gz",".7z",".exe",".dll",".so",".dylib",".pdf",".woff",".woff2",".ttf",".mp3",".mp4",".mov",".webm",".sqlite",".db",".bin"]);function PY(N){let U=q.extname(N).toLowerCase();if(U===".md"||U===".markdown")return"markdown";if(U===".json"||U===".jsonl")return"json";if(SY.has(U))return"image";if(jY.has(U))return"binary";return"text"}function r(N){return NN(M(),N)}function _0(N){let U=q.relative(M(),N);return U===""?".":i(U)}async function Z1(N){let U=await v.stat(N),H={name:q.basename(N)||".",path:_0(N),type:U.isDirectory()?"dir":"file",modifiedAt:U.mtime.toISOString()};if(H.type==="file")return H.size=U.size,H;let Y=await v.readdir(N,{withFileTypes:!0}),W=await Promise.all(Y.map((G)=>Z1(q.join(N,G.name))));return W.sort((G,$)=>G.type!==$.type?G.type==="dir"?-1:1:G.name.localeCompare($.name)),H.children=W,H}async function L1(N="."){return Z1(r(N))}async function z1(N){let U=r(N),H=await v.stat(U);if(H.isDirectory())throw Error(`Not a file: ${N}`);let Y=PY(U),W={path:_0(U),kind:Y,size:H.size,modifiedAt:H.mtime.toISOString()};if(Y==="image"||Y==="binary")return W;if(H.size>_Y)throw Error(`File too large to open (${H.size} bytes): ${N}`);return W.content=await v.readFile(U,"utf8"),W}async function D1(N,U){let H=r(N);await v.mkdir(q.dirname(H),{recursive:!0}),await v.writeFile(H,U,"utf8")}async function K1(N){await v.mkdir(r(N),{recursive:!0})}async function V1(N){let U=r(N);if(U===q.resolve(M()))throw Error("Cannot delete the workspace root");await v.rm(U,{recursive:!0,force:!0})}async function M1(N,U){let H=r(N),Y=r(U);if(H===q.resolve(M()))throw Error("Cannot rename the workspace root");await v.mkdir(q.dirname(Y),{recursive:!0}),await v.rename(H,Y)}async function J1(N,U,H){let Y=q.basename(U);if(!Y||Y==="."||Y==="..")throw Error(`Invalid file name: ${U}`);let W=NN(M(),q.join(N||".",Y));return await v.mkdir(q.dirname(W),{recursive:!0}),await Bun.write(W,H),_0(W)}function oN(N){return r(N)}import{randomBytes as IY}from"crypto";function nN(N){return`${N}_${IY(6).toString("hex")}`}var S0=null;function T1(N){S0=N}function g(N,U){S0?.publish(N,JSON.stringify(U))}function B1(N,U){S0?.publish(N,U)}import{promises as RN}from"fs";import wY from"os";import j0 from"path";var e=new Map,C1=!1;function P0(N){return j0.join(o(),N,"meta.json")}var E1=j0.join(wY.homedir(),".agenthost");function R1(N){let U=JSON.parse(N);if(U.cwd?.startsWith(E1))U.cwd=y+U.cwd.slice(E1.length);return U}async function _1(N){await RN.mkdir(j0.join(o(),N.id),{recursive:!0}),await RN.writeFile(P0(N.id),JSON.stringify(N,null,2)+`
275
+ `,"utf8")}async function xY(){if(C1)return;C1=!0;let N;try{N=await RN.readdir(o())}catch{return}for(let U of N){if(e.has(U))continue;try{let H=await RN.readFile(P0(U),"utf8"),Y=R1(H);e.set(Y.id,Y)}catch{}}}async function S1(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 e.set(U.id,U),await _1(U),U}async function UN(N,U){let H=await T(N);if(!H)return null;let Y={...H,...U};return e.set(N,Y),await _1(Y),Y}async function T(N){if(e.has(N))return e.get(N);try{let U=await RN.readFile(P0(N),"utf8"),H=R1(U);return e.set(N,H),H}catch{return null}}async function j1(){return await xY(),[...e.values()].sort((N,U)=>U.startedAt.localeCompare(N.startedAt))}function I(N){return N==="queued"||N==="starting"||N==="running"||N==="waiting_approval"}import{promises as P1}from"fs";import fY from"path";function I1(N){return fY.join(o(),N,"events.jsonl")}async function w1(N){await P1.appendFile(I1(N.runId),JSON.stringify(N)+`
276
+ `,"utf8")}var kY=/"type":\s*"run\.(started|resumed|steered)"/,yY=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 W=Y.length,G=Math.max(0,Math.min(U.before??W,W)),$=U.limit===void 0?0:Math.max(0,G-U.limit);if($>0){for(let Q=$;Q>=Math.max(0,$-yY);Q--)if(kY.test(Y[Q])){$=Q;break}}let O=[];for(let Q=$;Q<G;Q++){let F=Y[Q].trim();if(!F)continue;try{O.push(JSON.parse(F))}catch{}}return{events:O,offset:$,total:W}}import{promises as zU}from"fs";import rY from"os";import DU from"path";var k1={name:"junhost",version:"0.3.4",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 l=k1.version;import hY from"os";import S from"path";import{existsSync as jN,readdirSync as mY}from"fs";import{mkdir as c1}from"fs/promises";import{randomUUID as cY}from"crypto";import{readFileSync as qY}from"fs";import{promises as vY}from"fs";import gY from"path";var y1=["browserProxy","browserNoProxy"];function b1(){return gY.join(y,"config.json")}var aN=null;function sN(){if(aN)return aN;let N={};try{N=JSON.parse(qY(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 vY.writeFile(b1(),JSON.stringify(U,null,2)+`
278
+ `,"utf8"),aN=U,U}var lY="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=S.join(N,"node_modules",".bin");if(jN(S.join(H,l1)))return H;let Y=S.dirname(N);if(Y===N)break;N=Y}return null}function pY(N){let U=p1();if(U)return[S.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=k("CLOAK_PATH");if(N&&jN(N))return N;let U=S.join(hY.homedir(),".cloakbrowser"),H;try{H=mY(U).filter((W)=>W.startsWith("chromium-"))}catch{return null}H.sort().reverse();let Y=process.platform==="win32"?"chrome.exe":"chrome";for(let W of H){let G=S.join(U,W,Y);if(jN(G))return G}return null}function uY(){let N=k("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:lY,AGENT_BROWSER_PROFILE:S.join(BN(),"profile"),AGENT_BROWSER_DOWNLOAD_PATH:S.join(M(),"downloads"),AGENT_BROWSER_SCREENSHOT_DIR:S.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}${S.delimiter}${process.env[g1]??""}`;let W=u1();if(W)return N.AGENT_BROWSER_EXECUTABLE_PATH=W,N;let G=uY(),$=process.platform!=="linux"||Boolean(process.env.DISPLAY),O=k("BROWSER_HEADED")!=="false"&&$;if(process.platform==="linux"&&!process.env.DISPLAY&&k("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&&O)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 iY(){return{...process.env,...x0()}}function dY(){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=k("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=k("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(k("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(),W=new TextDecoder,G="",$=Date.now()+H;try{while(Date.now()<$){let O=Math.min(U,$-Date.now()),Q=await Promise.race([Y.read(),new Promise((F)=>setTimeout(()=>F("timeout"),O))]);if(Q==="timeout"||Q.done)break;G+=W.decode(Q.value,{stream:!0})}}finally{Y.releaseLock()}return G}async function B(N,U={}){let H=[...dY(),...N],Y=U.json?[...H,"--json"]:H,W=Bun.spawn(pY(Y),{env:iY(),stdout:"pipe",stderr:"pipe"}),G=setTimeout(()=>W.kill(),U.timeoutMs??120000),$=await W.exited;clearTimeout(G);let[O,Q]=await Promise.all([h1(W.stdout,80,1500),h1(W.stderr,60,300)]),F,L;if(U.json)try{let K=JSON.parse(O);if(F=K.data??K,K.success===!1)L=typeof K.error==="string"?K.error:"command failed"}catch{}return{ok:$===0&&!L,stdout:O,stderr:Q,data:F,error:L}}function p(N,U){if(tN.unshift({id:cY(),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 oY=2500,SN=null,_N=null;function u(){SN=null}async function PN(){if(SN&&Date.now()-SN.at<oY)return{...SN.status,controller:N0};if(_N)return _N;return _N=nY().then((N)=>{return SN={at:Date.now(),status:N},N}).finally(()=>{_N=null}),_N}async function nY(){let N=await B(["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 W=null,G=null;if(H){let[$,O]=await Promise.all([B(["get","url"],{json:!0,timeoutMs:30000}),B(["get","title"],{json:!0,timeoutMs:30000})]);W=$.ok?eN($.data):null,G=O.ok?eN(O.data):null}return{running:H,streaming:Y,streamPort:rN,url:W,title:G,controller:N0}}var m1={width:1280,height:720};async function f0(){await B(["set","viewport",String(m1.width),String(m1.height)],{timeoutMs:30000})}async function t1(){await Promise.all(["screenshots","downloads","reports"].map((N)=>c1(S.join(M(),N),{recursive:!0})))}async function r1(N){await t1(),await c1(S.join(BN(),"profile"),{recursive:!0});let U=await B(["open",N??"about:blank"],{timeoutMs:180000});if(!U.ok)throw Error(`agent-browser open failed: ${U.stderr||U.stdout}`);return await f0(),await B(["stream","enable"],{json:!0,timeoutMs:30000}),p("start",N??"about:blank"),u(),PN()}async function e1(){await B(["close"],{timeoutMs:30000}),rN=null,u(),p("stop")}async function NU(N){let U=await B(["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 B([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 B(["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=S.join(M(),"screenshots",N),H=await B(["screenshot",U],{timeoutMs:60000});if(!H.ok)throw Error(`Screenshot failed: ${H.stderr||H.stdout}`);return p("screenshot",`screenshots/${N}`),`screenshots/${N}`}async function WU(N=!0){let U=await B(["snapshot",...N?["-i"]:[]],{timeoutMs:60000});if(!U.ok)throw Error(`Snapshot failed: ${U.stderr||U.stdout}`);return U.stdout.trim()}async function $U(N){let U=await B(["click",N],{timeoutMs:30000});if(!U.ok)throw Error(`Click failed: ${U.stderr||U.stdout}`);u(),p("click",N)}async function GU(N,U){let H=await B(["fill",N,U],{timeoutMs:30000});if(!H.ok)throw Error(`Fill failed: ${H.stderr||H.stdout}`);p("fill",N)}async function OU(N){let H=await B(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 QU(N){let U=await B(["eval",N],{json:!0,timeoutMs:30000});if(!U.ok)throw Error(`Eval failed: ${U.stderr||U.stdout}`);return eN(U.data)??U.stdout.trim()}var aY=31536000;function sY(N){if(typeof N!=="string")return null;let U=N.toLowerCase();if(U==="strict")return"Strict";if(U==="lax")return"Lax";if(U==="none"||U==="no_restriction")return"None";return null}function FU(N){let U=[];for(let H of N.split(/\r?\n/)){let Y=H.trimEnd();if(!Y)continue;let W=!1,G=Y;if(G.startsWith("#HttpOnly_"))W=!0,G=G.slice(10);else if(G.startsWith("#"))continue;let $=G.split("\t");if($.length<7)continue;let[O,,Q,F,L,K,...J]=$;if(!K)continue;let f=Number(L);U.push({name:K,value:J.join("\t"),domain:O,path:Q||"/",secure:F.toUpperCase()==="TRUE",httpOnly:W,expirationDate:Number.isFinite(f)&&f>0?f:void 0})}return U}async function XU(N){if(!Array.isArray(N)||N.length===0)throw Error("No cookies provided");let U=[],H=0,Y=Math.floor(Date.now()/1000)+aY;for(let W of N){let G=typeof W?.name==="string"?W.name:"",$=typeof W?.value==="string"?W.value:"";if(!G){U.push({name:"(unnamed)",error:"missing name"});continue}let O=["cookies","set",G,$],Q=typeof W.domain==="string"?W.domain.trim():"";if(Q)O.push("--domain",Q),O.push("--url",`https://${Q.replace(/^\./,"")}/`);if(typeof W.path==="string"&&W.path)O.push("--path",W.path);if(W.httpOnly)O.push("--httpOnly");let F=sY(W.sameSite);if(W.secure||F==="None")O.push("--secure");if(F)O.push("--sameSite",F);let L=typeof W.expirationDate==="number"?W.expirationDate:typeof W.expires==="number"?W.expires:null,K=L&&L>0?Math.floor(L):Y;O.push("--expires",String(K));let J=await B(O,{timeoutMs:30000});if(J.ok)H+=1;else U.push({name:G,error:(J.error||J.stderr||J.stdout||"failed").trim().slice(0,200)})}return u(),p("cookies import",`${H}/${N.length} set`),{total:N.length,set:H,failed:U}}async function ZU(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 B(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((W,G)=>{this.pending.set(H,{method:N,resolve:W,reject:G})});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 LU(N){let U="",H=new TextDecoder;return{push(Y){U+=H.decode(Y,{stream:!0});let W;while((W=U.indexOf(`
279
+ `))!==-1){let G=U.slice(0,W).replace(/\r$/,"");if(U=U.slice(W+1),G.trim().length>0)N(G)}},flush(){let Y=U.trim();if(U="",Y.length>0)N(Y)}}}var y0=60000,b0=5,KU=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 eY();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:b(),...x0()},stdin:"pipe",stdout:"pipe",stderr:"pipe",onExit:(G,$)=>{this.lastExitCode=$,this.rpc?.failAll(`codex app-server exited (code ${$})`),this.proc=null,this.rpc=null,this.initialized=!1;let O=Date.now();if(this.exitTimes=this.exitTimes.filter((Q)=>O-Q<y0),this.exitTimes.push(O),this.exitTimes.length>=b0)this.backoffUntil=O+KU,this.exitTimes=[],console.error(`[codex] app-server crash-looping (${b0} exits in ${y0/1000}s) \u2014 backing off ${KU/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((G)=>{Y.stdin.write(G+`
280
+ `),Y.stdin.flush()},{onNotification:(G,$)=>this.handlers.onNotification(G,$),onServerRequest:(G,$,O)=>this.handlers.onServerRequest(G,$,O)});let W=this.rpc;(async()=>{let G=LU(($)=>W.handleLine($));for await(let $ of Y.stdout)G.push($);G.flush()})(),(async()=>{let G=new TextDecoder;for await(let $ of Y.stderr){let O=G.decode($).trimEnd();if(O)console.error("[codex:stderr]",O)}})()}async initializeOnce(){if(this.initialized)return;await this.requireRpc().request("initialize",{clientInfo:{name:"jun",title:"Jun",version:l},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 eY(){let N=DU.join(b(),"auth.json");try{await zU.access(N);return}catch{}let U=DU.join(rY.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 W0(){return IN}function VU(){return Y0}function MU(N){if(IN=N,N)Y0=null}function $0(){IN=null,Y0=null}function JU(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 N2={"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"},U2={"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 AU(N){return N2[N]??`codex.${N.split("/").join(".")}`}function TU(N){return U2[N]??null}function BU(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 CU={readOnly:"read-only",workspaceWrite:"workspace-write",dangerFullAccess:"danger-full-access"},EU={readOnly:{type:"readOnly"},workspaceWrite:{type:"workspaceWrite"},dangerFullAccess:{type:"dangerFullAccess"}},v0={never:"never",onRequest:"on-request",onFailure:"on-failure",untrusted:"untrusted"},G0=`# Who you are
281
281
 
282
282
  You are Jun. That's your name, use it if anyone asks. You live inside JunHost,
283
283
  your own self-hosted dashboard that runs you as a long-running local/VPS assistant, and
@@ -318,20 +318,20 @@ model powers you; you're just Jun.
318
318
  - Report outcomes honestly. If something failed, say so plainly with the actual
319
319
  error; don't dress up a partial result as done.
320
320
  - Per-workspace guidance lives in each workspace's AGENTS.md and takes
321
- precedence over this general guidance when they differ.`,HN=new Map,YN=new Map,xN=new Map,CU=new Set,fN=new Map,FN=new Map,g0="__default__";function U2(N){let U=N.error?.message;return typeof U==="string"&&U.includes("unsupported_parameter")&&U.includes("reasoning.summary")}async function RU(N,U,H){if(CU.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:H2,onServerRequest:Y2,onExit:W2});return XN}function _U(){return XN?.health??{running:!1,lastExitCode:null,crashLooping:!1,backoffMs:0}}async function C(N,U,H,Y){let W={id:nN("evt"),runId:N,ts:new Date().toISOString(),source:U,type:H,payload:Y};return await w1(W),q(`run:${N}`,W),q("runs",{type:"run.event",runId:N,eventType:H}),W}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 H2(N,U){if(N==="account/login/completed"){MU(U);return}let H=wN(U),Y=H?kN.get(H):void 0;if(Y){if(N==="item/completed"){let $=U.item;if($?.type==="agentMessage"&&typeof $.text==="string")Y.text=$.text}else if(N==="turn/completed"||N==="error")Y.done(Y.text);return}let W=H?HN.get(H):void 0;if(!W)return;(async()=>{if(await C(W,"codex",JU(N),U),N==="turn/started"){let $=U.turn?.id;if(typeof $==="string")xN.set(W,$)}else if(N==="turn/completed"){let $=U.turn?.id;if(typeof $==="string"&&FN.get(W)===$){FN.delete(W);return}FN.delete(W),xN.delete(W),fN.delete(W);let O=await T(W);if(O&&v(O.status))await I(W,"completed");if(YN.delete(W),O&&!O.title)$2(W)}else if(N==="error"){let $=U.turnId;xN.delete(W);let O=await T(W),G=fN.get(W);if(O&&G&&G.summary&&G.summary!=="none"&&U2(U)){CU.add(O.model??g0);let Q={...G,summary:"none"};console.warn(`[runs] ${O.model??"default model"} rejects reasoning.summary \u2014 retrying with summaries disabled`);try{if(typeof $==="string")FN.set(W,$);fN.set(W,Q),await P().request("turn/start",Q);return}catch(F){FN.delete(W),console.warn(`[runs] summary-less retry failed for ${W}:`,F)}}if(O&&v(O.status))await I(W,"failed")}else if(N==="thread/name/updated"){let $=U.threadName;if(typeof $==="string"&&$.trim()){let O=await UN(W,{title:$.trim()});if(O)q("runs",{type:"run.updated",run:O})}}})()}function Y2(N,U,H){let Y=AU(U),W=wN(H),$=W?HN.get(W):void 0;if(!Y||!$){if(console.warn(`[runs] auto-declining unroutable server request ${U} (id ${N})`),TU(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 T($);if(G?.approvalPolicy==="never"||G?.approvalsReviewer==="auto_review"){P().respond(N,{action:"accept"}),await C($,"daemon","approval.resolved",{requestId:N,decision:"accept",auto:!0});return}}let O=YN.get($)??[];O.push({requestId:N,method:U}),YN.set($,O),await I($,"waiting_approval"),await C($,"codex",Y,{requestId:N,method:U,params:H})})()}function W2(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(),FN.clear();for(let H of U)(async()=>{let Y=await T(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/")),W=(U??[]).filter((G)=>!G.mediaType?.startsWith("image/")),$=N;if(W.length>0)$+=`
321
+ precedence over this general guidance when they differ.`,HN=new Map,YN=new Map,xN=new Map,RU=new Set,fN=new Map,FN=new Map,g0="__default__";function H2(N){let U=N.error?.message;return typeof U==="string"&&U.includes("unsupported_parameter")&&U.includes("reasoning.summary")}async function _U(N,U,H){if(RU.has(U))H.summary="none";fN.set(N,H),await w().request("turn/start",H)}var kN=new Map,XN=null;function w(){if(!XN)XN=new q0({onNotification:Y2,onServerRequest:W2,onExit:$2});return XN}function SU(){return XN?.health??{running:!1,lastExitCode:null,crashLooping:!1,backoffMs:0}}async function E(N,U,H,Y){let W={id:nN("evt"),runId:N,ts:new Date().toISOString(),source:U,type:H,payload:Y};return await w1(W),g(`run:${N}`,W),g("runs",{type:"run.event",runId:N,eventType:H}),W}async function j(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)g("runs",{type:"run.updated",run:Y})}function Y2(N,U){if(N==="account/login/completed"){JU(U);return}let H=wN(U),Y=H?kN.get(H):void 0;if(Y){if(N==="item/completed"){let G=U.item;if(G?.type==="agentMessage"&&typeof G.text==="string")Y.text=G.text}else if(N==="turn/completed"||N==="error")Y.done(Y.text);return}let W=H?HN.get(H):void 0;if(!W)return;(async()=>{if(await E(W,"codex",AU(N),U),N==="turn/started"){let G=U.turn?.id;if(typeof G==="string")xN.set(W,G);let $=await T(W);if($&&!I($.status))await j(W,"running")}else if(N==="turn/completed"){let G=U.turn?.id;if(typeof G==="string"&&FN.get(W)===G){FN.delete(W);return}FN.delete(W),xN.delete(W),fN.delete(W);let $=await T(W);if($&&I($.status))await j(W,"completed");if(YN.delete(W),$&&!$.title)O2(W)}else if(N==="error"){if(U.willRetry===!0)return;let G=U.turnId;xN.delete(W);let $=await T(W),O=fN.get(W);if($&&O&&O.summary&&O.summary!=="none"&&H2(U)){RU.add($.model??g0);let Q={...O,summary:"none"};console.warn(`[runs] ${$.model??"default model"} rejects reasoning.summary \u2014 retrying with summaries disabled`);try{if(typeof G==="string")FN.set(W,G);fN.set(W,Q),await w().request("turn/start",Q);return}catch(F){FN.delete(W),console.warn(`[runs] summary-less retry failed for ${W}:`,F)}}if($&&I($.status))await j(W,"failed")}else if(N==="thread/name/updated"){let G=U.threadName;if(typeof G==="string"&&G.trim()){let $=await UN(W,{title:G.trim()});if($)g("runs",{type:"run.updated",run:$})}}})()}function W2(N,U,H){let Y=TU(U),W=wN(H),G=W?HN.get(W):void 0;if(!Y||!G){if(console.warn(`[runs] auto-declining unroutable server request ${U} (id ${N})`),BU(U))w().respond(N,{decision:"decline"});else w().respondError(N,-32601,"Jun cannot handle this request yet");return}(async()=>{if(U==="mcpServer/elicitation/request"){let O=await T(G);if(O?.approvalPolicy==="never"||O?.approvalsReviewer==="auto_review"){w().respond(N,{action:"accept"}),await E(G,"daemon","approval.resolved",{requestId:N,decision:"accept",auto:!0});return}}let $=YN.get(G)??[];$.push({requestId:N,method:U}),YN.set(G,$),await j(G,"waiting_approval"),await E(G,"codex",Y,{requestId:N,method:U,params:H})})()}function $2(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(),FN.clear();for(let H of U)(async()=>{let Y=await T(H);if(!Y||!I(Y.status))return;await E(H,"daemon","run.failed",{reason:`codex app-server exited (code ${N})`}),await j(H,"failed")})()}function h0(N,U,H){let Y=(U??[]).filter((O)=>O.mediaType?.startsWith("image/")),W=(U??[]).filter((O)=>!O.mediaType?.startsWith("image/")),G=N;if(W.length>0)G+=`
322
322
 
323
323
  Attached workspace files:
324
- `+W.map((G)=>`- ${G.path}`).join(`
325
- `);let O=[{type:"text",text:$}];if(H)O.push({type:"skill",name:H.name,path:H.path});for(let G of Y)O.push({type:"localImage",path:oN(G.path)});return O}function O2(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 $2(N){let U=await T(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"}),W=wN(Y);if(!W)return;let $=await new Promise((Q)=>{let F=(K)=>{clearTimeout(L),kN.delete(W),Q(K)},L=setTimeout(()=>F(null),30000);kN.set(W,{text:null,done:F}),H.request("turn/start",{threadId:W,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
+ `+W.map((O)=>`- ${O.path}`).join(`
325
+ `);let $=[{type:"text",text:G}];if(H)$.push({type:"skill",name:H.name,path:H.path});for(let O of Y)$.push({type:"localImage",path:oN(O.path)});return $}function G2(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 O2(N){let U=await T(N);if(!U||U.title||!U.codexThreadId)return;try{let H=w(),Y=await H.request("thread/start",{cwd:U.cwd,ephemeral:!0,sandbox:"read-only",approvalPolicy:"never",serviceName:"jun"}),W=wN(Y);if(!W)return;let G=await new Promise((Q)=>{let F=(K)=>{clearTimeout(L),kN.delete(W),Q(K)},L=setTimeout(()=>F(null),30000);kN.set(W,{text:null,done:F}),H.request("turn/start",{threadId:W,input:[{type:"text",text:`Reply with ONLY a short title (3-6 words, no quotes, no punctuation at the end) summarizing this conversation opener:
327
327
 
328
- `+U.prompt.slice(0,2000)}],effort:"low"}).catch(()=>F(null))}),O=O2($);if(!O)return;await H.request("thread/name/set",{threadId:U.codexThreadId,name:O});let G=await UN(N,{title:O});if(G)q("runs",{type:"run.updated",run:G})}catch(H){console.warn(`[runs] title generation failed for ${N}:`,H)}}async function E(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 S1({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 W=await Y.request("thread/start",{cwd:U,model:N.model??null,sandbox:BU[N.sandbox??"workspaceWrite"],approvalPolicy:v0[N.approvalPolicy??"onRequest"],...N.approvalsReviewer==="auto_review"?{approvalsReviewer:"auto_review"}:{},...$0?{developerInstructions:$0}:{},serviceName:"jun"}),$=wN(W)??(typeof W.threadId==="string"?W.threadId:null);if(!$)throw Error(`thread/start returned no thread id: ${JSON.stringify(W)}`);HN.set($,H.id),await UN(H.id,{codexThreadId:$}),await I(H.id,"running"),await RU(H.id,N.model??g0,{threadId:$,input:h0(N.prompt,N.attachments,N.skill),summary:"detailed",effort:N.effort??"medium",sandboxPolicy:EU[N.sandbox??"workspaceWrite"]})}catch(Y){let W=Y instanceof Error?Y.message:String(Y);await C(H.id,"daemon","run.failed",{reason:W}),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 T(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:BU[Y.sandbox]}:{},...$0?{developerInstructions:$0}:{}}),HN.set(U,N),{server:H,resumed:!0}}async function G0(N,U,H,Y){let W=await T(N);if(!W)throw Error(`Run not found: ${N}`);if(v(W.status))throw Error("Run is still active \u2014 wait for the current turn to finish");let $=W.codexThreadId;if(!$)throw Error("Run has no Codex thread to resume");let O={};if(Y?.sandbox&&Y.sandbox!==W.sandbox)O.sandbox=Y.sandbox;if(Y?.approvalPolicy&&Y.approvalPolicy!==W.approvalPolicy)O.approvalPolicy=Y.approvalPolicy;if(Y?.approvalsReviewer&&Y.approvalsReviewer!==W.approvalsReviewer)O.approvalsReviewer=Y.approvalsReviewer;if(Y?.model&&Y.model!==W.model)O.model=Y.model;if(Y?.effort&&Y.effort!==W.effort)O.effort=Y.effort;if(Object.keys(O).length>0){let G=await UN(N,O);if(G)q("runs",{type:"run.updated",run:G})}return await C(N,"daemon","run.resumed",{prompt:U,attachments:H??[],...Object.keys(O).length>0?{modeChanges:O}:{}}),await I(N,"running"),(async()=>{try{await m0(N,$);let G=O.sandbox??W.sandbox??"workspaceWrite",Q=O.approvalPolicy??W.approvalPolicy??"onRequest",F=O.approvalsReviewer??W.approvalsReviewer,L=O.model??W.model,K=(await T(N))?.serviceTier;await RU(N,L??g0,{threadId:$,input:h0(U,H),summary:"detailed",effort:O.effort??W.effort??"medium",sandboxPolicy:EU[G],approvalPolicy:v0[Q],...F==="auto_review"?{approvalsReviewer:F}:{},...L?{model:L}:{},...K?{serviceTier:K}:{}})}catch(G){let Q=G instanceof Error?G.message:String(G);await C(N,"daemon","run.failed",{reason:Q}),await I(N,"failed")}})(),await T(N)}async function SU(N,U,H){let Y=await T(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 W=Y.codexThreadId,$=xN.get(N);if(!W||!$)throw Error("No active turn to steer");await C(N,"daemon","run.steered",{prompt:U,attachments:H??[]}),await P().request("turn/steer",{threadId:W,expectedTurnId:$,input:h0(U,H)})}async function jU(N,U){let H=await T(N);if(!H)throw Error(`Run not found: ${N}`);if(U){let $=((await E("model/list",{})).data??[]).find((O)=>H.model?O.model===H.model:O.isDefault);if(!$?.serviceTiers?.some((O)=>O.id==="priority"))throw Error(`Model ${$?.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 PU(N){let U=await T(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 IU(N,U){let H=await T(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:W}=await m0(N,Y),$=U?.trim();await C(N,"daemon","run.review.started",{instructions:$??null}),await I(N,"running");try{await W.request("review/start",{threadId:Y,target:$?{type:"custom",instructions:$}:{type:"uncommittedChanges"},delivery:"inline"})}catch(O){let G=O instanceof Error?O.message:String(O);throw await C(N,"daemon","run.failed",{reason:G}),await I(N,"failed"),O}return await T(N)}async function wU(N){let U=await T(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 xU(N,U,H){let Y=YN.get(N)??[],W=Y.findIndex((O)=>String(O.requestId)===String(U));if(W===-1)return!1;let[$]=Y.splice(W,1);if(Y.length===0)YN.delete(N);if($.method==="mcpServer/elicitation/request"){let O=H==="decline"||H==="cancel"?H:"accept";P().respond($.requestId,{action:O})}else P().respond($.requestId,{decision:H});if(await C(N,"daemon","approval.resolved",{requestId:$.requestId,decision:H}),Y.length===0)await I(N,"running");return!0}function zN(){return G2.join(k(),"config.toml")}async function i(){try{return await LN.readFile(zN(),"utf8")}catch{return""}}async function kU(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 Q2(N){if(!N.trim())return{};let H=m(N).mcp_servers;if(typeof H!=="object"||H===null)return{};return H}async function F2(){let N=new Map;try{let U=await E("mcpServerStatus/list",{detail:"full"});for(let H of U.data??[]){let Y=Object.entries(H.tools??{}).map(([W,$])=>({name:W,description:$?.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 yU(){let N=await i(),U=Q2(N),H=await F2();return{servers:Object.entries(U).map(([W,$])=>{let O=H.get(W);return{name:W,command:$.command,args:$.args,envKeys:$.env?Object.keys($.env):void 0,url:$.url,enabled:$.enabled!==!1,startupState:O?.startupState??null,authStatus:O?.authStatus??null,tools:O?.tools??[],error:O?.error}})}}var X2=/^[A-Za-z0-9_-]+$/;async function bU(N){if(!X2.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??{},W={};if(N.command)W.command=N.command;if(N.args&&N.args.length>0)W.args=N.args;if(N.env&&Object.keys(N.env).length>0)W.env=N.env;if(N.url)W.url=N.url;if(N.enabled===!1)W.enabled=!1;Y[N.name]=W,H.mcp_servers=Y,await LN.writeFile(zN(),s(H),"utf8")}async function qU(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 vU(N,U){let H=await i(),Y=m(H||""),W=Y.mcp_servers??{};if(!W[N])throw new J(`Server not found: ${N}`);W[N].enabled=U,Y.mcp_servers=W,await LN.writeFile(zN(),s(Y),"utf8")}async function gU(){await E("config/mcpServer/reload",{})}async function hU(N,U,H,Y){let W=await i(),$=W.trim()?m(W):{},O=$.mcp_servers??{},G={command:process.execPath,args:[U],env:{JUN_PORT:String(H)}},Q=O[N],F=Boolean(Y&&O[Y]);if(Q&&!F&&Q.command===G.command&&JSON.stringify(Q.args)===JSON.stringify(G.args)&&Q.env?.JUN_PORT===String(H))return;if(Y)delete O[Y];O[N]=G,$.mcp_servers=O,await LN.writeFile(zN(),s($),"utf8")}var L2="https://registry.npmjs.org/junhost/latest",z2=7200000,D2=1800000,c0=null,mU=0,l0=!1,DN=null;async function cU(){try{let N=await fetch(L2,{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{mU=Date.now(),DN=null}}function p0(){let N=l0?z2:D2;if(!DN&&Date.now()-mU>N)DN=cU();return c0}async function Q0(){if(!DN)DN=cU();await DN}function u0(N,U){let H=N.split(".").map((W)=>parseInt(W,10)||0),Y=U.split(".").map((W)=>parseInt(W,10)||0);for(let W=0;W<Math.max(H.length,Y.length);W++){let $=H[W]??0,O=Y[W]??0;if($!==O)return $>O}return!1}function lU(){let N=p0();return{latestVersion:N,updateAvailable:N!==null&&u0(N,c)}}var K2=Date.now();function pU(){return Z({ok:!0})}async function uU(N){if(N?.searchParams.get("refresh")==="1")await Q0();let U={ok:!0,name:"jun",version:c,...lU(),dataRoot:f,workspaceRoot:M(),uptimeSeconds:Math.round((Date.now()-K2)/1000),engine:_U()};return Z(U)}import V2 from"path";var F0={ok:!0};async function iU(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 W=oN(Y),$=Bun.file(W);if(!await $.exists())return X(404,`File not found: ${Y}`);return new Response($,{headers:{"content-disposition":`attachment; filename="${encodeURIComponent(V2.basename(W))}"`}})}case"POST write":{let W=await z(N);return await D1(V(W.path,"path"),typeof W.content==="string"?W.content:""),Z(F0)}case"POST mkdir":{let W=await z(N);return await K1(V(W.path,"path")),Z(F0)}case"POST delete":{let W=await z(N);return await V1(V(W.path,"path")),Z(F0)}case"POST rename":{let W=await z(N);return await M1(V(W.from,"from"),V(W.to,"to")),Z(F0)}case"POST upload":{let W;try{W=await N.formData()}catch{throw new J("Expected multipart/form-data body")}let $=String(W.get("path")??"."),O=W.getAll("file").filter((Q)=>Q instanceof File);if(O.length===0)throw new J("No files in upload (field name: file)");let G=[];for(let Q of O)G.push(await J1($,Q.name,Q));return Z({ok:!0,saved:G})}default:return X(404,`Unknown files endpoint: ${N.method} /api/files/${H}`)}}var M2=new Set(["accept","acceptForSession","decline","cancel"]);async function dU(N,U,H){let Y=U.pathname.split("/").filter(Boolean),W=Y[2],$=Y[3];if(!W){if(N.method==="GET"){let O={runs:await j1()};return Z(O)}if(N.method==="POST"){let O=await z(N);V(O.prompt,"prompt");let Q={run:await ZN(O)};return Z(Q,201)}return X(405,"Method not allowed")}if($==="events"){if(!await T(W))return X(404,`Run not found: ${W}`);return H.upgrade(N,{data:{channel:`run:${W}`}})?void 0:X(400,"WebSocket upgrade required")}if(!$&&N.method==="GET"){let O=await T(W);if(!O)return X(404,`Run not found: ${W}`);let G=Number(U.searchParams.get("tail")??NaN),Q=Number(U.searchParams.get("before")??NaN),F=await x1(W,{limit:Number.isFinite(G)&&G>0?G:void 0,before:Number.isFinite(Q)&&Q>=0?Q:void 0}),L={run:O,events:F.events,eventsOffset:F.offset,totalEvents:F.total};return Z(L)}if(N.method!=="POST")return X(405,"Method not allowed");switch($){case"stop":return await wU(W)?Z({ok:!0}):X(409,"Run is not active");case"resume":{let O=await z(N);V(O.prompt,"prompt");try{let G=await G0(W,O.prompt,Array.isArray(O.attachments)?O.attachments:void 0,{sandbox:O.sandbox,approvalPolicy:O.approvalPolicy,approvalsReviewer:O.approvalsReviewer,model:O.model,effort:O.effort});return Z({run:G})}catch(G){let Q=G instanceof Error?G.message:String(G),F=Q.includes("not found")?404:Q.includes("still active")?409:400;return X(F,Q)}}case"steer":{let O=await z(N);V(O.prompt,"prompt");try{return await SU(W,O.prompt,Array.isArray(O.attachments)?O.attachments:void 0),Z({ok:!0})}catch(G){let Q=G instanceof Error?G.message:String(G),F=Q.includes("not found")?404:Q.includes("not active")||Q.includes("No active turn")?409:400;return X(F,Q)}}case"fast":{let O=await z(N);if(typeof O.enabled!=="boolean")return X(400,"Missing or invalid field: enabled");try{let G=await jU(W,O.enabled);return Z({run:G})}catch(G){let Q=G instanceof Error?G.message:String(G),F=Q.includes("not found")?404:Q.includes("does not support")?400:500;return X(F,Q)}}case"compact":try{return await PU(W),Z({ok:!0})}catch(O){let G=O instanceof Error?O.message:String(O),Q=G.includes("not found")?404:G.includes("still active")?409:400;return X(Q,G)}case"review":{let O=await z(N);try{let G=await IU(W,O.instructions);return Z({run:G})}catch(G){let Q=G instanceof Error?G.message:String(G),F=Q.includes("not found")?404:Q.includes("still active")?409:400;return X(F,Q)}}case"approve":{let O=await z(N);if(!M2.has(String(O.decision)))return X(400,`Invalid decision: ${String(O.decision)}`);if(O.requestId===void 0||O.requestId===null)return X(400,"Missing field: requestId");return await xU(W,O.requestId,O.decision)?Z({ok:!0}):X(404,"No matching pending approval")}default:return X(404,`Unknown runs endpoint: ${U.pathname}`)}}var WN="browser-stream",g=null,oU=null,KN=0,VN=null,i0=null;function J2(N){if(g&&oU===N&&g.readyState<=WebSocket.OPEN)return;g?.close(),oU=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(WN,Y)},U.onclose=()=>{if(g===U)g=null,i0=null,nU()},U.onerror=()=>{}}function nU(){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)p();U=(await PN()).streamPort}if(U!==null)J2(U);else nU()}function aU(){KN+=1,yN()}function sU(){return i0}function tU(){if(KN=Math.max(0,KN-1),KN===0){if(g?.close(),g=null,VN)clearTimeout(VN),VN=null}}var A2=new Set(["input_mouse","input_keyboard","input_touch"]);function rU(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"&&A2.has(H.type))g.send(U)}catch{}}var T2=new Set(["user","agent","paused"]);async function eU(N,U,H){let W=U.pathname.split("/").filter(Boolean)[2];if(W==="stream")return H.upgrade(N,{data:{channel:WN}})?void 0:X(400,"WebSocket upgrade required");if(N.method==="GET")switch(W){case"status":{let $=await PN();if($.streaming)yN();return Z({status:$})}case"actions":{let $={actions:d1()};return Z($)}default:return X(404,`Unknown browser endpoint: ${U.pathname}`)}if(N.method!=="POST")return X(405,"Method not allowed");switch(W){case"start":{let $=await z(N).catch(()=>({})),O=await r1(typeof $.url==="string"&&$.url.length>0?$.url:void 0);return yN(),Z({status:O})}case"stop":return await e1(),Z({ok:!0});case"navigate":{let $=await z(N);return V($.url,"url"),await NU($.url),Z({ok:!0})}case"key":{let $=await z(N);return V($.key,"key"),await HU($.key),Z({ok:!0})}case"back":case"forward":case"reload":return await UU(W),Z({ok:!0});case"screenshot":{let O={path:await YU()};return Z(O)}case"snapshot":{let $=await z(N).catch(()=>({})),O=await WU($.interactive??!0);return Z({snapshot:O})}case"click":{let $=await z(N);return V($.target,"target"),await OU($.target),Z({ok:!0})}case"fill":{let $=await z(N);return V($.target,"target"),V($.text,"text"),await $U($.target,$.text),Z({ok:!0})}case"read":{let $=await z(N).catch(()=>({})),O=await GU($.selector);return Z({text:O})}case"eval":{let $=await z(N);V($.expression,"expression");let O=await QU($.expression);return Z({result:O})}case"cookies":{let O=(await z(N)).cookies;if(typeof O==="string")try{O=JSON.parse(O)}catch{return X(400,"cookies must be a JSON array (Cookie-Editor export) or array")}if(O&&typeof O==="object"&&!Array.isArray(O)&&Array.isArray(O.cookies))O=O.cookies;if(!Array.isArray(O)||O.length===0)return X(400,"Provide a non-empty array of cookies (Cookie-Editor JSON export)");let G=await FU(O);return Z(G)}case"exec":{let $=await z(N);if(!Array.isArray($.args)||$.args.length===0)return X(400,"args must be a non-empty array of strings");let O=await XU($.args,{json:$.json});return Z(O)}case"control":{let $=await z(N);if(!T2.has(String($.controller)))return X(400,`Invalid controller: ${String($.controller)}`);return n1($.controller),Z({ok:!0})}default:return X(404,`Unknown browser endpoint: ${U.pathname}`)}}import{promises as j}from"fs";import R from"path";var HH=".agents/skills";function MN(){return R.join(M(),HH)}var B2=/^[a-z0-9][a-z0-9-]*$/,E2=new Set(["registry","install"]);function JN(N){if(!B2.test(N))throw new J(`Invalid skill id "${N}" \u2014 use lowercase letters, digits and dashes`);return R.join(MN(),N)}function NH(N){return N.replace(/\x1b\[[0-9;?]*[A-Za-z]/g,"")}async function YH(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"}),W=setTimeout(()=>Y.kill(),H);try{let[$,O,G]=await Promise.all([new Response(Y.stdout).text(),new Response(Y.stderr).text(),Y.exited]);return{stdout:NH($),stderr:NH(O),code:G}}finally{clearTimeout(W)}}function C2(N){let U=[],H=null;for(let Y of N.split(/\r?\n/)){let W=Y.trim(),$=/^(\S+@\S+)\s+([\d.]+[KMB]?)\s+installs\b/.exec(W);if($){let G=$[1],Q=G.indexOf("@");H={source:G,repo:G.slice(0,Q),name:G.slice(Q+1),installs:$[2]},U.push(H);continue}let O=/^[\u2514\u2570]\s*(https?:\/\/\S+)/.exec(W);if(O&&H)H.url=O[1],H=null}return U}function R2(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 W of H[1].split(/\r?\n/)){let $=/^([A-Za-z_][\w-]*):\s*(.*)$/.exec(W);if($)Y[$[1].toLowerCase()]=$[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 _2=15000,bN=null,X0=null;function qN(){bN=null}async function S2(){if(bN&&Date.now()-bN.at<_2)return bN.view;if(X0)return X0;let N=j2().then((U)=>{return bN={at:Date.now(),view:U},U}).finally(()=>{X0=null});return X0=N,N}async function j2(){let N=new Map,U=[];try{let H=await E("skills/list",{cwds:[M()],forceReload:!0});for(let Y of H.data??[]){for(let W of Y.errors??[])U.push(W);for(let W of Y.skills??[]){let $=R.basename(R.dirname(W.path));N.set($,W)}}}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((O)=>O.isDirectory()).map((O)=>O.name),{byDir:H,errors:Y}=await S2(),W=[];for(let O of U){let G=R.join(MN(),O,"SKILL.md"),Q=null;try{Q=await j.readFile(G,"utf8")}catch{W.push({id:O,name:O,description:"",enabled:!1,errors:["Missing SKILL.md"]});continue}let F=R2(Q),L=H.get(O),K=Y.filter((A)=>u(A.path).includes(`/${O}/`)||R.basename(R.dirname(A.path))===O).map((A)=>A.message);W.push({id:O,name:L?.name??F.name??O,description:L?.description??F.description??"",enabled:L?.enabled??!0,errors:[...new Set([...F.errors,...K])]})}let $=Y.filter((O)=>!U.some((G)=>u(O.path).includes(`/${G}/`)));return{skills:W,errors:$}}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(),W=Y.find((G)=>G.id===N)??{id:N,name:N,description:"",enabled:!0,errors:[]},$=[],O=async(G)=>{let Q=await j.readdir(R.join(U,G),{withFileTypes:!0});for(let F of Q){let L=G?`${G}/${F.name}`:F.name;if(F.isDirectory())await O(L);else if(L!=="SKILL.md")$.push(`${HH}/${N}/${L}`)}};return await O(""),{info:W,content:H,files:$}}async function WH(N){let U=N.name.trim().toLowerCase().replace(/\s+/g,"-");if(E2.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(W){if(W instanceof J)throw W}let Y=`---
328
+ `+U.prompt.slice(0,2000)}],effort:"low"}).catch(()=>F(null))}),$=G2(G);if(!$)return;await H.request("thread/name/set",{threadId:U.codexThreadId,name:$});let O=await UN(N,{title:$});if(O)g("runs",{type:"run.updated",run:O})}catch(H){console.warn(`[runs] title generation failed for ${N}:`,H)}}async function C(N,U){let H=w();return await H.start(),await H.initializeOnce(),H.request(N,U)}async function ZN(N){let U=N.cwd??M(),H=await S1({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 g("runs",{type:"run.updated",run:H}),await E(H.id,"daemon","run.started",{prompt:N.prompt,cwd:U,attachments:N.attachments??[]}),(async()=>{try{let Y=w();await Y.start(),await Y.initializeOnce();let W=await Y.request("thread/start",{cwd:U,model:N.model??null,sandbox:CU[N.sandbox??"workspaceWrite"],approvalPolicy:v0[N.approvalPolicy??"onRequest"],...N.approvalsReviewer==="auto_review"?{approvalsReviewer:"auto_review"}:{},...G0?{developerInstructions:G0}:{},serviceName:"jun"}),G=wN(W)??(typeof W.threadId==="string"?W.threadId:null);if(!G)throw Error(`thread/start returned no thread id: ${JSON.stringify(W)}`);HN.set(G,H.id),await UN(H.id,{codexThreadId:G}),await j(H.id,"running"),await _U(H.id,N.model??g0,{threadId:G,input:h0(N.prompt,N.attachments,N.skill),summary:"detailed",effort:N.effort??"medium",sandboxPolicy:EU[N.sandbox??"workspaceWrite"]})}catch(Y){let W=Y instanceof Error?Y.message:String(Y);await E(H.id,"daemon","run.failed",{reason:W}),await j(H.id,"failed")}})(),H}async function m0(N,U){let H=w();if(await H.start(),await H.initializeOnce(),HN.has(U))return{server:H,resumed:!1};let Y=await T(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:CU[Y.sandbox]}:{},...G0?{developerInstructions:G0}:{}}),HN.set(U,N),{server:H,resumed:!0}}async function O0(N,U,H,Y){let W=await T(N);if(!W)throw Error(`Run not found: ${N}`);if(I(W.status))throw Error("Run is still active \u2014 wait for the current turn to finish");let G=W.codexThreadId;if(!G)throw Error("Run has no Codex thread to resume");let $={};if(Y?.sandbox&&Y.sandbox!==W.sandbox)$.sandbox=Y.sandbox;if(Y?.approvalPolicy&&Y.approvalPolicy!==W.approvalPolicy)$.approvalPolicy=Y.approvalPolicy;if(Y?.approvalsReviewer&&Y.approvalsReviewer!==W.approvalsReviewer)$.approvalsReviewer=Y.approvalsReviewer;if(Y?.model&&Y.model!==W.model)$.model=Y.model;if(Y?.effort&&Y.effort!==W.effort)$.effort=Y.effort;if(Object.keys($).length>0){let O=await UN(N,$);if(O)g("runs",{type:"run.updated",run:O})}return await E(N,"daemon","run.resumed",{prompt:U,attachments:H??[],...Object.keys($).length>0?{modeChanges:$}:{}}),await j(N,"running"),(async()=>{try{await m0(N,G);let O=$.sandbox??W.sandbox??"workspaceWrite",Q=$.approvalPolicy??W.approvalPolicy??"onRequest",F=$.approvalsReviewer??W.approvalsReviewer,L=$.model??W.model,K=(await T(N))?.serviceTier;await _U(N,L??g0,{threadId:G,input:h0(U,H),summary:"detailed",effort:$.effort??W.effort??"medium",sandboxPolicy:EU[O],approvalPolicy:v0[Q],...F==="auto_review"?{approvalsReviewer:F}:{},...L?{model:L}:{},...K?{serviceTier:K}:{}})}catch(O){let Q=O instanceof Error?O.message:String(O);await E(N,"daemon","run.failed",{reason:Q}),await j(N,"failed")}})(),await T(N)}async function jU(N,U,H){let Y=await T(N);if(!Y)throw Error(`Run not found: ${N}`);if(!I(Y.status))throw Error("Run is not active \u2014 send a follow-up message instead");let W=Y.codexThreadId,G=xN.get(N);if(!W||!G)throw Error("No active turn to steer");await E(N,"daemon","run.steered",{prompt:U,attachments:H??[]}),await w().request("turn/steer",{threadId:W,expectedTurnId:G,input:h0(U,H)})}async function PU(N,U){let H=await T(N);if(!H)throw Error(`Run not found: ${N}`);if(U){let G=((await C("model/list",{})).data??[]).find(($)=>H.model?$.model===H.model:$.isDefault);if(!G?.serviceTiers?.some(($)=>$.id==="priority"))throw Error(`Model ${G?.model??H.model??"unknown"} does not support fast mode`)}let Y=await UN(N,{serviceTier:U?"priority":"standard"});if(Y)g("runs",{type:"run.updated",run:Y});return await E(N,"daemon","run.fast",{enabled:U}),Y}async function IU(N){let U=await T(N);if(!U)throw Error(`Run not found: ${N}`);if(I(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 E(N,"daemon","run.compact.started",{}),await Y.request("thread/compact/start",{threadId:H})}async function wU(N,U){let H=await T(N);if(!H)throw Error(`Run not found: ${N}`);if(I(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 m0(N,Y),G=U?.trim();await E(N,"daemon","run.review.started",{instructions:G??null}),await j(N,"running");try{await W.request("review/start",{threadId:Y,target:G?{type:"custom",instructions:G}:{type:"uncommittedChanges"},delivery:"inline"})}catch($){let O=$ instanceof Error?$.message:String($);throw await E(N,"daemon","run.failed",{reason:O}),await j(N,"failed"),$}return await T(N)}async function xU(N){let U=await T(N);if(!U||!I(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 E(N,"daemon","run.stopped",{}),await j(N,"stopped"),!0}async function fU(N,U,H){let Y=YN.get(N)??[],W=Y.findIndex(($)=>String($.requestId)===String(U));if(W===-1)return!1;let[G]=Y.splice(W,1);if(Y.length===0)YN.delete(N);if(G.method==="mcpServer/elicitation/request"){let $=H==="decline"||H==="cancel"?H:"accept";w().respond(G.requestId,{action:$})}else w().respond(G.requestId,{decision:H});if(await E(N,"daemon","approval.resolved",{requestId:G.requestId,decision:H}),Y.length===0)await j(N,"running");return!0}function zN(){return Q2.join(b(),"config.toml")}async function d(){try{return await LN.readFile(zN(),"utf8")}catch{return""}}async function yU(N){try{c(N)}catch(U){throw new A(`Invalid TOML: ${U instanceof Error?U.message:String(U)}`)}await LN.writeFile(zN(),N,"utf8")}function F2(N){if(!N.trim())return{};let H=c(N).mcp_servers;if(typeof H!=="object"||H===null)return{};return H}async function X2(){let N=new Map;try{let U=await C("mcpServerStatus/list",{detail:"full"});for(let H of U.data??[]){let Y=Object.entries(H.tools??{}).map(([W,G])=>({name:W,description:G?.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 bU(){let N=await d(),U=F2(N),H=await X2();return{servers:Object.entries(U).map(([W,G])=>{let $=H.get(W);return{name:W,command:G.command,args:G.args,envKeys:G.env?Object.keys(G.env):void 0,url:G.url,enabled:G.enabled!==!1,startupState:$?.startupState??null,authStatus:$?.authStatus??null,tools:$?.tools??[],error:$?.error}})}}var Z2=/^[A-Za-z0-9_-]+$/;async function qU(N){if(!Z2.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 U=await d(),H=U.trim()?c(U):{},Y=H.mcp_servers??{},W={};if(N.command)W.command=N.command;if(N.args&&N.args.length>0)W.args=N.args;if(N.env&&Object.keys(N.env).length>0)W.env=N.env;if(N.url)W.url=N.url;if(N.enabled===!1)W.enabled=!1;Y[N.name]=W,H.mcp_servers=Y,await LN.writeFile(zN(),t(H),"utf8")}async function vU(N){let U=await d();if(!U.trim())return!1;let H=c(U),Y=H.mcp_servers;if(!Y||!(N in Y))return!1;return delete Y[N],await LN.writeFile(zN(),t(H),"utf8"),!0}async function gU(N,U){let H=await d(),Y=c(H||""),W=Y.mcp_servers??{};if(!W[N])throw new A(`Server not found: ${N}`);W[N].enabled=U,Y.mcp_servers=W,await LN.writeFile(zN(),t(Y),"utf8")}async function hU(){await C("config/mcpServer/reload",{})}async function mU(N,U,H,Y){let W=await d(),G=W.trim()?c(W):{},$=G.mcp_servers??{},O={command:process.execPath,args:[U],env:{JUN_PORT:String(H)}},Q=$[N],F=Boolean(Y&&$[Y]);if(Q&&!F&&Q.command===O.command&&JSON.stringify(Q.args)===JSON.stringify(O.args)&&Q.env?.JUN_PORT===String(H))return;if(Y)delete $[Y];$[N]=O,G.mcp_servers=$,await LN.writeFile(zN(),t(G),"utf8")}var z2="https://registry.npmjs.org/junhost/latest",D2=7200000,K2=1800000,c0=null,cU=0,l0=!1,DN=null;async function lU(){try{let N=await fetch(z2,{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{cU=Date.now(),DN=null}}function p0(){let N=l0?D2:K2;if(!DN&&Date.now()-cU>N)DN=lU();return c0}async function Q0(){if(!DN)DN=lU();await DN}function u0(N,U){let H=N.split(".").map((W)=>parseInt(W,10)||0),Y=U.split(".").map((W)=>parseInt(W,10)||0);for(let W=0;W<Math.max(H.length,Y.length);W++){let G=H[W]??0,$=Y[W]??0;if(G!==$)return G>$}return!1}function pU(){let N=p0();return{latestVersion:N,updateAvailable:N!==null&&u0(N,l)}}var V2=Date.now();function uU(){return Z({ok:!0})}async function iU(N){if(N?.searchParams.get("refresh")==="1")await Q0();let U={ok:!0,name:"jun",version:l,...pU(),dataRoot:y,workspaceRoot:M(),uptimeSeconds:Math.round((Date.now()-V2)/1000),engine:SU()};return Z(U)}import M2 from"path";var F0={ok:!0};async function dU(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 W=oN(Y),G=Bun.file(W);if(!await G.exists())return X(404,`File not found: ${Y}`);return new Response(G,{headers:{"content-disposition":`attachment; filename="${encodeURIComponent(M2.basename(W))}"`}})}case"POST write":{let W=await z(N);return await D1(V(W.path,"path"),typeof W.content==="string"?W.content:""),Z(F0)}case"POST mkdir":{let W=await z(N);return await K1(V(W.path,"path")),Z(F0)}case"POST delete":{let W=await z(N);return await V1(V(W.path,"path")),Z(F0)}case"POST rename":{let W=await z(N);return await M1(V(W.from,"from"),V(W.to,"to")),Z(F0)}case"POST upload":{let W;try{W=await N.formData()}catch{throw new A("Expected multipart/form-data body")}let G=String(W.get("path")??"."),$=W.getAll("file").filter((Q)=>Q instanceof File);if($.length===0)throw new A("No files in upload (field name: file)");let O=[];for(let Q of $)O.push(await J1(G,Q.name,Q));return Z({ok:!0,saved:O})}default:return X(404,`Unknown files endpoint: ${N.method} /api/files/${H}`)}}var J2=new Set(["accept","acceptForSession","decline","cancel"]);async function oU(N,U,H){let Y=U.pathname.split("/").filter(Boolean),W=Y[2],G=Y[3];if(!W){if(N.method==="GET"){let $={runs:await j1()};return Z($)}if(N.method==="POST"){let $=await z(N);V($.prompt,"prompt");let Q={run:await ZN($)};return Z(Q,201)}return X(405,"Method not allowed")}if(W==="events"&&!G)return H.upgrade(N,{data:{channel:"runs"}})?void 0:X(400,"WebSocket upgrade required");if(G==="events"){if(!await T(W))return X(404,`Run not found: ${W}`);return H.upgrade(N,{data:{channel:`run:${W}`}})?void 0:X(400,"WebSocket upgrade required")}if(!G&&N.method==="GET"){let $=await T(W);if(!$)return X(404,`Run not found: ${W}`);let O=Number(U.searchParams.get("tail")??NaN),Q=Number(U.searchParams.get("before")??NaN),F=await x1(W,{limit:Number.isFinite(O)&&O>0?O:void 0,before:Number.isFinite(Q)&&Q>=0?Q:void 0}),L={run:$,events:F.events,eventsOffset:F.offset,totalEvents:F.total};return Z(L)}if(N.method!=="POST")return X(405,"Method not allowed");switch(G){case"stop":return await xU(W)?Z({ok:!0}):X(409,"Run is not active");case"resume":{let $=await z(N);V($.prompt,"prompt");try{let O=await O0(W,$.prompt,Array.isArray($.attachments)?$.attachments:void 0,{sandbox:$.sandbox,approvalPolicy:$.approvalPolicy,approvalsReviewer:$.approvalsReviewer,model:$.model,effort:$.effort});return Z({run:O})}catch(O){let Q=O instanceof Error?O.message:String(O),F=Q.includes("not found")?404:Q.includes("still active")?409:400;return X(F,Q)}}case"steer":{let $=await z(N);V($.prompt,"prompt");try{return await jU(W,$.prompt,Array.isArray($.attachments)?$.attachments:void 0),Z({ok:!0})}catch(O){let Q=O instanceof Error?O.message:String(O),F=Q.includes("not found")?404:Q.includes("not active")||Q.includes("No active turn")?409:400;return X(F,Q)}}case"fast":{let $=await z(N);if(typeof $.enabled!=="boolean")return X(400,"Missing or invalid field: enabled");try{let O=await PU(W,$.enabled);return Z({run:O})}catch(O){let Q=O instanceof Error?O.message:String(O),F=Q.includes("not found")?404:Q.includes("does not support")?400:500;return X(F,Q)}}case"compact":try{return await IU(W),Z({ok:!0})}catch($){let O=$ instanceof Error?$.message:String($),Q=O.includes("not found")?404:O.includes("still active")?409:400;return X(Q,O)}case"review":{let $=await z(N);try{let O=await wU(W,$.instructions);return Z({run:O})}catch(O){let Q=O instanceof Error?O.message:String(O),F=Q.includes("not found")?404:Q.includes("still active")?409:400;return X(F,Q)}}case"approve":{let $=await z(N);if(!J2.has(String($.decision)))return X(400,`Invalid decision: ${String($.decision)}`);if($.requestId===void 0||$.requestId===null)return X(400,"Missing field: requestId");return await fU(W,$.requestId,$.decision)?Z({ok:!0}):X(404,"No matching pending approval")}default:return X(404,`Unknown runs endpoint: ${U.pathname}`)}}var WN="browser-stream",h=null,nU=null,KN=0,VN=null,i0=null;function A2(N){if(h&&nU===N&&h.readyState<=WebSocket.OPEN)return;h?.close(),nU=N;let U=new WebSocket(`ws://127.0.0.1:${N}`);h=U,U.onmessage=(H)=>{let Y=String(H.data);if(Y.includes('"type":"frame"'))i0=Y;B1(WN,Y)},U.onclose=()=>{if(h===U)h=null,i0=null,aU()},U.onerror=()=>{}}function aU(){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)A2(U);else aU()}function sU(){KN+=1,yN()}function tU(){return i0}function rU(){if(KN=Math.max(0,KN-1),KN===0){if(h?.close(),h=null,VN)clearTimeout(VN),VN=null}}var T2=new Set(["input_mouse","input_keyboard","input_touch"]);function eU(N){if(o1()!=="user")return;if(!h||h.readyState!==WebSocket.OPEN)return;let U=typeof N==="string"?N:N.toString("utf8");try{let H=JSON.parse(U);if(typeof H.type==="string"&&T2.has(H.type))h.send(U)}catch{}}var B2=new Set(["user","agent","paused"]);async function NH(N,U,H){let W=U.pathname.split("/").filter(Boolean)[2];if(W==="stream")return H.upgrade(N,{data:{channel:WN}})?void 0:X(400,"WebSocket upgrade required");if(N.method==="GET")switch(W){case"status":{let G=await PN();if(G.streaming)yN();return Z({status:G})}case"actions":{let G={actions:d1()};return Z(G)}default:return X(404,`Unknown browser endpoint: ${U.pathname}`)}if(N.method!=="POST")return X(405,"Method not allowed");switch(W){case"start":{let G=await z(N).catch(()=>({})),$=await r1(typeof G.url==="string"&&G.url.length>0?G.url:void 0);return yN(),Z({status:$})}case"stop":return await e1(),Z({ok:!0});case"navigate":{let G=await z(N);return V(G.url,"url"),await NU(G.url),Z({ok:!0})}case"key":{let G=await z(N);return V(G.key,"key"),await HU(G.key),Z({ok:!0})}case"back":case"forward":case"reload":return await UU(W),Z({ok:!0});case"screenshot":{let $={path:await YU()};return Z($)}case"snapshot":{let G=await z(N).catch(()=>({})),$=await WU(G.interactive??!0);return Z({snapshot:$})}case"click":{let G=await z(N);return V(G.target,"target"),await $U(G.target),Z({ok:!0})}case"fill":{let G=await z(N);return V(G.target,"target"),V(G.text,"text"),await GU(G.target,G.text),Z({ok:!0})}case"read":{let G=await z(N).catch(()=>({})),$=await OU(G.selector);return Z({text:$})}case"eval":{let G=await z(N);V(G.expression,"expression");let $=await QU(G.expression);return Z({result:$})}case"cookies":{let $=(await z(N)).cookies;if(typeof $==="string"){let Q=$.trim();try{$=JSON.parse(Q)}catch{let F=FU(Q);if(F.length===0)return X(400,"cookies must be a JSON array (Cookie-Editor export) or Netscape cookies.txt");$=F}}if($&&typeof $==="object"&&!Array.isArray($)&&Array.isArray($.cookies))$=$.cookies;if(!Array.isArray($)||$.length===0)return X(400,"Provide a non-empty array of cookies (Cookie-Editor JSON export)");let O=await XU($);return Z(O)}case"exec":{let G=await z(N);if(!Array.isArray(G.args)||G.args.length===0)return X(400,"args must be a non-empty array of strings");let $=await ZU(G.args,{json:G.json});return Z($)}case"control":{let G=await z(N);if(!B2.has(String(G.controller)))return X(400,`Invalid controller: ${String(G.controller)}`);return n1(G.controller),Z({ok:!0})}default:return X(404,`Unknown browser endpoint: ${U.pathname}`)}}import{promises as P}from"fs";import R from"path";var YH=".agents/skills";function MN(){return R.join(M(),YH)}var C2=/^[a-z0-9][a-z0-9-]*$/,E2=new Set(["registry","install"]);function JN(N){if(!C2.test(N))throw new A(`Invalid skill id "${N}" \u2014 use lowercase letters, digits and dashes`);return R.join(MN(),N)}function UH(N){return N.replace(/\x1b\[[0-9;?]*[A-Za-z]/g,"")}async function WH(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"}),W=setTimeout(()=>Y.kill(),H);try{let[G,$,O]=await Promise.all([new Response(Y.stdout).text(),new Response(Y.stderr).text(),Y.exited]);return{stdout:UH(G),stderr:UH($),code:O}}finally{clearTimeout(W)}}function R2(N){let U=[],H=null;for(let Y of N.split(/\r?\n/)){let W=Y.trim(),G=/^(\S+@\S+)\s+([\d.]+[KMB]?)\s+installs\b/.exec(W);if(G){let O=G[1],Q=O.indexOf("@");H={source:O,repo:O.slice(0,Q),name:O.slice(Q+1),installs:G[2]},U.push(H);continue}let $=/^[\u2514\u2570]\s*(https?:\/\/\S+)/.exec(W);if($&&H)H.url=$[1],H=null}return U}function _2(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 W of H[1].split(/\r?\n/)){let G=/^([A-Za-z_][\w-]*):\s*(.*)$/.exec(W);if(G)Y[G[1].toLowerCase()]=G[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 S2=15000,bN=null,X0=null;function qN(){bN=null}async function j2(){if(bN&&Date.now()-bN.at<S2)return bN.view;if(X0)return X0;let N=P2().then((U)=>{return bN={at:Date.now(),view:U},U}).finally(()=>{X0=null});return X0=N,N}async function P2(){let N=new Map,U=[];try{let H=await C("skills/list",{cwds:[M()],forceReload:!0});for(let Y of H.data??[]){for(let W of Y.errors??[])U.push(W);for(let W of Y.skills??[]){let G=R.basename(R.dirname(W.path));N.set(G,W)}}}catch(H){console.warn("[skills] skills/list failed:",H)}return{byDir:N,errors:U}}async function Z0(){await P.mkdir(MN(),{recursive:!0});let U=(await P.readdir(MN(),{withFileTypes:!0})).filter(($)=>$.isDirectory()).map(($)=>$.name),{byDir:H,errors:Y}=await j2(),W=[];for(let $ of U){let O=R.join(MN(),$,"SKILL.md"),Q=null;try{Q=await P.readFile(O,"utf8")}catch{W.push({id:$,name:$,description:"",enabled:!1,errors:["Missing SKILL.md"]});continue}let F=_2(Q),L=H.get($),K=Y.filter((J)=>i(J.path).includes(`/${$}/`)||R.basename(R.dirname(J.path))===$).map((J)=>J.message);W.push({id:$,name:L?.name??F.name??$,description:L?.description??F.description??"",enabled:L?.enabled??!0,errors:[...new Set([...F.errors,...K])]})}let G=Y.filter(($)=>!U.some((O)=>i($.path).includes(`/${O}/`)));return{skills:W,errors:G}}async function vN(N){let U=JN(N),H;try{H=await P.readFile(R.join(U,"SKILL.md"),"utf8")}catch{return null}let{skills:Y}=await Z0(),W=Y.find((O)=>O.id===N)??{id:N,name:N,description:"",enabled:!0,errors:[]},G=[],$=async(O)=>{let Q=await P.readdir(R.join(U,O),{withFileTypes:!0});for(let F of Q){let L=O?`${O}/${F.name}`:F.name;if(F.isDirectory())await $(L);else if(L!=="SKILL.md")G.push(`${YH}/${N}/${L}`)}};return await $(""),{info:W,content:H,files:G}}async function $H(N){let U=N.name.trim().toLowerCase().replace(/\s+/g,"-");if(E2.has(U))throw new A(`"${U}" is a reserved name \u2014 pick another`);let H=JN(U);try{throw await P.access(R.join(H,"SKILL.md")),new A(`Skill "${U}" already exists`)}catch(W){if(W instanceof A)throw W}let Y=`---
329
329
  name: ${U}
330
330
  description: ${N.description.trim()}
331
331
  ---
332
332
 
333
333
  ${N.instructions?.trim()??"Describe when and how to use this skill."}
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 $H(N){let U=JN(N);try{return await j.rm(U,{recursive:!0,force:!1}),qN(),!0}catch{return!1}}async function GH(N,U){let H=R.join(JN(N),"SKILL.md");await E("skills/config/write",{path:H,enabled:U,name:null}),qN()}async function QH(N){let U=N.trim();if(!U)return[];let{stdout:H}=await YH(["find",U],M(),30000);return C2(H)}async function UH(){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 UH(),{stdout:W,stderr:$}=await YH(["add",U,"-a","codex","--copy","-y"],H);qN();let G=[...await UH()].filter((F)=>!Y.has(F));if(G.length===0){let F=[W,$].filter(Boolean).join(`
335
- `).trim();throw new J(`No skill installed from "${U}".${F?`
336
- ${F}`:""}`)}let{skills:Q}=await Z0();return{installed:G,skills:Q,log:[W,$].filter(Boolean).join(`
337
- `).trim()}}async function XH(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 ZH(N,U){let H=U.pathname.split("/").filter(Boolean),Y=H[2],W=H[3];if(Y==="registry"){if(W==="search"&&N.method==="GET"){let $=U.searchParams.get("q")??"",O=await QH($);return Z({results:O})}if(W==="install"&&N.method==="POST"){let $=await z(N);V($.source,"source");let O=await FH($.source);return Z(O,201)}return X(404,`Unknown skills endpoint: ${U.pathname}`)}if(!Y){if(N.method==="GET")return Z(await Z0());if(N.method==="POST"){let $=await z(N);V($.name,"name"),V($.description,"description");let O=await WH($);return Z({skill:O},201)}return X(405,"Method not allowed")}if(!W)switch(N.method){case"GET":{let $=await vN(Y);return $?Z({skill:$}):X(404,`Skill not found: ${Y}`)}case"PUT":{let $=await z(N);V($.content,"content");let O=await OH(Y,$.content);return Z({skill:O})}case"DELETE":return await $H(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(W){case"enable":{let $=await z(N);if(typeof $.enabled!=="boolean")return X(400,"Missing or invalid field: enabled");return await GH(Y,$.enabled),Z({ok:!0})}case"test":{let $=await z(N).catch(()=>({})),O=await XH(Y,$.prompt);return Z({run:O},201)}default:return X(404,`Unknown skills endpoint: ${U.pathname}`)}}async function LH(N,U){let H=U.pathname.split("/").filter(Boolean),Y=H[2];if(!Y){if(N.method==="GET")return Z(await yU());return X(405,"Method not allowed")}if(Y==="config"){if(N.method==="GET"){let W={toml:await i()};return Z(W)}if(N.method==="PUT"){let W=await z(N);return V(W.toml,"toml"),await kU(W.toml),Z({ok:!0})}return X(405,"Method not allowed")}if(Y==="reload"&&N.method==="POST")return await gU(),Z({ok:!0});if(Y==="servers"){let W=H[3];if(!W){if(N.method==="POST"){let O=await z(N);return V(O.name,"name"),await bU(O),Z({ok:!0},201)}return X(405,"Method not allowed")}let $=H[4];if($==="enable"&&N.method==="POST"){let O=await z(N);if(typeof O.enabled!=="boolean")return X(400,"Missing or invalid field: enabled");return await vU(W,O.enabled),Z({ok:!0})}if(!$&&N.method==="DELETE")return await qU(W)?Z({ok:!0}):X(404,`Server not found: ${W}`);return X(405,"Method not allowed")}return X(404,`Unknown MCP endpoint: ${U.pathname}`)}import{promises as ON}from"fs";import gN from"path";function I2(){return gN.join(k(),"config.toml")}function z0(){return gN.join(k(),"memories")}async function zH(){let N=await i();return N.trim()?m(N):{}}function L0(N){return typeof N==="object"&&N!==null?N:{}}function w2(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 x2(){let N=z0(),U=[];async function H(Y){let W;try{W=await ON.readdir(Y,{withFileTypes:!0})}catch{return}for(let $ of W){let O=gN.join(Y,$.name);if($.isDirectory()){if($.name===".git")continue;await H(O)}else if($.isFile()){let G=await ON.stat(O);U.push({path:u(gN.relative(N,O)),name:$.name,size:G.size,modifiedAt:G.mtime.toISOString()})}}}return await H(N),U.sort((Y,W)=>W.modifiedAt.localeCompare(Y.modifiedAt)),U}async function f2(){try{let U=((await E("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 DH(){let N=await zH();return{enabled:L0(N.features).memories===!0,liveEnabled:await f2(),settings:w2(N),files:await x2()}}async function KH(N){let U=await zH();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 ON.writeFile(I2(),s(U),"utf8"),typeof N.enabled==="boolean")try{await E("experimentalFeature/enablement/set",{enablement:{memories:N.enabled}})}catch(H){console.warn("[memories] live enablement/set failed (applies on restart):",H)}}async function VH(N){let U=NN(z0(),N);return ON.readFile(U,"utf8")}async function MH(N,U){let H=NN(z0(),N);await ON.mkdir(gN.dirname(H),{recursive:!0}),await ON.writeFile(H,U,"utf8")}async function JH(N){let U=NN(z0(),N);await ON.rm(U)}async function AH(N,U){let Y=U.pathname.split("/").filter(Boolean)[2];if(!Y){if(N.method==="GET")return Z(await DH());return X(405,"Method not allowed")}if(Y==="config"){if(N.method==="PUT"){let W=await z(N);if(typeof W.enabled!=="boolean"&&!W.settings)return X(400,"Nothing to update: pass enabled and/or settings");return await KH(W),Z({ok:!0})}return X(405,"Method not allowed")}if(Y==="file"){if(N.method==="GET"){let W=V(U.searchParams.get("path"),"path"),$={path:W,content:await VH(W)};return Z($)}if(N.method==="PUT"){let W=await z(N);if(V(W.path,"path"),typeof W.content!=="string")return X(400,"Missing or invalid field: content");return await MH(W.path,W.content),Z({ok:!0})}if(N.method==="DELETE"){let W=V(U.searchParams.get("path"),"path");return await JH(W),Z({ok:!0})}return X(405,"Method not allowed")}return X(404,`Unknown memories endpoint: ${U.pathname}`)}var y2=300000,D0=null;async function TH(N){if(N.method!=="GET")return X(405,"Method not allowed");if(D0&&Date.now()-D0.at<y2)return Z({models:D0.models});let H=((await E("model/list",{})).data??[]).filter((W)=>!W.hidden).map((W)=>({id:W.id,model:W.model,displayName:W.displayName,description:W.description,isDefault:W.isDefault,defaultReasoningEffort:W.defaultReasoningEffort,supportedReasoningEfforts:W.supportedReasoningEfforts??[]}));return D0={at:Date.now(),models:H},Z({models:H})}async function K0(){let N=await E("account/read",{});return{account:N.account??null,requiresOpenaiAuth:N.requiresOpenaiAuth,pendingLogin:W0(),lastLoginResult:KU()}}async function BH(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:V(H.apiKey,"apiKey")};else throw new J("type must be one of: chatgpt, chatgptDeviceCode, apiKey");let W=W0();if(W)await E("account/login/cancel",{loginId:W.loginId}).catch(()=>{});O0();let $=await E("account/login/start",Y);if(($.type==="chatgpt"||$.type==="chatgptDeviceCode")&&$.loginId){let O={loginId:$.loginId,type:$.type,authUrl:$.authUrl,userCode:$.userCode,verificationUrl:$.verificationUrl,startedAt:new Date().toISOString()};VU(O)}return Z(await K0())}if(U.pathname==="/api/account/login/cancel"&&N.method==="POST"){let H=W0();if(H)await E("account/login/cancel",{loginId:H.loginId}).catch(()=>{});return O0(),Z(await K0())}if(U.pathname==="/api/account/logout"&&N.method==="POST")return await E("account/logout",{}),O0(),Z(await K0());return X(404,`Not found: ${U.pathname}`)}function b2(N){if(!N)return null;return N.replace(/^([a-z0-9+.-]+:\/\/[^:@/]+):[^@/]+@/i,"$1:\u2022\u2022\u2022\u2022@")}function EH(){let N=U0(),U=H0();return{browserProxy:{proxyUrl:b2(N.value),source:N.source,noProxy:U.value,noProxySource:U.source}}}async function CH(N,U){if(U.pathname==="/api/settings"&&N.method==="GET")return Z(EH());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(EH())}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 wH from"path";import{randomUUID as l2}from"crypto";function hN(N,U,H,Y){let W=new Set,$=N.trim()!=="*";for(let O of N.split(",")){let G=O.trim();if(!G)throw Error(`Invalid ${Y} field: empty term`);let Q=G,F=1,L=G.indexOf("/");if(L!==-1){if(Q=G.slice(0,L),F=Number(G.slice(L+1)),!Number.isInteger(F)||F<=0)throw Error(`Invalid step in ${Y}: ${G}`)}let K,A;if(Q==="*")K=U,A=H;else if(Q.includes("-")){let[e,$N]=Q.split("-");K=Number(e),A=Number($N)}else K=Number(Q),A=K;if(!Number.isInteger(K)||!Number.isInteger(A))throw Error(`Invalid ${Y} value: ${G}`);if(K<U||A>H||K>A)throw Error(`${Y} out of range (${U}-${H}): ${G}`);for(let e=K;e<=A;e+=F)W.add(e)}return{set:W,restricted:$}}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"),W=hN(U[2],1,31,"day-of-month"),$=hN(U[3],1,12,"month"),O=hN(U[4],0,7,"day-of-week"),G=new Set;for(let Q of O.set)G.add(Q===7?0:Q);return{minute:H.set,hour:Y.set,dom:W.set,month:$.set,dow:G,domRestricted:W.restricted,dowRestricted:O.restricted}}function jH(N){try{return SH(N),null}catch(U){return U instanceof Error?U.message:"Invalid cron expression"}}function q2(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 PH(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 q2(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 v2(N,U){return new Date(Date.UTC(N,U,0)).getUTCDate()}function g2(N){return new Date(Date.UTC(N.year,N.month-1,N.day)).getUTCDay()}function RH(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<=v2(N.year,N.month))return;if(N.day=1,N.month++,N.month<=12)return;N.month=1,N.year++}function h2(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(g2(U));if(N.domRestricted&&N.dowRestricted)return H||Y;if(N.domRestricted)return H;if(N.dowRestricted)return Y;return!0}function _H(N,U){let H=PH(N,U);return Date.UTC(H.year,H.month-1,H.day,H.hour,H.minute,H.second)-N.getTime()}function m2(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=_H(new Date(H),U),W=H-Y,$=_H(new Date(W),U);if($!==Y)W=H-$;return new Date(W)}var c2=4216320;function IH(N,U,H){let Y=SH(N),W=PH(U,H),$={year:W.year,month:W.month,day:W.day,hour:W.hour,minute:W.minute};RH($);for(let O=0;O<c2;O++){if(h2(Y,$))return m2($,H);RH($)}return null}var p2={sandbox:"workspaceWrite",approvalPolicy:"onRequest",approvalsReviewer:"auto_review",effort:"medium"};function u2(N){return N.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40)}function o0(N){return wH.join(TN(),`${N}.json`)}async function xH(){await AN.mkdir(TN(),{recursive:!0})}async function n0(N){await xH(),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=IH(N.cron,U,N.tz);return H?H.toISOString():null}function fH(N,U){if(U==="cron"){if(!N.cron)throw Error("cron expression is required for a cron schedule");let H=jH(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 xH();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(wH.join(TN(),H),"utf8"),W=JSON.parse(Y);U.push(W)}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 kH(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";fH(N,H);let Y=`${u2(U)||"schedule"}-${l2().slice(0,8)}`,W=new Date,$={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:{...p2,...N.mode??{}},resume:N.resume??!1,threadRunId:null,enabled:N.enabled??!0,createdAt:W.toISOString(),lastRunAt:null,lastRunId:null,lastError:null,nextRunAt:null};return $.nextRunAt=a0($,W),await n0($),$}async function yH(N,U){let H=await V0(N);if(!H)return null;let Y=U.kind??H.kind,W={...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(fH(W,Y),Y==="once"&&U.runAt&&W.runAt!==H.runAt)W.lastRunAt=null;return W.nextRunAt=a0(W,new Date),await n0(W),W}async function bH(N){try{return await AN.unlink(o0(N)),!0}catch{return!1}}function i2(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,W=N.threadRunId??null;try{let O=N.mode;if(N.resume&&W&&await T(W)){let G=await T(W);if(G&&v(G.status))throw Error("previous run still active \u2014 skipped this fire");H=(await G0(W,N.prompt,[],i2(O))).id}else{let G=await ZN({prompt:N.prompt,sandbox:O.sandbox,approvalPolicy:O.approvalPolicy,approvalsReviewer:O.approvalsReviewer,model:O.model,effort:O.effort,source:"schedule",scheduleId:N.id,scheduleName:N.name});if(H=G.id,N.resume)W=G.id}}catch(O){Y=O instanceof Error?O.message:String(O)}let $={...N,lastRunAt:U.toISOString(),lastRunId:H,lastError:Y,threadRunId:W};return $.nextRunAt=a0($,U),await n0($),$}var d0=!1;async function qH(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(W){console.error(`[schedules] fire failed for ${H.id}:`,W)}}}catch(U){console.error("[schedules] tick failed:",U)}finally{d0=!1}}async function vH(N,U){let H=U.pathname.split("/").filter(Boolean),Y=H[2],W=H[3];if(!Y){if(N.method==="GET"){let $={schedules:await s0()};return Z($)}if(N.method==="POST"){let $=await z(N);try{let G={schedule:await kH($)};return Z(G,201)}catch(O){return X(400,O instanceof Error?O.message:String(O))}}return X(405,"Method not allowed")}if(W==="run"&&N.method==="POST"){let $=await V0(Y);if(!$)return X(404,`Schedule not found: ${Y}`);let G={schedule:await t0($,new Date)};return Z(G)}if(W)return X(404,`Not found: ${U.pathname}`);if(N.method==="GET"){let $=await V0(Y);return $?Z({schedule:$}):X(404,`Schedule not found: ${Y}`)}if(N.method==="PUT"){let $=await z(N);try{let O=await yH(Y,$);return O?Z({schedule:O}):X(404,`Schedule not found: ${Y}`)}catch(O){return X(400,O instanceof Error?O.message:String(O))}}if(N.method==="DELETE")return await bH(Y)?Z({ok:!0}):X(404,`Schedule not found: ${Y}`);return X(405,"Method not allowed")}var o2=2000,M0=[],n2=0,gH=!1,r0="logs";function a2(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 s2(N,U){let H={seq:++n2,ts:new Date().toISOString(),level:N,text:a2(U)};if(M0.push(H),M0.length>o2)M0.shift();q(r0,H)}function hH(){if(gH)return;gH=!0;let N=(U,H)=>{let Y=console[U].bind(console);console[U]=(...W)=>{try{s2(H,W)}catch{}Y(...W)}};N("log","info"),N("info","info"),N("warn","warn"),N("error","error")}function mH(N={}){let U={info:0,warn:1,error:2},H=N.level?U[N.level]:0,Y=N.query?.toLowerCase(),W=M0.filter(($)=>U[$.level]>=H&&(!Y||$.text.toLowerCase().includes(Y)));if(N.limit&&W.length>N.limit)W=W.slice(-N.limit);return W}var t2=new Set(["info","warn","error"]);function cH(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")),W=U.searchParams.get("level"),$=W&&t2.has(W)?W:void 0,O={logs:mH({limit:Number.isFinite(Y)&&Y>0?Math.min(Y,2000):500,level:$,query:U.searchParams.get("q")??void 0})};return Z(O)}var e0=!1;function r2(){return Boolean(process.env.INVOCATION_ID)}function e2(){return import.meta.url.endsWith(".js")}async function lH(N,U){if(U.pathname!=="/api/system/upgrade")return X(404,"Not found");if(N.method!=="POST")return X(405,"Method not allowed");if(!e2())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 Q0();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"}),W=setTimeout(()=>Y.kill(),300000),$=await Y.exited;if(clearTimeout(W),$!==0){let Q=await new Response(Y.stderr).text();return X(500,`bun install failed (exit ${$}): ${Q.slice(0,500)}`)}let O=r2();if(O)setTimeout(()=>process.exit(0),750);return Z({ok:!0,from:c,to:H,restarting:O})}finally{e0=!1}}async function pH(N,U){let H=new URL(N.url);try{if(H.pathname==="/api/health")return pU();if(H.pathname==="/api/status")return await uU(H);if(H.pathname.startsWith("/api/system/"))return lH(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 iU(N,H);if(H.pathname==="/api/runs"||H.pathname.startsWith("/api/runs/"))return await dU(N,H,U);if(H.pathname.startsWith("/api/browser/"))return await eU(N,H,U);if(H.pathname==="/api/skills"||H.pathname.startsWith("/api/skills/"))return await ZH(N,H);if(H.pathname==="/api/mcp"||H.pathname.startsWith("/api/mcp/"))return await LH(N,H);if(H.pathname==="/api/memories"||H.pathname.startsWith("/api/memories/"))return await AH(N,H);if(H.pathname==="/api/models")return await TH(N);if(H.pathname==="/api/account"||H.pathname.startsWith("/api/account/"))return await BH(N,H);if(H.pathname==="/api/settings"||H.pathname.startsWith("/api/settings/"))return await CH(N,H);if(H.pathname==="/api/schedules"||H.pathname.startsWith("/api/schedules/"))return await vH(N,H);if(H.pathname==="/api/logs"||H.pathname.startsWith("/api/logs/"))return cH(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(NW(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 NW(N){return typeof N==="object"&&N!==null&&"code"in N&&N.code==="ENOENT"}hH();await Y1();var J0=[w.resolve(import.meta.dir,"../ui-dist"),w.resolve(import.meta.dir,"../../ui/dist")].find((N)=>uH(w.join(N,"index.html")))??w.resolve(import.meta.dir,"../../ui/dist"),HW=(N)=>[`${N}.ts`,`${N}.js`].map((U)=>w.join(import.meta.dir,U)).find((U)=>uH(U));for(let[N,U,H]of[["jun","mcp-server","agenthost"],["jun-browser","browser-mcp-server",void 0]])try{let Y=HW(U);if(Y)await hU(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 dH=Bun.serve({hostname:T0,port:mN,async fetch(N,U){let H=new URL(N.url);if(H.pathname.startsWith("/api/"))return pH(N,U);let Y=await WW(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===WN){aU();let U=sU();if(U)N.send(U)}},message(N,U){if(N.data.channel===WN)rU(U)},close(N){if(N.unsubscribe(N.data.channel),N.data.channel===WN)tU()}}});T1(dH);try{UW(M(),{recursive:!0},(N,U)=>{let H={type:"fs.changed",path:U?u(String(U)):null,ts:new Date().toISOString()};dH.publish("files",JSON.stringify(H))})}catch(N){console.warn("[daemon] workspace watcher unavailable:",N)}var YW=30000;setInterval(()=>{qH()},YW);console.log(`Jun daemon running at http://${T0}:${mN}`);console.log(`Workspace: ${w.resolve(M())}`);async function WW(N){let U=w.join(J0,"index.html");if(!await OW(U))return null;let H=w.normalize(decodeURIComponent(N)).replace(/^[/\\]+/,""),Y=w.resolve(J0,H||"index.html"),W=`${J0}${w.sep}`;if(Y!==J0&&!Y.startsWith(W))return new Response("Not found",{status:404});if(await $W(Y))return new Response(Bun.file(Y),{headers:{"content-type":GW(Y)}});return new Response(Bun.file(U),{headers:{"content-type":"text/html; charset=utf-8"}})}async function OW(N){try{return await iH(N),!0}catch{return!1}}async function $W(N){try{return(await iH(N)).isFile()}catch{return!1}}function GW(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"}}
334
+ `;return await P.mkdir(H,{recursive:!0}),await P.writeFile(R.join(H,"SKILL.md"),Y,"utf8"),qN(),await vN(U)}async function GH(N,U){let H=JN(N);try{await P.access(H)}catch{throw new A(`Skill not found: ${N}`)}return await P.writeFile(R.join(H,"SKILL.md"),U,"utf8"),qN(),await vN(N)}async function OH(N){let U=JN(N);try{return await P.rm(U,{recursive:!0,force:!1}),qN(),!0}catch{return!1}}async function QH(N,U){let H=R.join(JN(N),"SKILL.md");await C("skills/config/write",{path:H,enabled:U,name:null}),qN()}async function FH(N){let U=N.trim();if(!U)return[];let{stdout:H}=await WH(["find",U],M(),30000);return R2(H)}async function HH(){await P.mkdir(MN(),{recursive:!0});let N=await P.readdir(MN(),{withFileTypes:!0});return new Set(N.filter((U)=>U.isDirectory()).map((U)=>U.name))}async function XH(N){let U=N.trim();if(!U)throw new A("Missing skill source");if(/[\s;&|`$(){}<>]/.test(U))throw new A("Invalid source \u2014 expected owner/repo[@skill] or a URL");let H=M(),Y=await HH(),{stdout:W,stderr:G}=await WH(["add",U,"-a","codex","--copy","-y"],H);qN();let O=[...await HH()].filter((F)=>!Y.has(F));if(O.length===0){let F=[W,G].filter(Boolean).join(`
335
+ `).trim();throw new A(`No skill installed from "${U}".${F?`
336
+ ${F}`:""}`)}let{skills:Q}=await Z0();return{installed:O,skills:Q,log:[W,G].filter(Boolean).join(`
337
+ `).trim()}}async function ZH(N,U){let H=await vN(N);if(!H)throw new A(`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 LH(N,U){let H=U.pathname.split("/").filter(Boolean),Y=H[2],W=H[3];if(Y==="registry"){if(W==="search"&&N.method==="GET"){let G=U.searchParams.get("q")??"",$=await FH(G);return Z({results:$})}if(W==="install"&&N.method==="POST"){let G=await z(N);V(G.source,"source");let $=await XH(G.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 G=await z(N);V(G.name,"name"),V(G.description,"description");let $=await $H(G);return Z({skill:$},201)}return X(405,"Method not allowed")}if(!W)switch(N.method){case"GET":{let G=await vN(Y);return G?Z({skill:G}):X(404,`Skill not found: ${Y}`)}case"PUT":{let G=await z(N);V(G.content,"content");let $=await GH(Y,G.content);return Z({skill:$})}case"DELETE":return await OH(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(W){case"enable":{let G=await z(N);if(typeof G.enabled!=="boolean")return X(400,"Missing or invalid field: enabled");return await QH(Y,G.enabled),Z({ok:!0})}case"test":{let G=await z(N).catch(()=>({})),$=await ZH(Y,G.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 bU());return X(405,"Method not allowed")}if(Y==="config"){if(N.method==="GET"){let W={toml:await d()};return Z(W)}if(N.method==="PUT"){let W=await z(N);return V(W.toml,"toml"),await yU(W.toml),Z({ok:!0})}return X(405,"Method not allowed")}if(Y==="reload"&&N.method==="POST")return await hU(),Z({ok:!0});if(Y==="servers"){let W=H[3];if(!W){if(N.method==="POST"){let $=await z(N);return V($.name,"name"),await qU($),Z({ok:!0},201)}return X(405,"Method not allowed")}let G=H[4];if(G==="enable"&&N.method==="POST"){let $=await z(N);if(typeof $.enabled!=="boolean")return X(400,"Missing or invalid field: enabled");return await gU(W,$.enabled),Z({ok:!0})}if(!G&&N.method==="DELETE")return await vU(W)?Z({ok:!0}):X(404,`Server not found: ${W}`);return X(405,"Method not allowed")}return X(404,`Unknown MCP endpoint: ${U.pathname}`)}import{promises as $N}from"fs";import gN from"path";function w2(){return gN.join(b(),"config.toml")}function z0(){return gN.join(b(),"memories")}async function DH(){let N=await d();return N.trim()?c(N):{}}function L0(N){return typeof N==="object"&&N!==null?N:{}}function x2(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 f2(){let N=z0(),U=[];async function H(Y){let W;try{W=await $N.readdir(Y,{withFileTypes:!0})}catch{return}for(let G of W){let $=gN.join(Y,G.name);if(G.isDirectory()){if(G.name===".git")continue;await H($)}else if(G.isFile()){let O=await $N.stat($);U.push({path:i(gN.relative(N,$)),name:G.name,size:O.size,modifiedAt:O.mtime.toISOString()})}}}return await H(N),U.sort((Y,W)=>W.modifiedAt.localeCompare(Y.modifiedAt)),U}async function k2(){try{let U=((await C("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 KH(){let N=await DH();return{enabled:L0(N.features).memories===!0,liveEnabled:await k2(),settings:x2(N),files:await f2()}}async function VH(N){let U=await DH();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 $N.writeFile(w2(),t(U),"utf8"),typeof N.enabled==="boolean")try{await C("experimentalFeature/enablement/set",{enablement:{memories:N.enabled}})}catch(H){console.warn("[memories] live enablement/set failed (applies on restart):",H)}}async function MH(N){let U=NN(z0(),N);return $N.readFile(U,"utf8")}async function JH(N,U){let H=NN(z0(),N);await $N.mkdir(gN.dirname(H),{recursive:!0}),await $N.writeFile(H,U,"utf8")}async function AH(N){let U=NN(z0(),N);await $N.rm(U)}async function TH(N,U){let Y=U.pathname.split("/").filter(Boolean)[2];if(!Y){if(N.method==="GET")return Z(await KH());return X(405,"Method not allowed")}if(Y==="config"){if(N.method==="PUT"){let W=await z(N);if(typeof W.enabled!=="boolean"&&!W.settings)return X(400,"Nothing to update: pass enabled and/or settings");return await VH(W),Z({ok:!0})}return X(405,"Method not allowed")}if(Y==="file"){if(N.method==="GET"){let W=V(U.searchParams.get("path"),"path"),G={path:W,content:await MH(W)};return Z(G)}if(N.method==="PUT"){let W=await z(N);if(V(W.path,"path"),typeof W.content!=="string")return X(400,"Missing or invalid field: content");return await JH(W.path,W.content),Z({ok:!0})}if(N.method==="DELETE"){let W=V(U.searchParams.get("path"),"path");return await AH(W),Z({ok:!0})}return X(405,"Method not allowed")}return X(404,`Unknown memories endpoint: ${U.pathname}`)}var b2=300000,D0=null;async function BH(N){if(N.method!=="GET")return X(405,"Method not allowed");if(D0&&Date.now()-D0.at<b2)return Z({models:D0.models});let H=((await C("model/list",{})).data??[]).filter((W)=>!W.hidden).map((W)=>({id:W.id,model:W.model,displayName:W.displayName,description:W.description,isDefault:W.isDefault,defaultReasoningEffort:W.defaultReasoningEffort,supportedReasoningEfforts:W.supportedReasoningEfforts??[]}));return D0={at:Date.now(),models:H},Z({models:H})}async function K0(){let N=await C("account/read",{});return{account:N.account??null,requiresOpenaiAuth:N.requiresOpenaiAuth,pendingLogin:W0(),lastLoginResult:VU()}}async function CH(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:V(H.apiKey,"apiKey")};else throw new A("type must be one of: chatgpt, chatgptDeviceCode, apiKey");let W=W0();if(W)await C("account/login/cancel",{loginId:W.loginId}).catch(()=>{});$0();let G=await C("account/login/start",Y);if((G.type==="chatgpt"||G.type==="chatgptDeviceCode")&&G.loginId){let $={loginId:G.loginId,type:G.type,authUrl:G.authUrl,userCode:G.userCode,verificationUrl:G.verificationUrl,startedAt:new Date().toISOString()};MU($)}return Z(await K0())}if(U.pathname==="/api/account/login/cancel"&&N.method==="POST"){let H=W0();if(H)await C("account/login/cancel",{loginId:H.loginId}).catch(()=>{});return $0(),Z(await K0())}if(U.pathname==="/api/account/logout"&&N.method==="POST")return await C("account/logout",{}),$0(),Z(await K0());return X(404,`Not found: ${U.pathname}`)}function q2(N){if(!N)return null;return N.replace(/^([a-z0-9+.-]+:\/\/[^:@/]+):[^@/]+@/i,"$1:\u2022\u2022\u2022\u2022@")}function EH(){let N=U0(),U=H0();return{browserProxy:{proxyUrl:q2(N.value),source:N.source,noProxy:U.value,noProxySource:U.source}}}async function RH(N,U){if(U.pathname==="/api/settings"&&N.method==="GET")return Z(EH());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(EH())}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 xH from"path";import{randomUUID as p2}from"crypto";function hN(N,U,H,Y){let W=new Set,G=N.trim()!=="*";for(let $ of N.split(",")){let O=$.trim();if(!O)throw Error(`Invalid ${Y} field: empty term`);let Q=O,F=1,L=O.indexOf("/");if(L!==-1){if(Q=O.slice(0,L),F=Number(O.slice(L+1)),!Number.isInteger(F)||F<=0)throw Error(`Invalid step in ${Y}: ${O}`)}let K,J;if(Q==="*")K=U,J=H;else if(Q.includes("-")){let[f,GN]=Q.split("-");K=Number(f),J=Number(GN)}else K=Number(Q),J=K;if(!Number.isInteger(K)||!Number.isInteger(J))throw Error(`Invalid ${Y} value: ${O}`);if(K<U||J>H||K>J)throw Error(`${Y} out of range (${U}-${H}): ${O}`);for(let f=K;f<=J;f+=F)W.add(f)}return{set:W,restricted:G}}function jH(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"),W=hN(U[2],1,31,"day-of-month"),G=hN(U[3],1,12,"month"),$=hN(U[4],0,7,"day-of-week"),O=new Set;for(let Q of $.set)O.add(Q===7?0:Q);return{minute:H.set,hour:Y.set,dom:W.set,month:G.set,dow:O,domRestricted:W.restricted,dowRestricted:$.restricted}}function PH(N){try{return jH(N),null}catch(U){return U instanceof Error?U.message:"Invalid cron expression"}}function v2(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 IH(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 v2(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 g2(N,U){return new Date(Date.UTC(N,U,0)).getUTCDate()}function h2(N){return new Date(Date.UTC(N.year,N.month-1,N.day)).getUTCDay()}function _H(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<=g2(N.year,N.month))return;if(N.day=1,N.month++,N.month<=12)return;N.month=1,N.year++}function m2(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(h2(U));if(N.domRestricted&&N.dowRestricted)return H||Y;if(N.domRestricted)return H;if(N.dowRestricted)return Y;return!0}function SH(N,U){let H=IH(N,U);return Date.UTC(H.year,H.month-1,H.day,H.hour,H.minute,H.second)-N.getTime()}function c2(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=SH(new Date(H),U),W=H-Y,G=SH(new Date(W),U);if(G!==Y)W=H-G;return new Date(W)}var l2=4216320;function wH(N,U,H){let Y=jH(N),W=IH(U,H),G={year:W.year,month:W.month,day:W.day,hour:W.hour,minute:W.minute};_H(G);for(let $=0;$<l2;$++){if(m2(Y,G))return c2(G,H);_H(G)}return null}var u2={sandbox:"workspaceWrite",approvalPolicy:"onRequest",approvalsReviewer:"auto_review",effort:"medium"};function i2(N){return N.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40)}function o0(N){return xH.join(TN(),`${N}.json`)}async function fH(){await AN.mkdir(TN(),{recursive:!0})}async function n0(N){await fH(),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=wH(N.cron,U,N.tz);return H?H.toISOString():null}function kH(N,U){if(U==="cron"){if(!N.cron)throw Error("cron expression is required for a cron schedule");let H=PH(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 fH();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(xH.join(TN(),H),"utf8"),W=JSON.parse(Y);U.push(W)}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 yH(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";kH(N,H);let Y=`${i2(U)||"schedule"}-${p2().slice(0,8)}`,W=new Date,G={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:{...u2,...N.mode??{}},resume:N.resume??!1,threadRunId:null,enabled:N.enabled??!0,createdAt:W.toISOString(),lastRunAt:null,lastRunId:null,lastError:null,nextRunAt:null};return G.nextRunAt=a0(G,W),await n0(G),G}async function bH(N,U){let H=await V0(N);if(!H)return null;let Y=U.kind??H.kind,W={...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(kH(W,Y),Y==="once"&&U.runAt&&W.runAt!==H.runAt)W.lastRunAt=null;return W.nextRunAt=a0(W,new Date),await n0(W),W}async function qH(N){try{return await AN.unlink(o0(N)),!0}catch{return!1}}function d2(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,W=N.threadRunId??null;try{let $=N.mode;if(N.resume&&W&&await T(W)){let O=await T(W);if(O&&I(O.status))throw Error("previous run still active \u2014 skipped this fire");H=(await O0(W,N.prompt,[],d2($))).id}else{let O=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=O.id,N.resume)W=O.id}}catch($){Y=$ instanceof Error?$.message:String($)}let G={...N,lastRunAt:U.toISOString(),lastRunId:H,lastError:Y,threadRunId:W};return G.nextRunAt=a0(G,U),await n0(G),G}var d0=!1;async function vH(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(W){console.error(`[schedules] fire failed for ${H.id}:`,W)}}}catch(U){console.error("[schedules] tick failed:",U)}finally{d0=!1}}async function gH(N,U){let H=U.pathname.split("/").filter(Boolean),Y=H[2],W=H[3];if(!Y){if(N.method==="GET"){let G={schedules:await s0()};return Z(G)}if(N.method==="POST"){let G=await z(N);try{let O={schedule:await yH(G)};return Z(O,201)}catch($){return X(400,$ instanceof Error?$.message:String($))}}return X(405,"Method not allowed")}if(W==="run"&&N.method==="POST"){let G=await V0(Y);if(!G)return X(404,`Schedule not found: ${Y}`);let O={schedule:await t0(G,new Date)};return Z(O)}if(W)return X(404,`Not found: ${U.pathname}`);if(N.method==="GET"){let G=await V0(Y);return G?Z({schedule:G}):X(404,`Schedule not found: ${Y}`)}if(N.method==="PUT"){let G=await z(N);try{let $=await bH(Y,G);return $?Z({schedule:$}):X(404,`Schedule not found: ${Y}`)}catch($){return X(400,$ instanceof Error?$.message:String($))}}if(N.method==="DELETE")return await qH(Y)?Z({ok:!0}):X(404,`Schedule not found: ${Y}`);return X(405,"Method not allowed")}var n2=2000,M0=[],a2=0,hH=!1,r0="logs";function s2(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 t2(N,U){let H={seq:++a2,ts:new Date().toISOString(),level:N,text:s2(U)};if(M0.push(H),M0.length>n2)M0.shift();g(r0,H)}function mH(){if(hH)return;hH=!0;let N=(U,H)=>{let Y=console[U].bind(console);console[U]=(...W)=>{try{t2(H,W)}catch{}Y(...W)}};N("log","info"),N("info","info"),N("warn","warn"),N("error","error")}function cH(N={}){let U={info:0,warn:1,error:2},H=N.level?U[N.level]:0,Y=N.query?.toLowerCase(),W=M0.filter((G)=>U[G.level]>=H&&(!Y||G.text.toLowerCase().includes(Y)));if(N.limit&&W.length>N.limit)W=W.slice(-N.limit);return W}var r2=new Set(["info","warn","error"]);function lH(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")),W=U.searchParams.get("level"),G=W&&r2.has(W)?W:void 0,$={logs:cH({limit:Number.isFinite(Y)&&Y>0?Math.min(Y,2000):500,level:G,query:U.searchParams.get("q")??void 0})};return Z($)}var e0=!1;function e2(){return Boolean(process.env.INVOCATION_ID)}function NW(){return import.meta.url.endsWith(".js")}async function pH(N,U){if(U.pathname!=="/api/system/upgrade")return X(404,"Not found");if(N.method!=="POST")return X(405,"Method not allowed");if(!NW())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 Q0();let H=p0();if(!H)return X(502,"Could not reach the npm registry to check the latest version");if(!u0(H,l))return X(400,`Already up to date (v${l})`);e0=!0;try{let Y=Bun.spawn([process.execPath,"install","-g","junhost@latest"],{stdout:"pipe",stderr:"pipe"}),W=setTimeout(()=>Y.kill(),300000),G=await Y.exited;if(clearTimeout(W),G!==0){let Q=await new Response(Y.stderr).text();return X(500,`bun install failed (exit ${G}): ${Q.slice(0,500)}`)}let $=e2();if($)setTimeout(()=>process.exit(0),750);return Z({ok:!0,from:l,to:H,restarting:$})}finally{e0=!1}}async function uH(N,U){let H=new URL(N.url);try{if(H.pathname==="/api/health")return uU();if(H.pathname==="/api/status")return await iU(H);if(H.pathname.startsWith("/api/system/"))return pH(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 dU(N,H);if(H.pathname==="/api/runs"||H.pathname.startsWith("/api/runs/"))return await oU(N,H,U);if(H.pathname.startsWith("/api/browser/"))return await NH(N,H,U);if(H.pathname==="/api/skills"||H.pathname.startsWith("/api/skills/"))return await LH(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 TH(N,H);if(H.pathname==="/api/models")return await BH(N);if(H.pathname==="/api/account"||H.pathname.startsWith("/api/account/"))return await CH(N,H);if(H.pathname==="/api/settings"||H.pathname.startsWith("/api/settings/"))return await RH(N,H);if(H.pathname==="/api/schedules"||H.pathname.startsWith("/api/schedules/"))return await gH(N,H);if(H.pathname==="/api/logs"||H.pathname.startsWith("/api/logs/"))return lH(N,H,U);return X(404,`Not found: ${H.pathname}`)}catch(Y){if(Y instanceof dN)return X(400,Y.message);if(Y instanceof A)return X(400,Y.message);if(UW(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 UW(N){return typeof N==="object"&&N!==null&&"code"in N&&N.code==="ENOENT"}mH();await Y1();var J0=[x.resolve(import.meta.dir,"../ui-dist"),x.resolve(import.meta.dir,"../../ui/dist")].find((N)=>iH(x.join(N,"index.html")))??x.resolve(import.meta.dir,"../../ui/dist"),YW=(N)=>[`${N}.ts`,`${N}.js`].map((U)=>x.join(import.meta.dir,U)).find((U)=>iH(U));for(let[N,U,H]of[["jun","mcp-server","agenthost"],["jun-browser","browser-mcp-server",void 0]])try{let Y=YW(U);if(Y)await mU(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(x.join(import.meta.dir,".."));var oH=Bun.serve({hostname:T0,port:mN,async fetch(N,U){let H=new URL(N.url);if(H.pathname.startsWith("/api/"))return uH(N,U);let Y=await $W(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===WN){sU();let U=tU();if(U)N.send(U)}},message(N,U){if(N.data.channel===WN)eU(U)},close(N){if(N.unsubscribe(N.data.channel),N.data.channel===WN)rU()}}});T1(oH);try{HW(M(),{recursive:!0},(N,U)=>{let H={type:"fs.changed",path:U?i(String(U)):null,ts:new Date().toISOString()};oH.publish("files",JSON.stringify(H))})}catch(N){console.warn("[daemon] workspace watcher unavailable:",N)}var WW=30000;setInterval(()=>{vH()},WW);console.log(`Jun daemon running at http://${T0}:${mN}`);console.log(`Workspace: ${x.resolve(M())}`);async function $W(N){let U=x.join(J0,"index.html");if(!await GW(U))return null;let H=x.normalize(decodeURIComponent(N)).replace(/^[/\\]+/,""),Y=x.resolve(J0,H||"index.html"),W=`${J0}${x.sep}`;if(Y!==J0&&!Y.startsWith(W))return new Response("Not found",{status:404});if(await OW(Y))return new Response(Bun.file(Y),{headers:{"content-type":QW(Y)}});return new Response(Bun.file(U),{headers:{"content-type":"text/html; charset=utf-8"}})}async function GW(N){try{return await dH(N),!0}catch{return!1}}async function OW(N){try{return(await dH(N)).isFile()}catch{return!1}}function QW(N){switch(x.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"}}