pi-webapp 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +17 -2
  2. package/README.zh-CN.md +15 -2
  3. package/THIRD_PARTY_LICENSE.txt +24 -0
  4. package/bin/pi-webapp.mjs +31 -4
  5. package/dist/extension.js +22 -6
  6. package/docs/sentry.md +54 -0
  7. package/package.json +41 -9
  8. package/web/dist/.vite/manifest.json +859 -0
  9. package/web/dist/assets/KaTeX_AMS-Regular.ttf +0 -0
  10. package/web/dist/assets/KaTeX_AMS-Regular.woff +0 -0
  11. package/web/dist/assets/KaTeX_AMS-Regular.woff2 +0 -0
  12. package/web/dist/assets/KaTeX_Caligraphic-Bold.ttf +0 -0
  13. package/web/dist/assets/KaTeX_Caligraphic-Bold.woff +0 -0
  14. package/web/dist/assets/KaTeX_Caligraphic-Bold.woff2 +0 -0
  15. package/web/dist/assets/KaTeX_Caligraphic-Regular.ttf +0 -0
  16. package/web/dist/assets/KaTeX_Caligraphic-Regular.woff +0 -0
  17. package/web/dist/assets/KaTeX_Caligraphic-Regular.woff2 +0 -0
  18. package/web/dist/assets/KaTeX_Fraktur-Bold.ttf +0 -0
  19. package/web/dist/assets/KaTeX_Fraktur-Bold.woff +0 -0
  20. package/web/dist/assets/KaTeX_Fraktur-Bold.woff2 +0 -0
  21. package/web/dist/assets/KaTeX_Fraktur-Regular.ttf +0 -0
  22. package/web/dist/assets/KaTeX_Fraktur-Regular.woff +0 -0
  23. package/web/dist/assets/KaTeX_Fraktur-Regular.woff2 +0 -0
  24. package/web/dist/assets/KaTeX_Main-Bold.ttf +0 -0
  25. package/web/dist/assets/KaTeX_Main-Bold.woff +0 -0
  26. package/web/dist/assets/KaTeX_Main-Bold.woff2 +0 -0
  27. package/web/dist/assets/KaTeX_Main-BoldItalic.ttf +0 -0
  28. package/web/dist/assets/KaTeX_Main-BoldItalic.woff +0 -0
  29. package/web/dist/assets/KaTeX_Main-BoldItalic.woff2 +0 -0
  30. package/web/dist/assets/KaTeX_Main-Italic.ttf +0 -0
  31. package/web/dist/assets/KaTeX_Main-Italic.woff +0 -0
  32. package/web/dist/assets/KaTeX_Main-Italic.woff2 +0 -0
  33. package/web/dist/assets/KaTeX_Main-Regular.ttf +0 -0
  34. package/web/dist/assets/KaTeX_Main-Regular.woff +0 -0
  35. package/web/dist/assets/KaTeX_Main-Regular.woff2 +0 -0
  36. package/web/dist/assets/KaTeX_Math-BoldItalic.ttf +0 -0
  37. package/web/dist/assets/KaTeX_Math-BoldItalic.woff +0 -0
  38. package/web/dist/assets/KaTeX_Math-BoldItalic.woff2 +0 -0
  39. package/web/dist/assets/KaTeX_Math-Italic.ttf +0 -0
  40. package/web/dist/assets/KaTeX_Math-Italic.woff +0 -0
  41. package/web/dist/assets/KaTeX_Math-Italic.woff2 +0 -0
  42. package/web/dist/assets/KaTeX_SansSerif-Bold.ttf +0 -0
  43. package/web/dist/assets/KaTeX_SansSerif-Bold.woff +0 -0
  44. package/web/dist/assets/KaTeX_SansSerif-Bold.woff2 +0 -0
  45. package/web/dist/assets/KaTeX_SansSerif-Italic.ttf +0 -0
  46. package/web/dist/assets/KaTeX_SansSerif-Italic.woff +0 -0
  47. package/web/dist/assets/KaTeX_SansSerif-Italic.woff2 +0 -0
  48. package/web/dist/assets/KaTeX_SansSerif-Regular.ttf +0 -0
  49. package/web/dist/assets/KaTeX_SansSerif-Regular.woff +0 -0
  50. package/web/dist/assets/KaTeX_SansSerif-Regular.woff2 +0 -0
  51. package/web/dist/assets/KaTeX_Script-Regular.ttf +0 -0
  52. package/web/dist/assets/KaTeX_Script-Regular.woff +0 -0
  53. package/web/dist/assets/KaTeX_Script-Regular.woff2 +0 -0
  54. package/web/dist/assets/KaTeX_Size1-Regular.ttf +0 -0
  55. package/web/dist/assets/KaTeX_Size1-Regular.woff +0 -0
  56. package/web/dist/assets/KaTeX_Size1-Regular.woff2 +0 -0
  57. package/web/dist/assets/KaTeX_Size2-Regular.ttf +0 -0
  58. package/web/dist/assets/KaTeX_Size2-Regular.woff +0 -0
  59. package/web/dist/assets/KaTeX_Size2-Regular.woff2 +0 -0
  60. package/web/dist/assets/KaTeX_Size3-Regular.ttf +0 -0
  61. package/web/dist/assets/KaTeX_Size3-Regular.woff +0 -0
  62. package/web/dist/assets/KaTeX_Size4-Regular.ttf +0 -0
  63. package/web/dist/assets/KaTeX_Size4-Regular.woff +0 -0
  64. package/web/dist/assets/KaTeX_Size4-Regular.woff2 +0 -0
  65. package/web/dist/assets/KaTeX_Typewriter-Regular.ttf +0 -0
  66. package/web/dist/assets/KaTeX_Typewriter-Regular.woff +0 -0
  67. package/web/dist/assets/KaTeX_Typewriter-Regular.woff2 +0 -0
  68. package/web/dist/assets/app-B2Ac56ic.js +544 -0
  69. package/web/dist/assets/app.js +10 -93
  70. package/web/dist/assets/asciidoc-fDuF7HNn.js +3 -0
  71. package/web/dist/assets/bat-CIKKTCO7.js +3 -0
  72. package/web/dist/assets/bibtex-D13O2Wvh.js +3 -0
  73. package/web/dist/assets/c-BxgHfdNM.js +3 -0
  74. package/web/dist/assets/clojure-CiHGeAtp.js +3 -0
  75. package/web/dist/assets/cmake-DmzJtVCe.js +3 -0
  76. package/web/dist/assets/cpp-WTsyTmWk.js +3 -0
  77. package/web/dist/assets/csharp-BusYHIEz.js +3 -0
  78. package/web/dist/assets/css-D-q0lhfR.js +3 -0
  79. package/web/dist/assets/csv-DFLln536.js +3 -0
  80. package/web/dist/assets/dart-CafiI-9_.js +3 -0
  81. package/web/dist/assets/diff-Br1ISN9_.js +3 -0
  82. package/web/dist/assets/dotenv-CIz2XDph.js +3 -0
  83. package/web/dist/assets/elixir-DRaGIFOe.js +3 -0
  84. package/web/dist/assets/erlang-NGps-vi9.js +3 -0
  85. package/web/dist/assets/fish-ByHW6pZw.js +3 -0
  86. package/web/dist/assets/fsharp-BOBx9XdV.js +3 -0
  87. package/web/dist/assets/go-BeHf35-M.js +3 -0
  88. package/web/dist/assets/graphql-DvPK7yuL.js +3 -0
  89. package/web/dist/assets/groovy-zjY2ZfG0.js +3 -0
  90. package/web/dist/assets/haskell-CMvfT32Y.js +3 -0
  91. package/web/dist/assets/hcl-RKiXyu-a.js +3 -0
  92. package/web/dist/assets/html-DsaiN7Ee.js +3 -0
  93. package/web/dist/assets/html-derivative-CADUTaWI.js +3 -0
  94. package/web/dist/assets/http-B5WHvjtS.js +3 -0
  95. package/web/dist/assets/ini-DuzuNcum.js +3 -0
  96. package/web/dist/assets/java-K8yEFi64.js +3 -0
  97. package/web/dist/assets/javascript-D_ijBMSX.js +3 -0
  98. package/web/dist/assets/julia-BCSipsbD.js +3 -0
  99. package/web/dist/assets/kotlin-BSbocnsc.js +3 -0
  100. package/web/dist/assets/latex-B2rh6wcV.js +3 -0
  101. package/web/dist/assets/less-DrDudO82.js +3 -0
  102. package/web/dist/assets/log-ljR8DmTe.js +3 -0
  103. package/web/dist/assets/lua-DyIUvKwX.js +3 -0
  104. package/web/dist/assets/make-D75dUjYA.js +3 -0
  105. package/web/dist/assets/markdown-CW047eNb.js +3 -0
  106. package/web/dist/assets/mdx-XsqTTZB4.js +3 -0
  107. package/web/dist/assets/nix-CipIrdNI.js +3 -0
  108. package/web/dist/assets/perl-D7RI67n_.js +3 -0
  109. package/web/dist/assets/php-s52DiJil.js +3 -0
  110. package/web/dist/assets/powershell-jgDnaG9I.js +3 -0
  111. package/web/dist/assets/proto-BIjSd36w.js +3 -0
  112. package/web/dist/assets/python-D7_Ztkaq.js +3 -0
  113. package/web/dist/assets/r-CJzV5ecV.js +3 -0
  114. package/web/dist/assets/rst-CN3AX0Wt.js +3 -0
  115. package/web/dist/assets/ruby-TeaxAh4o.js +3 -0
  116. package/web/dist/assets/rust-DSBpfBj6.js +3 -0
  117. package/web/dist/assets/scala-C5J7wQ_u.js +3 -0
  118. package/web/dist/assets/scss-Ce0Xtdy1.js +3 -0
  119. package/web/dist/assets/sql-B8q9hRYB.js +3 -0
  120. package/web/dist/assets/style.css +1 -1
  121. package/web/dist/assets/svelte-D-qO2kbs.js +3 -0
  122. package/web/dist/assets/swift-BYyWkiAC.js +3 -0
  123. package/web/dist/assets/system-verilog-DeQRavVp.js +3 -0
  124. package/web/dist/assets/telemetry-client-BUyFe34_.js +7 -0
  125. package/web/dist/assets/toml-D4Tpftfr.js +3 -0
  126. package/web/dist/assets/vb-CT8kYl35.js +3 -0
  127. package/web/dist/assets/verilog-CRrcH6Pt.js +3 -0
  128. package/web/dist/assets/vue-xQhdtb6A.js +3 -0
  129. package/web/dist/assets/xml-DCBoxqhY.js +3 -0
  130. package/web/dist/assets/yaml-jmrW97Mk.js +3 -0
package/dist/extension.js CHANGED
@@ -1,7 +1,23 @@
1
- import{dirname as wr,join as q,resolve as Ue}from"node:path";import{realpath as J}from"node:fs/promises";import{fileURLToPath as hr}from"node:url";import{DefaultPackageManager as Be,getAgentDir as N,ModelRuntime as yr,SessionManager as Oe,SettingsManager as vr}from"@earendil-works/pi-coding-agent";import{getSupportedThinkingLevels as kr}from"@earendil-works/pi-ai";import{randomBytes as Vt,timingSafeEqual as Ut}from"node:crypto";import{readFile as Bt}from"node:fs/promises";import{createServer as Ot}from"node:http";import{join as Dt}from"node:path";import{mkdir as He,opendir as Ge,stat as ze}from"node:fs/promises";import{homedir as Ke}from"node:os";import{basename as Ye,dirname as te,join as re,posix as Xe,resolve as ie,win32 as Ze}from"node:path";function se(t){return process.platform==="win32"?Ze.isAbsolute(t)&&/^(?:[A-Za-z]:[\\/]|[\\/]{2}[^\\/]+[\\/]+[^\\/]+)/.test(t):Xe.isAbsolute(t)}function Qe(t,e,r){if(t.length===r&&e.name.localeCompare(t[t.length-1].name)>=0)return!0;let i=0,n=t.length;for(;i<n;){let p=i+n>>>1;e.name.localeCompare(t[p].name)<0?n=p:i=p+1}return t.splice(i,0,e),t.length<=r?!1:(t.pop(),!0)}async function ne(t){if(t!==void 0&&!se(t))throw new Error("\u76EE\u5F55\u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");let e=Ke(),r=ie(t??e),i=[];for(let a=r;;a=te(a)){let u=te(a);if(i.unshift({name:u===a?a:Ye(a),path:a,hidden:!1}),u===a)break}let n=[],p=!1,o=await Ge(r);for await(let a of o)!a.isDirectory()&&!a.isSymbolicLink()||Qe(n,{name:a.name,isDirectory:a.isDirectory(),isSymbolicLink:a.isSymbolicLink()},1001)&&(p=!0);let l=[];for(let a of n){let u=re(r,a.name);if(!a.isDirectory&&a.isSymbolicLink)try{if(!(await ze(u)).isDirectory())continue}catch{continue}if(l.length===1e3){p=!0;break}l.push({name:a.name,path:u,hidden:a.name.startsWith(".")})}return{path:r,home:e,crumbs:i,entries:l,truncated:p}}async function oe(t,e){if(!se(t))throw new Error("\u7236\u76EE\u5F55\u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");if(!e.trim()||e==="."||e===".."||/[/\\]/.test(e))throw new Error("\u6587\u4EF6\u5939\u540D\u79F0\u65E0\u6548");let r=re(ie(t),e);return await He(r),r}import{execFile as qe}from"node:child_process";import{accessSync as et,constants as tt}from"node:fs";import{delimiter as rt,join as it}from"node:path";var st=(t,e,r)=>new Promise((i,n)=>{qe(t,[...e],{encoding:"utf8",signal:r,windowsHide:!0},(p,o,l)=>{p?n(Object.assign(new Error(p.message,{cause:p}),{code:p.code,stdout:o,stderr:l})):i({stdout:o,stderr:l})})});function nt(t){for(let e of(t??"").split(rt))if(e)for(let r of["zenity","kdialog"])try{return et(it(e,r),tt.X_OK),!0}catch{}return!1}function ae(t=process.platform,e=process.env){return e.SSH_CONNECTION||e.SSH_TTY?"browse":t==="darwin"||t==="linux"&&(e.DISPLAY||e.WAYLAND_DISPLAY)&&nt(e.PATH)?"native":"browse"}function L(t){if(!(typeof t!="object"||t===null||!("code"in t)))return typeof t.code=="string"||typeof t.code=="number"?t.code:void 0}function ot(t){return typeof t=="object"&&t!==null&&"stderr"in t&&typeof t.stderr=="string"?t.stderr:""}function H(t){return t.replace(/[\r\n]+$/,"")||null}async function ce(t,e=process.platform,r=st){if(e==="darwin")try{let i=await r("osascript",["-e",'set selectedFolder to choose folder with prompt "Select Workspace Directory"',"-e","POSIX path of selectedFolder"],t);return H(i.stdout)}catch(i){if(!t.aborted&&L(i)===1&&/(?:User canceled|-128)/i.test(ot(i)))return null;throw i}if(e==="linux"){try{return H((await r("zenity",["--file-selection","--directory","--title=Select Workspace Directory"],t)).stdout)}catch(i){if(t.aborted)throw i;if(L(i)===1)return null;if(L(i)!=="ENOENT")throw i}try{return H((await r("kdialog",["--getexistingdirectory",".","--title","Select Workspace Directory"],t)).stdout)}catch(i){if(t.aborted)throw i;if(L(i)===1)return null;throw i}}throw new Error(`\u5F53\u524D\u7CFB\u7EDF\u4E0D\u652F\u6301\u672C\u5730\u76EE\u5F55\u9009\u62E9\u5668\uFF1A${e}`)}import{createHash as at,randomUUID as ct}from"node:crypto";import{mkdir as lt,readFile as dt,writeFile as pt}from"node:fs/promises";import{join as le}from"node:path";import{getAgentDir as ut}from"@earendil-works/pi-coding-agent";var _=20*1024*1024,de=20,mt=/^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])$/iu;function ft(t){let e=t.indexOf("."),r=(e<0?t:t.slice(0,e)).replace(/[. ]+$/u,"");return mt.test(r)}function gt(t,e){let r=0,i="";for(let n of Buffer.from(t).toString("utf8")){let p=Buffer.byteLength(n);if(r+p>e)break;i+=n,r+=p}return i}function wt(t){if(t===void 0)return"file";let r=t.slice(Math.max(t.lastIndexOf("/"),t.lastIndexOf("\\"))+1).replace(/[\u0000-\u001f\u007f]/g,"").replace(/[<>:"|?*]/g,"_").trim().replace(/[. ]+$/u,"");return ft(r)&&(r=`_${r}`),r=gt(r,255).replace(/[. ]+$/u,""),r===""||r==="."||r===".."?"file":r}function ht(t){return t.length>=8&&t.subarray(0,8).equals(Buffer.from([137,80,78,71,13,10,26,10]))?"image/png":t.length>=3&&t.subarray(0,3).equals(Buffer.from([255,216,255]))?"image/jpeg":t.length>=6&&["GIF87a","GIF89a"].includes(t.toString("ascii",0,6))?"image/gif":t.length>=12&&t.toString("ascii",0,4)==="RIFF"&&t.toString("ascii",8,12)==="WEBP"?"image/webp":null}async function pe(t,e,r,i){if(i.byteLength===0||i.byteLength>_)throw new Error("\u6587\u4EF6\u4E3A\u7A7A\u6216\u8D85\u8FC7 20 MB");let n=wt(e),p=at("sha256").update(i).digest("hex"),o=le(ut(),"pi-web","attachments",p);await lt(o,{recursive:!0});let l=le(o,n);try{await pt(l,i,{flag:"wx",mode:384})}catch(a){if(!(a instanceof Error&&"code"in a&&a.code==="EEXIST"))throw a}return{id:ct(),name:n,bytes:i.byteLength,path:l,mediaType:ht(i)??r.replace(/^image\//,"application/"),sessionId:t}}async function ue(t){return{type:"image",data:(await dt(t.path)).toString("base64"),mimeType:t.mediaType}}import{randomBytes as yt}from"node:crypto";function me(t,e,r){return t!=="openai-codex"||e!=="oauth"?r:{...r,prompt:i=>i.type==="select"&&i.options.some(n=>n.id==="browser")&&i.options.some(n=>n.id==="device_code")?Promise.resolve("browser"):r.prompt(i)}}var V=class{flows=new Map;start(e,r,i,n){let p=this.getActive();if(p){if(p.providerId===e&&p.method===r&&n===void 0)return p;throw new Error("\u5176\u4ED6\u63D0\u4F9B\u65B9\u7684\u767B\u5F55\u6B63\u5728\u8FDB\u884C\uFF0C\u8BF7\u5148\u5B8C\u6210\u6216\u53D6\u6D88\u5F53\u524D\u767B\u5F55")}this.flows.clear();let o=yt(18).toString("base64url"),l={view:{id:o,providerId:e,method:r,status:"running"},controller:new AbortController};return this.flows.set(o,l),i(e,r,{signal:l.controller.signal,notify:a=>{l.view={...l.view,event:a,...a.type==="auth_url"||a.type==="device_code"?{authorization:a}:{}}},prompt:a=>{if(a.type==="secret"&&n!==void 0){let u=n;return n=void 0,Promise.resolve(u)}return new Promise((u,h)=>{let{signal:y,...b}=a;l.answer=u,l.reject=h,l.view={...l.view,status:"waiting",prompt:b},y?.aborted?h(new Error("\u767B\u5F55\u8F93\u5165\u5DF2\u53D6\u6D88")):y?.addEventListener("abort",()=>h(new Error("\u767B\u5F55\u8F93\u5165\u5DF2\u53D6\u6D88")),{once:!0})})}}).then(()=>{l.view.status!=="cancelled"&&(l.view={id:o,providerId:e,method:r,status:"done"})}).catch(()=>{l.view.status!=="cancelled"&&(l.view={id:o,providerId:e,method:r,status:"error",error:"\u767B\u5F55\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u63D0\u4F9B\u65B9\u63D0\u793A\u5E76\u91CD\u8BD5\u3002"})}),{...l.view}}get(e){let r=this.flows.get(e)?.view;return r?{...r}:void 0}getActive(){let e=[...this.flows.values()].find(({view:r})=>r.status==="running"||r.status==="waiting")?.view;return e?{...e}:void 0}respond(e,r){let i=this.flows.get(e);if(!i?.answer||i.view.status!=="waiting"||i.view.prompt?.type==="select"&&!i.view.prompt.options.some(p=>p.id===r))return!1;let n=i.answer;return i.answer=void 0,i.reject=void 0,i.view={...i.view,status:"running",prompt:void 0},n(r),!0}cancel(e){let r=this.flows.get(e);return!r||r.view.status==="done"||r.view.status==="error"?!1:(r.view={...r.view,status:"cancelled",prompt:void 0},r.controller.abort(),r.reject?.(new Error("\u767B\u5F55\u5DF2\u53D6\u6D88")),r.answer=void 0,r.reject=void 0,!0)}close(){for(let e of this.flows.keys())this.cancel(e);this.flows.clear()}};import{randomBytes as vt}from"node:crypto";import{readFile as kt,rename as bt,rm as Pt,stat as St,writeFile as xt,mkdir as Et}from"node:fs/promises";import{dirname as It}from"node:path";var Ct=["openai-completions","openai-responses","anthropic-messages"];function G(t){if(!t||typeof t!="object")return!1;let e=t;if(typeof e.id!="string"||!/^[a-z0-9][a-z0-9._-]{0,63}$/.test(e.id)||typeof e.name!="string"||!e.name.trim()||e.name.length>100||typeof e.modelId!="string"||!e.modelId.trim()||e.modelId.length>200||!Ct.includes(e.api)||typeof e.baseUrl!="string"||e.baseUrl.length>2048)return!1;try{let r=new URL(e.baseUrl);return(r.protocol==="https:"||r.protocol==="http:")&&!!r.hostname&&!r.username&&!r.password&&!r.hash}catch{return!1}}async function fe(t,e){if(!G(e))throw new Error("\u81EA\u5B9A\u4E49\u63D0\u4F9B\u65B9\u540D\u79F0\u3001\u5730\u5740\u6216\u6A21\u578B\u65E0\u6548");let r;try{r=await kt(t,"utf8")}catch(l){if(l.code!=="ENOENT")throw l}let i;if(r===void 0)i={providers:{}};else{try{i=JSON.parse(r)}catch{throw new Error("models.json \u542B\u6CE8\u91CA\u6216\u683C\u5F0F\u9519\u8BEF\uFF0C\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u624B\u52A8\u6DFB\u52A0\u63D0\u4F9B\u65B9")}if(!i||typeof i!="object"||!i.providers||typeof i.providers!="object"||Array.isArray(i.providers))throw new Error("models.json \u7ED3\u6784\u65E0\u6548")}if(Object.hasOwn(i.providers,e.id))throw new Error("\u63D0\u4F9B\u65B9\u5DF2\u5B58\u5728");let n={...i,providers:{...i.providers,[e.id]:{name:e.name.trim(),baseUrl:e.baseUrl,api:e.api,models:[{id:e.modelId.trim()}]}}};await Et(It(t),{recursive:!0});let p=r===void 0?384:(await St(t)).mode&511,o=`${t}.pi-web-${vt(6).toString("hex")}.tmp`;try{await xt(o,`${JSON.stringify(n,null,2)}
2
- `,{mode:p,flag:"wx"}),await bt(o,t)}finally{await Pt(o,{force:!0})}}import{randomBytes as Mt}from"node:crypto";import{mkdir as At,readFile as Tt,rename as Nt,rm as Rt,stat as Wt,writeFile as jt}from"node:fs/promises";import{dirname as Lt}from"node:path";function ge(t){if(!t||t.length>2048)return!1;try{let e=new URL(t);return(e.protocol==="https:"||e.protocol==="http:")&&!!e.hostname&&!e.username&&!e.password&&!e.search&&!e.hash}catch{return!1}}function we(t){if(!t||typeof t!="object")return!1;let e=t;return e.action==="save"?(e.originalId===void 0||typeof e.originalId=="string")&&he(e.model):e.action==="base_url"?e.baseUrl===null||typeof e.baseUrl=="string"&&ge(e.baseUrl):e.action==="remove"&&typeof e.id=="string"&&e.id.length>0&&e.id.length<=200}function he(t){if(!t||typeof t!="object")return!1;let e=t;if(typeof e.id!="string"||!e.id.trim()||e.id.length>200||e.name!==void 0&&(typeof e.name!="string"||!e.name.trim()||e.name.length>200))return!1;for(let r of[e.contextWindow,e.maxTokens])if(r!==void 0&&(!Number.isSafeInteger(r)||r<=0))return!1;return e.input===void 0||Array.isArray(e.input)&&e.input.length>0&&e.input.every(r=>r==="text"||r==="image")&&new Set(e.input).size===e.input.length}async function ye(t){let e;try{e=await Tt(t,"utf8")}catch(i){if(i.code!=="ENOENT")throw i}if(e===void 0)return{config:{providers:{}}};let r;try{r=JSON.parse(e)}catch{throw new Error("models.json \u542B\u6CE8\u91CA\u6216\u683C\u5F0F\u9519\u8BEF\uFF0C\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u624B\u52A8\u4FEE\u6539")}if(!r||typeof r!="object"||!r.providers||typeof r.providers!="object"||Array.isArray(r.providers))throw new Error("models.json \u7ED3\u6784\u65E0\u6548");return{config:r,existing:e}}async function _t(t,e,r){await At(Lt(t),{recursive:!0});let i=r===void 0?384:(await Wt(t)).mode&511,n=`${t}.pi-web-${Mt(6).toString("hex")}.tmp`;try{await jt(n,`${JSON.stringify(e,null,2)}
3
- `,{mode:i,flag:"wx"}),await Nt(n,t)}finally{await Rt(n,{force:!0})}}async function ve(t,e,r){if(!r.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:i}=await ye(t),n=i.providers[e],p=new Set(n?.models?.map(o=>o.id)??[]);return{providerId:e,baseUrl:n?.baseUrl,models:r.getModels(e).map(o=>({id:o.id,name:o.name,contextWindow:o.contextWindow,maxTokens:o.maxTokens,input:[...o.input],source:p.has(o.id)?"custom":"builtin",overridden:!!n?.modelOverrides?.[o.id]}))}}async function ke(t,e,r,i){if(!i.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:n,existing:p}=await ye(t),o={...n.providers[e]??{}},l=[...o.models??[]],a={...o.modelOverrides??{}};if(r.action==="base_url"){if(r.baseUrl!==null&&!ge(r.baseUrl))throw new Error("API \u5730\u5740\u65E0\u6548");r.baseUrl===null?delete o.baseUrl:o.baseUrl=r.baseUrl}else if(r.action==="save"){if(!he(r.model))throw new Error("\u6A21\u578B\u53C2\u6570\u65E0\u6548");let u={id:r.model.id.trim(),...r.model.name===void 0?{}:{name:r.model.name},...r.model.contextWindow===void 0?{}:{contextWindow:r.model.contextWindow},...r.model.maxTokens===void 0?{}:{maxTokens:r.model.maxTokens},...r.model.input===void 0?{}:{input:r.model.input}},h=r.originalId,y=h===void 0?-1:l.findIndex(b=>b.id===h);if(h===void 0&&(l.some(b=>b.id===u.id)||i.getModel(e,u.id)))throw new Error("\u6A21\u578B ID \u5DF2\u5B58\u5728");if(y>=0){if(u.id!==h&&(l.some(g=>g.id===u.id)||i.getModel(e,u.id)))throw new Error("\u6A21\u578B ID \u5DF2\u5B58\u5728");let b={...l[y],...u};for(let g of["name","contextWindow","maxTokens","input"])u[g]===void 0&&delete b[g];l[y]=b}else if(h!==void 0&&i.getModel(e,h)){if(u.id!==h)throw new Error("\u5185\u7F6E\u6A21\u578B ID \u4E0D\u53EF\u4FEE\u6539");let{id:b,...g}=u;a[h]={...a[h],...g};for(let d of["name","contextWindow","maxTokens","input"])u[d]===void 0&&delete a[h][d]}else{if(h!==void 0)throw new Error("\u6A21\u578B\u4E0D\u5B58\u5728");l.push(u)}}else{let u=l.findIndex(h=>h.id===r.id);if(u>=0)l.splice(u,1);else if(Object.hasOwn(a,r.id))delete a[r.id];else throw new Error("\u53EA\u80FD\u79FB\u9664\u81EA\u5B9A\u4E49\u6A21\u578B\u6216\u6062\u590D\u5DF2\u4FEE\u6539\u7684\u5185\u7F6E\u6A21\u578B")}l.length?o.models=l:delete o.models,Object.keys(a).length?o.modelOverrides=a:delete o.modelOverrides,Object.keys(o).length?n.providers[e]=o:delete n.providers[e],await _t(t,n,p)}function be(t){return/^(?:npm:|git:|https?:\/\/|ssh:\/\/|git@)/i.test(t.trim())}var $t={"/":{path:"index.html",type:"text/html; charset=utf-8"},"/assets/app.js":{path:"assets/app.js",type:"text/javascript; charset=utf-8"},"/assets/style.css":{path:"assets/style.css",type:"text/css; charset=utf-8"}};function m(t,e,r){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}),t.end(JSON.stringify(r))}function Ft(t,e){let r=t.headers.authorization;if(typeof r!="string"||!r.startsWith("Bearer "))return!1;let i=Buffer.from(r.slice(7),"utf8");return i.length===e.length&&Ut(i,e)}async function Jt(t){let e=0,r=[];for await(let i of t){let n=Buffer.isBuffer(i)?i:Buffer.from(i);if(e+=n.length,e>64*1024)throw new Error("\u8BF7\u6C42\u5185\u5BB9\u8FC7\u5927");r.push(n)}return JSON.parse(Buffer.concat(r).toString("utf8"))}async function Ht(t){let e=0,r=[];for await(let i of t){let n=Buffer.isBuffer(i)?i:Buffer.from(i);if(e+=n.length,e>_)throw new Error("\u6587\u4EF6\u8D85\u8FC7 20 MB");r.push(n)}return Buffer.concat(r)}async function Gt(t,e=0){await new Promise((i,n)=>{t.once("error",n),t.listen(e,"127.0.0.1",()=>{t.off("error",n),i()})});let r=t.address();if(r===null||typeof r=="string")throw new Error("\u65E0\u6CD5\u786E\u5B9A\u76D1\u542C\u7AEF\u53E3");return r.port}async function Pe(t,e){let r=process.env.PI_WEBAPP_RESTART_TOKEN,i=r&&/^[A-Za-z0-9_-]{32}$/.test(r)?r:Vt(24).toString("base64url"),n=Buffer.from(i),p=ae(),o=new Set,l=new Map,a=new V,u="",h=Ot(async(g,d)=>{d.setHeader("X-Content-Type-Options","nosniff"),d.setHeader("Referrer-Policy","no-referrer"),d.setHeader("Content-Security-Policy","default-src 'self'; script-src 'self'; style-src 'self'; connect-src 'self'; img-src 'self' data: blob:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'");let f;try{f=new URL(g.url??"/",u).pathname}catch{m(d,400,{error:"\u8BF7\u6C42\u5730\u5740\u65E0\u6548"});return}let W=$t[f];if(g.method==="GET"&&W){try{let c=await Bt(Dt(e,W.path));d.writeHead(200,{"Content-Type":W.type,"Cache-Control":"no-store"}),d.end(c)}catch{m(d,500,{error:"\u9875\u9762\u6587\u4EF6\u4E0D\u53EF\u7528"})}return}if(!f.startsWith("/api/")){m(d,404,{error:"\u672A\u627E\u5230"});return}if(!Ft(g,n)){m(d,401,{error:"\u8BBF\u95EE\u4EE4\u724C\u65E0\u6548"});return}if(g.method==="GET"&&f==="/api/update/version"){try{m(d,200,{current:await t.selfUpdate?.runningVersion()??null})}catch(c){m(d,503,{error:c instanceof Error?c.message:"\u65E0\u6CD5\u8BFB\u53D6\u7248\u672C"})}return}if(g.method==="GET"&&f==="/api/update"){try{m(d,200,await t.selfUpdate?.check()??{canRestart:!1,reason:"\u5F53\u524D\u6269\u5C55\u4E0D\u652F\u6301\u5728\u7EBF\u5347\u7EA7"})}catch(c){m(d,503,{error:c instanceof Error?c.message:"\u68C0\u67E5\u66F4\u65B0\u5931\u8D25"})}return}if(g.method==="GET"&&f==="/api/image"){let c=new URL(g.url??f,u),w=c.searchParams.get("sessionId")??"",k=c.searchParams.get("messageId")??"",v=Number(c.searchParams.get("index"));if(!w||w!==t.snapshot().sessionId||!k||!Number.isInteger(v)||v<0||v>100){m(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u56FE\u7247\u5730\u5740\u65E0\u6548"});return}let A=t.image?.(w,k,v);if(!A||!["image/png","image/jpeg","image/webp","image/gif"].includes(A.mimeType)){m(d,404,{error:"\u56FE\u7247\u4E0D\u53EF\u7528"});return}d.writeHead(200,{"Content-Type":A.mimeType,"Cache-Control":"private, no-store"}),d.end(A.data);return}if(g.method==="POST"&&f==="/api/attachment"){if(g.headers.origin!==void 0&&g.headers.origin!==u){m(d,403,{error:"\u6765\u6E90\u4E0D\u5339\u914D"});return}let c=new URL(g.url??f,u),w=c.searchParams.get("sessionId"),k=c.searchParams.get("name");try{if(!w||!k||k.length>1024||w!==t.snapshot().sessionId){m(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u6587\u4EF6\u540D\u65E0\u6548"});return}if(Number(g.headers["content-length"]??0)>_){m(d,413,{error:"\u6587\u4EF6\u8D85\u8FC7 20 MB"});return}let v=await pe(w,k,g.headers["content-type"]??"application/octet-stream",await Ht(g));if(w!==t.snapshot().sessionId){m(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}l.set(v.id,v),m(d,201,{id:v.id,name:v.name,bytes:v.bytes})}catch(v){m(d,400,{error:v instanceof Error?v.message:"\u4E0A\u4F20\u5931\u8D25"})}return}if(g.method==="GET"&&f==="/api/session"){try{m(d,200,t.snapshot())}catch{m(d,503,{error:"\u5F53\u524D\u4F1A\u8BDD\u4E0D\u53EF\u7528"})}return}if(g.method==="GET"&&f==="/api/providers"){try{m(d,200,await t.providers?.()??[])}catch{m(d,503,{error:"\u6A21\u578B\u63D0\u4F9B\u65B9\u4E0D\u53EF\u7528"})}return}if(g.method==="GET"&&f==="/api/provider/models"){let c=new URL(g.url??f,u).searchParams.get("providerId")??"";try{if(!c||!t.providerModels){m(d,400,{error:"\u63D0\u4F9B\u65B9\u65E0\u6548"});return}m(d,200,await t.providerModels(c))}catch(w){m(d,400,{error:w instanceof Error?w.message:"\u6A21\u578B\u76EE\u5F55\u4E0D\u53EF\u7528"})}return}if(g.method==="GET"&&f==="/api/provider/login/active"){m(d,200,{active:a.getActive()??null});return}if(g.method==="GET"&&f==="/api/provider/login"){let c=new URL(g.url??f,u).searchParams.get("id")??"",w=a.get(c);m(d,w?200:404,w??{error:"\u767B\u5F55\u6D41\u7A0B\u4E0D\u5B58\u5728"});return}if(g.method==="GET"&&(f==="/api/models"||f==="/api/config"||f==="/api/workspaces"||f==="/api/commands")){try{m(d,200,f==="/api/models"?await t.models():f==="/api/config"?await t.config():f==="/api/commands"?t.commands?.()??[]:await t.workspaces())}catch{m(d,503,{error:"Pi \u914D\u7F6E\u4E0D\u53EF\u7528"})}return}if(g.method==="GET"&&f==="/api/directory/capability"){m(d,200,{kind:p});return}if(g.method==="GET"&&f==="/api/events"){let c;try{c=t.snapshot()}catch{m(d,503,{error:"\u5F53\u524D\u4F1A\u8BDD\u4E0D\u53EF\u7528"});return}d.writeHead(200,{"Content-Type":"application/x-ndjson; charset=utf-8","Cache-Control":"no-store",Connection:"keep-alive","X-Accel-Buffering":"no"}),o.add(d),d.write(`${JSON.stringify({type:"snapshot",session:c})}
4
- `),d.on("close",()=>o.delete(d));return}if(g.method==="POST"&&["/api/update","/api/message","/api/attachment/remove","/api/abort","/api/compact","/api/new-session","/api/model","/api/thinking-level","/api/config","/api/provider/login","/api/provider/login/respond","/api/provider/login/cancel","/api/provider/custom","/api/provider/models","/api/provider/logout","/api/workspace/add","/api/workspace/select","/api/workspace/new-session","/api/workspace/remove","/api/session/select","/api/directory/list","/api/directory/create","/api/directory/pick"].includes(f)){if(g.headers.origin!==void 0&&g.headers.origin!==u){m(d,403,{error:"\u6765\u6E90\u4E0D\u5339\u914D"});return}if(!g.headers["content-type"]?.startsWith("application/json")){m(d,415,{error:"\u9700\u8981 JSON \u8BF7\u6C42"});return}try{let c=await Jt(g);if(typeof c!="object"||c===null||!("sessionId"in c)||typeof c.sessionId!="string"){m(d,400,{error:"\u7F3A\u5C11\u4F1A\u8BDD\u6807\u8BC6"});return}if(f==="/api/update"){if(c.sessionId!==t.snapshot().sessionId){m(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!t.snapshot().idle){m(d,409,{error:"\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u540E\u518D\u5347\u7EA7"});return}if(!t.selfUpdate){m(d,409,{error:"\u5F53\u524D\u6269\u5C55\u4E0D\u652F\u6301\u5728\u7EBF\u5347\u7EA7"});return}let w=await t.selfUpdate.prepare();m(d,202,{accepted:!0,version:w.version}),setTimeout(()=>{t.selfUpdate?.requestRestart(w).catch(k=>console.error("pi-webapp restart:",k))},500).unref();return}if(f==="/api/provider/custom"){if(c.sessionId!==t.snapshot().sessionId){m(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("provider"in c)||!G(c.provider)||!t.addCustomProvider){m(d,400,{error:"\u81EA\u5B9A\u4E49\u63D0\u4F9B\u65B9\u65E0\u6548"});return}await t.addCustomProvider(c.sessionId,c.provider),m(d,201,{accepted:!0});return}if(f==="/api/provider/models"||f==="/api/provider/logout"){if(c.sessionId!==t.snapshot().sessionId){m(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("providerId"in c)||typeof c.providerId!="string"){m(d,400,{error:"\u63D0\u4F9B\u65B9\u65E0\u6548"});return}if(f==="/api/provider/models"){if(!("change"in c)||!we(c.change)||!t.updateProviderModel){m(d,400,{error:"\u6A21\u578B\u53C2\u6570\u65E0\u6548"});return}await t.updateProviderModel(c.sessionId,c.providerId,c.change)}else{if(!t.logoutProvider){m(d,400,{error:"\u65E0\u6CD5\u79FB\u9664\u8BA4\u8BC1"});return}await t.logoutProvider(c.sessionId,c.providerId)}m(d,200,{accepted:!0});return}if(f.startsWith("/api/provider/login")){if(c.sessionId!==t.snapshot().sessionId){m(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(f==="/api/provider/login"){if(!("providerId"in c)||typeof c.providerId!="string"||!("method"in c)||c.method!=="api_key"&&c.method!=="oauth"||!t.loginProvider||!t.providers){m(d,400,{error:"\u767B\u5F55\u65B9\u5F0F\u65E0\u6548"});return}if(!(await t.providers()).some(A=>A.id===c.providerId&&A.methods.includes(c.method))){m(d,400,{error:"\u63D0\u4F9B\u65B9\u4E0D\u652F\u6301\u6B64\u767B\u5F55\u65B9\u5F0F"});return}let k="initialSecret"in c?c.initialSecret:void 0;if(k!==void 0&&(c.method!=="api_key"||typeof k!="string"||!k.trim()||k.length>16384)){m(d,400,{error:"API Key \u65E0\u6548"});return}let v=a.start(c.providerId,c.method,t.loginProvider,k);m(d,202,{id:v.id});return}if(!("id"in c)||typeof c.id!="string"){m(d,400,{error:"\u767B\u5F55\u6D41\u7A0B\u65E0\u6548"});return}if(f==="/api/provider/login/cancel"){m(d,a.cancel(c.id)?202:404,{accepted:!0});return}if(!("value"in c)||typeof c.value!="string"||c.value.length>16384||!a.respond(c.id,c.value)){m(d,400,{error:"\u767B\u5F55\u8F93\u5165\u65E0\u6548"});return}m(d,202,{accepted:!0});return}if(f==="/api/attachment/remove"){if(!("id"in c)||typeof c.id!="string"||c.sessionId!==t.snapshot().sessionId){m(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u9644\u4EF6\u65E0\u6548"});return}l.get(c.id)?.sessionId===c.sessionId&&l.delete(c.id),m(d,202,{accepted:!0});return}if(f==="/api/directory/pick"){if(p!=="native"){m(d,409,{error:"\u672C\u5730\u76EE\u5F55\u9009\u62E9\u5668\u4E0D\u53EF\u7528"});return}let w=new AbortController;d.once("close",()=>w.abort()),m(d,200,{path:await ce(w.signal)});return}if(f==="/api/directory/list"){if("path"in c&&(typeof c.path!="string"||c.path.length>4096)){m(d,400,{error:"\u76EE\u5F55\u8DEF\u5F84\u65E0\u6548"});return}m(d,200,await ne("path"in c?c.path:void 0));return}if(f==="/api/directory/create"){if(!("path"in c)||typeof c.path!="string"||c.path.length>4096||!("name"in c)||typeof c.name!="string"||c.name.length>255){m(d,400,{error:"\u6587\u4EF6\u5939\u540D\u79F0\u6216\u8DEF\u5F84\u65E0\u6548"});return}m(d,200,{path:await oe(c.path,c.name)});return}if(f==="/api/workspace/add"){if(!("path"in c)||typeof c.path!="string"||c.path.length>4096||!("create"in c)||typeof c.create!="boolean"){m(d,400,{error:"\u5DE5\u4F5C\u533A\u8DEF\u5F84\u65E0\u6548"});return}await t.addWorkspace(c.path,c.create),m(d,202,{accepted:!0});return}if(f==="/api/workspace/select"||f==="/api/workspace/remove"||f==="/api/workspace/new-session"){if(!("id"in c)||typeof c.id!="string"){m(d,400,{error:"\u5DE5\u4F5C\u533A\u65E0\u6548"});return}f==="/api/workspace/select"?await t.selectWorkspace(c.id):f==="/api/workspace/new-session"?await t.newSessionInWorkspace(c.id):await t.removeWorkspace(c.id),m(d,202,{accepted:!0});return}if(f==="/api/session/select"){if(!("workspaceId"in c)||typeof c.workspaceId!="string"||!("id"in c)||typeof c.id!="string"||!("path"in c)||typeof c.path!="string"){m(d,400,{error:"\u4F1A\u8BDD\u65E0\u6548"});return}await t.selectSession(c.workspaceId,c.id,c.path),m(d,202,{accepted:!0});return}if(f==="/api/thinking-level"){if(!("level"in c)||typeof c.level!="string"){m(d,400,{error:"\u63A8\u7406\u5F3A\u5EA6\u65E0\u6548"});return}await t.setThinkingLevel(c.sessionId,c.level)}else if(f==="/api/model"){if(!("provider"in c)||typeof c.provider!="string"||!("id"in c)||typeof c.id!="string"){m(d,400,{error:"\u6A21\u578B\u65E0\u6548"});return}await t.setModel(c.sessionId,c.provider,c.id)}else if(f==="/api/config"){let w=c;if(!["packages","extensions","skills"].includes(w.kind)||!["global","project"].includes(w.scope)||!["add","remove"].includes(w.action)||typeof w.value!="string"||!w.value.trim()||w.value.length>2048){m(d,400,{error:"\u914D\u7F6E\u9879\u65E0\u6548"});return}if(w.action==="add"&&w.kind!=="packages"&&be(w.value)){m(d,400,{error:"npm \u6216 Git \u6765\u6E90\u8BF7\u5728\u300C\u5305\u300D\u4E2D\u6DFB\u52A0\uFF1B\u6269\u5C55\u548C\u6280\u80FD\u53EA\u63A5\u53D7\u6587\u4EF6\u6216\u76EE\u5F55\u8DEF\u5F84"});return}m(d,200,await t.updateConfig(w));return}else if(f==="/api/message"){let w="attachments"in c?c.attachments:[];if(!Array.isArray(w)||w.length>de||w.some(S=>typeof S!="string")||new Set(w).size!==w.length){m(d,400,{error:"\u9644\u4EF6\u65E0\u6548\u6216\u8FC7\u591A"});return}let k=w.map(S=>l.get(S));if(k.some(S=>!S||S.sessionId!==c.sessionId)){m(d,400,{error:"\u9644\u4EF6\u4E0D\u53EF\u7528"});return}if(!("text"in c)||typeof c.text!="string"||!c.text.trim()&&w.length===0||c.text.length>32e3){m(d,400,{error:"\u6D88\u606F\u65E0\u6548\u6216\u8FC7\u957F"});return}let v=k,A=[c.text.trim(),...v.map(S=>`\u9644\u4EF6 ${JSON.stringify(S.name)}\uFF1A${S.path}`)].filter(Boolean).join(`
1
+ (function(){try{var r=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},e=new r.Error().stack;e&&(r._sentryDebugIds=r._sentryDebugIds||{},r._sentryDebugIds[e]="449b6114-32dc-4dde-9b3e-7a3c77caffc8",r._sentryDebugIdIdentifier="sentry-dbid-449b6114-32dc-4dde-9b3e-7a3c77caffc8")}catch{}})();import{delimiter as os,dirname as as,join as he,resolve as Be}from"node:path";import{realpathSync as cs,watch as ls}from"node:fs";import{realpath as ve}from"node:fs/promises";import{fileURLToPath as ds}from"node:url";import{DefaultPackageManager as $t,getAgentDir as J,ModelRuntime as ps,SessionManager as Vt,SettingsManager as us,VERSION as we}from"@earendil-works/pi-coding-agent";import{getSupportedThinkingLevels as fs}from"@earendil-works/pi-ai";import{randomBytes as Kr,randomUUID as ut,timingSafeEqual as Xr}from"node:crypto";import{readFile as Zr,readdir as Qr}from"node:fs/promises";import{createServer as ei}from"node:http";import{join as ft}from"node:path";import{mkdir as Jt,opendir as qt,stat as Yt}from"node:fs/promises";import{homedir as Kt}from"node:os";import{basename as Xt,dirname as Oe,join as Le,posix as Zt,resolve as $e,win32 as Qt}from"node:path";function Ve(r){return process.platform==="win32"?Qt.isAbsolute(r)&&/^(?:[A-Za-z]:[\\/]|[\\/]{2}[^\\/]+[\\/]+[^\\/]+)/.test(r):Zt.isAbsolute(r)}function er(r,e,t){if(r.length===t&&e.name.localeCompare(r[r.length-1].name)>=0)return!0;let i=0,n=r.length;for(;i<n;){let o=i+n>>>1;e.name.localeCompare(r[o].name)<0?n=o:i=o+1}return r.splice(i,0,e),r.length<=t?!1:(r.pop(),!0)}async function Ue(r){if(r!==void 0&&!Ve(r))throw new Error("\u76EE\u5F55\u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");let e=Kt(),t=$e(r??e),i=[];for(let f=t;;f=Oe(f)){let y=Oe(f);if(i.unshift({name:y===f?f:Xt(f),path:f,hidden:!1}),y===f)break}let n=[],o=!1,l=await qt(t);for await(let f of l)!f.isDirectory()&&!f.isSymbolicLink()||er(n,{name:f.name,isDirectory:f.isDirectory(),isSymbolicLink:f.isSymbolicLink()},1001)&&(o=!0);let u=[];for(let f of n){let y=Le(t,f.name);if(!f.isDirectory&&f.isSymbolicLink)try{if(!(await Yt(y)).isDirectory())continue}catch{continue}if(u.length===1e3){o=!0;break}u.push({name:f.name,path:y,hidden:f.name.startsWith(".")})}return{path:t,home:e,crumbs:i,entries:u,truncated:o}}async function Fe(r,e){if(!Ve(r))throw new Error("\u7236\u76EE\u5F55\u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");if(!e.trim()||e==="."||e===".."||/[/\\]/.test(e))throw new Error("\u6587\u4EF6\u5939\u540D\u79F0\u65E0\u6548");let t=Le($e(r),e);return await Jt(t),t}import{execFile as tr}from"node:child_process";import{accessSync as rr,constants as ir}from"node:fs";import{delimiter as sr,join as nr}from"node:path";var or=(r,e,t)=>new Promise((i,n)=>{tr(r,[...e],{encoding:"utf8",signal:t,windowsHide:!0},(o,l,u)=>{o?n(Object.assign(new Error(o.message,{cause:o}),{code:o.code,stdout:l,stderr:u})):i({stdout:l,stderr:u})})});function ar(r){for(let e of(r??"").split(sr))if(e)for(let t of["zenity","kdialog"])try{return rr(nr(e,t),ir.X_OK),!0}catch{}return!1}function He(r=process.platform,e=process.env){return e.SSH_CONNECTION||e.SSH_TTY?"browse":r==="darwin"||r==="linux"&&(e.DISPLAY||e.WAYLAND_DISPLAY)&&ar(e.PATH)?"native":"browse"}function re(r){if(!(typeof r!="object"||r===null||!("code"in r)))return typeof r.code=="string"||typeof r.code=="number"?r.code:void 0}function cr(r){return typeof r=="object"&&r!==null&&"stderr"in r&&typeof r.stderr=="string"?r.stderr:""}function be(r){return r.replace(/[\r\n]+$/,"")||null}async function ze(r,e=process.platform,t=or){if(e==="darwin")try{let i=await t("osascript",["-e",'set selectedFolder to choose folder with prompt "Select Workspace Directory"',"-e","POSIX path of selectedFolder"],r);return be(i.stdout)}catch(i){if(!r.aborted&&re(i)===1&&/(?:User canceled|-128)/i.test(cr(i)))return null;throw i}if(e==="linux"){try{return be((await t("zenity",["--file-selection","--directory","--title=Select Workspace Directory"],r)).stdout)}catch(i){if(r.aborted)throw i;if(re(i)===1)return null;if(re(i)!=="ENOENT")throw i}try{return be((await t("kdialog",["--getexistingdirectory",".","--title","Select Workspace Directory"],r)).stdout)}catch(i){if(r.aborted)throw i;if(re(i)===1)return null;throw i}}throw new Error(`\u5F53\u524D\u7CFB\u7EDF\u4E0D\u652F\u6301\u672C\u5730\u76EE\u5F55\u9009\u62E9\u5668\uFF1A${e}`)}import{createHash as lr,randomUUID as dr}from"node:crypto";import{mkdir as pr,readFile as ur,writeFile as fr}from"node:fs/promises";import{join as Ge}from"node:path";import{getAgentDir as gr}from"@earendil-works/pi-coding-agent";var ie=20*1024*1024,Je=20,mr=/^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])$/iu;function hr(r){let e=r.indexOf("."),t=(e<0?r:r.slice(0,e)).replace(/[. ]+$/u,"");return mr.test(t)}function wr(r,e){let t=0,i="";for(let n of Buffer.from(r).toString("utf8")){let o=Buffer.byteLength(n);if(t+o>e)break;i+=n,t+=o}return i}function yr(r){if(r===void 0)return"file";let t=r.slice(Math.max(r.lastIndexOf("/"),r.lastIndexOf("\\"))+1).replace(/[\u0000-\u001f\u007f]/g,"").replace(/[<>:"|?*]/g,"_").trim().replace(/[. ]+$/u,"");return hr(t)&&(t=`_${t}`),t=wr(t,255).replace(/[. ]+$/u,""),t===""||t==="."||t===".."?"file":t}function vr(r){return r.length>=8&&r.subarray(0,8).equals(Buffer.from([137,80,78,71,13,10,26,10]))?"image/png":r.length>=3&&r.subarray(0,3).equals(Buffer.from([255,216,255]))?"image/jpeg":r.length>=6&&["GIF87a","GIF89a"].includes(r.toString("ascii",0,6))?"image/gif":r.length>=12&&r.toString("ascii",0,4)==="RIFF"&&r.toString("ascii",8,12)==="WEBP"?"image/webp":null}async function qe(r,e,t,i){if(i.byteLength===0||i.byteLength>ie)throw new Error("\u6587\u4EF6\u4E3A\u7A7A\u6216\u8D85\u8FC7 20 MB");let n=yr(e),o=lr("sha256").update(i).digest("hex"),l=Ge(gr(),"pi-web","attachments",o);await pr(l,{recursive:!0});let u=Ge(l,n);try{await fr(u,i,{flag:"wx",mode:384})}catch(f){if(!(f instanceof Error&&"code"in f&&f.code==="EEXIST"))throw f}return{id:dr(),name:n,bytes:i.byteLength,path:u,mediaType:vr(i)??t.replace(/^image\//,"application/"),sessionId:r}}async function Ye(r){return{type:"image",data:(await ur(r.path)).toString("base64"),mimeType:r.mediaType}}import{randomBytes as br}from"node:crypto";function Ke(r,e,t){return r!=="openai-codex"||e!=="oauth"?t:{...t,prompt:i=>i.type==="select"&&i.options.some(n=>n.id==="browser")&&i.options.some(n=>n.id==="device_code")?Promise.resolve("browser"):t.prompt(i)}}var se=class{flows=new Map;reportError;constructor(e=()=>{}){this.reportError=e}start(e,t,i,n,o){let l=this.getActive();if(l){if(l.providerId===e&&l.method===t&&n===void 0)return l;throw new Error("\u5176\u4ED6\u63D0\u4F9B\u65B9\u7684\u767B\u5F55\u6B63\u5728\u8FDB\u884C\uFF0C\u8BF7\u5148\u5B8C\u6210\u6216\u53D6\u6D88\u5F53\u524D\u767B\u5F55")}this.flows.clear();let u=br(18).toString("base64url"),f={view:{id:u,providerId:e,method:t,status:"running"},controller:new AbortController};return this.flows.set(u,f),i(e,t,{signal:f.controller.signal,notify:y=>{f.view={...f.view,event:y,...y.type==="auth_url"||y.type==="device_code"?{authorization:y}:{}}},prompt:y=>{if(y.type==="secret"&&n!==void 0){let c=n;return n=void 0,Promise.resolve(c)}return new Promise((c,p)=>{let{signal:g,...m}=y;f.answer=c,f.reject=p,f.view={...f.view,status:"waiting",prompt:m},g?.aborted?p(new Error("\u767B\u5F55\u8F93\u5165\u5DF2\u53D6\u6D88")):g?.addEventListener("abort",()=>p(new Error("\u767B\u5F55\u8F93\u5165\u5DF2\u53D6\u6D88")),{once:!0})})}}).then(()=>{f.view.status!=="cancelled"&&(f.view={id:u,providerId:e,method:t,status:"done"})}).catch(y=>{if(f.view.status!=="cancelled"){let c=new Error("Provider login failed");y instanceof Error&&y.stack&&(c.stack=`${c.message}
2
+ ${y.stack.split(`
3
+ `).slice(1).join(`
4
+ `)}`);let p=this.reportError(c,{...o,stage:"provider_login"});f.view={id:u,providerId:e,method:t,status:"error",error:"\u767B\u5F55\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u63D0\u4F9B\u65B9\u63D0\u793A\u5E76\u91CD\u8BD5\u3002",errorId:p}}}),{...f.view}}get(e){let t=this.flows.get(e)?.view;return t?{...t}:void 0}getActive(){let e=[...this.flows.values()].find(({view:t})=>t.status==="running"||t.status==="waiting")?.view;return e?{...e}:void 0}respond(e,t){let i=this.flows.get(e);if(!i?.answer||i.view.status!=="waiting"||i.view.prompt?.type==="select"&&!i.view.prompt.options.some(o=>o.id===t))return!1;let n=i.answer;return i.answer=void 0,i.reject=void 0,i.view={...i.view,status:"running",prompt:void 0},n(t),!0}cancel(e){let t=this.flows.get(e);return!t||t.view.status==="done"||t.view.status==="error"?!1:(t.view={...t.view,status:"cancelled",prompt:void 0},t.controller.abort(),t.reject?.(new Error("\u767B\u5F55\u5DF2\u53D6\u6D88")),t.answer=void 0,t.reject=void 0,!0)}close(){for(let e of this.flows.keys())this.cancel(e);this.flows.clear()}};import{randomBytes as kr}from"node:crypto";import{readFile as Pr,rename as Er,rm as Ir,stat as Sr,writeFile as xr,mkdir as Cr}from"node:fs/promises";import{dirname as Ar}from"node:path";var _r=["openai-completions","openai-responses","anthropic-messages"];function ke(r){if(!r||typeof r!="object")return!1;let e=r;if(typeof e.id!="string"||!/^[a-z0-9][a-z0-9._-]{0,63}$/.test(e.id)||typeof e.name!="string"||!e.name.trim()||e.name.length>100||typeof e.modelId!="string"||!e.modelId.trim()||e.modelId.length>200||!_r.includes(e.api)||typeof e.baseUrl!="string"||e.baseUrl.length>2048)return!1;try{let t=new URL(e.baseUrl);return(t.protocol==="https:"||t.protocol==="http:")&&!!t.hostname&&!t.username&&!t.password&&!t.hash}catch{return!1}}async function Xe(r,e){if(!ke(e))throw new Error("\u81EA\u5B9A\u4E49\u63D0\u4F9B\u65B9\u540D\u79F0\u3001\u5730\u5740\u6216\u6A21\u578B\u65E0\u6548");let t;try{t=await Pr(r,"utf8")}catch(u){if(u.code!=="ENOENT")throw u}let i;if(t===void 0)i={providers:{}};else{try{i=JSON.parse(t)}catch{throw new Error("models.json \u542B\u6CE8\u91CA\u6216\u683C\u5F0F\u9519\u8BEF\uFF0C\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u624B\u52A8\u6DFB\u52A0\u63D0\u4F9B\u65B9")}if(!i||typeof i!="object"||!i.providers||typeof i.providers!="object"||Array.isArray(i.providers))throw new Error("models.json \u7ED3\u6784\u65E0\u6548")}if(Object.hasOwn(i.providers,e.id))throw new Error("\u63D0\u4F9B\u65B9\u5DF2\u5B58\u5728");let n={...i,providers:{...i.providers,[e.id]:{name:e.name.trim(),baseUrl:e.baseUrl,api:e.api,models:[{id:e.modelId.trim()}]}}};await Cr(Ar(r),{recursive:!0});let o=t===void 0?384:(await Sr(r)).mode&511,l=`${r}.pi-web-${kr(6).toString("hex")}.tmp`;try{await xr(l,`${JSON.stringify(n,null,2)}
5
+ `,{mode:o,flag:"wx"}),await Er(l,r)}finally{await Ir(l,{force:!0})}}import{randomBytes as Tr}from"node:crypto";import{mkdir as Mr,readFile as Rr,rename as Wr,rm as Nr,stat as jr,writeFile as Br}from"node:fs/promises";import{dirname as Dr}from"node:path";function Ze(r){if(!r||r.length>2048)return!1;try{let e=new URL(r);return(e.protocol==="https:"||e.protocol==="http:")&&!!e.hostname&&!e.username&&!e.password&&!e.search&&!e.hash}catch{return!1}}function Qe(r){if(!r||typeof r!="object")return!1;let e=r;return e.action==="save"?(e.originalId===void 0||typeof e.originalId=="string")&&et(e.model):e.action==="base_url"?e.baseUrl===null||typeof e.baseUrl=="string"&&Ze(e.baseUrl):e.action==="remove"&&typeof e.id=="string"&&e.id.length>0&&e.id.length<=200}function et(r){if(!r||typeof r!="object")return!1;let e=r;if(typeof e.id!="string"||!e.id.trim()||e.id.length>200||e.name!==void 0&&(typeof e.name!="string"||!e.name.trim()||e.name.length>200))return!1;for(let t of[e.contextWindow,e.maxTokens])if(t!==void 0&&(!Number.isSafeInteger(t)||t<=0))return!1;return e.input===void 0||Array.isArray(e.input)&&e.input.length>0&&e.input.every(t=>t==="text"||t==="image")&&new Set(e.input).size===e.input.length}async function tt(r){let e;try{e=await Rr(r,"utf8")}catch(i){if(i.code!=="ENOENT")throw i}if(e===void 0)return{config:{providers:{}}};let t;try{t=JSON.parse(e)}catch{throw new Error("models.json \u542B\u6CE8\u91CA\u6216\u683C\u5F0F\u9519\u8BEF\uFF0C\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u624B\u52A8\u4FEE\u6539")}if(!t||typeof t!="object"||!t.providers||typeof t.providers!="object"||Array.isArray(t.providers))throw new Error("models.json \u7ED3\u6784\u65E0\u6548");return{config:t,existing:e}}async function Or(r,e,t){await Mr(Dr(r),{recursive:!0});let i=t===void 0?384:(await jr(r)).mode&511,n=`${r}.pi-web-${Tr(6).toString("hex")}.tmp`;try{await Br(n,`${JSON.stringify(e,null,2)}
6
+ `,{mode:i,flag:"wx"}),await Wr(n,r)}finally{await Nr(n,{force:!0})}}async function rt(r,e,t){if(!t.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:i}=await tt(r),n=i.providers[e],o=new Set(n?.models?.map(l=>l.id)??[]);return{providerId:e,baseUrl:n?.baseUrl,models:t.getModels(e).map(l=>({id:l.id,name:l.name,contextWindow:l.contextWindow,maxTokens:l.maxTokens,input:[...l.input],source:o.has(l.id)?"custom":"builtin",overridden:!!n?.modelOverrides?.[l.id]}))}}async function it(r,e,t,i){if(!i.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:n,existing:o}=await tt(r),l={...n.providers[e]??{}},u=[...l.models??[]],f={...l.modelOverrides??{}};if(t.action==="base_url"){if(t.baseUrl!==null&&!Ze(t.baseUrl))throw new Error("API \u5730\u5740\u65E0\u6548");t.baseUrl===null?delete l.baseUrl:l.baseUrl=t.baseUrl}else if(t.action==="save"){if(!et(t.model))throw new Error("\u6A21\u578B\u53C2\u6570\u65E0\u6548");let y={id:t.model.id.trim(),...t.model.name===void 0?{}:{name:t.model.name},...t.model.contextWindow===void 0?{}:{contextWindow:t.model.contextWindow},...t.model.maxTokens===void 0?{}:{maxTokens:t.model.maxTokens},...t.model.input===void 0?{}:{input:t.model.input}},c=t.originalId,p=c===void 0?-1:u.findIndex(g=>g.id===c);if(c===void 0&&(u.some(g=>g.id===y.id)||i.getModel(e,y.id)))throw new Error("\u6A21\u578B ID \u5DF2\u5B58\u5728");if(p>=0){if(y.id!==c&&(u.some(m=>m.id===y.id)||i.getModel(e,y.id)))throw new Error("\u6A21\u578B ID \u5DF2\u5B58\u5728");let g={...u[p],...y};for(let m of["name","contextWindow","maxTokens","input"])y[m]===void 0&&delete g[m];u[p]=g}else if(c!==void 0&&i.getModel(e,c)){if(y.id!==c)throw new Error("\u5185\u7F6E\u6A21\u578B ID \u4E0D\u53EF\u4FEE\u6539");let{id:g,...m}=y;f[c]={...f[c],...m};for(let k of["name","contextWindow","maxTokens","input"])y[k]===void 0&&delete f[c][k]}else{if(c!==void 0)throw new Error("\u6A21\u578B\u4E0D\u5B58\u5728");u.push(y)}}else{let y=u.findIndex(c=>c.id===t.id);if(y>=0)u.splice(y,1);else if(Object.hasOwn(f,t.id))delete f[t.id];else throw new Error("\u53EA\u80FD\u79FB\u9664\u81EA\u5B9A\u4E49\u6A21\u578B\u6216\u6062\u590D\u5DF2\u4FEE\u6539\u7684\u5185\u7F6E\u6A21\u578B")}u.length?l.models=u:delete l.models,Object.keys(f).length?l.modelOverrides=f:delete l.modelOverrides,Object.keys(l).length?n.providers[e]=l:delete n.providers[e],await Or(r,n,o)}function st(r){return/^(?:npm:|git:|https?:\/\/|ssh:\/\/|git@)/i.test(r.trim())}import{randomBytes as dt,createHash as Hr}from"node:crypto";import{fileURLToPath as zr}from"node:url";var nt="pi-webapp@0.1.8+d80a7230908decf48708",$="d80a7230908decf48708";var ot={userInfo:!1,cookies:!1,httpHeaders:!1,httpBodies:[],urlQueryParams:!1,genAI:{inputs:!1,outputs:!1},graphQL:{document:!1,variables:!1},databaseQueryData:!1,queues:!1,stackFrameVariables:!1,frameContextLines:0},Lr=new Set(["stage","route","method","status","durationMs","connection","idle","model","thinkingLevel","messageCount","attachmentCount","session","requestId","operationId","errorId","repeats","dropped","componentStack","eventType","sequence","nodeVersion","piVersion","platform","browser","buildId","code"]),$r=new Set(["/api/plugins","/api/plugin-action","/api/plugin-interaction","/api/resume","/api/update","/api/update/version","/api/provider/models","/api/provider/logout","/api/provider/login/active","/api/telemetry/config","/api/image","/api/attachment","/api/attachment/remove","/api/session","/api/providers","/api/models","/api/config","/api/workspaces","/api/commands","/api/events","/api/message","/api/abort","/api/compact","/api/new-session","/api/model","/api/thinking-level","/api/provider/login","/api/provider/login/respond","/api/provider/login/cancel","/api/provider/custom","/api/workspace/add","/api/workspace/select","/api/workspace/new-session","/api/workspace/remove","/api/session/select","/api/directory/capability","/api/directory/list","/api/directory/create","/api/directory/pick"]);function at(r){return r==="/api/message"||r.startsWith("/api/provider/")||["/api/plugin-action","/api/plugin-interaction","/api/resume","/api/compact"].includes(r)}function B(r){return r.slice(0,8192).replace(/(?:Bearer\s+\S+|(?:api[_-]?key|token|password|secret|authorization)\s*[=:]\s*\S+)/gi,"[redacted]").replace(/\b(?:sk-|sntrys_|eyJ)[A-Za-z0-9_.-]+/g,"[redacted]").replace(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g,"[email]").replace(/https?:\/\/[^\s)]+/gi,"[url]").replace(/(?:file:\/\/)?(?:\/[\w.~-]+){2,}(?::\d+(?::\d+)?)?/g,"[path]").replace(/[A-Za-z]:\\[^\s)]+/g,"[path]").replace(/(["'`])[^\n]*?\1/g,"[quoted]").replace(/\{[^\n]*\}/g,"[object]").replace(/\b[A-Za-z0-9_-]{24,}\b/g,"[redacted]").slice(0,1024)}function V(r){let e={};for(let t of Lr){let i=r[t];t==="route"&&typeof i=="string"?e[t]=$r.has(i.split("?")[0])?i.split("?")[0]:"[route]":typeof i=="string"?e[t]=["requestId","operationId","errorId","session","buildId"].includes(t)&&/^[\w-]{1,80}$/.test(i)?i:B(i):(typeof i=="boolean"||typeof i=="number"&&Number.isFinite(i)||i===null)&&(e[t]=i)}return e}function Pe(r){let e=r.replace(/\\/g,"/").split(/[?#]/)[0];return e.startsWith("node:")?e.slice(0,150):`app:///${(e.match(/(?:^|\/)((?:web\/src|extension|shared|dist|assets)\/[^\s:)]+)$/)?.[1]??e.split("/").pop()??"unknown").replace(/[^\w./-]/g,"_").slice(-200)}`}function oe(r,e=0){let t=r instanceof Error?r:new Error(typeof r=="string"?r:"Non-Error rejection"),i=new Error(B(t.message));if(i.name=B(t.name).slice(0,100),t.stack){let n=t.stack.split(`
7
+ `).slice(1,31).map(o=>{let l=o.match(/((?:file:\/\/|https?:\/\/|\/|[A-Za-z]:\\)[^\s()]+):(\d+):(\d+)(\)?)$/);return l?`${B(o.slice(0,l.index))}${l[1]}:${l[2]}:${l[3]}${l[4]}`:B(o)});i.stack=`${i.name}: ${i.message}
8
+ ${n.join(`
9
+ `)}`}return e<3&&t.cause!==void 0&&(i.cause=oe(t.cause,e+1)),i}function ae(r,e){let t=new Error(e);return r instanceof Error&&(t.name=r.name,r.stack&&(t.stack=`${t.name}: ${e}
10
+ ${r.stack.split(`
11
+ `).slice(1).join(`
12
+ `)}`)),t}function Vr(r){return{...r.filename?{filename:Pe(r.filename)}:{},...r.abs_path?{abs_path:Pe(r.abs_path)}:{},...r.function?{function:B(r.function)}:{},lineno:r.lineno,colno:r.colno,in_app:r.in_app}}function Ur(r){return{event_id:r.event_id,timestamp:r.timestamp,platform:r.platform,level:r.level,release:r.release,dist:r.dist,environment:B(r.environment??"production"),...r.message?{message:B(r.message)}:{},exception:r.exception?{values:r.exception.values?.slice(0,4).map(e=>({type:B(e.type??"Error"),value:B(e.value??""),...e.stacktrace?{stacktrace:{frames:e.stacktrace.frames?.slice(-30).map(Vr)}}:{},...e.mechanism?{mechanism:{type:e.mechanism.type,handled:e.mechanism.handled}}:{}}))}:void 0,tags:{side:r.tags?.side,buildId:r.tags?.buildId},contexts:{diagnostic:V(r.contexts?.diagnostic??{})},breadcrumbs:r.breadcrumbs?.slice(-100).map(e=>({timestamp:e.timestamp,category:B(e.category??"app"),data:V(e.data??{})})),debug_meta:r.debug_meta?{images:r.debug_meta.images?.slice(0,10).map(e=>({type:e.type,debug_id:e.debug_id,...e.code_file?{code_file:Pe(e.code_file)}:{}}))}:void 0}}function ct(r,e){return e.attachments=[],Ur(r)}var K=class{items=[];bytes=0;encoder=new TextEncoder;add(e,t={}){let i={timestamp:Date.now()/1e3,category:B(e),data:V(t)},n=this.encoder.encode(JSON.stringify(i)).byteLength+1;for(this.items.push({item:i,size:n}),this.bytes+=n;this.items.length>100||this.bytes>64*1024-2;)this.bytes-=this.items.shift().size}snapshot(){return this.items.map(({item:e})=>e)}},Ee=class{windowAt=-1;total=0;seen=new Map;take(e,t=Date.now()){(this.windowAt<0||t-this.windowAt>=6e4)&&(this.windowAt=t,this.total=0);let i=this.seen.get(e);if(i&&t-i.at<6e4){i.repeats++;return}if(!(this.total>=20))return this.total++,this.seen.size>=64&&!i&&this.seen.delete(this.seen.keys().next().value),this.seen.set(e,{at:t,repeats:0}),{repeats:i?.repeats??0}}},Fr=new Set(["\u4F1A\u8BDD\u5DF2\u5207\u6362","Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F","\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F","\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u518D\u5207\u6362\u5DE5\u4F5C\u533A","\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u518D\u5207\u6362\u4F1A\u8BDD","\u8BF7\u5148\u5207\u6362\u5230\u5176\u4ED6\u5DE5\u4F5C\u533A","\u65B0\u4F1A\u8BDD\u5DF2\u53D6\u6D88","\u5DF2\u6709\u767B\u5F55\u6B63\u5728\u8FDB\u884C","\u6A21\u578B\u4E0D\u53EF\u7528","\u6A21\u578B\u63D0\u4F9B\u65B9\u672A\u914D\u7F6E\u8BA4\u8BC1","\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u6B64\u63A8\u7406\u5F3A\u5EA6","\u5176\u4ED6\u63D0\u4F9B\u65B9\u7684\u767B\u5F55\u6B63\u5728\u8FDB\u884C\uFF0C\u8BF7\u5148\u5B8C\u6210\u6216\u53D6\u6D88\u5F53\u524D\u767B\u5F55","\u5F53\u524D\u4F1A\u8BDD\u6CA1\u6709\u6682\u505C\u7684\u4EFB\u52A1","\u8BF7\u5148\u5B8C\u6210\u5F53\u524D\u4EA4\u4E92\u6216\u5BA1\u6279","\u8BF7\u5148\u9009\u62E9\u6A21\u578B","\u8BF7\u5148\u8FDE\u63A5\u5F53\u524D\u6A21\u578B","\u63D2\u4EF6\u672A\u542F\u7528","\u4F1A\u8BDD\u8FD0\u884C\u5B9E\u4F8B\u5DF2\u5207\u6362","\u63D0\u4F9B\u65B9\u5DF2\u5B58\u5728","\u6587\u4EF6\u8D85\u8FC7 20 MB","\u8BF7\u6C42\u5185\u5BB9\u8FC7\u5927","\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A","\u63A8\u7406\u5F3A\u5EA6\u65E0\u6548"]);function U(r){return r instanceof Error&&(r.name==="AbortError"||Fr.has(r.message))}var ne=class{budget=new Ee;breadcrumbs;scopeClass;seen=new WeakSet;state={};client;side;buildId;constructor(e,t,i,n,o=new K){this.client=e,this.side=t,this.buildId=i,this.scopeClass=n.Scope,this.breadcrumbs=o,e.addIntegration(n.linkedErrorsIntegration({limit:4}))}setState(e){this.state=V(e)}capture(e,t={},i){try{if(U(e))return;if(typeof e=="object"&&e!==null){if(this.seen.has(e))return;this.seen.add(e)}let n=oe(e),o=`${n.name}:${n.message}:${n.stack?.split(`
13
+ `)[1]??""}:${t.stage??""}`,l=this.budget.take(o);if(!l)return;let u=new this.scopeClass;u.setClient(this.client),u.setTags({side:this.side,buildId:this.buildId}),u.setContext("diagnostic",V({...this.state,...t,repeats:l.repeats}));for(let f of this.breadcrumbs.snapshot())u.addBreadcrumb(f,100);return u.captureException(n,i?{event_id:i}:void 0)}catch{return}}ignore(e){this.seen.add(e)}};function lt(r,e){return r({...e,bufferSize:20},async({body:t})=>{let i=await fetch(e.url,{method:"POST",body:t,signal:AbortSignal.timeout(3e3),credentials:"omit",referrerPolicy:"no-referrer",redirect:"error",headers:{"Content-Type":"application/x-sentry-envelope"}});return{statusCode:i.status,headers:{"x-sentry-rate-limits":i.headers.get("x-sentry-rate-limits"),"retry-after":i.headers.get("retry-after")}}})}var Gr="https://070c0b7c5ac18d940c294e63ecfa0793@o4506663318716416.ingest.us.sentry.io/4512191040716800";function Jr(r=process.env,e=console.warn){let t=i=>{let n={enabled:!1,environment:r.PI_WEB_SENTRY_ENVIRONMENT||"production",release:nt,buildId:$},o=r[`PI_WEB_SENTRY_${i}_DSN`]??r.PI_WEB_SENTRY_DSN??Gr;if(r.PI_WEB_SENTRY_ENABLED==="false"||!o)return n;try{let l=new URL(o);if(l.protocol!=="https:"||!/^[\w-]+$/.test(l.username)||l.password||l.search||l.hash||!/\/(?:[\w-]+\/)*\d+$/.test(l.pathname))throw new Error;return{...n,enabled:!0,dsn:o}}catch{return e(`pi-webapp: invalid ${i.toLowerCase()} Sentry DSN; error reporting disabled for this side.`),n}};return{browser:t("BROWSER"),node:t("NODE")}}var F=class{config;ready;reporter;client;salt=dt(16);breadcrumbs=new K;seen=new WeakSet;early=[];state={nodeVersion:process.version,platform:process.platform};fatal;closed=!1;failed=!1;get enabled(){return this.config.node.enabled&&!this.closed&&!this.failed}constructor(e={}){if(this.config=Jr(e.env),!this.config.node.enabled){this.ready=Promise.resolve();return}if(e.monitor!==!1){let t=zr(import.meta.url).replace(/\\/g,"/"),i=t.slice(0,t.lastIndexOf("/")+1);this.fatal=n=>{n.stack?.replace(/\\/g,"/").includes(t.endsWith("extension.js")?t:i)&&this.capture(n,{stage:"fatal"})},process.on("uncaughtExceptionMonitor",this.fatal)}this.ready=import("@sentry/node").then(t=>{if(!this.closed){this.client=new t.NodeClient({...this.config.node,dist:$,integrations:[],transport:e.transport??(i=>lt(t.createTransport,i)),stackParser:t.defaultStackParser,beforeSend:ct,sendClientReports:!1,dataCollection:{...ot,httpBodies:[]},includeServerName:!1,enableRuntimeChannelInjection:!1,beforeSendLog:()=>null,beforeSendMetric:()=>null,enableOpenTelemetrySetup:!1,maxBreadcrumbs:100}),this.reporter=new ne(this.client,"node",$,t,this.breadcrumbs),this.reporter.setState(this.state);for(let i of this.early)this.reporter.capture(i.error,i.context,i.eventId)}}).catch(()=>{this.failed=!0,console.warn("pi-webapp: Sentry initialization failed; error reporting disabled.")}).finally(()=>{this.early=[]})}capture(e,t={}){try{if(!this.enabled||U(e))return;if(typeof e=="object"&&e!==null){if(this.seen.has(e))return;this.seen.add(e)}if(this.reporter)return this.reporter.capture(e,t);if(this.early.length>=20)return;let i=dt(16).toString("hex");return this.early.push({error:oe(e),context:V(t),eventId:i}),i}catch{return}}setState(e){this.state=V({...this.state,...e}),this.reporter?.setState(this.state)}breadcrumb(e,t={}){this.enabled&&this.breadcrumbs.add(e,t)}session(e){return Hr("sha256").update(this.salt).update(e).digest("hex").slice(0,16)}async close(){let e=performance.now(),t;try{await Promise.race([this.ready,new Promise(i=>{t=setTimeout(i,500)})])}finally{clearTimeout(t),this.closed=!0,this.fatal&&process.off("uncaughtExceptionMonitor",this.fatal)}try{await this.client?.close(Math.max(1,500-(performance.now()-e)))}catch{}}};import{VERSION as ti}from"@earendil-works/pi-coding-agent";import{readFile as qr}from"node:fs/promises";import{join as Yr}from"node:path";async function pt(r){try{let e=JSON.parse(await qr(Yr(r,".vite/manifest.json"),"utf8"));if(!e||typeof e!="object")return{};let t=new Set;for(let n of Object.values(e))if(!(!n||typeof n!="object"))for(let o of[n.file,...Array.isArray(n.css)?n.css:[],...Array.isArray(n.assets)?n.assets:[]])typeof o=="string"&&/^assets\/[\w.-]+\.(?:js|css|woff2?|ttf|png|jpe?g|svg|webp)$/.test(o)&&t.add(o);let i={js:"text/javascript; charset=utf-8",css:"text/css; charset=utf-8",svg:"image/svg+xml",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",webp:"image/webp",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf"};return Object.fromEntries([...t].map(n=>[`/${n}`,{path:n,type:i[n.split(".").pop()]}]))}catch{return{}}}var ri={"/":{path:"index.html",type:"text/html; charset=utf-8"},"/assets/app.js":{path:"assets/app.js",type:"text/javascript; charset=utf-8"},"/assets/style.css":{path:"assets/style.css",type:"text/css; charset=utf-8"}};function w(r,e,t){typeof t=="object"&&t!==null&&"error"in t&&(t={errorCode:e>=500?"server_error":"validation_error",...t,requestId:r.getHeader("X-Request-ID"),operationId:r.getHeader("X-Operation-ID")}),r.writeHead(e,{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}),r.end(JSON.stringify(t))}function ii(r,e){let t=r.headers.authorization;if(typeof t!="string"||!t.startsWith("Bearer "))return!1;let i=Buffer.from(t.slice(7),"utf8");return i.length===e.length&&Xr(i,e)}async function si(r){let e=0,t=[];for await(let i of r){let n=Buffer.isBuffer(i)?i:Buffer.from(i);if(e+=n.length,e>64*1024)throw new Error("\u8BF7\u6C42\u5185\u5BB9\u8FC7\u5927");t.push(n)}return JSON.parse(Buffer.concat(t).toString("utf8"))}async function ni(r){let e=0,t=[];for await(let i of r){let n=Buffer.isBuffer(i)?i:Buffer.from(i);if(e+=n.length,e>ie)throw new Error("\u6587\u4EF6\u8D85\u8FC7 20 MB");t.push(n)}return Buffer.concat(t)}async function oi(r,e=0){await new Promise((i,n)=>{r.once("error",n),r.listen(e,"127.0.0.1",()=>{r.off("error",n),i()})});let t=r.address();if(t===null||typeof t=="string")throw new Error("\u65E0\u6CD5\u786E\u5B9A\u76D1\u542C\u7AEF\u53E3");return t.port}async function gt(r,e,t=new F){t.setState({piVersion:ti});let i=process.env.PI_WEBAPP_RESTART_TOKEN,n=i&&/^[A-Za-z0-9_-]{32}$/.test(i)?i:Kr(24).toString("base64url"),o=Buffer.from(n),l=He(),u=new Set,f=new Map,y=new se((h,d)=>t.capture(h,d)),c=h=>t.setState({nodeVersion:process.version,platform:process.platform,session:t.session(h.sessionId),idle:h.idle,model:h.model,thinkingLevel:h.thinkingLevel,messageCount:h.messages.length}),p="",g=!1,m={...ri,...await pt(e)};for(let h of await Qr(ft(e,"assets")).catch(()=>[])){let d=/^[\w.-]+\.(js|css|woff2?|ttf)$/.exec(h);if(!d)continue;let C={js:"text/javascript; charset=utf-8",css:"text/css; charset=utf-8",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf"};m[`/assets/${h}`]={path:`assets/${h}`,type:C[d[1]]}}let k=ei(async(h,d)=>{let C=R=>typeof R=="string"&&/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(R),E=C(h.headers["x-request-id"])?h.headers["x-request-id"]:ut(),x={requestId:E,operationId:C(h.headers["x-operation-id"])?h.headers["x-operation-id"]:void 0};d.setHeader("X-Request-ID",E),x.operationId&&d.setHeader("X-Operation-ID",x.operationId);let v="/",zt=performance.now(),W=(R,a,b)=>{let I=!U(R)&&at(v)?ae(R,"Agent or provider operation failed"):R,O=t.capture(I,{...x,route:v,method:h.method,status:a,stage:"http"});w(d,a,{error:b,errorId:O,errorReported:t.enabled,errorCode:U(R)?"validation_error":"unexpected_error"})};d.once("finish",()=>{v.startsWith("/api/telemetry/")||t.breadcrumb("request",{...x,route:v,method:h.method,status:d.statusCode,durationMs:Math.round(performance.now()-zt)})});try{d.setHeader("X-Content-Type-Options","nosniff"),d.setHeader("Referrer-Policy","no-referrer"),d.setHeader("Content-Security-Policy",`default-src 'self'; script-src 'self'; style-src 'self'; connect-src 'self'${t.config.browser.dsn?` ${new URL(t.config.browser.dsn).origin}`:""}; img-src 'self' data: blob:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'`);try{v=new URL(h.url??"/",p).pathname}catch{w(d,400,{error:"\u8BF7\u6C42\u5730\u5740\u65E0\u6548"});return}let R=m[v];if(h.method==="GET"&&R){try{let a=await Zr(ft(e,R.path));d.writeHead(200,{"Content-Type":R.type,"Cache-Control":"no-store"}),d.end(a)}catch(a){W(a,500,"\u9875\u9762\u6587\u4EF6\u4E0D\u53EF\u7528")}return}if(h.method==="GET"&&v.startsWith("/plugins/")){try{let a=await r.pluginAsset?.(h.url??v);if(!a){w(d,404,{error:"\u63D2\u4EF6\u8D44\u6E90\u4E0D\u5B58\u5728"});return}d.writeHead(200,{"Content-Type":a.type,"Cache-Control":"no-store"}),d.end(a.bytes)}catch(a){W(a,404,"\u63D2\u4EF6\u8D44\u6E90\u4E0D\u53EF\u7528")}return}if(!v.startsWith("/api/")){w(d,404,{error:"\u672A\u627E\u5230"});return}if(!ii(h,o)){w(d,401,{error:"\u8BBF\u95EE\u4EE4\u724C\u65E0\u6548"});return}if(h.method==="GET"&&v==="/api/telemetry/config"){w(d,200,t.config.browser);return}if(h.method==="GET"&&v==="/api/update/version"){try{w(d,200,{current:await r.selfUpdate?.runningVersion()??null})}catch(a){W(a,503,a instanceof Error?a.message:"\u65E0\u6CD5\u8BFB\u53D6\u7248\u672C")}return}if(h.method==="GET"&&v==="/api/update"){try{w(d,200,await r.selfUpdate?.check()??{canRestart:!1,reason:"\u5F53\u524D\u6269\u5C55\u4E0D\u652F\u6301\u5728\u7EBF\u5347\u7EA7"})}catch(a){W(a,503,a instanceof Error?a.message:"\u68C0\u67E5\u66F4\u65B0\u5931\u8D25")}return}if(h.method==="GET"&&v==="/api/image"){let a=new URL(h.url??v,p),b=a.searchParams.get("sessionId")??"",S=a.searchParams.get("messageId")??"",I=Number(a.searchParams.get("index"));if(!b||b!==r.snapshot().sessionId||!S||!Number.isInteger(I)||I<0||I>100){w(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u56FE\u7247\u5730\u5740\u65E0\u6548"});return}let O=r.image?.(b,S,I);if(!O||!["image/png","image/jpeg","image/webp","image/gif"].includes(O.mimeType)){w(d,404,{error:"\u56FE\u7247\u4E0D\u53EF\u7528"});return}d.writeHead(200,{"Content-Type":O.mimeType,"Cache-Control":"private, no-store"}),d.end(O.data);return}if(h.method==="POST"&&v==="/api/attachment"){if(h.headers.origin!==void 0&&h.headers.origin!==p){w(d,403,{error:"\u6765\u6E90\u4E0D\u5339\u914D"});return}let a=new URL(h.url??v,p),b=a.searchParams.get("sessionId"),S=a.searchParams.get("name");try{if(!b||!S||S.length>1024||b!==r.snapshot().sessionId){w(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u6587\u4EF6\u540D\u65E0\u6548"});return}if(Number(h.headers["content-length"]??0)>ie){w(d,413,{error:"\u6587\u4EF6\u8D85\u8FC7 20 MB"});return}let I=await qe(b,S,h.headers["content-type"]??"application/octet-stream",await ni(h));if(b!==r.snapshot().sessionId){w(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}f.set(I.id,I),w(d,201,{id:I.id,name:I.name,bytes:I.bytes})}catch(I){W(I,400,I instanceof Error?I.message:"\u4E0A\u4F20\u5931\u8D25")}return}if(h.method==="GET"&&v==="/api/session"){try{let a=r.snapshot();c(a),w(d,200,a)}catch(a){W(a,503,"\u5F53\u524D\u4F1A\u8BDD\u4E0D\u53EF\u7528")}return}if(h.method==="GET"&&v==="/api/plugins"){try{w(d,200,await r.plugins?.()??{plugins:[],errors:[]})}catch(a){W(a,503,"\u63D2\u4EF6\u76EE\u5F55\u4E0D\u53EF\u7528")}return}if(h.method==="GET"&&v==="/api/providers"){try{w(d,200,await r.providers?.()??[])}catch(a){W(a,503,"\u6A21\u578B\u63D0\u4F9B\u65B9\u4E0D\u53EF\u7528")}return}if(h.method==="GET"&&v==="/api/provider/models"){let a=new URL(h.url??v,p).searchParams.get("providerId")??"";try{if(!a||!r.providerModels){w(d,400,{error:"\u63D0\u4F9B\u65B9\u65E0\u6548"});return}w(d,200,await r.providerModels(a))}catch(b){W(b,400,b instanceof Error?b.message:"\u6A21\u578B\u76EE\u5F55\u4E0D\u53EF\u7528")}return}if(h.method==="GET"&&v==="/api/provider/login/active"){w(d,200,{active:y.getActive()??null});return}if(h.method==="GET"&&v==="/api/provider/login"){let a=new URL(h.url??v,p).searchParams.get("id")??"",b=y.get(a);w(d,b?200:404,b??{error:"\u767B\u5F55\u6D41\u7A0B\u4E0D\u5B58\u5728"});return}if(h.method==="GET"&&(v==="/api/models"||v==="/api/config"||v==="/api/workspaces"||v==="/api/commands")){try{w(d,200,v==="/api/models"?await r.models():v==="/api/config"?await r.config():v==="/api/commands"?r.commands?.()??[]:await r.workspaces())}catch(a){W(a,503,"Pi \u914D\u7F6E\u4E0D\u53EF\u7528")}return}if(h.method==="GET"&&v==="/api/directory/capability"){w(d,200,{kind:l});return}if(h.method==="GET"&&v==="/api/events"){let a;try{a=r.snapshot(),c(a)}catch(b){W(b,503,"\u5F53\u524D\u4F1A\u8BDD\u4E0D\u53EF\u7528");return}d.writeHead(200,{"Content-Type":"application/x-ndjson; charset=utf-8","Cache-Control":"no-store",Connection:"keep-alive","X-Accel-Buffering":"no"}),u.add(d),d.write(`${JSON.stringify({type:"snapshot",session:a})}
14
+ `),d.on("close",()=>u.delete(d));return}if(h.method==="POST"&&["/api/plugin-interaction","/api/plugin-action","/api/update","/api/message","/api/attachment/remove","/api/abort","/api/resume","/api/compact","/api/new-session","/api/model","/api/thinking-level","/api/config","/api/provider/login","/api/provider/login/respond","/api/provider/login/cancel","/api/provider/custom","/api/provider/models","/api/provider/logout","/api/workspace/add","/api/workspace/select","/api/workspace/new-session","/api/workspace/remove","/api/session/select","/api/directory/list","/api/directory/create","/api/directory/pick"].includes(v)){if(h.headers.origin!==void 0&&h.headers.origin!==p){w(d,403,{error:"\u6765\u6E90\u4E0D\u5339\u914D"});return}if(!h.headers["content-type"]?.startsWith("application/json")){w(d,415,{error:"\u9700\u8981 JSON \u8BF7\u6C42"});return}try{let a;try{a=await si(h)}catch(b){if(b instanceof SyntaxError||U(b)){w(d,400,{error:"\u8BF7\u6C42\u5185\u5BB9\u65E0\u6548"});return}throw b}if(typeof a!="object"||a===null||!("sessionId"in a)||typeof a.sessionId!="string"){w(d,400,{error:"\u7F3A\u5C11\u4F1A\u8BDD\u6807\u8BC6"});return}if(v==="/api/plugin-interaction"){if(a.sessionId!==r.snapshot().sessionId){w(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("pluginId"in a)||typeof a.pluginId!="string"||a.pluginId.length>200||!("requestId"in a)||typeof a.requestId!="string"||a.requestId.length>200||!r.resolvePluginInteraction||!("value"in a)){w(d,400,{error:"\u63D2\u4EF6\u4EA4\u4E92\u54CD\u5E94\u65E0\u6548"});return}await r.resolvePluginInteraction(a.sessionId,a.pluginId,a.requestId,a.value),w(d,200,{accepted:!0});return}if(v==="/api/plugin-action"){if(a.sessionId!==r.snapshot().sessionId){w(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("pluginId"in a)||typeof a.pluginId!="string"||a.pluginId.length>200||!("action"in a)||typeof a.action!="string"||a.action.length>100||!r.invokePluginAction){w(d,400,{error:"\u63D2\u4EF6\u52A8\u4F5C\u65E0\u6548"});return}let b=await r.invokePluginAction(a.sessionId,a.pluginId,a.action,"input"in a?a.input:void 0);w(d,200,{value:b});return}if(v==="/api/update"){if(a.sessionId!==r.snapshot().sessionId){w(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!r.snapshot().idle){w(d,409,{error:"\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u540E\u518D\u5347\u7EA7"});return}if(!r.selfUpdate){w(d,409,{error:"\u5F53\u524D\u6269\u5C55\u4E0D\u652F\u6301\u5728\u7EBF\u5347\u7EA7"});return}let b=await r.selfUpdate.prepare();g=!0,w(d,202,{accepted:!0,version:b.version}),setTimeout(()=>{r.selfUpdate?.requestRestart(b).catch(S=>{g=!1,t.capture(S,{stage:"restart"}),console.error("pi-webapp restart:",S)})},500).unref();return}if(v==="/api/provider/custom"){if(a.sessionId!==r.snapshot().sessionId){w(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("provider"in a)||!ke(a.provider)||!r.addCustomProvider){w(d,400,{error:"\u81EA\u5B9A\u4E49\u63D0\u4F9B\u65B9\u65E0\u6548"});return}await r.addCustomProvider(a.sessionId,a.provider),w(d,201,{accepted:!0});return}if(v==="/api/provider/models"||v==="/api/provider/logout"){if(a.sessionId!==r.snapshot().sessionId){w(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("providerId"in a)||typeof a.providerId!="string"){w(d,400,{error:"\u63D0\u4F9B\u65B9\u65E0\u6548"});return}if(v==="/api/provider/models"){if(!("change"in a)||!Qe(a.change)||!r.updateProviderModel){w(d,400,{error:"\u6A21\u578B\u53C2\u6570\u65E0\u6548"});return}await r.updateProviderModel(a.sessionId,a.providerId,a.change)}else{if(!r.logoutProvider){w(d,400,{error:"\u65E0\u6CD5\u79FB\u9664\u8BA4\u8BC1"});return}await r.logoutProvider(a.sessionId,a.providerId)}w(d,200,{accepted:!0});return}if(v.startsWith("/api/provider/login")){if(a.sessionId!==r.snapshot().sessionId){w(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(v==="/api/provider/login"){if(!("providerId"in a)||typeof a.providerId!="string"||!("method"in a)||a.method!=="api_key"&&a.method!=="oauth"||!r.loginProvider||!r.providers){w(d,400,{error:"\u767B\u5F55\u65B9\u5F0F\u65E0\u6548"});return}if(!(await r.providers()).some(O=>O.id===a.providerId&&O.methods.includes(a.method))){w(d,400,{error:"\u63D0\u4F9B\u65B9\u4E0D\u652F\u6301\u6B64\u767B\u5F55\u65B9\u5F0F"});return}let S="initialSecret"in a?a.initialSecret:void 0;if(S!==void 0&&(a.method!=="api_key"||typeof S!="string"||!S.trim()||S.length>16384)){w(d,400,{error:"API Key \u65E0\u6548"});return}let I=y.start(a.providerId,a.method,r.loginProvider,S,x);w(d,202,{id:I.id});return}if(!("id"in a)||typeof a.id!="string"){w(d,400,{error:"\u767B\u5F55\u6D41\u7A0B\u65E0\u6548"});return}if(v==="/api/provider/login/cancel"){w(d,y.cancel(a.id)?202:404,{accepted:!0});return}if(!("value"in a)||typeof a.value!="string"||a.value.length>16384||!y.respond(a.id,a.value)){w(d,400,{error:"\u767B\u5F55\u8F93\u5165\u65E0\u6548"});return}w(d,202,{accepted:!0});return}if(v==="/api/attachment/remove"){if(!("id"in a)||typeof a.id!="string"||a.sessionId!==r.snapshot().sessionId){w(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u9644\u4EF6\u65E0\u6548"});return}f.get(a.id)?.sessionId===a.sessionId&&f.delete(a.id),w(d,202,{accepted:!0});return}if(v==="/api/directory/pick"){if(l!=="native"){w(d,409,{error:"\u672C\u5730\u76EE\u5F55\u9009\u62E9\u5668\u4E0D\u53EF\u7528"});return}let b=new AbortController;d.once("close",()=>b.abort()),w(d,200,{path:await ze(b.signal)});return}if(v==="/api/directory/list"){if("path"in a&&(typeof a.path!="string"||a.path.length>4096)){w(d,400,{error:"\u76EE\u5F55\u8DEF\u5F84\u65E0\u6548"});return}w(d,200,await Ue("path"in a?a.path:void 0));return}if(v==="/api/directory/create"){if(!("path"in a)||typeof a.path!="string"||a.path.length>4096||!("name"in a)||typeof a.name!="string"||a.name.length>255){w(d,400,{error:"\u6587\u4EF6\u5939\u540D\u79F0\u6216\u8DEF\u5F84\u65E0\u6548"});return}w(d,200,{path:await Fe(a.path,a.name)});return}if(v==="/api/workspace/add"){if(!("path"in a)||typeof a.path!="string"||a.path.length>4096||!("create"in a)||typeof a.create!="boolean"){w(d,400,{error:"\u5DE5\u4F5C\u533A\u8DEF\u5F84\u65E0\u6548"});return}await r.addWorkspace(a.path,a.create),w(d,202,{accepted:!0});return}if(v==="/api/workspace/select"||v==="/api/workspace/remove"||v==="/api/workspace/new-session"){if(!("id"in a)||typeof a.id!="string"){w(d,400,{error:"\u5DE5\u4F5C\u533A\u65E0\u6548"});return}v==="/api/workspace/select"?await r.selectWorkspace(a.id):v==="/api/workspace/new-session"?await r.newSessionInWorkspace(a.id):await r.removeWorkspace(a.id),w(d,202,{accepted:!0});return}if(v==="/api/session/select"){if(!("workspaceId"in a)||typeof a.workspaceId!="string"||!("id"in a)||typeof a.id!="string"||!("path"in a)||typeof a.path!="string"){w(d,400,{error:"\u4F1A\u8BDD\u65E0\u6548"});return}await r.selectSession(a.workspaceId,a.id,a.path),w(d,202,{accepted:!0});return}if(v==="/api/thinking-level"){if(!("level"in a)||typeof a.level!="string"){w(d,400,{error:"\u63A8\u7406\u5F3A\u5EA6\u65E0\u6548"});return}await r.setThinkingLevel(a.sessionId,a.level)}else if(v==="/api/model"){if(!("provider"in a)||typeof a.provider!="string"||!("id"in a)||typeof a.id!="string"){w(d,400,{error:"\u6A21\u578B\u65E0\u6548"});return}await r.setModel(a.sessionId,a.provider,a.id)}else if(v==="/api/config"){let b=a;if(!["packages","extensions","skills"].includes(b.kind)||!["global","project"].includes(b.scope)||!["add","remove"].includes(b.action)||typeof b.value!="string"||!b.value.trim()||b.value.length>2048){w(d,400,{error:"\u914D\u7F6E\u9879\u65E0\u6548"});return}if(b.action==="add"&&b.kind!=="packages"&&st(b.value)){w(d,400,{error:"npm \u6216 Git \u6765\u6E90\u8BF7\u5728\u300C\u5305\u300D\u4E2D\u6DFB\u52A0\uFF1B\u6269\u5C55\u548C\u6280\u80FD\u53EA\u63A5\u53D7\u6587\u4EF6\u6216\u76EE\u5F55\u8DEF\u5F84"});return}w(d,200,await r.updateConfig(b));return}else if(v==="/api/message"){let b="attachments"in a?a.attachments:[];if(!Array.isArray(b)||b.length>Je||b.some(N=>typeof N!="string")||new Set(b).size!==b.length){w(d,400,{error:"\u9644\u4EF6\u65E0\u6548\u6216\u8FC7\u591A"});return}let S=b.map(N=>f.get(N));if(S.some(N=>!N||N.sessionId!==a.sessionId)){w(d,400,{error:"\u9644\u4EF6\u4E0D\u53EF\u7528"});return}if(!("text"in a)||typeof a.text!="string"||!a.text.trim()&&b.length===0||a.text.length>32e3){w(d,400,{error:"\u6D88\u606F\u65E0\u6548\u6216\u8FC7\u957F"});return}let I=S,O=[a.text.trim(),...I.map(N=>`\u9644\u4EF6 ${JSON.stringify(N.name)}\uFF1A${N.path}`)].filter(Boolean).join(`
5
15
 
6
- `),Je=await Promise.all(v.filter(S=>["image/png","image/jpeg","image/webp","image/gif"].includes(S.mediaType)).map(ue));await t.send(c.sessionId,A,Je);for(let S of w)l.delete(S)}else if(f==="/api/compact"){if(!t.compact)throw new Error("\u5F53\u524D\u4F1A\u8BDD\u4E0D\u652F\u6301\u538B\u7F29");await t.compact(c.sessionId)}else f==="/api/abort"?t.abort(c.sessionId):await t.newSession(c.sessionId);m(d,202,{accepted:!0})}catch(c){let w=c instanceof Error?c.message:"\u8BF7\u6C42\u5931\u8D25";m(d,w==="\u4F1A\u8BDD\u5DF2\u5207\u6362"?409:400,{error:w})}return}m(d,404,{error:"\u672A\u627E\u5230"})}),y=Number(process.env.PI_WEBAPP_RESTART_PORT);return u=`http://127.0.0.1:${await Gt(h,Number.isInteger(y)&&y>0&&y<65536&&r===i?y:0)}`,{protocolVersion:4,url:`${u}/#${i}`,publish(g){if(g.type==="snapshot")for(let[f,W]of l)W.sessionId!==g.session.sessionId&&l.delete(f);let d=`${JSON.stringify(g)}
7
- `;for(let f of o)f.write(d)},async close(){a.close();for(let g of o)g.end();o.clear(),await new Promise((g,d)=>h.close(f=>f?d(f):g()))}}}import{getSupportedThinkingLevels as zt}from"@earendil-works/pi-ai";function Se(t){let e=[],r=t;for(;;){let i=/(^|\n\n)附件 ("(?:\\.|[^"\\])*"):([^\n]+)$/u.exec(r);if(!i||!/[\\/]pi-web[\\/]attachments[\\/][a-f0-9]{64}[\\/]/u.test(i[3]))break;let n;try{n=JSON.parse(i[2])}catch{break}e.unshift({name:n,image:/\.(?:png|jpe?g|webp|gif)$/iu.test(n)}),r=r.slice(0,i.index)}return{text:r,attachments:e}}function T(t){return typeof t=="string"?[{kind:"text",text:t}]:t.flatMap(e=>e.type==="text"?[{kind:"text",text:e.text}]:e.type==="thinking"?[{kind:"thinking",text:e.thinking}]:e.type==="image"?[{kind:"image",text:"\u56FE\u7247\u9644\u4EF6"}]:e.type==="toolCall"?[{kind:"toolCall",text:JSON.stringify(e.arguments??{}),toolName:e.name,toolCallId:e.id}]:[])}function z(t){if(t.type==="custom_message")return t.display?{id:t.id,role:"notice",timestamp:t.timestamp,blocks:T(t.content)}:null;if(t.type!=="message")return null;let{message:e}=t;return e.role==="user"||e.role==="assistant"?{id:t.id,role:e.role,timestamp:t.timestamp,blocks:T(e.content),...e.role==="assistant"?{...e.stopReason==="error"&&e.errorMessage?{error:e.errorMessage}:{},usage:{input:e.usage.input,output:e.usage.output,cacheRead:e.usage.cacheRead,cacheWrite:e.usage.cacheWrite,...e.usage.reasoning===void 0?{}:{reasoning:e.usage.reasoning},totalTokens:e.usage.totalTokens,cost:e.usage.cost.total},model:`${e.provider}/${e.model}`}:{}}:e.role==="toolResult"?{id:t.id,role:"tool",timestamp:t.timestamp,blocks:T(e.content),isError:e.isError,toolCallId:e.toolCallId,toolName:e.toolName}:null}function K(t,e){let r=t?.trim();if(r)return r;let i=e.find(p=>p.role==="user"),n=Se(i?.blocks.find(p=>p.kind==="text")?.text??"").text.replace(/\s+/g," ").trim();return n?n.slice(0,50):"\u5F53\u524D\u4F1A\u8BDD"}function xe(t,e){let r=t.sessionManager.getBranch().flatMap(i=>{let n=z(i);return n?[n]:[]});return{schemaVersion:1,sessionId:t.sessionManager.getSessionId(),cwd:t.cwd,name:K(e,r),model:t.model?`${t.model.provider}/${t.model.id}`:null,thinkingLevel:t.thinkingLevel??null,thinkingLevels:t.model?zt(t.model):["off"],idle:t.isIdle(),contextUsage:t.getContextUsage()??null,messages:r}}import{randomUUID as Y}from"node:crypto";import{mkdir as Ee,readFile as Kt,realpath as Ie,rename as Yt,rm as Xt,stat as Ce,writeFile as Zt}from"node:fs/promises";import{basename as Me,dirname as Qt,isAbsolute as Ae,join as qt}from"node:path";var U=class{items=[];hiddenPaths=[];mutationChain=Promise.resolve();file;constructor(e){this.file=e}async load(){try{let e=JSON.parse(await Kt(this.file,"utf8")),r,i=[];if(Array.isArray(e)?r=e:e&&typeof e=="object"&&"version"in e&&e.version===2&&"items"in e&&"hiddenPaths"in e&&(r=e.items,i=e.hiddenPaths),!Array.isArray(r)||!Array.isArray(i))throw new Error("\u5DE5\u4F5C\u533A\u8BB0\u5F55\u65E0\u6548");this.items=r.filter(n=>typeof n=="object"&&n!==null&&typeof n.id=="string"&&typeof n.path=="string"&&typeof n.title=="string"),this.hiddenPaths=i.filter(n=>typeof n=="string")}catch(e){if(e.code!=="ENOENT")throw e}}list(){return[...this.items]}get(e){return this.items.find(r=>r.id===e)}async add(e,r=!1){if(!Ae(e)||e.includes("\0"))throw new Error("\u8BF7\u8F93\u5165\u5B8C\u6574\u7684\u76EE\u5F55\u8DEF\u5F84");r&&await Ee(e,{recursive:!0});let i=await Ie(e);if(!(await Ce(i)).isDirectory())throw new Error("\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55");return this.mutate(async()=>{let n=this.hiddenPaths.filter(a=>a!==i),p=this.items.find(a=>a.path===i);if(p)return n.length!==this.hiddenPaths.length&&(await this.save(this.items,n),this.hiddenPaths=n),p;let o={id:Y(),path:i,title:Me(i)||i},l=[o,...this.items];return await this.save(l,n),this.items=l,this.hiddenPaths=n,o})}async discover(e){let r=(await Promise.all([...new Set(e)].filter(Ae).map(async i=>{try{let n=await Ie(i);return(await Ce(n)).isDirectory()?n:null}catch{return null}}))).filter(i=>i!==null);await this.mutate(async()=>{let i=new Set([...this.items.map(o=>o.path),...this.hiddenPaths]),n=[];for(let o of r)i.has(o)||(i.add(o),n.push({id:Y(),path:o,title:Me(o)||o}));if(n.length===0)return;let p=[...this.items,...n];await this.save(p,this.hiddenPaths),this.items=p})}async remove(e){await this.mutate(async()=>{let r=this.get(e);if(!r)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");let i=this.items.filter(p=>p.id!==e),n=[...new Set([...this.hiddenPaths,r.path])];await this.save(i,n),this.items=i,this.hiddenPaths=n})}mutate(e){let r=this.mutationChain.then(e,e);return this.mutationChain=r.then(()=>{},()=>{}),r}async save(e,r){await Ee(Qt(this.file),{recursive:!0});let i=`${this.file}.${Y()}.tmp`;try{await Zt(i,JSON.stringify({version:2,items:e,hiddenPaths:r},null,2),{mode:384}),await Yt(i,this.file)}catch(n){throw await Xt(i,{force:!0}),n}}};function Te(t){return qt(t,"pi-web","workspaces.json")}import{createAgentSession as tr,DefaultResourceLoader as rr,getAgentDir as ir,SessionManager as B}from"@earendil-works/pi-coding-agent";import{realpath as Re}from"node:fs/promises";import{realpath as Ne}from"node:fs/promises";import{SessionManager as er}from"@earendil-works/pi-coding-agent";async function j(t,e){let r=await Ne(t),i=e??await er.listAll(),n=await Promise.all(i.map(async p=>p.cwd!==""&&await Ne(p.cwd).catch(()=>null)===r));return i.filter((p,o)=>n[o])}var O=class{active=null;detach=null;cwd=null;lastStreamAt=0;publish;fallbackModel;constructor(e,r){this.publish=e,this.fallbackModel=r}get session(){return this.active}get path(){return this.cwd}async open(e,r){if(this.active&&!this.active.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u518D\u5207\u6362\u5DE5\u4F5C\u533A");let i=await Re(e),n;if(r==="new")n=B.create(i);else if(r==="continue"){let a=(await j(i))[0];n=a?B.open(a.path):B.create(i)}else n=B.open(r.sessionFile);if(await Re(n.getCwd())!==i)throw new Error("\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A");let p=n.buildSessionProjection().model?void 0:this.active?.model??this.fallbackModel(),o=new rr({cwd:i,agentDir:ir(),noExtensions:!0});await o.reload();let{session:l}=await tr({cwd:i,sessionManager:n,model:p,resourceLoader:o});this.detach?.(),this.active?.dispose(),this.active=l,this.cwd=i,this.detach=l.subscribe(a=>{if(a.type==="message_update"&&a.message.role==="assistant"){let u=Date.now();u-this.lastStreamAt>=60&&(this.lastStreamAt=u,this.publish({type:"stream",message:{id:"stream",role:"assistant",timestamp:new Date(a.message.timestamp).toISOString(),blocks:T(a.message.content)}}))}(a.type==="message_end"||a.type==="agent_start"||a.type==="agent_settled"||a.type==="session_info_changed")&&(a.type==="message_end"&&a.message.role==="assistant"&&this.publish({type:"stream",message:null}),this.publish({type:"snapshot",session:this.snapshot()}))}),this.publish({type:"stream",message:null}),this.publish({type:"snapshot",session:this.snapshot()})}snapshot(){let e=this.active;if(!e||!this.cwd)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u5DE5\u4F5C\u533A\u4F1A\u8BDD");let r=e.sessionManager.getBranch().flatMap(i=>{let n=z(i);return n?[n]:[]});return{schemaVersion:1,sessionId:e.sessionManager.getSessionId(),cwd:this.cwd,name:K(e.sessionManager.getSessionName(),r),model:e.model?`${e.model.provider}/${e.model.id}`:null,thinkingLevel:e.thinkingLevel,thinkingLevels:e.getAvailableThinkingLevels(),idle:e.isIdle,contextUsage:e.getContextUsage()??null,messages:r}}async send(e,r=[]){if(!this.active||!this.active.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let i=this.active,n=!1,p,o,l=new Promise((a,u)=>{p=a,o=u});i.prompt(e,{images:r,preflightResult:a=>{a&&(n=!0,p())}}).then(()=>{n||p()}).catch(a=>{n?this.publish({type:"error",message:a instanceof Error?a.message:"Pi \u8BF7\u6C42\u5931\u8D25"}):o(a)}),await l}async stop(){await this.active?.abort()}async models(){return(await this.active?.modelRuntime.getAvailable()??[]).map(r=>({provider:r.provider,id:r.id,name:r.name}))}async setModel(e,r){if(!this.active||!this.active.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let i=this.active.modelRuntime.getModel(e,r);if(!i)throw new Error("\u6A21\u578B\u4E0D\u53EF\u7528");await this.active.setModel(i),this.publish({type:"snapshot",session:this.snapshot()})}dispose(){this.detach?.(),this.active?.dispose(),this.detach=null,this.active=null,this.cwd=null}};import{basename as X,dirname as sr}from"node:path";function We(t,e){let r=i=>e[i].map(n=>({name:i==="skills"&&X(n.path).toLowerCase()==="skill.md"?X(sr(n.path)):X(n.path),path:n.path,source:n.metadata.source,scope:n.metadata.scope,enabled:n.enabled}));return{packages:t.map(i=>({name:i.source,path:i.installedPath??"",source:i.source,scope:i.scope,enabled:!!i.installedPath})),extensions:r("extensions"),skills:r("skills")}}import{execFile as nr}from"node:child_process";var or=(t,e)=>new Promise((r,i)=>{nr(t,[...e],{windowsHide:!0},n=>{n?i(n):r()})});async function Z(t,e=process.platform,r=process.env,i=or){if(r.SSH_CONNECTION||r.SSH_TTY||r.SSH_CLIENT||e==="linux"&&!r.DISPLAY&&!r.WAYLAND_DISPLAY)return!1;let n=e==="darwin"?"open":e==="linux"?"xdg-open":e==="win32"?"explorer.exe":null;return n===null?!1:(await i(n,[t]),!0)}import{execFile as ar}from"node:child_process";import{randomUUID as cr}from"node:crypto";import{existsSync as je}from"node:fs";import{access as lr,mkdir as dr,readFile as Le,rename as pr,rm as Q,writeFile as _e}from"node:fs/promises";import{join as x}from"node:path";import{promisify as ur}from"node:util";var mr=ur(ar),D=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/;function fr(t,e){let r=D.exec(t),i=D.exec(e);if(!r||!i)throw new Error("\u7248\u672C\u53F7\u65E0\u6548");for(let n=1;n<=3;n++){let p=Number(r[n])-Number(i[n]);if(p)return p}return!r[4]&&i[4]?1:r[4]&&!i[4]?-1:(r[4]??"").localeCompare(i[4]??"",void 0,{numeric:!0})}async function gr(t){try{let{stdout:e}=await mr("npm",t,{timeout:18e4,maxBuffer:1048576,encoding:"utf8"});return e}catch(e){let r=e;throw new Error(r.stderr?.trim()||r.message)}}var $=class{agentDir;packageRoot;launcherNonce;runNpm;preparing=!1;restartPending=!1;constructor(e){this.agentDir=e.agentDir,this.packageRoot=e.packageRoot,this.launcherNonce=e.launcherNonce,this.runNpm=e.runNpm??gr}async current(){let e=JSON.parse(await Le(x(this.packageRoot,"package.json"),"utf8"));if(e.name!=="pi-webapp"||typeof e.version!="string"||!D.test(e.version))throw new Error("\u5F53\u524D pi-webapp \u7248\u672C\u65E0\u6548");return e.version}async runningVersion(){return this.current()}async check(){let e=await this.current(),r=je(x(this.packageRoot,".git")),i={current:e,latest:null,available:!1,canRestart:!!this.launcherNonce&&!r};r?i.reason="\u5F53\u524D\u4ECE\u6E90\u7801\u76EE\u5F55\u8FD0\u884C\u3002\u7F51\u9875\u5347\u7EA7\u4EC5\u652F\u6301 npm \u5B89\u88C5\u7684\u7248\u672C\uFF0C\u4EE5\u514D\u8986\u76D6\u672C\u5730\u4EE3\u7801\u3002":i.canRestart||(i.reason="\u5F53\u524D\u9875\u9762\u7531 Pi \u7EC8\u7AEF\u6253\u5F00\uFF0C\u65E0\u6CD5\u4ECE\u7F51\u9875\u81EA\u52A8\u91CD\u542F Pi\uFF1B\u8BF7\u4F7F\u7528 pi-webapp \u542F\u52A8\u5668\u3002");try{let n=JSON.parse((await this.runNpm(["view","pi-webapp","dist-tags.latest","--json","--prefer-online"])).trim());if(typeof n!="string"||!D.test(n))throw new Error("npm \u8FD4\u56DE\u7684\u7248\u672C\u53F7\u65E0\u6548");i.latest=n,i.available=fr(n,e)>0}catch(n){throw new Error(`\u68C0\u67E5 npm \u66F4\u65B0\u5931\u8D25\uFF1A${n instanceof Error?n.message:String(n)}`)}return i}async prepare(){if(!this.launcherNonce)throw new Error("\u5F53\u524D\u9875\u9762\u65E0\u6CD5\u81EA\u52A8\u91CD\u542F Pi");if(je(x(this.packageRoot,".git")))throw new Error("\u6E90\u7801\u76EE\u5F55\u4E0D\u80FD\u901A\u8FC7\u7F51\u9875\u5347\u7EA7");if(this.restartPending)throw new Error("\u5347\u7EA7\u5DF2\u5B8C\u6210\uFF0C\u6B63\u5728\u91CD\u542F");if(this.preparing)throw new Error("\u5347\u7EA7\u6B63\u5728\u8FDB\u884C\u4E2D");this.preparing=!0;try{let e=await this.check();if(!e.available||!e.latest)throw new Error("\u5F53\u524D\u5DF2\u662F\u6700\u65B0\u7248\u672C");let r=x(this.agentDir,"pi-web","releases",e.latest);await Q(r,{recursive:!0,force:!0}),await dr(r,{recursive:!0});try{await this.runNpm(["install",`pi-webapp@${e.latest}`,"--prefix",r,"--ignore-scripts","--no-save","--no-audit","--no-fund"]);let i=x(r,"node_modules","pi-webapp"),n=JSON.parse(await Le(x(i,"package.json"),"utf8"));if(n.name!=="pi-webapp"||n.version!==e.latest)throw new Error("\u4E0B\u8F7D\u7684\u5305\u4E0E\u76EE\u6807\u7248\u672C\u4E0D\u7B26");let p=x(i,"bin","pi-webapp.mjs");await Promise.all([p,x(i,"dist","extension.js"),x(i,"web","dist","index.html")].map(a=>lr(a)));let o=x(this.agentDir,"pi-web"),l=x(o,`update.${cr()}.tmp`);try{await _e(l,JSON.stringify({version:e.latest,launcher:p}),{mode:384}),await pr(l,x(o,"update.json"))}finally{await Q(l,{force:!0})}return this.restartPending=!0,{version:e.latest,launcher:p}}catch(i){throw await Q(r,{recursive:!0,force:!0}),i}}finally{this.preparing=!1}}async requestRestart(e){if(!this.launcherNonce)throw new Error("\u5F53\u524D\u9875\u9762\u65E0\u6CD5\u81EA\u52A8\u91CD\u542F Pi");try{await _e(x(this.agentDir,"pi-web","launcher.restart"),JSON.stringify({nonce:this.launcherNonce,launcher:e.launcher}),{mode:384})}catch(r){throw this.restartPending=!1,r}}};var Ve=Ue(wr(hr(import.meta.url)),"../web/dist"),br=Symbol.for("pi-web.bridge-state"),s=globalThis[br]??={bridge:null,current:null,commandContext:null,pi:null,replacementContext:null,replacementSessionId:null,lastStreamAt:0,workspaces:null,workspaceSessions:null,selected:"tui",activeWorkspaceId:null,autoOpened:!1},Pr=null;function Sr(){return Pr??=yr.create({refreshOnCreate:!1})}var F=new Map;async function R(){let t=await Sr(),e=s.selected==="tui"?s.current?.modelRegistry:void 0,r=new Set(e?.getRegisteredProviderIds()??[]);for(let i of F.keys())r.has(i)||(t.unregisterProvider(i),F.delete(i));for(let i of r){let n=e?.getRegisteredNativeProvider(i),p=e?.getRegisteredProviderConfig(i),o=n??p;!o||F.get(i)===o||(n?t.registerNativeProvider(n):p&&t.registerProvider(i,p),F.set(i,o))}return await t.refresh({allowNetwork:!1}),t}function P(){if(s.selected==="sdk")return s.workspaceSessions?.snapshot()??(()=>{throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD")})();if(s.current===null)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");return xe(s.current,s.current.sessionManager.getSessionName())}function I(t){if(P().sessionId!==t)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362")}async function De(){let t=s.workspaces?.list()??[],e=P(),r=await J(e.cwd).catch(()=>e.cwd),i=await Oe.listAll(),n=(await Promise.all(t.map(async p=>{let l=(await j(p.path,i).catch(()=>[])).map(a=>({id:a.id,workspaceId:p.id,path:a.path,name:a.name||a.firstMessage?.slice(0,50)||"\u5F53\u524D\u4F1A\u8BDD",modified:a.modified.toISOString()}));return p.path===r&&!l.some(a=>a.id===e.sessionId)&&l.unshift({id:e.sessionId,workspaceId:p.id,path:null,name:e.name,modified:new Date().toISOString()}),l}))).flat();return{items:t,activeId:s.activeWorkspaceId,sessions:n}}async function M(){s.bridge&&s.bridge.publish({type:"workspaces",value:await De()})}async function ee(t,e=!1){let r=s.workspaces?.get(t);if(!r)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");if(await J(r.path),!e&&s.current&&r.path===await J(s.current.cwd)){if(s.selected==="sdk"&&s.workspaceSessions?.session&&!s.workspaceSessions.session.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u518D\u5207\u6362\u5DE5\u4F5C\u533A");s.selected="tui",s.activeWorkspaceId=t,s.bridge?.publish({type:"stream",message:null}),s.bridge?.publish({type:"snapshot",session:P()})}else{if(!s.workspaceSessions)throw new Error("Pi \u5DE5\u4F5C\u533A\u670D\u52A1\u4E0D\u53EF\u7528");await s.workspaceSessions.open(r.path,e?"new":"continue"),s.selected="sdk",s.activeWorkspaceId=t,s.bridge?.publish({type:"snapshot",session:P()})}await M()}function C(t){let e=s.current;if(e===null||e.sessionManager.getSessionId()!==t)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362");return e}function E(t){s.current=t,s.selected==="tui"&&s.bridge?.publish({type:"snapshot",session:P()})}function $e(){if(s.current===null)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");let t=s.selected==="sdk"?s.workspaceSessions?.path:s.current.cwd;if(!t)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u5DE5\u4F5C\u533A");let e=s.selected==="tui"?s.current.isProjectTrusted():s.workspaceSessions?.session?.settingsManager.isProjectTrusted()??!1;return vr.create(t,void 0,{projectTrusted:e})}async function Fe(){let t=$e(),e=n=>({packages:(n.packages??[]).map(p=>typeof p=="string"?p:p.source),extensions:n.extensions??[],skills:n.skills??[]}),r=new Be({cwd:P().cwd,agentDir:N(),settingsManager:t}),i=We(r.listConfiguredPackages(),await r.resolve(async()=>"skip"));return{projectTrusted:t.isProjectTrusted(),global:e(t.getGlobalSettings()),project:e(t.getProjectSettings()),installed:i}}async function xr(t){I(t.sessionId);let e=s.selected==="tui"?C(t.sessionId):null;if(e?!e.isIdle():!s.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let r=$e();if(t.scope==="project"&&!r.isProjectTrusted())throw new Error("\u5F53\u524D\u9879\u76EE\u5C1A\u672A\u53D7\u4FE1\u4EFB\uFF0C\u65E0\u6CD5\u4FEE\u6539\u9879\u76EE\u8BBE\u7F6E");let i=t.value.trim(),n=t.scope==="project"?r.getProjectSettings():r.getGlobalSettings();if(t.kind==="packages"){let p=new Be({cwd:P().cwd,agentDir:N(),settingsManager:r});t.action==="add"?await p.installAndPersist(i,{local:t.scope==="project"}):await p.removeAndPersist(i,{local:t.scope==="project"})}else if(t.kind==="extensions"){let p=n.extensions??[],o=t.action==="add"?[...new Set([...p,i])]:p.filter(l=>l!==i);t.scope==="project"?r.setProjectExtensionPaths(o):r.setExtensionPaths(o)}else{let p=n.skills??[],o=t.action==="add"?[...new Set([...p,i])]:p.filter(l=>l!==i);t.scope==="project"?r.setProjectSkillPaths(o):r.setSkillPaths(o)}return await r.flush(),s.selected==="tui"?(s.commandContext&&await s.commandContext.reload(),s.current&&E(s.current)):(await s.workspaceSessions?.session?.resourceLoader.reload(),s.workspaceSessions?.session?.refreshContext()),await Fe()}function Er(t,e=Z){s.pi=t,t.on("session_start",(i,n)=>{s.replacementSessionId!==n.sessionManager.getSessionId()&&(s.replacementContext=null,s.replacementSessionId=null),E(n),s.selected==="tui"&&s.workspaces&&s.workspaces.add(n.cwd).then(async p=>{s.selected!=="tui"||s.current?.sessionManager.getSessionId()!==n.sessionManager.getSessionId()||(s.activeWorkspaceId=p.id,await M())}).catch(p=>{s.bridge?.publish({type:"error",message:p instanceof Error?p.message:"\u65E0\u6CD5\u6CE8\u518C\u5F53\u524D\u5DE5\u4F5C\u533A"})}),process.env.PI_WEBAPP_AUTO_OPEN==="1"&&n.mode==="tui"&&!s.autoOpened&&(s.autoOpened=!0,r(n).catch(p=>{n.ui.notify(p instanceof Error?p.message:"Web \u542F\u52A8\u5931\u8D25","error")}))}),t.on("agent_start",(i,n)=>E(n)),t.on("agent_end",(i,n)=>E(n)),t.on("agent_settled",(i,n)=>E(n)),t.on("model_select",(i,n)=>E(n)),t.on("thinking_level_select",(i,n)=>E(n)),t.on("message_end",(i,n)=>{s.selected==="tui"&&i.message.role==="assistant"&&s.bridge?.publish({type:"stream",message:null}),E(n),s.selected==="tui"&&M()}),t.on("session_info_changed",(i,n)=>E(n)),t.on("message_update",(i,n)=>{if(s.current=n,s.selected!=="tui"||i.message.role!=="assistant"||s.bridge===null)return;let p=Date.now();p-s.lastStreamAt<60||(s.lastStreamAt=p,s.bridge.publish({type:"stream",message:{id:"stream",role:"assistant",timestamp:new Date(i.message.timestamp).toISOString(),blocks:T(i.message.content)}}))}),t.on("session_shutdown",i=>{if(s.current=null,i.reason==="new"||i.reason==="resume"||i.reason==="fork")return;let n=s.bridge;s.bridge=null,s.commandContext=null,s.replacementContext=null,s.replacementSessionId=null,s.pi=null,s.workspaceSessions?.dispose(),s.workspaceSessions=null,s.selected="tui",s.activeWorkspaceId=null,s.autoOpened=!1,n&&n.close()});let r=async i=>{s.current=i,s.commandContext="newSession"in i?i:null,s.pi=t,s.workspaces===null&&(s.workspaces=new U(Te(N())),await s.workspaces.load());try{await s.workspaces.discover((await Oe.listAll()).map(o=>o.cwd))}catch(o){i.ui.notify(`\u65E0\u6CD5\u8BFB\u53D6\u90E8\u5206 Pi \u5386\u53F2\u5DE5\u4F5C\u533A\uFF1A${o instanceof Error?o.message:String(o)}`,"warning")}let n=await s.workspaces.add(i.cwd);if(s.selected==="tui"&&(s.activeWorkspaceId=n.id),s.bridge&&s.bridge.protocolVersion!==4){let o=s.bridge;s.bridge=null,await o.close()}s.bridge===null&&(s.workspaceSessions=new O(o=>{s.selected==="sdk"&&(s.bridge?.publish(o),o.type==="snapshot"&&o.session.idle&&M())},()=>s.current?.model),s.bridge=await Pe({selfUpdate:new $({agentDir:N(),packageRoot:Ue(Ve,"../.."),launcherNonce:process.env.PI_WEBAPP_LAUNCHER_NONCE}),snapshot:P,image(o,l,a){I(o);let h=(s.selected==="sdk"?s.workspaceSessions?.session?.sessionManager.getBranch():s.current?.sessionManager.getBranch())?.find(b=>b.id===l);if(h?.type!=="message"||h.message.role!=="user"||!Array.isArray(h.message.content))return null;let y=h.message.content[a];return y?.type!=="image"?null:{data:Buffer.from(y.data,"base64"),mimeType:y.mimeType}},async workspaces(){return De()},async addWorkspace(o,l){let a=await s.workspaces.add(o,l);try{await ee(a.id,!0)}catch(u){throw await M(),u}},async selectWorkspace(o){await ee(o)},async newSessionInWorkspace(o){await ee(o,!0)},async removeWorkspace(o){if(o===s.activeWorkspaceId)throw new Error("\u8BF7\u5148\u5207\u6362\u5230\u5176\u4ED6\u5DE5\u4F5C\u533A");await s.workspaces.remove(o),await M()},async selectSession(o,l,a){let u=s.workspaces?.get(o);if(!u)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");if(l===s.current?.sessionManager.getSessionId()&&u.path===await J(s.current.cwd)){if(s.selected==="sdk"&&s.workspaceSessions?.session&&!s.workspaceSessions.session.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u518D\u5207\u6362\u4F1A\u8BDD");s.selected="tui",s.activeWorkspaceId=o,s.bridge?.publish({type:"snapshot",session:P()})}else{if(s.selected==="sdk"&&s.workspaceSessions?.session?.sessionManager.getSessionId()===l&&s.workspaceSessions.path===u.path)return;if(!(await j(u.path)).some(y=>y.id===l&&y.path===a))throw new Error("\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A");await s.workspaceSessions.open(u.path,{sessionFile:a}),s.selected="sdk",s.activeWorkspaceId=o,s.bridge?.publish({type:"snapshot",session:P()})}await M()},async models(){if(s.selected==="sdk")return s.workspaceSessions?.models()??[];let o=s.current;if(!o)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");let l=o.scopedModels?.map(a=>`${a.model.provider}/${a.model.id}`)??[];return o.modelRegistry.getAvailable().filter(a=>l.length===0||l.includes(`${a.provider}/${a.id}`)).map(a=>({provider:a.provider,id:a.id,name:a.name}))},async providers(){let o=await R(),l=new Set((await o.listCredentials()).map(a=>a.providerId));return o.getProviders().map(a=>({id:a.id,name:a.name,configured:o.getProviderAuthStatus(a.id).configured,storedCredential:l.has(a.id),methods:[a.auth.apiKey?.login?"api_key":null,a.auth.oauth?"oauth":null].filter(u=>u!==null)}))},async providerModels(o){let l=await R();return ve(q(N(),"models.json"),o,l)},async updateProviderModel(o,l,a){if(I(o),s.selected==="tui"?!C(o).isIdle():!s.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let u=P().model;if(a.action==="remove"&&u===`${l}/${a.id}`)throw new Error("\u8BF7\u5148\u5207\u6362\u5F53\u524D\u4F7F\u7528\u7684\u6A21\u578B");if(a.action==="save"&&a.originalId&&a.originalId!==a.model.id&&u===`${l}/${a.originalId}`)throw new Error("\u8BF7\u5148\u5207\u6362\u5F53\u524D\u4F7F\u7528\u7684\u6A21\u578B");let h=await R();await ke(q(N(),"models.json"),l,a,h),await h.refresh({providers:[l],allowNetwork:!1}),await s.current?.modelRegistry.refresh({providers:[l],allowNetwork:!1}),await s.workspaceSessions?.session?.modelRuntime.refresh({providers:[l],allowNetwork:!1});let y=a.action==="save"?a.model.id:a.action==="base_url"&&u?.startsWith(`${l}/`)?u.slice(l.length+1):null;if(y&&u===`${l}/${y}`)if(s.selected==="sdk")try{await s.workspaceSessions.setModel(l,y)}catch{throw new Error("\u6A21\u578B\u5DF2\u4FDD\u5B58\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u8BE5\u6A21\u578B\u4EE5\u5E94\u7528\u65B0\u53C2\u6570")}else{let b=C(o),g=b.modelRegistry.find(l,y);if(!g||!s.pi||!await s.pi.setModel(g))throw new Error("\u6A21\u578B\u5DF2\u4FDD\u5B58\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u8BE5\u6A21\u578B\u4EE5\u5E94\u7528\u65B0\u53C2\u6570");E(b)}},async logoutProvider(o,l){if(I(o),s.selected==="tui"?!C(o).isIdle():!s.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let a=await R();if(!(await a.listCredentials()).some(u=>u.providerId===l))throw new Error("\u8BE5\u63D0\u4F9B\u65B9\u6CA1\u6709\u5DF2\u4FDD\u5B58\u7684\u8BA4\u8BC1");await a.logout(l),await s.current?.modelRegistry.refresh({providers:[l],allowNetwork:!1}),await s.workspaceSessions?.session?.modelRuntime.refresh({providers:[l],allowNetwork:!1})},async loginProvider(o,l,a){let u=await R();await u.login(o,l,me(o,l,a)),await u.refresh({providers:[o],allowNetwork:!1}),await s.current?.modelRegistry.refresh({providers:[o],allowNetwork:!1}),await s.workspaceSessions?.session?.modelRuntime.refresh({providers:[o],allowNetwork:!1})},async addCustomProvider(o,l){if(I(o),s.selected==="tui"?!C(o).isIdle():!s.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let a=await R();if(a.getProvider(l.id))throw new Error("\u63D0\u4F9B\u65B9\u5DF2\u5B58\u5728");await fe(q(N(),"models.json"),l),await a.refresh({allowNetwork:!1}),await s.current?.modelRegistry.refresh({allowNetwork:!1}),await s.workspaceSessions?.session?.modelRuntime.refresh({allowNetwork:!1})},commands(){return s.selected==="tui"?(s.pi?.getCommands()??[]).filter(o=>o.name!=="web").map(o=>({name:o.name,description:o.description})):[]},async compact(o){if(I(o),s.selected==="sdk"){let a=s.workspaceSessions?.session;if(!a||!a.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");await a.compact(),s.bridge?.publish({type:"snapshot",session:P()});return}let l=C(o);if(!l.isIdle())throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");l.compact()},async setModel(o,l,a){if(I(o),s.selected==="sdk"){await s.workspaceSessions.setModel(l,a);return}let u=C(o);if(!u.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let h=u.modelRegistry.find(l,a);if(!h||!u.modelRegistry.getAvailable().some(y=>y.provider===l&&y.id===a))throw new Error("\u6A21\u578B\u4E0D\u53EF\u7528");if(!s.pi||!await s.pi.setModel(h))throw new Error("\u6A21\u578B\u63D0\u4F9B\u65B9\u672A\u914D\u7F6E\u8BA4\u8BC1");E(u)},async setThinkingLevel(o,l){if(I(o),!["off","minimal","low","medium","high","xhigh"].includes(l))throw new Error("\u63A8\u7406\u5F3A\u5EA6\u65E0\u6548");if(s.selected==="sdk"){let h=s.workspaceSessions?.session;if(!h||!h.isIdle||!h.getAvailableThinkingLevels().includes(l))throw new Error("\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u6B64\u63A8\u7406\u5F3A\u5EA6");h.setThinkingLevel(l),s.bridge?.publish({type:"snapshot",session:P()});return}let u=C(o);if(!u.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!u.model||!kr(u.model).includes(l))throw new Error("\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u6B64\u63A8\u7406\u5F3A\u5EA6");if(!s.pi)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");s.pi.setThinkingLevel(l),E(u)},config:Fe,updateConfig:xr,async send(o,l,a=[]){if(I(o),s.selected==="sdk"){await s.workspaceSessions.send(l,a);return}if(!C(o).isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(s.replacementContext!==null&&s.replacementSessionId===o){await s.replacementContext.sendUserMessage(a.length?[{type:"text",text:l},...a]:l,{expandPromptTemplates:!0});return}if(s.pi===null)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");s.pi.sendUserMessage(a.length?[{type:"text",text:l},...a]:l,{expandPromptTemplates:!0})},abort(o){I(o),s.selected==="sdk"?s.workspaceSessions.stop():C(o).abort()},async newSession(o){if(I(o),s.selected==="sdk"){let u=s.workspaces?.get(s.activeWorkspaceId??"");if(!u)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");await s.workspaceSessions.open(u.path,"new"),await M();return}let l=C(o);if(!l.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(s.commandContext===null){await s.workspaceSessions.open(l.cwd,"new"),s.selected="sdk",s.bridge?.publish({type:"snapshot",session:P()}),await M();return}if((await s.commandContext.newSession({withSession:async u=>{s.commandContext=u,s.replacementContext=u,s.replacementSessionId=u.sessionManager.getSessionId(),s.current=u}})).cancelled)throw new Error("\u65B0\u4F1A\u8BDD\u5DF2\u53D6\u6D88");await M()}},Ve));let p=await e(s.bridge.url).catch(()=>!1);i.ui.notify(`pi-webapp: ${s.bridge.url}`,p?"info":"warning"),i.ui.setStatus("pi-webapp","Web \u5DF2\u542F\u52A8 \xB7 /web \u91CD\u65B0\u6253\u5F00")};t.registerCommand("web",{description:"Open the current Pi session in a local web interface",handler:async(i,n)=>r(n)})}export{Er as default};
16
+ `),Gt=await Promise.all(I.filter(N=>["image/png","image/jpeg","image/webp","image/gif"].includes(N.mediaType)).map(Ye));x.operationId??=ut(),d.setHeader("X-Operation-ID",x.operationId),t.breadcrumb("send",{...x,attachmentCount:I.length}),await r.send(a.sessionId,O,Gt,x);for(let N of b)f.delete(N)}else if(v==="/api/compact"){if(!r.compact)throw new Error("\u5F53\u524D\u4F1A\u8BDD\u4E0D\u652F\u6301\u538B\u7F29");await r.compact(a.sessionId)}else if(v==="/api/resume"){let b=r.snapshot();if(a.sessionId!==b.sessionId){w(d,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!b.idle){w(d,409,{error:"Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F"});return}if(!b.paused){w(d,409,{error:"\u5F53\u524D\u4F1A\u8BDD\u6CA1\u6709\u6682\u505C\u7684\u4EFB\u52A1"});return}if(b.interactions?.length){w(d,409,{error:"\u8BF7\u5148\u5B8C\u6210\u5F53\u524D\u4EA4\u4E92\u6216\u5BA1\u6279"});return}if(!r.resume)throw new Error("\u5F53\u524D\u670D\u52A1\u4E0D\u652F\u6301\u7EE7\u7EED\uFF0C\u8BF7\u91CD\u8F7D Pi");await r.resume(a.sessionId)}else v==="/api/abort"?await r.abort(a.sessionId):await r.newSession(a.sessionId);w(d,202,{accepted:!0})}catch(a){let b=a instanceof Error?a.message:"\u8BF7\u6C42\u5931\u8D25";W(a,b==="\u4F1A\u8BDD\u5DF2\u5207\u6362"?409:400,b)}return}w(d,404,{error:"\u672A\u627E\u5230"})}catch(R){d.headersSent?(t.capture(R,{...x,route:v,stage:"http_stream"}),d.end()):W(R,500,"\u8BF7\u6C42\u5931\u8D25")}}),P=Number(process.env.PI_WEBAPP_RESTART_PORT),M;try{M=await oi(k,Number.isInteger(P)&&P>0&&P<65536&&i===n?P:0)}catch(h){throw t.capture(h,{stage:"listen"}),await t.close(),h}return p=`http://127.0.0.1:${M}`,{protocolVersion:7,buildId:$,reportError(h,d){return t.capture(h,d)},breadcrumb(h,d){t.breadcrumb(h,d)},url:`${p}/#${n}`,publish(h){if(h.type==="snapshot"&&c(h.session),h.type==="error"&&!h.errorCode&&(h={...h,errorCode:"unexpected_error",errorId:t.capture(new Error("Agent execution failed"),{stage:"agent",requestId:h.requestId,operationId:h.operationId})}),h.type==="error"&&(h={...h,errorReported:h.errorReported??t.enabled}),h.type==="snapshot")for(let[C,E]of f)E.sessionId!==h.session.sessionId&&f.delete(C);let d=`${JSON.stringify(h)}
17
+ `;for(let C of u)C.write(d)},async close(h){y.close();for(let C of u)C.end(`${JSON.stringify({type:"shutdown",reconnect:h?.reconnect??g})}
18
+ `);u.clear();let d;try{await new Promise((C,E)=>{k.close(x=>x?E(x):C()),d=setTimeout(()=>k.closeAllConnections(),50).unref()})}finally{clearTimeout(d),await t.close()}}}}import{getSupportedThinkingLevels as ai}from"@earendil-works/pi-ai";function mt(r){let e=[],t=r;for(;;){let i=/(^|\n\n)附件 ("(?:\\.|[^"\\])*"):([^\n]+)$/u.exec(t);if(!i||!/[\\/]pi-web[\\/]attachments[\\/][a-f0-9]{64}[\\/]/u.test(i[3]))break;let n;try{n=JSON.parse(i[2])}catch{break}e.unshift({name:n,image:/\.(?:png|jpe?g|webp|gif)$/iu.test(n)}),t=t.slice(0,i.index)}return{text:t,attachments:e}}var X="pi-webapp/paused",Ie="pi-webapp/resume";function Z(r){for(let e=r.length-1;e>=0;e--){let t=r[e];if(t.type==="custom_message"&&t.customType===Ie)return!1;if(t.type==="custom"&&t.customType===X)return!0;if(t.type==="message"){if(t.message.role==="user")return!1;if(t.message.role==="assistant"){if(t.message.stopReason==="aborted")return!0;if(t.message.stopReason==="stop"||t.message.stopReason==="length"||t.message.stopReason==="error")return!1}}}return!1}function Se(r,e){let t=[],i;for(let n of r){if(n.type==="message"&&(i=n.id),n.type!=="custom")continue;let o=e.find(l=>n.customType.startsWith(`${l}/`));if(o){try{if(JSON.stringify(n.data).length>128*1024)continue}catch{continue}t.push({id:n.id,pluginId:o,kind:n.customType,data:n.data,timestamp:n.timestamp,...i?{afterMessageId:i}:{}})}}return t}function H(r){return typeof r=="string"?[{kind:"text",text:r}]:r.flatMap(e=>e.type==="text"?[{kind:"text",text:e.text}]:e.type==="thinking"?[{kind:"thinking",text:e.thinking}]:e.type==="image"?[{kind:"image",text:"\u56FE\u7247\u9644\u4EF6"}]:e.type==="toolCall"?[{kind:"toolCall",text:JSON.stringify(e.arguments??{}),toolName:e.name,toolCallId:e.id}]:[])}function xe(r){if(r.type==="custom_message")return r.display?{id:r.id,role:"notice",timestamp:r.timestamp,blocks:H(r.content)}:null;if(r.type!=="message")return null;let{message:e}=r;return e.role==="user"||e.role==="assistant"?{id:r.id,role:e.role,timestamp:r.timestamp,blocks:H(e.content),...e.role==="assistant"?{...e.stopReason==="error"&&e.errorMessage?{error:e.errorMessage}:{},usage:{input:e.usage.input,output:e.usage.output,cacheRead:e.usage.cacheRead,cacheWrite:e.usage.cacheWrite,...e.usage.reasoning===void 0?{}:{reasoning:e.usage.reasoning},totalTokens:e.usage.totalTokens,cost:e.usage.cost.total},model:`${e.provider}/${e.model}`}:{}}:e.role==="toolResult"?{id:r.id,role:"tool",timestamp:r.timestamp,blocks:H(e.content),isError:e.isError,toolCallId:e.toolCallId,toolName:e.toolName}:null}function Ce(r,e){let t=r?.trim();if(t)return t;let i=e.find(o=>o.role==="user"),n=mt(i?.blocks.find(o=>o.kind==="text")?.text??"").text.replace(/\s+/g," ").trim();return n?n.slice(0,50):"\u5F53\u524D\u4F1A\u8BDD"}function ht(r,e,t=[]){let i=r.sessionManager.getBranch().flatMap(n=>{let o=xe(n);return o?[o]:[]});return{schemaVersion:1,sessionId:r.sessionManager.getSessionId(),cwd:r.cwd,name:Ce(e,i),model:r.model?`${r.model.provider}/${r.model.id}`:null,thinkingLevel:r.thinkingLevel??null,thinkingLevels:r.model?ai(r.model):["off"],idle:r.isIdle(),paused:Z(r.sessionManager.getBranch()),contextUsage:r.getContextUsage()??null,messages:i,pluginEntries:Se(r.sessionManager.getBranch(),t)}}import{randomUUID as Ae}from"node:crypto";import{mkdir as wt,readFile as ci,realpath as yt,rename as li,rm as di,stat as vt,writeFile as pi}from"node:fs/promises";import{basename as bt,dirname as ui,isAbsolute as kt,join as fi}from"node:path";var ce=class{items=[];hiddenPaths=[];mutationChain=Promise.resolve();file;constructor(e){this.file=e}async load(){try{let e=JSON.parse(await ci(this.file,"utf8")),t,i=[];if(Array.isArray(e)?t=e:e&&typeof e=="object"&&"version"in e&&e.version===2&&"items"in e&&"hiddenPaths"in e&&(t=e.items,i=e.hiddenPaths),!Array.isArray(t)||!Array.isArray(i))throw new Error("\u5DE5\u4F5C\u533A\u8BB0\u5F55\u65E0\u6548");this.items=t.filter(n=>typeof n=="object"&&n!==null&&typeof n.id=="string"&&typeof n.path=="string"&&typeof n.title=="string"),this.hiddenPaths=i.filter(n=>typeof n=="string")}catch(e){if(e.code!=="ENOENT")throw e}}list(){return[...this.items]}get(e){return this.items.find(t=>t.id===e)}async add(e,t=!1){if(!kt(e)||e.includes("\0"))throw new Error("\u8BF7\u8F93\u5165\u5B8C\u6574\u7684\u76EE\u5F55\u8DEF\u5F84");t&&await wt(e,{recursive:!0});let i=await yt(e);if(!(await vt(i)).isDirectory())throw new Error("\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55");return this.mutate(async()=>{let n=this.hiddenPaths.filter(f=>f!==i),o=this.items.find(f=>f.path===i);if(o)return n.length!==this.hiddenPaths.length&&(await this.save(this.items,n),this.hiddenPaths=n),o;let l={id:Ae(),path:i,title:bt(i)||i},u=[l,...this.items];return await this.save(u,n),this.items=u,this.hiddenPaths=n,l})}async discover(e){let t=(await Promise.all([...new Set(e)].filter(kt).map(async i=>{try{let n=await yt(i);return(await vt(n)).isDirectory()?n:null}catch{return null}}))).filter(i=>i!==null);await this.mutate(async()=>{let i=new Set([...this.items.map(l=>l.path),...this.hiddenPaths]),n=[];for(let l of t)i.has(l)||(i.add(l),n.push({id:Ae(),path:l,title:bt(l)||l}));if(n.length===0)return;let o=[...this.items,...n];await this.save(o,this.hiddenPaths),this.items=o})}async remove(e){await this.mutate(async()=>{let t=this.get(e);if(!t)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");let i=this.items.filter(o=>o.id!==e),n=[...new Set([...this.hiddenPaths,t.path])];await this.save(i,n),this.items=i,this.hiddenPaths=n})}mutate(e){let t=this.mutationChain.then(e,e);return this.mutationChain=t.then(()=>{},()=>{}),t}async save(e,t){await wt(ui(this.file),{recursive:!0});let i=`${this.file}.${Ae()}.tmp`;try{await pi(i,JSON.stringify({version:2,items:e,hiddenPaths:t},null,2),{mode:384}),await li(i,this.file)}catch(n){throw await di(i,{force:!0}),n}}};function Pt(r){return fi(r,"pi-web","workspaces.json")}import{createAgentSession as Hi,createEventBus as zi,DefaultResourceLoader as Gi,getAgentDir as Ji,SessionManager as ue,VERSION as Me}from"@earendil-works/pi-coding-agent";var gi="pi-webapp:interaction-open:v1",mi="pi-webapp:interaction-accept:v1",Et="pi-webapp:interaction-settle:v1",hi="pi-webapp:interaction-cancel:v1";var q=class{bus;accepts;changed;requests=new Map;detach;constructor(e,t,i){this.bus=e,this.accepts=t,this.changed=i,this.detach=[e.on(gi,n=>{!wi(n)||!t(n)||this.requests.has(n.requestId)||(this.requests.set(n.requestId,n),e.emit(mi,{requestId:n.requestId}),i())}),e.on(hi,n=>{let o=n,l=this.requests.get(o?.requestId);l&&l.sessionId===o.sessionId&&l.pluginId===o.pluginId&&(this.requests.delete(o.requestId),i())})]}pending(e){return[...this.requests.values()].filter(t=>t.sessionId===e)}resolve(e,t,i,n){let o=this.requests.get(i);if(!o||o.sessionId!==e||o.pluginId!==t||!this.accepts(o))throw new Error("Interaction expired or session changed");this.requests.delete(i),this.bus.emit(Et,{requestId:i,value:n}),this.changed()}cancelAll(e="Session changed"){for(let t of this.requests.values())this.bus.emit(Et,{requestId:t.requestId,error:e});this.requests.clear(),this.changed()}dispose(){for(let e of this.detach)e();this.cancelAll("Interaction host unloaded")}};function wi(r){if(!r||typeof r!="object")return!1;let e=r;for(let t of["requestId","sessionId","pluginId","kind"])if(typeof e[t]!="string"||!e[t]||e[t].length>200)return!1;try{return JSON.stringify(e.data).length<=128*1024}catch{return!1}}var yi=1,vi="pi-webapp:action:v1",bi="pi-webapp:action-response:v1",le="pi-webapp:plugin-changed:v1";function It(r){if(!r||typeof r!="object")return!1;let e=r;return e.apiVersion===yi&&typeof e.client=="string"&&/^\.\/dist\/[\w.-]+\.js$/.test(e.client)&&(e.style===void 0||typeof e.style=="string"&&/^\.\/dist\/[\w.-]+\.css$/.test(e.style))}function de(r,e,t=15e3,i){return new Promise((n,o)=>{let l=!1,u=(p,g)=>{l||(l=!0,clearTimeout(y),f(),i?.removeEventListener("abort",c),p?o(p):n(g))},f=r.on(bi,p=>{let g=p;g?.requestId===e.requestId&&u(g.ok?null:new Error(g.error??"Plugin action failed"),g.value)}),y=setTimeout(()=>u(new Error(`Plugin action timed out: ${e.pluginId}/${e.action}`)),t),c=()=>u(new Error("Plugin action runtime unloaded"));if(i?.addEventListener("abort",c,{once:!0}),i?.aborted)c();else try{r.emit(vi,e)}catch(p){u(p instanceof Error?p:new Error(String(p)))}})}import{realpath as Nt}from"node:fs/promises";import{readFile as _e,realpath as At,stat as _t}from"node:fs/promises";import{createHash as ki}from"node:crypto";import{dirname as St,isAbsolute as Pi,join as Te,parse as Ei,resolve as Ii,sep as Si,delimiter as xi}from"node:path";import{DefaultPackageManager as Ci,getAgentDir as Ai,SettingsManager as _i}from"@earendil-works/pi-coding-agent";async function xt(r,e){let t=await _e(r),i=e?await _e(e):void 0;if(t.length>8*1024*1024||(i?.length??0)>8*1024*1024)throw new Error("Plugin asset exceeds 8 MB");let n=ki("sha256").update(t).update("\0").update(i??"").digest("hex");return{clientBytes:t,styleBytes:i,revision:n}}function Ti(){return(process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS??"").split(xi).filter(Boolean).map(r=>Ii(r))}async function Mi(r){let e=St(r);for(;e!==Ei(e).root;)try{return await _t(Te(e,"package.json")),e}catch{e=St(e)}return null}async function Ct(r,e){let t=await At(Te(r,e));if(!t.startsWith(r+Si))throw new Error("Asset escapes package root");let i=await _t(t);if(!i.isFile()||i.size>8*1024*1024)throw new Error("Plugin asset is not a regular file under 8 MB");return t}var z=class r{plugins;errors;extensionRoots;constructor(e,t,i){this.plugins=e,this.errors=t,this.extensionRoots=i}static async discover(e,t,i=Ti()){let n=_i.create(e,void 0,{projectTrusted:t}),o=new Ci({cwd:e,agentDir:Ai(),settingsManager:n}),l=await o.resolve(async()=>"skip"),u=i.length?await o.resolveExtensionSources(i,{temporary:!0}):{extensions:[]},f=new Set;for(let m of[...l.extensions,...u.extensions]){if(!m.enabled)continue;let k=await Mi(m.path);k&&f.add(k)}for(let m of i)Pi(m)&&f.add(m);let y=[],c=[],p=[],g=new Set;for(let m of f)try{let k=await At(m),P=JSON.parse(await _e(Te(k,"package.json"),"utf8"));if(P.piWebapp===void 0)continue;if(typeof P.name!="string"||!P.name)throw new Error("Missing package name");if(!It(P.piWebapp))throw new Error("Unsupported piWebapp manifest or asset path");if(g.has(P.name))throw new Error(`Duplicate plugin id: ${P.name}`);let M=await Ct(k,P.piWebapp.client),h=P.piWebapp.style?await Ct(k,P.piWebapp.style):void 0;g.add(P.name),y.push({id:P.name,root:k,manifest:P.piWebapp,clientPath:M,stylePath:h,...await xt(M,h)}),p.push(k)}catch(k){c.push(`${m}: ${k instanceof Error?k.message:String(k)}`)}return y.sort((m,k)=>m.id.localeCompare(k.id)),new r(y,c,p)}has(e){return this.plugins.some(t=>t.id===e)}ids(){return this.plugins.map(e=>e.id)}async refreshAssets(){for(let e of this.plugins)Object.assign(e,await xt(e.clientPath,e.stylePath))}view(){return{plugins:this.plugins.map(e=>({id:e.id,client:`/plugins/${encodeURIComponent(e.id)}/client.js?v=${e.revision}`,...e.stylePath?{style:`/plugins/${encodeURIComponent(e.id)}/client.css?v=${e.revision}`}:{}})),errors:this.errors}}async asset(e){let t=new URL(e,"http://localhost"),i=/^\/plugins\/([^/]+)\/(client\.js|client\.css)$/.exec(t.pathname);if(!i)return null;let n;try{n=decodeURIComponent(i[1])}catch{return null}let o=this.plugins.find(u=>u.id===n);if(!o||t.searchParams.has("v")&&t.searchParams.get("v")!==o.revision)return null;let l=i[2]==="client.js"?o.clientBytes:o.styleBytes;return l?{bytes:l,type:i[2]==="client.js"?"text/javascript; charset=utf-8":"text/css; charset=utf-8"}:null}};import{realpath as Tt}from"node:fs/promises";import{SessionManager as Ri}from"@earendil-works/pi-coding-agent";async function Q(r,e){let t=await Tt(r),i=e??await Ri.listAll(),n=await Promise.all(i.map(async o=>o.cwd!==""&&await Tt(o.cwd).catch(()=>null)===t));return i.filter((o,l)=>n[l])}var G=class{tail=Promise.resolve();run(e){let t=this.tail.then(e);return this.tail=t.catch(()=>{}),t}wrap(e){return(...t)=>this.run(()=>e(...t))}},Mt=new WeakMap;function Rt(r,e,t,i=5e3,n=()=>{}){let o=Mt.get(r);if(o)return o;let l=(async()=>{let u;try{await Promise.race([r.extensionRunner.emit({type:"session_shutdown",reason:e}),new Promise((f,y)=>{u=setTimeout(()=>y(new Error("Plugin shutdown timed out")),i)})])}catch(f){t(f instanceof Error?f.message:String(f))}finally{clearTimeout(u);try{n()}finally{r.dispose()}}})();return Mt.set(r,l),l}function pe(r){let t=[...r].reverse().find(i=>i.role==="assistant")?.blocks.filter(i=>i.kind==="text").map(i=>i.text).join(`
19
+ `);return{customType:Ie,display:!1,details:{action:"resume"},content:"The user clicked Continue for the interrupted turn. Continue the response to the latest user request from the interrupted point. Preserve completed work and do not repeat text already delivered. Check existing task progress when needed."+(t?`
20
+ Already displayed assistant text (reference data):
21
+ ${JSON.stringify(t)}`:"")}}import{createHash as Wi}from"node:crypto";import{readFile as Ni,writeFile as ji,unlink as Bi}from"node:fs/promises";import{basename as Di,dirname as Oi,extname as Li,join as $i}from"node:path";import{DefaultPackageManager as Vi,getAgentDir as Ui,SettingsManager as Fi}from"@earendil-works/pi-coding-agent";var ee=new Map;async function Wt(r,e){let i=await new Vi({cwd:r,agentDir:Ui(),settingsManager:Fi.create(r)}).resolveExtensionSources([...e],{temporary:!0}),n=[],o=[],l=async()=>{for(let u of n.splice(0)){let f=(ee.get(u)??1)-1;f?ee.set(u,f):(ee.delete(u),await Bi(u).catch(()=>{}))}};try{for(let u of i.extensions){if(!u.enabled)continue;let f=Li(u.path);if(![".js",".mjs"].includes(f)){o.push(u.path);continue}let y=await Ni(u.path),c=Wi("sha256").update(y).digest("hex"),p=$i(Oi(u.path),`.pi-web-runtime-${Di(u.path,f)}-${c}${f}`);await ji(p,y,{flag:"wx"}).catch(g=>{if(g.code!=="EEXIST")throw g}),ee.set(p,(ee.get(p)??0)+1),n.push(p),o.push(p)}return{paths:o,release:l}}catch(u){throw await l(),u}}var fe=class{telemetryVersion=1;active=null;queue=new G;generation=0;disposed=!1;publish;fallbackModel;isProjectTrusted;reportError;constructor(e,t,i=()=>!1,n=()=>{}){this.publish=e,this.fallbackModel=t,this.isProjectTrusted=i,this.reportError=n}get session(){return this.active?.session??null}get path(){return this.active?.cwd??null}get catalog(){return this.active?.catalog??null}open(e,t){return this.queue.run(async()=>{this.ensureAvailable();let i=await Nt(e),n;if(t==="new")n=ue.create(i);else if(t==="continue"){let o=(await Q(i))[0];n=o?ue.open(o.path):ue.create(i)}else n="sessionManager"in t?t.sessionManager:ue.open(t.sessionFile);if(await Nt(n.getCwd())!==i)throw new Error("\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A");await this.replace(i,n,t==="new"?"new":"resume")})}reload(){return this.queue.run(async()=>{this.ensureAvailable();let e=this.active;if(!e)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u5DE5\u4F5C\u533A\u4F1A\u8BDD");await this.replace(e.cwd,e.session.sessionManager,"reload")})}ensureAvailable(){if(this.disposed)throw new Error("\u5DE5\u4F5C\u533A\u670D\u52A1\u5DF2\u5173\u95ED");if(this.active&&!this.active.session.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u518D\u5207\u6362\u5DE5\u4F5C\u533A")}diagnostic(e,t,i,n){let o=`plugin=${t} session=${e.session.sessionManager.getSessionId()} generation=${e.generation} stage=${i}: ${n}`;console.error(o),this.disposed||this.publish({type:"error",message:o})}async replace(e,t,i){let n=this.active,o=await z.discover(e,this.isProjectTrusted(e)),l=zi(),u=await Wt(e,o.extensionRoots),f=new Gi({cwd:e,agentDir:Ji(),noExtensions:!0,additionalExtensionPaths:u.paths,eventBus:l}),y=null;try{await f.reload();let c=f.getExtensions().errors;if(c.length)throw new Error(c.map(E=>`${E.path}: ${E.error}`).join("; "));let p=t.buildSessionProjection().model?void 0:n?.session.model??this.fallbackModel(),{session:g}=await Hi({cwd:e,sessionManager:t,model:p,resourceLoader:f}),m={session:g,cwd:e,catalog:o,bus:l,generation:++this.generation,closing:!1,waitController:new AbortController,interactions:null,detach:()=>{},releasePaths:u.release};y=m;let k=E=>{!this.disposed&&this.active===m&&!m.closing&&this.publish(E)};m.interactions=new q(l,E=>!m.closing&&E.sessionId===g.sessionManager.getSessionId()&&o.has(E.pluginId),()=>k({type:"snapshot",session:this.snapshotOf(m)}));let P=0,M=l.on(le,()=>k({type:"snapshot",session:this.snapshotOf(m)})),h=g.subscribe(E=>{if(this.active===m&&!m.closing){if(E.type==="message_end"&&E.message.role==="assistant"&&E.message.stopReason==="error"){m.agentErrorReported=!0;let x=this.reportError(new Error("Agent response failed"),{...m.operation,stage:"agent",code:"agent_failed",piVersion:Me});k({type:"error",message:E.message.errorMessage??"Agent response failed",errorCode:"unexpected_error",errorId:x,...m.operation})}E.type==="message_end"&&E.message.role==="toolResult"&&E.message.isError&&this.reportError(new Error("Tool execution failed"),{...m.operation,stage:"tool",code:"tool_failed",piVersion:Me}),E.type==="agent_settled"&&(m.operation=void 0)}E.type==="message_update"&&E.message.role==="assistant"&&Date.now()-P>=60&&(P=Date.now(),k({type:"stream",message:{id:"stream",role:"assistant",timestamp:new Date(E.message.timestamp).toISOString(),blocks:H(E.message.content)}})),["message_end","agent_start","agent_settled","session_info_changed","entry_appended"].includes(E.type)&&(E.type==="message_end"&&E.message.role==="assistant"&&k({type:"stream",message:null}),k({type:"snapshot",session:this.snapshotOf(m)}))});m.detach=()=>{M(),h()};let d=[],C=!0;if(await g.bindExtensions({mode:"print",shutdownHandler:()=>{},onError:E=>{C&&d.push(E.error),this.diagnostic(m,o.plugins.find(x=>E.extensionPath.startsWith(x.root+"/"))?.id??E.extensionPath,E.event??"runtime",E.error)}}),C=!1,d.length)throw new Error(d.join("; "));if(this.ensureAvailable(),n&&await this.close(n,i),this.disposed)throw new Error("\u5DE5\u4F5C\u533A\u670D\u52A1\u5DF2\u5173\u95ED");this.active=m,y=null,this.publish({type:"stream",message:null}),this.publish({type:"snapshot",session:this.snapshot()})}catch(c){throw y?await this.close(y,"quit"):(l.clear(),await u.release()),c}}async close(e,t){e.closing||(e.closing=!0,e.waitController.abort(),e.interactions.dispose(),await Rt(e.session,t,i=>this.diagnostic(e,"host","shutdown",i),5e3,()=>{e.detach(),e.bus.clear()}),await e.releasePaths())}snapshotOf(e){let{session:t,cwd:i,catalog:n}=e,o=t.sessionManager.getBranch().flatMap(l=>{let u=xe(l);return u?[u]:[]});return{schemaVersion:1,sessionId:t.sessionManager.getSessionId(),cwd:i,name:Ce(t.sessionManager.getSessionName(),o),model:t.model?`${t.model.provider}/${t.model.id}`:null,thinkingLevel:t.thinkingLevel,thinkingLevels:t.getAvailableThinkingLevels(),idle:t.isIdle,paused:Z(t.sessionManager.getBranch()),contextUsage:t.getContextUsage()??null,messages:o,interactions:e.interactions.pending(t.sessionManager.getSessionId()),pluginEntries:Se(t.sessionManager.getBranch(),n.ids())}}snapshot(){if(!this.active)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u5DE5\u4F5C\u533A\u4F1A\u8BDD");return this.snapshotOf(this.active)}async invokePluginAction(e){let t=this.active;if(this.disposed||!t||t.closing||e.sessionId!==t.session.sessionManager.getSessionId())throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362");if(!t.catalog.has(e.pluginId))throw new Error("\u63D2\u4EF6\u672A\u542F\u7528");let i=t.session.extensionRunner,n=await de(t.bus,e,15e3,t.waitController.signal);if(this.active!==t||t.closing||i!==t.session.extensionRunner)throw new Error("\u4F1A\u8BDD\u8FD0\u884C\u5B9E\u4F8B\u5DF2\u5207\u6362");return this.publish({type:"snapshot",session:this.snapshot()}),n}resolveInteraction(e,t,i,n){if(this.disposed||!this.active||this.active.closing)throw new Error("Interaction host unavailable");this.active.interactions.resolve(e,t,i,n)}async send(e,t=[],i){if(this.disposed||!this.session||!this.session.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let n=this.session,o=this.active;o.operation=i,o.agentErrorReported=!1;let l=!1,u,f,y=new Promise((c,p)=>{u=c,f=p});n.prompt(e,{images:t,preflightResult:c=>{c&&(l=!0,u())}}).then(()=>{l||u()}).catch(c=>{if(!l)f(c);else if(this.active===o&&!o.closing&&!o.agentErrorReported){let p=this.reportError(ae(c,"Agent response failed"),{...i,stage:"agent",code:"agent_failed",piVersion:Me});this.publish({type:"error",message:c instanceof Error?c.message:"Pi \u8BF7\u6C42\u5931\u8D25",errorCode:"unexpected_error",errorId:p,...i})}});try{await y}catch(c){throw o.operation=void 0,c}}async stop(){let e=this.active;!e||e.session.isIdle||(e.session.sessionManager.appendCustomEntry(X),await e.session.abort(),this.active===e&&!e.closing&&this.publish({type:"snapshot",session:this.snapshotOf(e)}))}async resume(){let e=this.active;if(this.disposed||!e||e.closing)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");let t=e.session;if(!t.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!Z(t.sessionManager.getBranch()))throw new Error("\u5F53\u524D\u4F1A\u8BDD\u6CA1\u6709\u6682\u505C\u7684\u4EFB\u52A1");if(!t.model)throw new Error("\u8BF7\u5148\u9009\u62E9\u6A21\u578B");if(!(t.modelRuntime.hasConfiguredAuth(t.model.provider)||await t.modelRuntime.checkAuth(t.model.provider)!==void 0))throw new Error("\u8BF7\u5148\u8FDE\u63A5\u5F53\u524D\u6A21\u578B");if(this.active!==e||e.closing)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362");if(!t.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!Z(t.sessionManager.getBranch()))throw new Error("\u5F53\u524D\u4F1A\u8BDD\u6CA1\u6709\u6682\u505C\u7684\u4EFB\u52A1");let n=pe(this.snapshotOf(e).messages);t.sendCustomMessage(n,{triggerTurn:!0}).catch(o=>{this.active===e&&!e.closing&&this.publish({type:"error",message:o instanceof Error?o.message:"\u7EE7\u7EED\u5931\u8D25"})})}async models(){return(await this.session?.modelRuntime.getAvailable()??[]).map(t=>({provider:t.provider,id:t.id,name:t.name}))}async setModel(e,t){if(this.disposed||!this.session||!this.session.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let i=this.session.modelRuntime.getModel(e,t);if(!i)throw new Error("\u6A21\u578B\u4E0D\u53EF\u7528");await this.session.setModel(i),this.publish({type:"snapshot",session:this.snapshot()})}dispose(){return this.disposed=!0,this.queue.run(async()=>{let e=this.active;this.active=null,e&&await this.close(e,"quit")})}};import{basename as Re,dirname as qi}from"node:path";function jt(r,e){let t=i=>e[i].map(n=>({name:i==="skills"&&Re(n.path).toLowerCase()==="skill.md"?Re(qi(n.path)):Re(n.path),path:n.path,source:n.metadata.source,scope:n.metadata.scope,enabled:n.enabled}));return{packages:r.map(i=>({name:i.source,path:i.installedPath??"",source:i.source,scope:i.scope,enabled:!!i.installedPath})),extensions:t("extensions"),skills:t("skills")}}import{execFile as Yi}from"node:child_process";var Ki=(r,e)=>new Promise((t,i)=>{Yi(r,[...e],{windowsHide:!0},n=>{n?i(n):t()})});async function We(r,e=process.platform,t=process.env,i=Ki){if(t.SSH_CONNECTION||t.SSH_TTY||t.SSH_CLIENT||e==="linux"&&!t.DISPLAY&&!t.WAYLAND_DISPLAY)return!1;let n=e==="darwin"?"open":e==="linux"?"xdg-open":e==="win32"?"explorer.exe":null;return n===null?!1:(await i(n,[r]),!0)}import{execFile as Xi}from"node:child_process";import{randomUUID as Zi}from"node:crypto";import{existsSync as Bt}from"node:fs";import{access as Qi,mkdir as es,readFile as Dt,rename as ts,rm as Ne,writeFile as Ot}from"node:fs/promises";import{join as j}from"node:path";import{promisify as rs}from"node:util";var is=rs(Xi),ge=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/;function ss(r,e){let t=ge.exec(r),i=ge.exec(e);if(!t||!i)throw new Error("\u7248\u672C\u53F7\u65E0\u6548");for(let n=1;n<=3;n++){let o=Number(t[n])-Number(i[n]);if(o)return o}return!t[4]&&i[4]?1:t[4]&&!i[4]?-1:(t[4]??"").localeCompare(i[4]??"",void 0,{numeric:!0})}async function ns(r){try{let{stdout:e}=await is("npm",r,{timeout:18e4,maxBuffer:1048576,encoding:"utf8"});return e}catch(e){let t=e;throw new Error(t.stderr?.trim()||t.message)}}var me=class{agentDir;packageRoot;launcherNonce;runNpm;preparing=!1;restartPending=!1;constructor(e){this.agentDir=e.agentDir,this.packageRoot=e.packageRoot,this.launcherNonce=e.launcherNonce,this.runNpm=e.runNpm??ns}async current(){let e=JSON.parse(await Dt(j(this.packageRoot,"package.json"),"utf8"));if(e.name!=="pi-webapp"||typeof e.version!="string"||!ge.test(e.version))throw new Error("\u5F53\u524D pi-webapp \u7248\u672C\u65E0\u6548");return e.version}async runningVersion(){return this.current()}async check(){let e=await this.current(),t=Bt(j(this.packageRoot,".git")),i={current:e,latest:null,available:!1,canRestart:!!this.launcherNonce&&!t};t?i.reason="\u5F53\u524D\u4ECE\u6E90\u7801\u76EE\u5F55\u8FD0\u884C\u3002\u7F51\u9875\u5347\u7EA7\u4EC5\u652F\u6301 npm \u5B89\u88C5\u7684\u7248\u672C\uFF0C\u4EE5\u514D\u8986\u76D6\u672C\u5730\u4EE3\u7801\u3002":i.canRestart||(i.reason="\u5F53\u524D\u9875\u9762\u7531 Pi \u7EC8\u7AEF\u6253\u5F00\uFF0C\u65E0\u6CD5\u4ECE\u7F51\u9875\u81EA\u52A8\u91CD\u542F Pi\uFF1B\u8BF7\u4F7F\u7528 pi-webapp \u542F\u52A8\u5668\u3002");try{let n=JSON.parse((await this.runNpm(["view","pi-webapp","dist-tags.latest","--json","--prefer-online"])).trim());if(typeof n!="string"||!ge.test(n))throw new Error("npm \u8FD4\u56DE\u7684\u7248\u672C\u53F7\u65E0\u6548");i.latest=n,i.available=ss(n,e)>0}catch(n){throw new Error(`\u68C0\u67E5 npm \u66F4\u65B0\u5931\u8D25\uFF1A${n instanceof Error?n.message:String(n)}`)}return i}async prepare(){if(!this.launcherNonce)throw new Error("\u5F53\u524D\u9875\u9762\u65E0\u6CD5\u81EA\u52A8\u91CD\u542F Pi");if(Bt(j(this.packageRoot,".git")))throw new Error("\u6E90\u7801\u76EE\u5F55\u4E0D\u80FD\u901A\u8FC7\u7F51\u9875\u5347\u7EA7");if(this.restartPending)throw new Error("\u5347\u7EA7\u5DF2\u5B8C\u6210\uFF0C\u6B63\u5728\u91CD\u542F");if(this.preparing)throw new Error("\u5347\u7EA7\u6B63\u5728\u8FDB\u884C\u4E2D");this.preparing=!0;try{let e=await this.check();if(!e.available||!e.latest)throw new Error("\u5F53\u524D\u5DF2\u662F\u6700\u65B0\u7248\u672C");let t=j(this.agentDir,"pi-web","releases",e.latest);await Ne(t,{recursive:!0,force:!0}),await es(t,{recursive:!0});try{await this.runNpm(["install",`pi-webapp@${e.latest}`,"--prefix",t,"--ignore-scripts","--no-save","--no-audit","--no-fund"]);let i=j(t,"node_modules","pi-webapp"),n=JSON.parse(await Dt(j(i,"package.json"),"utf8"));if(n.name!=="pi-webapp"||n.version!==e.latest)throw new Error("\u4E0B\u8F7D\u7684\u5305\u4E0E\u76EE\u6807\u7248\u672C\u4E0D\u7B26");let o=j(i,"bin","pi-webapp.mjs");await Promise.all([o,j(i,"dist","extension.js"),j(i,"web","dist","index.html")].map(f=>Qi(f)));let l=j(this.agentDir,"pi-web"),u=j(l,`update.${Zi()}.tmp`);try{await Ot(u,JSON.stringify({version:e.latest,launcher:o}),{mode:384}),await ts(u,j(l,"update.json"))}finally{await Ne(u,{force:!0})}return this.restartPending=!0,{version:e.latest,launcher:o}}catch(i){throw await Ne(t,{recursive:!0,force:!0}),i}}finally{this.preparing=!1}}async requestRestart(e){if(!this.launcherNonce)throw new Error("\u5F53\u524D\u9875\u9762\u65E0\u6CD5\u81EA\u52A8\u91CD\u542F Pi");try{await Ot(j(this.agentDir,"pi-web","launcher.restart"),JSON.stringify({nonce:this.launcherNonce,launcher:e.launcher}),{mode:384})}catch(t){throw this.restartPending=!1,t}}};import{randomUUID as gs}from"node:crypto";var Lt=Be(as(ds(import.meta.url)),"../web/dist"),ms=Symbol.for(`pi-web.bridge-state:${import.meta.url}`),s=globalThis[ms]??={bridge:null,current:null,commandContext:null,pi:null,replacementContext:null,replacementSessionId:null,lastStreamAt:0,workspaces:null,workspaceSessions:null,selected:"tui",activeWorkspaceId:null,autoOpened:!1,tuiCatalog:null,stopPluginWatch:null,interactions:null,lifecycle:new G,tuiGeneration:0,stopChanged:null,tuiWaitController:new AbortController};s.lifecycle??=new G;s.tuiGeneration??=0;s.stopChanged??=null;s.tuiWaitController??=new AbortController;function te(){return s.selected==="sdk"?s.workspaceSessions?.catalog??null:s.tuiCatalog}var hs=null;function ws(){return hs??=ps.create({refreshOnCreate:!1})}var ye=new Map;async function Y(){let r=await ws(),e=s.selected==="tui"?s.current?.modelRegistry:void 0,t=new Set(e?.getRegisteredProviderIds()??[]);for(let i of ye.keys())t.has(i)||(r.unregisterProvider(i),ye.delete(i));for(let i of t){let n=e?.getRegisteredNativeProvider(i),o=e?.getRegisteredProviderConfig(i),l=n??o;!l||ye.get(i)===l||(n?r.registerNativeProvider(n):o&&r.registerProvider(i,o),ye.set(i,l))}return await r.refresh({allowNetwork:!1}),r}function T(){if(s.selected==="sdk")return s.workspaceSessions?.snapshot()??(()=>{throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD")})();if(s.current===null)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");return{...ht(s.current,s.current.sessionManager.getSessionName(),te()?.ids()??[]),interactions:s.interactions?.pending(s.current.sessionManager.getSessionId())??[]}}function A(r){if(T().sessionId!==r)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362")}async function Ut(){let r=s.workspaces?.list()??[],e=T(),t=await ve(e.cwd).catch(o=>(s.bridge?.reportError?.(o,{stage:"workspace_path"}),e.cwd)),i=await Vt.listAll(),n=(await Promise.all(r.map(async o=>{let u=(await Q(o.path,i).catch(f=>(s.bridge?.reportError?.(f,{stage:"workspace_sessions"}),[]))).map(f=>({id:f.id,workspaceId:o.id,path:f.path,name:f.name||f.firstMessage?.slice(0,50)||"\u5F53\u524D\u4F1A\u8BDD",modified:f.modified.toISOString()}));return o.path===t&&!u.some(f=>f.id===e.sessionId)&&u.unshift({id:e.sessionId,workspaceId:o.id,path:null,name:e.name,modified:new Date().toISOString()}),u}))).flat();return{items:r,activeId:s.activeWorkspaceId,sessions:n}}async function L(){try{s.bridge&&s.bridge.publish({type:"workspaces",value:await Ut()})}catch(r){s.bridge?.reportError?.(r,{stage:"workspace_list"})}}async function je(r,e=!1){let t=s.workspaces?.get(r);if(!t)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");if(await ve(t.path),!e&&s.current&&t.path===await ve(s.current.cwd)){if(s.selected==="sdk"&&s.workspaceSessions?.session&&!s.workspaceSessions.session.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u518D\u5207\u6362\u5DE5\u4F5C\u533A");s.selected="tui",s.activeWorkspaceId=r,s.bridge?.publish({type:"stream",message:null}),s.bridge?.publish({type:"snapshot",session:T()})}else{if(!s.workspaceSessions)throw new Error("Pi \u5DE5\u4F5C\u533A\u670D\u52A1\u4E0D\u53EF\u7528");await s.workspaceSessions.open(t.path,e?"new":"continue"),s.selected="sdk",s.activeWorkspaceId=r,s.bridge?.publish({type:"snapshot",session:T()})}await L()}function D(r){let e=s.current;if(e===null||e.sessionManager.getSessionId()!==r)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362");return e}function _(r){s.current=r,s.selected==="tui"&&s.bridge?.publish({type:"snapshot",session:T()})}function Ft(){if(s.current===null)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");let r=s.selected==="sdk"?s.workspaceSessions?.path:s.current.cwd;if(!r)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u5DE5\u4F5C\u533A");let e=s.selected==="tui"?s.current.isProjectTrusted():s.workspaceSessions?.session?.settingsManager.isProjectTrusted()??!1;return us.create(r,void 0,{projectTrusted:e})}async function Ht(){let r=Ft(),e=n=>({packages:(n.packages??[]).map(o=>typeof o=="string"?o:o.source),extensions:n.extensions??[],skills:n.skills??[]}),t=new $t({cwd:T().cwd,agentDir:J(),settingsManager:r}),i=jt(t.listConfiguredPackages(),await t.resolve(async()=>"skip"));return{projectTrusted:r.isProjectTrusted(),global:e(r.getGlobalSettings()),project:e(r.getProjectSettings()),installed:i}}async function ys(r){A(r.sessionId);let e=s.selected==="tui"?D(r.sessionId):null;if(e?!e.isIdle():!s.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let t=Ft();if(r.scope==="project"&&!t.isProjectTrusted())throw new Error("\u5F53\u524D\u9879\u76EE\u5C1A\u672A\u53D7\u4FE1\u4EFB\uFF0C\u65E0\u6CD5\u4FEE\u6539\u9879\u76EE\u8BBE\u7F6E");let i=r.value.trim(),n=r.scope==="project"?t.getProjectSettings():t.getGlobalSettings();if(r.kind==="packages"){let o=new $t({cwd:T().cwd,agentDir:J(),settingsManager:t});r.action==="add"?await o.installAndPersist(i,{local:r.scope==="project"}):await o.removeAndPersist(i,{local:r.scope==="project"})}else if(r.kind==="extensions"){let o=n.extensions??[],l=r.action==="add"?[...new Set([...o,i])]:o.filter(u=>u!==i);r.scope==="project"?t.setProjectExtensionPaths(l):t.setExtensionPaths(l)}else{let o=n.skills??[],l=r.action==="add"?[...new Set([...o,i])]:o.filter(u=>u!==i);r.scope==="project"?t.setProjectSkillPaths(l):t.setSkillPaths(l)}return await t.flush(),s.selected==="tui"?(s.commandContext&&await s.commandContext.reload(),s.current&&_(s.current)):(await s.workspaceSessions?.reload(),s.bridge?.publish({type:"plugins_changed"})),await Ht()}function De(r,e=We){s.pi=r,s.interactions?.dispose(),s.interactions=new q(r.events,n=>!!s.bridge&&s.selected==="tui"&&n.sessionId===s.current?.sessionManager.getSessionId()&&!!s.tuiCatalog?.has(n.pluginId),()=>{s.current&&s.selected==="tui"&&_(s.current)});let t=()=>{s.stopChanged?.(),s.stopChanged=r.events.on(le,()=>{s.selected==="tui"&&s.current&&_(s.current)})};t(),r.on("session_start",async(n,o)=>{if(s.tuiWaitController.abort(),s.tuiWaitController=new AbortController,s.tuiGeneration++,t(),s.current=o,s.bridge){let l=await z.discover(o.cwd,o.isProjectTrusted?.()??!1);if(s.current!==o)return;s.tuiCatalog=l}s.replacementSessionId!==o.sessionManager.getSessionId()&&(s.replacementContext=null,s.replacementSessionId=null),_(o),s.bridge&&s.bridge.publish({type:"plugins_changed"}),s.selected==="tui"&&s.workspaces&&s.workspaces.add(o.cwd).then(async l=>{s.selected!=="tui"||s.current?.sessionManager.getSessionId()!==o.sessionManager.getSessionId()||(s.activeWorkspaceId=l.id,await L())}).catch(l=>{s.bridge?.publish({type:"error",message:l instanceof Error?l.message:"\u65E0\u6CD5\u6CE8\u518C\u5F53\u524D\u5DE5\u4F5C\u533A",errorCode:"unexpected_error",errorId:s.bridge.reportError?.(l,{stage:"workspace_register"})})}),process.env.PI_WEBAPP_AUTO_OPEN==="1"&&o.mode==="tui"&&!s.autoOpened&&(s.autoOpened=!0,i(o).catch(l=>{o.ui.notify(l instanceof Error?l.message:"Web \u542F\u52A8\u5931\u8D25","error")}))}),r.on("agent_start",(n,o)=>{s.bridge?.breadcrumb?.("agent_start",{...s.operation}),_(o)}),r.on("agent_end",(n,o)=>_(o)),r.on("agent_settled",(n,o)=>{s.bridge?.breadcrumb?.("agent_end",{...s.operation}),s.operation=void 0,_(o)}),r.on("model_select",(n,o)=>_(o)),r.on("thinking_level_select",(n,o)=>_(o)),r.on("message_end",(n,o)=>{if(s.selected==="tui"&&n.message.role==="assistant"&&n.message.stopReason==="error"){let l=s.bridge?.reportError?.(new Error("Agent response failed"),{...s.operation,stage:"agent",code:"agent_failed",piVersion:we});s.bridge?.publish({type:"error",message:n.message.errorMessage??"Agent response failed",errorCode:"unexpected_error",errorId:l,...s.operation})}s.selected==="tui"&&n.message.role==="toolResult"&&n.message.isError&&s.bridge?.reportError?.(new Error("Tool execution failed"),{...s.operation,stage:"tool",code:"tool_failed",piVersion:we}),s.selected==="tui"&&n.message.role==="assistant"&&s.bridge?.publish({type:"stream",message:null}),_(o),s.selected==="tui"&&L()}),r.on("session_info_changed",(n,o)=>_(o)),r.on("message_update",(n,o)=>{if(s.current=o,s.selected!=="tui"||n.message.role!=="assistant"||s.bridge===null)return;let l=Date.now();l-s.lastStreamAt<60||(s.lastStreamAt=l,s.bridge.publish({type:"stream",message:{id:"stream",role:"assistant",timestamp:new Date(n.message.timestamp).toISOString(),blocks:H(n.message.content)}}))}),r.on("session_shutdown",async n=>{if(s.tuiWaitController.abort(),s.tuiGeneration++,s.stopChanged?.(),s.stopChanged=null,s.interactions?.cancelAll(),s.current=null,n.reason==="new"||n.reason==="resume"||n.reason==="fork"||n.reason==="reload")return;let o=s.bridge,l=s.telemetry;s.bridge=null,s.commandContext=null,s.replacementContext=null,s.replacementSessionId=null,s.pi=null;let u=s.workspaceSessions;s.workspaceSessions=null,await u?.dispose(),s.selected="tui",s.activeWorkspaceId=null,s.autoOpened=!1,s.tuiCatalog=null,s.stopPluginWatch?.(),s.stopPluginWatch=null,s.operation=void 0,s.telemetry=null,o?await o.close():await l?.close()});let i=async n=>{s.telemetry??=new F;try{s.current=n,s.commandContext="newSession"in n?n:null,s.pi=r,s.tuiCatalog=await z.discover(n.cwd,n.isProjectTrusted?.()??!1),s.workspaces===null&&(s.workspaces=new ce(Pt(J())),await s.workspaces.load());try{await s.workspaces.discover((await Vt.listAll()).map(u=>u.cwd))}catch(u){n.ui.notify(`\u65E0\u6CD5\u8BFB\u53D6\u90E8\u5206 Pi \u5386\u53F2\u5DE5\u4F5C\u533A\uFF1A${u instanceof Error?u.message:String(u)}`,"warning")}let o=await s.workspaces.add(n.cwd);if(s.selected==="tui"&&(s.activeWorkspaceId=o.id),s.bridge&&(s.bridge.protocolVersion!==7||s.bridge.buildId!==$||typeof s.bridge.reportError!="function")){let u=s.bridge;if(s.workspaceSessions&&s.workspaceSessions.telemetryVersion!==1&&s.workspaceSessions.session&&!s.workspaceSessions.session.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u518D\u5207\u6362\u5DE5\u4F5C\u533A");s.bridge=null,await u.close(),await s.telemetry.close(),s.telemetry=new F}if(s.bridge===null){let u=s.workspaceSessions?.telemetryVersion!==1?s.workspaceSessions:null,f=u?.session&&u.path?{path:u.path,sessionManager:u.session.sessionManager}:null;u&&(await u.dispose(),s.workspaceSessions=null),s.workspaceSessions??=new fe(c=>{s.selected==="sdk"&&(s.bridge?.publish(c),c.type==="snapshot"&&c.session.idle&&L())},()=>s.current?.model,c=>{try{return!!s.current&&cs(s.current.cwd)===c&&(s.current.isProjectTrusted?.()??!1)}catch{return!1}},(c,p)=>s.bridge?.reportError?.(c,p)),f&&await s.workspaceSessions.open(f.path,{sessionManager:f.sessionManager});let y={selfUpdate:new me({agentDir:J(),packageRoot:Be(Lt,"../.."),launcherNonce:process.env.PI_WEBAPP_LAUNCHER_NONCE}),snapshot:T,plugins:async()=>{let c=te();return await c?.refreshAssets(),c?.view()??{plugins:[],errors:[]}},pluginAsset:async c=>te()?.asset(c)??null,async invokePluginAction(c,p,g,m){if(A(c),!te()?.has(p))throw new Error("\u63D2\u4EF6\u672A\u542F\u7528");let k=s.selected,P=s.tuiGeneration,M=s.workspaceSessions?.session,h={requestId:gs(),sessionId:c,pluginId:p,action:g,input:m},d=s.selected==="sdk"?await s.workspaceSessions.invokePluginAction(h):await de(s.pi.events,h,15e3,s.tuiWaitController.signal);if(A(c),k!==s.selected||(k==="tui"?P!==s.tuiGeneration:M!==s.workspaceSessions?.session))throw new Error("\u4F1A\u8BDD\u8FD0\u884C\u5B9E\u4F8B\u5DF2\u5207\u6362");return s.selected==="tui"&&s.current&&_(s.current),d},async resolvePluginInteraction(c,p,g,m){if(A(c),!te()?.has(p))throw new Error("\u63D2\u4EF6\u672A\u542F\u7528");s.selected==="sdk"?s.workspaceSessions.resolveInteraction(c,p,g,m):s.interactions.resolve(c,p,g,m)},image(c,p,g){A(c);let k=(s.selected==="sdk"?s.workspaceSessions?.session?.sessionManager.getBranch():s.current?.sessionManager.getBranch())?.find(M=>M.id===p);if(k?.type!=="message"||k.message.role!=="user"||!Array.isArray(k.message.content))return null;let P=k.message.content[g];return P?.type!=="image"?null:{data:Buffer.from(P.data,"base64"),mimeType:P.mimeType}},async workspaces(){return Ut()},async addWorkspace(c,p){let g=await s.workspaces.add(c,p);try{await je(g.id,!0)}catch(m){throw await L(),m}},async selectWorkspace(c){await je(c)},async newSessionInWorkspace(c){await je(c,!0)},async removeWorkspace(c){if(c===s.activeWorkspaceId)throw new Error("\u8BF7\u5148\u5207\u6362\u5230\u5176\u4ED6\u5DE5\u4F5C\u533A");await s.workspaces.remove(c),await L()},async selectSession(c,p,g){let m=s.workspaces?.get(c);if(!m)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");if(p===s.current?.sessionManager.getSessionId()&&m.path===await ve(s.current.cwd)){if(s.selected==="sdk"&&s.workspaceSessions?.session&&!s.workspaceSessions.session.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u518D\u5207\u6362\u4F1A\u8BDD");s.selected="tui",s.activeWorkspaceId=c,s.bridge?.publish({type:"snapshot",session:T()})}else{if(s.selected==="sdk"&&s.workspaceSessions?.session?.sessionManager.getSessionId()===p&&s.workspaceSessions.path===m.path)return;if(!(await Q(m.path)).some(P=>P.id===p&&P.path===g))throw new Error("\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A");await s.workspaceSessions.open(m.path,{sessionFile:g}),s.selected="sdk",s.activeWorkspaceId=c,s.bridge?.publish({type:"snapshot",session:T()})}await L()},async models(){if(s.selected==="sdk")return s.workspaceSessions?.models()??[];let c=s.current;if(!c)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");let p=c.scopedModels?.map(g=>`${g.model.provider}/${g.model.id}`)??[];return c.modelRegistry.getAvailable().filter(g=>p.length===0||p.includes(`${g.provider}/${g.id}`)).map(g=>({provider:g.provider,id:g.id,name:g.name}))},async providers(){let c=await Y(),p=new Set((await c.listCredentials()).map(g=>g.providerId));return c.getProviders().map(g=>({id:g.id,name:g.name,configured:c.getProviderAuthStatus(g.id).configured,storedCredential:p.has(g.id),methods:[g.auth.apiKey?.login?"api_key":null,g.auth.oauth?"oauth":null].filter(m=>m!==null)}))},async providerModels(c){let p=await Y();return rt(he(J(),"models.json"),c,p)},async updateProviderModel(c,p,g){if(A(c),s.selected==="tui"?!D(c).isIdle():!s.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let m=T().model;if(g.action==="remove"&&m===`${p}/${g.id}`)throw new Error("\u8BF7\u5148\u5207\u6362\u5F53\u524D\u4F7F\u7528\u7684\u6A21\u578B");if(g.action==="save"&&g.originalId&&g.originalId!==g.model.id&&m===`${p}/${g.originalId}`)throw new Error("\u8BF7\u5148\u5207\u6362\u5F53\u524D\u4F7F\u7528\u7684\u6A21\u578B");let k=await Y();await it(he(J(),"models.json"),p,g,k),await k.refresh({providers:[p],allowNetwork:!1}),await s.current?.modelRegistry.refresh({providers:[p],allowNetwork:!1}),await s.workspaceSessions?.session?.modelRuntime.refresh({providers:[p],allowNetwork:!1});let P=g.action==="save"?g.model.id:g.action==="base_url"&&m?.startsWith(`${p}/`)?m.slice(p.length+1):null;if(P&&m===`${p}/${P}`)if(s.selected==="sdk")try{await s.workspaceSessions.setModel(p,P)}catch{throw new Error("\u6A21\u578B\u5DF2\u4FDD\u5B58\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u8BE5\u6A21\u578B\u4EE5\u5E94\u7528\u65B0\u53C2\u6570")}else{let M=D(c),h=M.modelRegistry.find(p,P);if(!h||!s.pi||!await s.pi.setModel(h))throw new Error("\u6A21\u578B\u5DF2\u4FDD\u5B58\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u8BE5\u6A21\u578B\u4EE5\u5E94\u7528\u65B0\u53C2\u6570");_(M)}},async logoutProvider(c,p){if(A(c),s.selected==="tui"?!D(c).isIdle():!s.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let g=await Y();if(!(await g.listCredentials()).some(m=>m.providerId===p))throw new Error("\u8BE5\u63D0\u4F9B\u65B9\u6CA1\u6709\u5DF2\u4FDD\u5B58\u7684\u8BA4\u8BC1");await g.logout(p),await s.current?.modelRegistry.refresh({providers:[p],allowNetwork:!1}),await s.workspaceSessions?.session?.modelRuntime.refresh({providers:[p],allowNetwork:!1})},async loginProvider(c,p,g){let m=await Y();await m.login(c,p,Ke(c,p,g)),await m.refresh({providers:[c],allowNetwork:!1}),await s.current?.modelRegistry.refresh({providers:[c],allowNetwork:!1}),await s.workspaceSessions?.session?.modelRuntime.refresh({providers:[c],allowNetwork:!1})},async addCustomProvider(c,p){if(A(c),s.selected==="tui"?!D(c).isIdle():!s.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let g=await Y();if(g.getProvider(p.id))throw new Error("\u63D0\u4F9B\u65B9\u5DF2\u5B58\u5728");await Xe(he(J(),"models.json"),p),await g.refresh({allowNetwork:!1}),await s.current?.modelRegistry.refresh({allowNetwork:!1}),await s.workspaceSessions?.session?.modelRuntime.refresh({allowNetwork:!1})},commands(){return s.selected==="tui"?(s.pi?.getCommands()??[]).filter(c=>c.name!=="web"&&c.name!=="web-dev-reload").map(c=>({name:c.name,description:c.description})):[]},async compact(c){if(A(c),s.selected==="sdk"){let g=s.workspaceSessions?.session;if(!g||!g.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");await g.compact(),s.bridge?.publish({type:"snapshot",session:T()});return}let p=D(c);if(!p.isIdle())throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");p.compact()},async setModel(c,p,g){if(A(c),s.selected==="sdk"){await s.workspaceSessions.setModel(p,g);return}let m=D(c);if(!m.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let k=m.modelRegistry.find(p,g);if(!k||!m.modelRegistry.getAvailable().some(P=>P.provider===p&&P.id===g))throw new Error("\u6A21\u578B\u4E0D\u53EF\u7528");if(!s.pi||!await s.pi.setModel(k))throw new Error("\u6A21\u578B\u63D0\u4F9B\u65B9\u672A\u914D\u7F6E\u8BA4\u8BC1");_(m)},async setThinkingLevel(c,p){if(A(c),!["off","minimal","low","medium","high","xhigh"].includes(p))throw new Error("\u63A8\u7406\u5F3A\u5EA6\u65E0\u6548");if(s.selected==="sdk"){let k=s.workspaceSessions?.session;if(!k||!k.isIdle||!k.getAvailableThinkingLevels().includes(p))throw new Error("\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u6B64\u63A8\u7406\u5F3A\u5EA6");k.setThinkingLevel(p),s.bridge?.publish({type:"snapshot",session:T()});return}let m=D(c);if(!m.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!m.model||!fs(m.model).includes(p))throw new Error("\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u6B64\u63A8\u7406\u5F3A\u5EA6");if(!s.pi)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");s.pi.setThinkingLevel(p),_(m)},config:Ht,updateConfig:ys,async send(c,p,g=[],m){if(A(c),s.selected==="sdk"){await s.workspaceSessions.send(p,g,m);return}if(!D(c).isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");s.operation=m;try{if(s.bridge?.breadcrumb?.("send",{...m,piVersion:we}),s.replacementContext!==null&&s.replacementSessionId===c){await s.replacementContext.sendUserMessage(g.length?[{type:"text",text:p},...g]:p,{expandPromptTemplates:!0});return}if(s.pi===null)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");s.pi.sendUserMessage(g.length?[{type:"text",text:p},...g]:p,{expandPromptTemplates:!0})}catch(P){throw s.operation=void 0,P}},async abort(c){if(A(c),s.selected==="sdk")await s.workspaceSessions.stop();else{let p=D(c);if(p.isIdle())return;if(!s.pi)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");s.pi.appendEntry(X),p.abort()}},async resume(c){if(A(c),s.selected==="sdk"){await s.workspaceSessions.resume();return}let p=D(c);if(!p.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!p.model||!s.pi)throw new Error("\u8BF7\u5148\u9009\u62E9\u6A21\u578B");if(!p.modelRegistry.hasConfiguredAuth(p.model))throw new Error("\u8BF7\u5148\u8FDE\u63A5\u5F53\u524D\u6A21\u578B");s.pi.sendMessage(pe(T().messages),{triggerTurn:!0})},async newSession(c){if(A(c),s.selected==="sdk"){let m=s.workspaces?.get(s.activeWorkspaceId??"");if(!m)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");await s.workspaceSessions.open(m.path,"new"),await L();return}let p=D(c);if(!p.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(s.commandContext===null){await s.workspaceSessions.open(p.cwd,"new"),s.selected="sdk",s.bridge?.publish({type:"snapshot",session:T()}),await L();return}if((await s.commandContext.newSession({withSession:async m=>{s.commandContext=m,s.replacementContext=m,s.replacementSessionId=m.sessionManager.getSessionId(),s.current=m}})).cancelled)throw new Error("\u65B0\u4F1A\u8BDD\u5DF2\u53D6\u6D88");await L()}};y.addWorkspace=s.lifecycle.wrap(y.addWorkspace),y.selectWorkspace=s.lifecycle.wrap(y.selectWorkspace),y.newSessionInWorkspace=s.lifecycle.wrap(y.newSessionInWorkspace),y.removeWorkspace=s.lifecycle.wrap(y.removeWorkspace),y.selectSession=s.lifecycle.wrap(y.selectSession),y.newSession=s.lifecycle.wrap(y.newSession),y.updateConfig=s.lifecycle.wrap(y.updateConfig),s.bridge=await gt(y,Lt,s.telemetry)}if(s.stopPluginWatch===null&&process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS){let u=[],f=null;for(let y of(process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS??"").split(os).filter(Boolean))try{u.push(ls(he(Be(y),"dist"),(c,p)=>{let g=String(p??"");["client.js","client.css"].includes(g)&&(f&&clearTimeout(f),f=setTimeout(()=>s.bridge?.publish({type:"plugins_changed"}),180))}))}catch(c){s.bridge?.publish({type:"error",message:`\u63D2\u4EF6\u76D1\u542C\u5931\u8D25\uFF1A${y}: ${String(c)}`})}s.stopPluginWatch=()=>{for(let y of u)y.close();f&&clearTimeout(f)}}let l=await e(s.bridge.url).catch(()=>!1);n.ui.notify(`pi-webapp: ${s.bridge.url}`,l?"info":"warning"),n.ui.setStatus("pi-webapp","Web \u5DF2\u542F\u52A8 \xB7 /web \u91CD\u65B0\u6253\u5F00")}catch(o){throw s.telemetry?.capture(o,{stage:"open_web",piVersion:we}),s.bridge||(await s.telemetry?.close(),s.telemetry=null),o}};r.registerCommand("web",{description:"Open the current Pi session in a local web interface",handler:async(n,o)=>i(o)}),r.registerCommand("web-dev-reload",{description:"Reload local pi-webapp plugins during development",handler:async(n,o)=>{process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS&&(await o.waitForIdle(),await s.lifecycle.run(async()=>{let l=s.workspaceSessions?.session;l&&(await l.waitForIdle(),await s.workspaceSessions.reload()),await o.reload()}))}})}var Uo=De;export{Uo as default};
22
+
23
+ //# debugId=449b6114-32dc-4dde-9b3e-7a3c77caffc8
package/docs/sentry.md ADDED
@@ -0,0 +1,54 @@
1
+ # Sentry error collection
2
+
3
+ Browser and extension error reporting are enabled by default with this built-in public DSN:
4
+
5
+ ```text
6
+ https://070c0b7c5ac18d940c294e63ecfa0793@o4506663318716416.ingest.us.sentry.io/4512191040716800
7
+ ```
8
+
9
+ Start Pi and run `/web`; no environment configuration is needed. To override the default destination, set `PI_WEB_SENTRY_DSN` in the **Pi process environment**. Pi does not automatically read `.env`; `.env.example` is a configuration reference.
10
+
11
+ ```sh
12
+ PI_WEB_SENTRY_DSN='https://PUBLIC_KEY@o123.ingest.sentry.io/123' pi
13
+ ```
14
+
15
+ Replace the example with your project's public DSN. `PI_WEB_SENTRY_BROWSER_DSN` and `PI_WEB_SENTRY_NODE_DSN` override the common destination; an explicitly empty override disables that side. An explicitly empty common DSN disables both sides unless a per-side DSN overrides it. Use `PI_WEB_SENTRY_ENABLED=false` to disable both regardless of DSN overrides; disabled SDKs are not loaded and no events are sent. `PI_WEB_SENTRY_ENVIRONMENT` defaults to `production`. Restart Pi after changing runtime configuration. The host's `SENTRY_DSN` is deliberately ignored.
16
+
17
+ ## What is collected
18
+
19
+ - Browser errors, unhandled rejections, React render failures, HTTP/response parsing failures, invalid NDJSON/protocol events and unexpected connection failures.
20
+ - Extension request/workspace/configuration failures, asynchronous Agent and tool failures, and provider-login failures. Fatal exceptions attributable to this extension are best effort; process exit can prevent delivery.
21
+ - Sanitized stack locations and causes, build/release versions, runtime/platform, model and session-state summaries, anonymous session identifiers, request/operation IDs and up to 100 semantic breadcrumbs (64 KiB total).
22
+
23
+ User cancellation, stopping an Agent, normal shutdown, known validation failures and stale-session conflicts are excluded. No conversation, source contents, attachments, login values, request/response bodies, console output or DOM recordings are deliberately collected. Agent/provider error messages are replaced with generic diagnostic labels. Other exception text is scrubbed for credentials, URLs, quoted values, email addresses and absolute paths. Arbitrary free-form exception messages cannot be classified perfectly; do not put private data in exceptions.
24
+
25
+ Browser events go directly to the configured Sentry host with no Pi authorization header, cookies or referrer. The authenticated configuration endpoint returns only the public DSN and build metadata. Node reporting uses a private client and explicit scopes without initializing a global SDK or changing Pi's uncaught-error/async-context handling; inherited SDK attachments are discarded before sending.
26
+
27
+ ## Performance and reliability
28
+
29
+ Each side sends at most 20 events/minute and one event per fingerprint/minute. Repetition counts appear on the next retained event. Startup and transport queues are bounded to 20 events. Transport requests time out after 3 seconds, do not persist offline, and do not retry indefinitely. Rate-limited/dropped events are intentionally lossy. Browser configuration has a 1-second timeout and never gates rendering; SDKs load only when reporting is enabled. No tracing, profiling, automatic console/DOM instrumentation or token-by-token logging is enabled.
30
+
31
+ Request failures and asynchronous error events include additive `errorId`, `requestId`, `operationId`, `errorCode` and `errorReported` metadata. `errorReported` prevents the browser from bypassing server-side deduplication/rate limits. Protocol version 7 is retained. A `shutdown` event stops reconnection on normal exit; controlled launcher upgrades mark it with `reconnect: true` so the browser reconnects without reporting the expected interruption. A changed build ID replaces a retained bridge on `/web` after `/reload` so its static manifest matches the new assets.
32
+
33
+ ## Private source maps and releases
34
+
35
+ `npm run build` produces matching browser/extension release IDs and debug IDs. It archives bundles/maps in `.sentry-artifacts/<buildId>/` and removes `.map` files from `web/dist` and `dist`. Archive directories are git-ignored and excluded from the npm package. These private files contain application source; store them as access-controlled CI artifacts. Ordinary local builds do not upload or contact Sentry.
36
+
37
+ For an upload-required release build, provide these **CI-only** variables:
38
+
39
+ ```sh
40
+ export SENTRY_AUTH_TOKEN='YOUR_CI_TOKEN'
41
+ export SENTRY_ORG='YOUR_ORGANIZATION'
42
+ export SENTRY_PROJECT='YOUR_PROJECT'
43
+ npm run build:sentry
44
+ ```
45
+
46
+ Use `SENTRY_BROWSER_PROJECT` / `SENTRY_NODE_PROJECT` for separate projects. The upload-required command fails on missing credentials or upload failure, and still removes maps from public output. Do not publish after a failed command. Auth tokens are never part of runtime configuration. The ordinary npm `prepack` rebuilds locally without uploading; use `npm pack --ignore-scripts` or `npm publish --ignore-scripts` only after checks and a successful `build:sentry` to package the exact uploaded artifacts.
47
+
48
+ ## Verification and finding an error
49
+
50
+ Run `npm run check`, `npm run test`, `npm run build`, then `npm run test:browser`. Install test Chromium with `npx playwright install chromium`; on a machine with Chrome use `PI_WEB_TEST_CHROME=true npm run test:browser`. Browser tests intercept a synthetic Sentry destination and do not send to a real project. Optional performance comparison: `PI_WEB_TEST_CHROME=true PI_WEB_BENCHMARK=true npm run test:browser -- --grep 'streaming frame budget'`.
51
+
52
+ In Sentry, filter by `release`, `environment` and the `side` tag. Use `contexts.diagnostic.requestId` / `operationId` to follow a browser action into its asynchronous Agent result. Confirm a production-build exception has a `debug_meta` ID matching an uploaded map and resolves to original TypeScript.
53
+
54
+ The included tests verify default reporting through a mock transport, local delivery, correlation, privacy, bounded buffering, render fallback, reconnection and build debug IDs. Real ingestion must be checked in the configured Sentry project; Sentry-side source-map restoration additionally requires CI upload credentials. Context describes the failure path; it does not deterministically replay model responses, tool side effects or private content.