pi-webapp 0.1.6 → 0.1.7

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 (126) hide show
  1. package/README.md +13 -2
  2. package/README.zh-CN.md +11 -2
  3. package/THIRD_PARTY_LICENSE.txt +24 -0
  4. package/bin/pi-webapp.mjs +31 -4
  5. package/dist/extension.js +9 -6
  6. package/package.json +28 -5
  7. package/web/dist/assets/KaTeX_AMS-Regular.ttf +0 -0
  8. package/web/dist/assets/KaTeX_AMS-Regular.woff +0 -0
  9. package/web/dist/assets/KaTeX_AMS-Regular.woff2 +0 -0
  10. package/web/dist/assets/KaTeX_Caligraphic-Bold.ttf +0 -0
  11. package/web/dist/assets/KaTeX_Caligraphic-Bold.woff +0 -0
  12. package/web/dist/assets/KaTeX_Caligraphic-Bold.woff2 +0 -0
  13. package/web/dist/assets/KaTeX_Caligraphic-Regular.ttf +0 -0
  14. package/web/dist/assets/KaTeX_Caligraphic-Regular.woff +0 -0
  15. package/web/dist/assets/KaTeX_Caligraphic-Regular.woff2 +0 -0
  16. package/web/dist/assets/KaTeX_Fraktur-Bold.ttf +0 -0
  17. package/web/dist/assets/KaTeX_Fraktur-Bold.woff +0 -0
  18. package/web/dist/assets/KaTeX_Fraktur-Bold.woff2 +0 -0
  19. package/web/dist/assets/KaTeX_Fraktur-Regular.ttf +0 -0
  20. package/web/dist/assets/KaTeX_Fraktur-Regular.woff +0 -0
  21. package/web/dist/assets/KaTeX_Fraktur-Regular.woff2 +0 -0
  22. package/web/dist/assets/KaTeX_Main-Bold.ttf +0 -0
  23. package/web/dist/assets/KaTeX_Main-Bold.woff +0 -0
  24. package/web/dist/assets/KaTeX_Main-Bold.woff2 +0 -0
  25. package/web/dist/assets/KaTeX_Main-BoldItalic.ttf +0 -0
  26. package/web/dist/assets/KaTeX_Main-BoldItalic.woff +0 -0
  27. package/web/dist/assets/KaTeX_Main-BoldItalic.woff2 +0 -0
  28. package/web/dist/assets/KaTeX_Main-Italic.ttf +0 -0
  29. package/web/dist/assets/KaTeX_Main-Italic.woff +0 -0
  30. package/web/dist/assets/KaTeX_Main-Italic.woff2 +0 -0
  31. package/web/dist/assets/KaTeX_Main-Regular.ttf +0 -0
  32. package/web/dist/assets/KaTeX_Main-Regular.woff +0 -0
  33. package/web/dist/assets/KaTeX_Main-Regular.woff2 +0 -0
  34. package/web/dist/assets/KaTeX_Math-BoldItalic.ttf +0 -0
  35. package/web/dist/assets/KaTeX_Math-BoldItalic.woff +0 -0
  36. package/web/dist/assets/KaTeX_Math-BoldItalic.woff2 +0 -0
  37. package/web/dist/assets/KaTeX_Math-Italic.ttf +0 -0
  38. package/web/dist/assets/KaTeX_Math-Italic.woff +0 -0
  39. package/web/dist/assets/KaTeX_Math-Italic.woff2 +0 -0
  40. package/web/dist/assets/KaTeX_SansSerif-Bold.ttf +0 -0
  41. package/web/dist/assets/KaTeX_SansSerif-Bold.woff +0 -0
  42. package/web/dist/assets/KaTeX_SansSerif-Bold.woff2 +0 -0
  43. package/web/dist/assets/KaTeX_SansSerif-Italic.ttf +0 -0
  44. package/web/dist/assets/KaTeX_SansSerif-Italic.woff +0 -0
  45. package/web/dist/assets/KaTeX_SansSerif-Italic.woff2 +0 -0
  46. package/web/dist/assets/KaTeX_SansSerif-Regular.ttf +0 -0
  47. package/web/dist/assets/KaTeX_SansSerif-Regular.woff +0 -0
  48. package/web/dist/assets/KaTeX_SansSerif-Regular.woff2 +0 -0
  49. package/web/dist/assets/KaTeX_Script-Regular.ttf +0 -0
  50. package/web/dist/assets/KaTeX_Script-Regular.woff +0 -0
  51. package/web/dist/assets/KaTeX_Script-Regular.woff2 +0 -0
  52. package/web/dist/assets/KaTeX_Size1-Regular.ttf +0 -0
  53. package/web/dist/assets/KaTeX_Size1-Regular.woff +0 -0
  54. package/web/dist/assets/KaTeX_Size1-Regular.woff2 +0 -0
  55. package/web/dist/assets/KaTeX_Size2-Regular.ttf +0 -0
  56. package/web/dist/assets/KaTeX_Size2-Regular.woff +0 -0
  57. package/web/dist/assets/KaTeX_Size2-Regular.woff2 +0 -0
  58. package/web/dist/assets/KaTeX_Size3-Regular.ttf +0 -0
  59. package/web/dist/assets/KaTeX_Size3-Regular.woff +0 -0
  60. package/web/dist/assets/KaTeX_Size4-Regular.ttf +0 -0
  61. package/web/dist/assets/KaTeX_Size4-Regular.woff +0 -0
  62. package/web/dist/assets/KaTeX_Size4-Regular.woff2 +0 -0
  63. package/web/dist/assets/KaTeX_Typewriter-Regular.ttf +0 -0
  64. package/web/dist/assets/KaTeX_Typewriter-Regular.woff +0 -0
  65. package/web/dist/assets/KaTeX_Typewriter-Regular.woff2 +0 -0
  66. package/web/dist/assets/app.js +504 -55
  67. package/web/dist/assets/asciidoc.js +1 -0
  68. package/web/dist/assets/bat.js +1 -0
  69. package/web/dist/assets/bibtex.js +1 -0
  70. package/web/dist/assets/c.js +1 -0
  71. package/web/dist/assets/clojure.js +1 -0
  72. package/web/dist/assets/cmake.js +1 -0
  73. package/web/dist/assets/cpp.js +1 -0
  74. package/web/dist/assets/csharp.js +1 -0
  75. package/web/dist/assets/css.js +1 -0
  76. package/web/dist/assets/csv.js +1 -0
  77. package/web/dist/assets/dart.js +1 -0
  78. package/web/dist/assets/diff.js +1 -0
  79. package/web/dist/assets/dotenv.js +1 -0
  80. package/web/dist/assets/elixir.js +1 -0
  81. package/web/dist/assets/erlang.js +1 -0
  82. package/web/dist/assets/fish.js +1 -0
  83. package/web/dist/assets/fsharp.js +1 -0
  84. package/web/dist/assets/go.js +1 -0
  85. package/web/dist/assets/graphql.js +1 -0
  86. package/web/dist/assets/groovy.js +1 -0
  87. package/web/dist/assets/haskell.js +1 -0
  88. package/web/dist/assets/hcl.js +1 -0
  89. package/web/dist/assets/html-derivative.js +1 -0
  90. package/web/dist/assets/html.js +1 -0
  91. package/web/dist/assets/http.js +1 -0
  92. package/web/dist/assets/ini.js +1 -0
  93. package/web/dist/assets/java.js +1 -0
  94. package/web/dist/assets/javascript.js +1 -0
  95. package/web/dist/assets/julia.js +1 -0
  96. package/web/dist/assets/kotlin.js +1 -0
  97. package/web/dist/assets/latex.js +1 -0
  98. package/web/dist/assets/less.js +1 -0
  99. package/web/dist/assets/log.js +1 -0
  100. package/web/dist/assets/lua.js +1 -0
  101. package/web/dist/assets/make.js +1 -0
  102. package/web/dist/assets/markdown.js +1 -0
  103. package/web/dist/assets/mdx.js +1 -0
  104. package/web/dist/assets/nix.js +1 -0
  105. package/web/dist/assets/perl.js +1 -0
  106. package/web/dist/assets/php.js +1 -0
  107. package/web/dist/assets/powershell.js +1 -0
  108. package/web/dist/assets/proto.js +1 -0
  109. package/web/dist/assets/python.js +1 -0
  110. package/web/dist/assets/r.js +1 -0
  111. package/web/dist/assets/rst.js +1 -0
  112. package/web/dist/assets/ruby.js +1 -0
  113. package/web/dist/assets/rust.js +1 -0
  114. package/web/dist/assets/scala.js +1 -0
  115. package/web/dist/assets/scss.js +1 -0
  116. package/web/dist/assets/sql.js +1 -0
  117. package/web/dist/assets/style.css +1 -1
  118. package/web/dist/assets/svelte.js +1 -0
  119. package/web/dist/assets/swift.js +1 -0
  120. package/web/dist/assets/system-verilog.js +1 -0
  121. package/web/dist/assets/toml.js +1 -0
  122. package/web/dist/assets/vb.js +1 -0
  123. package/web/dist/assets/verilog.js +1 -0
  124. package/web/dist/assets/vue.js +1 -0
  125. package/web/dist/assets/xml.js +1 -0
  126. package/web/dist/assets/yaml.js +1 -0
package/dist/extension.js CHANGED
@@ -1,7 +1,10 @@
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
+ import{delimiter as yi,dirname as vi,join as ee,resolve as we}from"node:path";import{realpathSync as ki,watch as bi}from"node:fs";import{realpath as re}from"node:fs/promises";import{fileURLToPath as Pi}from"node:url";import{DefaultPackageManager as pt,getAgentDir as j,ModelRuntime as Ei,SessionManager as ut,SettingsManager as Si}from"@earendil-works/pi-coding-agent";import{getSupportedThinkingLevels as Ii}from"@earendil-works/pi-ai";import{randomBytes as lr,timingSafeEqual as dr}from"node:crypto";import{readFile as pr,readdir as ur}from"node:fs/promises";import{createServer as fr}from"node:http";import{join as Oe}from"node:path";import{mkdir as ht,opendir as yt,stat as vt}from"node:fs/promises";import{homedir as kt}from"node:os";import{basename as bt,dirname as he,join as ye,posix as Pt,resolve as ve,win32 as Et}from"node:path";function ke(r){return process.platform==="win32"?Et.isAbsolute(r)&&/^(?:[A-Za-z]:[\\/]|[\\/]{2}[^\\/]+[\\/]+[^\\/]+)/.test(r):Pt.isAbsolute(r)}function St(r,e,t){if(r.length===t&&e.name.localeCompare(r[r.length-1].name)>=0)return!0;let n=0,s=r.length;for(;n<s;){let a=n+s>>>1;e.name.localeCompare(r[a].name)<0?s=a:n=a+1}return r.splice(n,0,e),r.length<=t?!1:(r.pop(),!0)}async function be(r){if(r!==void 0&&!ke(r))throw new Error("\u76EE\u5F55\u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");let e=kt(),t=ve(r??e),n=[];for(let o=t;;o=he(o)){let d=he(o);if(n.unshift({name:d===o?o:bt(o),path:o,hidden:!1}),d===o)break}let s=[],a=!1,u=await yt(t);for await(let o of u)!o.isDirectory()&&!o.isSymbolicLink()||St(s,{name:o.name,isDirectory:o.isDirectory(),isSymbolicLink:o.isSymbolicLink()},1001)&&(a=!0);let p=[];for(let o of s){let d=ye(t,o.name);if(!o.isDirectory&&o.isSymbolicLink)try{if(!(await vt(d)).isDirectory())continue}catch{continue}if(p.length===1e3){a=!0;break}p.push({name:o.name,path:d,hidden:o.name.startsWith(".")})}return{path:t,home:e,crumbs:n,entries:p,truncated:a}}async function Pe(r,e){if(!ke(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=ye(ve(r),e);return await ht(t),t}import{execFile as It}from"node:child_process";import{accessSync as xt,constants as Ct}from"node:fs";import{delimiter as At,join as Mt}from"node:path";var Wt=(r,e,t)=>new Promise((n,s)=>{It(r,[...e],{encoding:"utf8",signal:t,windowsHide:!0},(a,u,p)=>{a?s(Object.assign(new Error(a.message,{cause:a}),{code:a.code,stdout:u,stderr:p})):n({stdout:u,stderr:p})})});function Tt(r){for(let e of(r??"").split(At))if(e)for(let t of["zenity","kdialog"])try{return xt(Mt(e,t),Ct.X_OK),!0}catch{}return!1}function Ee(r=process.platform,e=process.env){return e.SSH_CONNECTION||e.SSH_TTY?"browse":r==="darwin"||r==="linux"&&(e.DISPLAY||e.WAYLAND_DISPLAY)&&Tt(e.PATH)?"native":"browse"}function F(r){if(!(typeof r!="object"||r===null||!("code"in r)))return typeof r.code=="string"||typeof r.code=="number"?r.code:void 0}function Rt(r){return typeof r=="object"&&r!==null&&"stderr"in r&&typeof r.stderr=="string"?r.stderr:""}function ie(r){return r.replace(/[\r\n]+$/,"")||null}async function Se(r,e=process.platform,t=Wt){if(e==="darwin")try{let n=await t("osascript",["-e",'set selectedFolder to choose folder with prompt "Select Workspace Directory"',"-e","POSIX path of selectedFolder"],r);return ie(n.stdout)}catch(n){if(!r.aborted&&F(n)===1&&/(?:User canceled|-128)/i.test(Rt(n)))return null;throw n}if(e==="linux"){try{return ie((await t("zenity",["--file-selection","--directory","--title=Select Workspace Directory"],r)).stdout)}catch(n){if(r.aborted)throw n;if(F(n)===1)return null;if(F(n)!=="ENOENT")throw n}try{return ie((await t("kdialog",["--getexistingdirectory",".","--title","Select Workspace Directory"],r)).stdout)}catch(n){if(r.aborted)throw n;if(F(n)===1)return null;throw n}}throw new Error(`\u5F53\u524D\u7CFB\u7EDF\u4E0D\u652F\u6301\u672C\u5730\u76EE\u5F55\u9009\u62E9\u5668\uFF1A${e}`)}import{createHash as Nt,randomUUID as _t}from"node:crypto";import{mkdir as jt,readFile as Bt,writeFile as Lt}from"node:fs/promises";import{join as Ie}from"node:path";import{getAgentDir as Ot}from"@earendil-works/pi-coding-agent";var H=20*1024*1024,xe=20,Ut=/^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])$/iu;function Vt(r){let e=r.indexOf("."),t=(e<0?r:r.slice(0,e)).replace(/[. ]+$/u,"");return Ut.test(t)}function Dt(r,e){let t=0,n="";for(let s of Buffer.from(r).toString("utf8")){let a=Buffer.byteLength(s);if(t+a>e)break;n+=s,t+=a}return n}function $t(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 Vt(t)&&(t=`_${t}`),t=Dt(t,255).replace(/[. ]+$/u,""),t===""||t==="."||t===".."?"file":t}function Ft(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 Ce(r,e,t,n){if(n.byteLength===0||n.byteLength>H)throw new Error("\u6587\u4EF6\u4E3A\u7A7A\u6216\u8D85\u8FC7 20 MB");let s=$t(e),a=Nt("sha256").update(n).digest("hex"),u=Ie(Ot(),"pi-web","attachments",a);await jt(u,{recursive:!0});let p=Ie(u,s);try{await Lt(p,n,{flag:"wx",mode:384})}catch(o){if(!(o instanceof Error&&"code"in o&&o.code==="EEXIST"))throw o}return{id:_t(),name:s,bytes:n.byteLength,path:p,mediaType:Ft(n)??t.replace(/^image\//,"application/"),sessionId:r}}async function Ae(r){return{type:"image",data:(await Bt(r.path)).toString("base64"),mimeType:r.mediaType}}import{randomBytes as Ht}from"node:crypto";function Me(r,e,t){return r!=="openai-codex"||e!=="oauth"?t:{...t,prompt:n=>n.type==="select"&&n.options.some(s=>s.id==="browser")&&n.options.some(s=>s.id==="device_code")?Promise.resolve("browser"):t.prompt(n)}}var G=class{flows=new Map;start(e,t,n,s){let a=this.getActive();if(a){if(a.providerId===e&&a.method===t&&s===void 0)return a;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=Ht(18).toString("base64url"),p={view:{id:u,providerId:e,method:t,status:"running"},controller:new AbortController};return this.flows.set(u,p),n(e,t,{signal:p.controller.signal,notify:o=>{p.view={...p.view,event:o,...o.type==="auth_url"||o.type==="device_code"?{authorization:o}:{}}},prompt:o=>{if(o.type==="secret"&&s!==void 0){let d=s;return s=void 0,Promise.resolve(d)}return new Promise((d,f)=>{let{signal:m,...v}=o;p.answer=d,p.reject=f,p.view={...p.view,status:"waiting",prompt:v},m?.aborted?f(new Error("\u767B\u5F55\u8F93\u5165\u5DF2\u53D6\u6D88")):m?.addEventListener("abort",()=>f(new Error("\u767B\u5F55\u8F93\u5165\u5DF2\u53D6\u6D88")),{once:!0})})}}).then(()=>{p.view.status!=="cancelled"&&(p.view={id:u,providerId:e,method:t,status:"done"})}).catch(()=>{p.view.status!=="cancelled"&&(p.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"})}),{...p.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 n=this.flows.get(e);if(!n?.answer||n.view.status!=="waiting"||n.view.prompt?.type==="select"&&!n.view.prompt.options.some(a=>a.id===t))return!1;let s=n.answer;return n.answer=void 0,n.reject=void 0,n.view={...n.view,status:"running",prompt:void 0},s(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 Gt}from"node:crypto";import{readFile as Jt,rename as zt,rm as qt,stat as Kt,writeFile as Yt,mkdir as Xt}from"node:fs/promises";import{dirname as Qt}from"node:path";var Zt=["openai-completions","openai-responses","anthropic-messages"];function ne(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||!Zt.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 We(r,e){if(!ne(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 Jt(r,"utf8")}catch(p){if(p.code!=="ENOENT")throw p}let n;if(t===void 0)n={providers:{}};else{try{n=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(!n||typeof n!="object"||!n.providers||typeof n.providers!="object"||Array.isArray(n.providers))throw new Error("models.json \u7ED3\u6784\u65E0\u6548")}if(Object.hasOwn(n.providers,e.id))throw new Error("\u63D0\u4F9B\u65B9\u5DF2\u5B58\u5728");let s={...n,providers:{...n.providers,[e.id]:{name:e.name.trim(),baseUrl:e.baseUrl,api:e.api,models:[{id:e.modelId.trim()}]}}};await Xt(Qt(r),{recursive:!0});let a=t===void 0?384:(await Kt(r)).mode&511,u=`${r}.pi-web-${Gt(6).toString("hex")}.tmp`;try{await Yt(u,`${JSON.stringify(s,null,2)}
2
+ `,{mode:a,flag:"wx"}),await zt(u,r)}finally{await qt(u,{force:!0})}}import{randomBytes as er}from"node:crypto";import{mkdir as tr,readFile as rr,rename as ir,rm as nr,stat as sr,writeFile as or}from"node:fs/promises";import{dirname as ar}from"node:path";function Te(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 Re(r){if(!r||typeof r!="object")return!1;let e=r;return e.action==="save"?(e.originalId===void 0||typeof e.originalId=="string")&&Ne(e.model):e.action==="base_url"?e.baseUrl===null||typeof e.baseUrl=="string"&&Te(e.baseUrl):e.action==="remove"&&typeof e.id=="string"&&e.id.length>0&&e.id.length<=200}function Ne(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 _e(r){let e;try{e=await rr(r,"utf8")}catch(n){if(n.code!=="ENOENT")throw n}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 cr(r,e,t){await tr(ar(r),{recursive:!0});let n=t===void 0?384:(await sr(r)).mode&511,s=`${r}.pi-web-${er(6).toString("hex")}.tmp`;try{await or(s,`${JSON.stringify(e,null,2)}
3
+ `,{mode:n,flag:"wx"}),await ir(s,r)}finally{await nr(s,{force:!0})}}async function je(r,e,t){if(!t.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:n}=await _e(r),s=n.providers[e],a=new Set(s?.models?.map(u=>u.id)??[]);return{providerId:e,baseUrl:s?.baseUrl,models:t.getModels(e).map(u=>({id:u.id,name:u.name,contextWindow:u.contextWindow,maxTokens:u.maxTokens,input:[...u.input],source:a.has(u.id)?"custom":"builtin",overridden:!!s?.modelOverrides?.[u.id]}))}}async function Be(r,e,t,n){if(!n.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:s,existing:a}=await _e(r),u={...s.providers[e]??{}},p=[...u.models??[]],o={...u.modelOverrides??{}};if(t.action==="base_url"){if(t.baseUrl!==null&&!Te(t.baseUrl))throw new Error("API \u5730\u5740\u65E0\u6548");t.baseUrl===null?delete u.baseUrl:u.baseUrl=t.baseUrl}else if(t.action==="save"){if(!Ne(t.model))throw new Error("\u6A21\u578B\u53C2\u6570\u65E0\u6548");let d={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}},f=t.originalId,m=f===void 0?-1:p.findIndex(v=>v.id===f);if(f===void 0&&(p.some(v=>v.id===d.id)||n.getModel(e,d.id)))throw new Error("\u6A21\u578B ID \u5DF2\u5B58\u5728");if(m>=0){if(d.id!==f&&(p.some(k=>k.id===d.id)||n.getModel(e,d.id)))throw new Error("\u6A21\u578B ID \u5DF2\u5B58\u5728");let v={...p[m],...d};for(let k of["name","contextWindow","maxTokens","input"])d[k]===void 0&&delete v[k];p[m]=v}else if(f!==void 0&&n.getModel(e,f)){if(d.id!==f)throw new Error("\u5185\u7F6E\u6A21\u578B ID \u4E0D\u53EF\u4FEE\u6539");let{id:v,...k}=d;o[f]={...o[f],...k};for(let w of["name","contextWindow","maxTokens","input"])d[w]===void 0&&delete o[f][w]}else{if(f!==void 0)throw new Error("\u6A21\u578B\u4E0D\u5B58\u5728");p.push(d)}}else{let d=p.findIndex(f=>f.id===t.id);if(d>=0)p.splice(d,1);else if(Object.hasOwn(o,t.id))delete o[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")}p.length?u.models=p:delete u.models,Object.keys(o).length?u.modelOverrides=o:delete u.modelOverrides,Object.keys(u).length?s.providers[e]=u:delete s.providers[e],await cr(r,s,a)}function Le(r){return/^(?:npm:|git:|https?:\/\/|ssh:\/\/|git@)/i.test(r.trim())}var gr={"/":{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 g(r,e,t){r.writeHead(e,{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}),r.end(JSON.stringify(t))}function mr(r,e){let t=r.headers.authorization;if(typeof t!="string"||!t.startsWith("Bearer "))return!1;let n=Buffer.from(t.slice(7),"utf8");return n.length===e.length&&dr(n,e)}async function wr(r){let e=0,t=[];for await(let n of r){let s=Buffer.isBuffer(n)?n:Buffer.from(n);if(e+=s.length,e>64*1024)throw new Error("\u8BF7\u6C42\u5185\u5BB9\u8FC7\u5927");t.push(s)}return JSON.parse(Buffer.concat(t).toString("utf8"))}async function hr(r){let e=0,t=[];for await(let n of r){let s=Buffer.isBuffer(n)?n:Buffer.from(n);if(e+=s.length,e>H)throw new Error("\u6587\u4EF6\u8D85\u8FC7 20 MB");t.push(s)}return Buffer.concat(t)}async function yr(r,e=0){await new Promise((n,s)=>{r.once("error",s),r.listen(e,"127.0.0.1",()=>{r.off("error",s),n()})});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 Ue(r,e){let t=process.env.PI_WEBAPP_RESTART_TOKEN,n=t&&/^[A-Za-z0-9_-]{32}$/.test(t)?t:lr(24).toString("base64url"),s=Buffer.from(n),a=Ee(),u=new Set,p=new Map,o=new G,d="",f={...gr};for(let w of await ur(Oe(e,"assets")).catch(()=>[])){let l=/^[\w.-]+\.(js|css|woff2?|ttf)$/.exec(w);if(!l)continue;let h={js:"text/javascript; charset=utf-8",css:"text/css; charset=utf-8",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf"};f[`/assets/${w}`]={path:`assets/${w}`,type:h[l[1]]}}let m=fr(async(w,l)=>{l.setHeader("X-Content-Type-Options","nosniff"),l.setHeader("Referrer-Policy","no-referrer"),l.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 h;try{h=new URL(w.url??"/",d).pathname}catch{g(l,400,{error:"\u8BF7\u6C42\u5730\u5740\u65E0\u6548"});return}let M=f[h];if(w.method==="GET"&&M){try{let c=await pr(Oe(e,M.path));l.writeHead(200,{"Content-Type":M.type,"Cache-Control":"no-store"}),l.end(c)}catch{g(l,500,{error:"\u9875\u9762\u6587\u4EF6\u4E0D\u53EF\u7528"})}return}if(w.method==="GET"&&h.startsWith("/plugins/")){try{let c=await r.pluginAsset?.(w.url??h);if(!c){g(l,404,{error:"\u63D2\u4EF6\u8D44\u6E90\u4E0D\u5B58\u5728"});return}l.writeHead(200,{"Content-Type":c.type,"Cache-Control":"no-store"}),l.end(c.bytes)}catch{g(l,404,{error:"\u63D2\u4EF6\u8D44\u6E90\u4E0D\u53EF\u7528"})}return}if(!h.startsWith("/api/")){g(l,404,{error:"\u672A\u627E\u5230"});return}if(!mr(w,s)){g(l,401,{error:"\u8BBF\u95EE\u4EE4\u724C\u65E0\u6548"});return}if(w.method==="GET"&&h==="/api/update/version"){try{g(l,200,{current:await r.selfUpdate?.runningVersion()??null})}catch(c){g(l,503,{error:c instanceof Error?c.message:"\u65E0\u6CD5\u8BFB\u53D6\u7248\u672C"})}return}if(w.method==="GET"&&h==="/api/update"){try{g(l,200,await r.selfUpdate?.check()??{canRestart:!1,reason:"\u5F53\u524D\u6269\u5C55\u4E0D\u652F\u6301\u5728\u7EBF\u5347\u7EA7"})}catch(c){g(l,503,{error:c instanceof Error?c.message:"\u68C0\u67E5\u66F4\u65B0\u5931\u8D25"})}return}if(w.method==="GET"&&h==="/api/image"){let c=new URL(w.url??h,d),y=c.searchParams.get("sessionId")??"",b=c.searchParams.get("messageId")??"",P=Number(c.searchParams.get("index"));if(!y||y!==r.snapshot().sessionId||!b||!Number.isInteger(P)||P<0||P>100){g(l,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u56FE\u7247\u5730\u5740\u65E0\u6548"});return}let T=r.image?.(y,b,P);if(!T||!["image/png","image/jpeg","image/webp","image/gif"].includes(T.mimeType)){g(l,404,{error:"\u56FE\u7247\u4E0D\u53EF\u7528"});return}l.writeHead(200,{"Content-Type":T.mimeType,"Cache-Control":"private, no-store"}),l.end(T.data);return}if(w.method==="POST"&&h==="/api/attachment"){if(w.headers.origin!==void 0&&w.headers.origin!==d){g(l,403,{error:"\u6765\u6E90\u4E0D\u5339\u914D"});return}let c=new URL(w.url??h,d),y=c.searchParams.get("sessionId"),b=c.searchParams.get("name");try{if(!y||!b||b.length>1024||y!==r.snapshot().sessionId){g(l,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u6587\u4EF6\u540D\u65E0\u6548"});return}if(Number(w.headers["content-length"]??0)>H){g(l,413,{error:"\u6587\u4EF6\u8D85\u8FC7 20 MB"});return}let P=await Ce(y,b,w.headers["content-type"]??"application/octet-stream",await hr(w));if(y!==r.snapshot().sessionId){g(l,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}p.set(P.id,P),g(l,201,{id:P.id,name:P.name,bytes:P.bytes})}catch(P){g(l,400,{error:P instanceof Error?P.message:"\u4E0A\u4F20\u5931\u8D25"})}return}if(w.method==="GET"&&h==="/api/session"){try{g(l,200,r.snapshot())}catch{g(l,503,{error:"\u5F53\u524D\u4F1A\u8BDD\u4E0D\u53EF\u7528"})}return}if(w.method==="GET"&&h==="/api/plugins"){try{g(l,200,await r.plugins?.()??{plugins:[],errors:[]})}catch{g(l,503,{error:"\u63D2\u4EF6\u76EE\u5F55\u4E0D\u53EF\u7528"})}return}if(w.method==="GET"&&h==="/api/providers"){try{g(l,200,await r.providers?.()??[])}catch{g(l,503,{error:"\u6A21\u578B\u63D0\u4F9B\u65B9\u4E0D\u53EF\u7528"})}return}if(w.method==="GET"&&h==="/api/provider/models"){let c=new URL(w.url??h,d).searchParams.get("providerId")??"";try{if(!c||!r.providerModels){g(l,400,{error:"\u63D0\u4F9B\u65B9\u65E0\u6548"});return}g(l,200,await r.providerModels(c))}catch(y){g(l,400,{error:y instanceof Error?y.message:"\u6A21\u578B\u76EE\u5F55\u4E0D\u53EF\u7528"})}return}if(w.method==="GET"&&h==="/api/provider/login/active"){g(l,200,{active:o.getActive()??null});return}if(w.method==="GET"&&h==="/api/provider/login"){let c=new URL(w.url??h,d).searchParams.get("id")??"",y=o.get(c);g(l,y?200:404,y??{error:"\u767B\u5F55\u6D41\u7A0B\u4E0D\u5B58\u5728"});return}if(w.method==="GET"&&(h==="/api/models"||h==="/api/config"||h==="/api/workspaces"||h==="/api/commands")){try{g(l,200,h==="/api/models"?await r.models():h==="/api/config"?await r.config():h==="/api/commands"?r.commands?.()??[]:await r.workspaces())}catch{g(l,503,{error:"Pi \u914D\u7F6E\u4E0D\u53EF\u7528"})}return}if(w.method==="GET"&&h==="/api/directory/capability"){g(l,200,{kind:a});return}if(w.method==="GET"&&h==="/api/events"){let c;try{c=r.snapshot()}catch{g(l,503,{error:"\u5F53\u524D\u4F1A\u8BDD\u4E0D\u53EF\u7528"});return}l.writeHead(200,{"Content-Type":"application/x-ndjson; charset=utf-8","Cache-Control":"no-store",Connection:"keep-alive","X-Accel-Buffering":"no"}),u.add(l),l.write(`${JSON.stringify({type:"snapshot",session:c})}
4
+ `),l.on("close",()=>u.delete(l));return}if(w.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(h)){if(w.headers.origin!==void 0&&w.headers.origin!==d){g(l,403,{error:"\u6765\u6E90\u4E0D\u5339\u914D"});return}if(!w.headers["content-type"]?.startsWith("application/json")){g(l,415,{error:"\u9700\u8981 JSON \u8BF7\u6C42"});return}try{let c=await wr(w);if(typeof c!="object"||c===null||!("sessionId"in c)||typeof c.sessionId!="string"){g(l,400,{error:"\u7F3A\u5C11\u4F1A\u8BDD\u6807\u8BC6"});return}if(h==="/api/plugin-interaction"){if(c.sessionId!==r.snapshot().sessionId){g(l,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("pluginId"in c)||typeof c.pluginId!="string"||c.pluginId.length>200||!("requestId"in c)||typeof c.requestId!="string"||c.requestId.length>200||!r.resolvePluginInteraction||!("value"in c)){g(l,400,{error:"\u63D2\u4EF6\u4EA4\u4E92\u54CD\u5E94\u65E0\u6548"});return}await r.resolvePluginInteraction(c.sessionId,c.pluginId,c.requestId,c.value),g(l,200,{accepted:!0});return}if(h==="/api/plugin-action"){if(c.sessionId!==r.snapshot().sessionId){g(l,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("pluginId"in c)||typeof c.pluginId!="string"||c.pluginId.length>200||!("action"in c)||typeof c.action!="string"||c.action.length>100||!r.invokePluginAction){g(l,400,{error:"\u63D2\u4EF6\u52A8\u4F5C\u65E0\u6548"});return}let y=await r.invokePluginAction(c.sessionId,c.pluginId,c.action,"input"in c?c.input:void 0);g(l,200,{value:y});return}if(h==="/api/update"){if(c.sessionId!==r.snapshot().sessionId){g(l,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!r.snapshot().idle){g(l,409,{error:"\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u540E\u518D\u5347\u7EA7"});return}if(!r.selfUpdate){g(l,409,{error:"\u5F53\u524D\u6269\u5C55\u4E0D\u652F\u6301\u5728\u7EBF\u5347\u7EA7"});return}let y=await r.selfUpdate.prepare();g(l,202,{accepted:!0,version:y.version}),setTimeout(()=>{r.selfUpdate?.requestRestart(y).catch(b=>console.error("pi-webapp restart:",b))},500).unref();return}if(h==="/api/provider/custom"){if(c.sessionId!==r.snapshot().sessionId){g(l,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("provider"in c)||!ne(c.provider)||!r.addCustomProvider){g(l,400,{error:"\u81EA\u5B9A\u4E49\u63D0\u4F9B\u65B9\u65E0\u6548"});return}await r.addCustomProvider(c.sessionId,c.provider),g(l,201,{accepted:!0});return}if(h==="/api/provider/models"||h==="/api/provider/logout"){if(c.sessionId!==r.snapshot().sessionId){g(l,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("providerId"in c)||typeof c.providerId!="string"){g(l,400,{error:"\u63D0\u4F9B\u65B9\u65E0\u6548"});return}if(h==="/api/provider/models"){if(!("change"in c)||!Re(c.change)||!r.updateProviderModel){g(l,400,{error:"\u6A21\u578B\u53C2\u6570\u65E0\u6548"});return}await r.updateProviderModel(c.sessionId,c.providerId,c.change)}else{if(!r.logoutProvider){g(l,400,{error:"\u65E0\u6CD5\u79FB\u9664\u8BA4\u8BC1"});return}await r.logoutProvider(c.sessionId,c.providerId)}g(l,200,{accepted:!0});return}if(h.startsWith("/api/provider/login")){if(c.sessionId!==r.snapshot().sessionId){g(l,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(h==="/api/provider/login"){if(!("providerId"in c)||typeof c.providerId!="string"||!("method"in c)||c.method!=="api_key"&&c.method!=="oauth"||!r.loginProvider||!r.providers){g(l,400,{error:"\u767B\u5F55\u65B9\u5F0F\u65E0\u6548"});return}if(!(await r.providers()).some(T=>T.id===c.providerId&&T.methods.includes(c.method))){g(l,400,{error:"\u63D0\u4F9B\u65B9\u4E0D\u652F\u6301\u6B64\u767B\u5F55\u65B9\u5F0F"});return}let b="initialSecret"in c?c.initialSecret:void 0;if(b!==void 0&&(c.method!=="api_key"||typeof b!="string"||!b.trim()||b.length>16384)){g(l,400,{error:"API Key \u65E0\u6548"});return}let P=o.start(c.providerId,c.method,r.loginProvider,b);g(l,202,{id:P.id});return}if(!("id"in c)||typeof c.id!="string"){g(l,400,{error:"\u767B\u5F55\u6D41\u7A0B\u65E0\u6548"});return}if(h==="/api/provider/login/cancel"){g(l,o.cancel(c.id)?202:404,{accepted:!0});return}if(!("value"in c)||typeof c.value!="string"||c.value.length>16384||!o.respond(c.id,c.value)){g(l,400,{error:"\u767B\u5F55\u8F93\u5165\u65E0\u6548"});return}g(l,202,{accepted:!0});return}if(h==="/api/attachment/remove"){if(!("id"in c)||typeof c.id!="string"||c.sessionId!==r.snapshot().sessionId){g(l,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u9644\u4EF6\u65E0\u6548"});return}p.get(c.id)?.sessionId===c.sessionId&&p.delete(c.id),g(l,202,{accepted:!0});return}if(h==="/api/directory/pick"){if(a!=="native"){g(l,409,{error:"\u672C\u5730\u76EE\u5F55\u9009\u62E9\u5668\u4E0D\u53EF\u7528"});return}let y=new AbortController;l.once("close",()=>y.abort()),g(l,200,{path:await Se(y.signal)});return}if(h==="/api/directory/list"){if("path"in c&&(typeof c.path!="string"||c.path.length>4096)){g(l,400,{error:"\u76EE\u5F55\u8DEF\u5F84\u65E0\u6548"});return}g(l,200,await be("path"in c?c.path:void 0));return}if(h==="/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){g(l,400,{error:"\u6587\u4EF6\u5939\u540D\u79F0\u6216\u8DEF\u5F84\u65E0\u6548"});return}g(l,200,{path:await Pe(c.path,c.name)});return}if(h==="/api/workspace/add"){if(!("path"in c)||typeof c.path!="string"||c.path.length>4096||!("create"in c)||typeof c.create!="boolean"){g(l,400,{error:"\u5DE5\u4F5C\u533A\u8DEF\u5F84\u65E0\u6548"});return}await r.addWorkspace(c.path,c.create),g(l,202,{accepted:!0});return}if(h==="/api/workspace/select"||h==="/api/workspace/remove"||h==="/api/workspace/new-session"){if(!("id"in c)||typeof c.id!="string"){g(l,400,{error:"\u5DE5\u4F5C\u533A\u65E0\u6548"});return}h==="/api/workspace/select"?await r.selectWorkspace(c.id):h==="/api/workspace/new-session"?await r.newSessionInWorkspace(c.id):await r.removeWorkspace(c.id),g(l,202,{accepted:!0});return}if(h==="/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"){g(l,400,{error:"\u4F1A\u8BDD\u65E0\u6548"});return}await r.selectSession(c.workspaceId,c.id,c.path),g(l,202,{accepted:!0});return}if(h==="/api/thinking-level"){if(!("level"in c)||typeof c.level!="string"){g(l,400,{error:"\u63A8\u7406\u5F3A\u5EA6\u65E0\u6548"});return}await r.setThinkingLevel(c.sessionId,c.level)}else if(h==="/api/model"){if(!("provider"in c)||typeof c.provider!="string"||!("id"in c)||typeof c.id!="string"){g(l,400,{error:"\u6A21\u578B\u65E0\u6548"});return}await r.setModel(c.sessionId,c.provider,c.id)}else if(h==="/api/config"){let y=c;if(!["packages","extensions","skills"].includes(y.kind)||!["global","project"].includes(y.scope)||!["add","remove"].includes(y.action)||typeof y.value!="string"||!y.value.trim()||y.value.length>2048){g(l,400,{error:"\u914D\u7F6E\u9879\u65E0\u6548"});return}if(y.action==="add"&&y.kind!=="packages"&&Le(y.value)){g(l,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}g(l,200,await r.updateConfig(y));return}else if(h==="/api/message"){let y="attachments"in c?c.attachments:[];if(!Array.isArray(y)||y.length>xe||y.some(x=>typeof x!="string")||new Set(y).size!==y.length){g(l,400,{error:"\u9644\u4EF6\u65E0\u6548\u6216\u8FC7\u591A"});return}let b=y.map(x=>p.get(x));if(b.some(x=>!x||x.sessionId!==c.sessionId)){g(l,400,{error:"\u9644\u4EF6\u4E0D\u53EF\u7528"});return}if(!("text"in c)||typeof c.text!="string"||!c.text.trim()&&y.length===0||c.text.length>32e3){g(l,400,{error:"\u6D88\u606F\u65E0\u6548\u6216\u8FC7\u957F"});return}let P=b,T=[c.text.trim(),...P.map(x=>`\u9644\u4EF6 ${JSON.stringify(x.name)}\uFF1A${x.path}`)].filter(Boolean).join(`
5
5
 
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};
6
+ `),wt=await Promise.all(P.filter(x=>["image/png","image/jpeg","image/webp","image/gif"].includes(x.mediaType)).map(Ae));await r.send(c.sessionId,T,wt);for(let x of y)p.delete(x)}else if(h==="/api/compact"){if(!r.compact)throw new Error("\u5F53\u524D\u4F1A\u8BDD\u4E0D\u652F\u6301\u538B\u7F29");await r.compact(c.sessionId)}else if(h==="/api/resume"){let y=r.snapshot();if(c.sessionId!==y.sessionId){g(l,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!y.idle){g(l,409,{error:"Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F"});return}if(!y.paused){g(l,409,{error:"\u5F53\u524D\u4F1A\u8BDD\u6CA1\u6709\u6682\u505C\u7684\u4EFB\u52A1"});return}if(y.interactions?.length){g(l,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(c.sessionId)}else h==="/api/abort"?await r.abort(c.sessionId):await r.newSession(c.sessionId);g(l,202,{accepted:!0})}catch(c){let y=c instanceof Error?c.message:"\u8BF7\u6C42\u5931\u8D25";g(l,y==="\u4F1A\u8BDD\u5DF2\u5207\u6362"?409:400,{error:y})}return}g(l,404,{error:"\u672A\u627E\u5230"})}),v=Number(process.env.PI_WEBAPP_RESTART_PORT);return d=`http://127.0.0.1:${await yr(m,Number.isInteger(v)&&v>0&&v<65536&&t===n?v:0)}`,{protocolVersion:7,url:`${d}/#${n}`,publish(w){if(w.type==="snapshot")for(let[h,M]of p)M.sessionId!==w.session.sessionId&&p.delete(h);let l=`${JSON.stringify(w)}
7
+ `;for(let h of u)h.write(l)},async close(){o.close();for(let w of u)w.end();u.clear(),await new Promise((w,l)=>m.close(h=>h?l(h):w()))}}}import{getSupportedThinkingLevels as vr}from"@earendil-works/pi-ai";function Ve(r){let e=[],t=r;for(;;){let n=/(^|\n\n)附件 ("(?:\\.|[^"\\])*"):([^\n]+)$/u.exec(t);if(!n||!/[\\/]pi-web[\\/]attachments[\\/][a-f0-9]{64}[\\/]/u.test(n[3]))break;let s;try{s=JSON.parse(n[2])}catch{break}e.unshift({name:s,image:/\.(?:png|jpe?g|webp|gif)$/iu.test(s)}),t=t.slice(0,n.index)}return{text:t,attachments:e}}var O="pi-webapp/paused",se="pi-webapp/resume";function U(r){for(let e=r.length-1;e>=0;e--){let t=r[e];if(t.type==="custom_message"&&t.customType===se)return!1;if(t.type==="custom"&&t.customType===O)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 oe(r,e){let t=[],n;for(let s of r){if(s.type==="message"&&(n=s.id),s.type!=="custom")continue;let a=e.find(u=>s.customType.startsWith(`${u}/`));if(a){try{if(JSON.stringify(s.data).length>128*1024)continue}catch{continue}t.push({id:s.id,pluginId:a,kind:s.customType,data:s.data,timestamp:s.timestamp,...n?{afterMessageId:n}:{}})}}return t}function R(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 ae(r){if(r.type==="custom_message")return r.display?{id:r.id,role:"notice",timestamp:r.timestamp,blocks:R(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:R(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:R(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 n=e.find(a=>a.role==="user"),s=Ve(n?.blocks.find(a=>a.kind==="text")?.text??"").text.replace(/\s+/g," ").trim();return s?s.slice(0,50):"\u5F53\u524D\u4F1A\u8BDD"}function De(r,e,t=[]){let n=r.sessionManager.getBranch().flatMap(s=>{let a=ae(s);return a?[a]:[]});return{schemaVersion:1,sessionId:r.sessionManager.getSessionId(),cwd:r.cwd,name:ce(e,n),model:r.model?`${r.model.provider}/${r.model.id}`:null,thinkingLevel:r.thinkingLevel??null,thinkingLevels:r.model?vr(r.model):["off"],idle:r.isIdle(),paused:U(r.sessionManager.getBranch()),contextUsage:r.getContextUsage()??null,messages:n,pluginEntries:oe(r.sessionManager.getBranch(),t)}}import{randomUUID as le}from"node:crypto";import{mkdir as $e,readFile as kr,realpath as Fe,rename as br,rm as Pr,stat as He,writeFile as Er}from"node:fs/promises";import{basename as Ge,dirname as Sr,isAbsolute as Je,join as Ir}from"node:path";var J=class{items=[];hiddenPaths=[];mutationChain=Promise.resolve();file;constructor(e){this.file=e}async load(){try{let e=JSON.parse(await kr(this.file,"utf8")),t,n=[];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,n=e.hiddenPaths),!Array.isArray(t)||!Array.isArray(n))throw new Error("\u5DE5\u4F5C\u533A\u8BB0\u5F55\u65E0\u6548");this.items=t.filter(s=>typeof s=="object"&&s!==null&&typeof s.id=="string"&&typeof s.path=="string"&&typeof s.title=="string"),this.hiddenPaths=n.filter(s=>typeof s=="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(!Je(e)||e.includes("\0"))throw new Error("\u8BF7\u8F93\u5165\u5B8C\u6574\u7684\u76EE\u5F55\u8DEF\u5F84");t&&await $e(e,{recursive:!0});let n=await Fe(e);if(!(await He(n)).isDirectory())throw new Error("\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55");return this.mutate(async()=>{let s=this.hiddenPaths.filter(o=>o!==n),a=this.items.find(o=>o.path===n);if(a)return s.length!==this.hiddenPaths.length&&(await this.save(this.items,s),this.hiddenPaths=s),a;let u={id:le(),path:n,title:Ge(n)||n},p=[u,...this.items];return await this.save(p,s),this.items=p,this.hiddenPaths=s,u})}async discover(e){let t=(await Promise.all([...new Set(e)].filter(Je).map(async n=>{try{let s=await Fe(n);return(await He(s)).isDirectory()?s:null}catch{return null}}))).filter(n=>n!==null);await this.mutate(async()=>{let n=new Set([...this.items.map(u=>u.path),...this.hiddenPaths]),s=[];for(let u of t)n.has(u)||(n.add(u),s.push({id:le(),path:u,title:Ge(u)||u}));if(s.length===0)return;let a=[...this.items,...s];await this.save(a,this.hiddenPaths),this.items=a})}async remove(e){await this.mutate(async()=>{let t=this.get(e);if(!t)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");let n=this.items.filter(a=>a.id!==e),s=[...new Set([...this.hiddenPaths,t.path])];await this.save(n,s),this.items=n,this.hiddenPaths=s})}mutate(e){let t=this.mutationChain.then(e,e);return this.mutationChain=t.then(()=>{},()=>{}),t}async save(e,t){await $e(Sr(this.file),{recursive:!0});let n=`${this.file}.${le()}.tmp`;try{await Er(n,JSON.stringify({version:2,items:e,hiddenPaths:t},null,2),{mode:384}),await br(n,this.file)}catch(s){throw await Pr(n,{force:!0}),s}}};function ze(r){return Ir(r,"pi-web","workspaces.json")}import{createAgentSession as ri,createEventBus as ii,DefaultResourceLoader as ni,getAgentDir as si,SessionManager as Y}from"@earendil-works/pi-coding-agent";var xr="pi-webapp:interaction-open:v1",Cr="pi-webapp:interaction-accept:v1",qe="pi-webapp:interaction-settle:v1",Ar="pi-webapp:interaction-cancel:v1";var B=class{bus;accepts;changed;requests=new Map;detach;constructor(e,t,n){this.bus=e,this.accepts=t,this.changed=n,this.detach=[e.on(xr,s=>{!Mr(s)||!t(s)||this.requests.has(s.requestId)||(this.requests.set(s.requestId,s),e.emit(Cr,{requestId:s.requestId}),n())}),e.on(Ar,s=>{let a=s,u=this.requests.get(a?.requestId);u&&u.sessionId===a.sessionId&&u.pluginId===a.pluginId&&(this.requests.delete(a.requestId),n())})]}pending(e){return[...this.requests.values()].filter(t=>t.sessionId===e)}resolve(e,t,n,s){let a=this.requests.get(n);if(!a||a.sessionId!==e||a.pluginId!==t||!this.accepts(a))throw new Error("Interaction expired or session changed");this.requests.delete(n),this.bus.emit(qe,{requestId:n,value:s}),this.changed()}cancelAll(e="Session changed"){for(let t of this.requests.values())this.bus.emit(qe,{requestId:t.requestId,error:e});this.requests.clear(),this.changed()}dispose(){for(let e of this.detach)e();this.cancelAll("Interaction host unloaded")}};function Mr(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 Wr=1,Tr="pi-webapp:action:v1",Rr="pi-webapp:action-response:v1",z="pi-webapp:plugin-changed:v1";function Ke(r){if(!r||typeof r!="object")return!1;let e=r;return e.apiVersion===Wr&&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 q(r,e,t=15e3,n){return new Promise((s,a)=>{let u=!1,p=(m,v)=>{u||(u=!0,clearTimeout(d),o(),n?.removeEventListener("abort",f),m?a(m):s(v))},o=r.on(Rr,m=>{let v=m;v?.requestId===e.requestId&&p(v.ok?null:new Error(v.error??"Plugin action failed"),v.value)}),d=setTimeout(()=>p(new Error(`Plugin action timed out: ${e.pluginId}/${e.action}`)),t),f=()=>p(new Error("Plugin action runtime unloaded"));if(n?.addEventListener("abort",f,{once:!0}),n?.aborted)f();else try{r.emit(Tr,e)}catch(m){p(m instanceof Error?m:new Error(String(m)))}})}import{realpath as st}from"node:fs/promises";import{readFile as de,realpath as Ze,stat as et}from"node:fs/promises";import{createHash as Nr}from"node:crypto";import{dirname as Ye,isAbsolute as _r,join as pe,parse as jr,resolve as Br,sep as Lr,delimiter as Or}from"node:path";import{DefaultPackageManager as Ur,getAgentDir as Vr,SettingsManager as Dr}from"@earendil-works/pi-coding-agent";async function Xe(r,e){let t=await de(r),n=e?await de(e):void 0;if(t.length>8*1024*1024||(n?.length??0)>8*1024*1024)throw new Error("Plugin asset exceeds 8 MB");let s=Nr("sha256").update(t).update("\0").update(n??"").digest("hex");return{clientBytes:t,styleBytes:n,revision:s}}function $r(){return(process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS??"").split(Or).filter(Boolean).map(r=>Br(r))}async function Fr(r){let e=Ye(r);for(;e!==jr(e).root;)try{return await et(pe(e,"package.json")),e}catch{e=Ye(e)}return null}async function Qe(r,e){let t=await Ze(pe(r,e));if(!t.startsWith(r+Lr))throw new Error("Asset escapes package root");let n=await et(t);if(!n.isFile()||n.size>8*1024*1024)throw new Error("Plugin asset is not a regular file under 8 MB");return t}var N=class r{plugins;errors;extensionRoots;constructor(e,t,n){this.plugins=e,this.errors=t,this.extensionRoots=n}static async discover(e,t,n=$r()){let s=Dr.create(e,void 0,{projectTrusted:t}),a=new Ur({cwd:e,agentDir:Vr(),settingsManager:s}),u=await a.resolve(async()=>"skip"),p=n.length?await a.resolveExtensionSources(n,{temporary:!0}):{extensions:[]},o=new Set;for(let k of[...u.extensions,...p.extensions]){if(!k.enabled)continue;let w=await Fr(k.path);w&&o.add(w)}for(let k of n)_r(k)&&o.add(k);let d=[],f=[],m=[],v=new Set;for(let k of o)try{let w=await Ze(k),l=JSON.parse(await de(pe(w,"package.json"),"utf8"));if(l.piWebapp===void 0)continue;if(typeof l.name!="string"||!l.name)throw new Error("Missing package name");if(!Ke(l.piWebapp))throw new Error("Unsupported piWebapp manifest or asset path");if(v.has(l.name))throw new Error(`Duplicate plugin id: ${l.name}`);let h=await Qe(w,l.piWebapp.client),M=l.piWebapp.style?await Qe(w,l.piWebapp.style):void 0;v.add(l.name),d.push({id:l.name,root:w,manifest:l.piWebapp,clientPath:h,stylePath:M,...await Xe(h,M)}),m.push(w)}catch(w){f.push(`${k}: ${w instanceof Error?w.message:String(w)}`)}return d.sort((k,w)=>k.id.localeCompare(w.id)),new r(d,f,m)}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 Xe(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"),n=/^\/plugins\/([^/]+)\/(client\.js|client\.css)$/.exec(t.pathname);if(!n)return null;let s;try{s=decodeURIComponent(n[1])}catch{return null}let a=this.plugins.find(p=>p.id===s);if(!a||t.searchParams.has("v")&&t.searchParams.get("v")!==a.revision)return null;let u=n[2]==="client.js"?a.clientBytes:a.styleBytes;return u?{bytes:u,type:n[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 Hr}from"@earendil-works/pi-coding-agent";async function V(r,e){let t=await tt(r),n=e??await Hr.listAll(),s=await Promise.all(n.map(async a=>a.cwd!==""&&await tt(a.cwd).catch(()=>null)===t));return n.filter((a,u)=>s[u])}var _=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))}},rt=new WeakMap;function it(r,e,t,n=5e3,s=()=>{}){let a=rt.get(r);if(a)return a;let u=(async()=>{let p;try{await Promise.race([r.extensionRunner.emit({type:"session_shutdown",reason:e}),new Promise((o,d)=>{p=setTimeout(()=>d(new Error("Plugin shutdown timed out")),n)})])}catch(o){t(o instanceof Error?o.message:String(o))}finally{clearTimeout(p);try{s()}finally{r.dispose()}}})();return rt.set(r,u),u}function K(r){let t=[...r].reverse().find(n=>n.role==="assistant")?.blocks.filter(n=>n.kind==="text").map(n=>n.text).join(`
8
+ `);return{customType:se,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?`
9
+ Already displayed assistant text (reference data):
10
+ ${JSON.stringify(t)}`:"")}}import{createHash as Gr}from"node:crypto";import{readFile as Jr,writeFile as zr,unlink as qr}from"node:fs/promises";import{basename as Kr,dirname as Yr,extname as Xr,join as Qr}from"node:path";import{DefaultPackageManager as Zr,getAgentDir as ei,SettingsManager as ti}from"@earendil-works/pi-coding-agent";var D=new Map;async function nt(r,e){let n=await new Zr({cwd:r,agentDir:ei(),settingsManager:ti.create(r)}).resolveExtensionSources([...e],{temporary:!0}),s=[],a=[],u=async()=>{for(let p of s.splice(0)){let o=(D.get(p)??1)-1;o?D.set(p,o):(D.delete(p),await qr(p).catch(()=>{}))}};try{for(let p of n.extensions){if(!p.enabled)continue;let o=Xr(p.path);if(![".js",".mjs"].includes(o)){a.push(p.path);continue}let d=await Jr(p.path),f=Gr("sha256").update(d).digest("hex"),m=Qr(Yr(p.path),`.pi-web-runtime-${Kr(p.path,o)}-${f}${o}`);await zr(m,d,{flag:"wx"}).catch(v=>{if(v.code!=="EEXIST")throw v}),D.set(m,(D.get(m)??0)+1),s.push(m),a.push(m)}return{paths:a,release:u}}catch(p){throw await u(),p}}var X=class{active=null;queue=new _;generation=0;disposed=!1;publish;fallbackModel;isProjectTrusted;constructor(e,t,n=()=>!1){this.publish=e,this.fallbackModel=t,this.isProjectTrusted=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 n=await st(e),s;if(t==="new")s=Y.create(n);else if(t==="continue"){let a=(await V(n))[0];s=a?Y.open(a.path):Y.create(n)}else s=Y.open(t.sessionFile);if(await st(s.getCwd())!==n)throw new Error("\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A");await this.replace(n,s,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,n,s){let a=`plugin=${t} session=${e.session.sessionManager.getSessionId()} generation=${e.generation} stage=${n}: ${s}`;console.error(a),this.disposed||this.publish({type:"error",message:a})}async replace(e,t,n){let s=this.active,a=await N.discover(e,this.isProjectTrusted(e)),u=ii(),p=await nt(e,a.extensionRoots),o=new ni({cwd:e,agentDir:si(),noExtensions:!0,additionalExtensionPaths:p.paths,eventBus:u}),d=null;try{await o.reload();let f=o.getExtensions().errors;if(f.length)throw new Error(f.map(b=>`${b.path}: ${b.error}`).join("; "));let m=t.buildSessionProjection().model?void 0:s?.session.model??this.fallbackModel(),{session:v}=await ri({cwd:e,sessionManager:t,model:m,resourceLoader:o}),k={session:v,cwd:e,catalog:a,bus:u,generation:++this.generation,closing:!1,waitController:new AbortController,interactions:null,detach:()=>{},releasePaths:p.release};d=k;let w=b=>{!this.disposed&&this.active===k&&!k.closing&&this.publish(b)};k.interactions=new B(u,b=>!k.closing&&b.sessionId===v.sessionManager.getSessionId()&&a.has(b.pluginId),()=>w({type:"snapshot",session:this.snapshotOf(k)}));let l=0,h=u.on(z,()=>w({type:"snapshot",session:this.snapshotOf(k)})),M=v.subscribe(b=>{b.type==="message_update"&&b.message.role==="assistant"&&Date.now()-l>=60&&(l=Date.now(),w({type:"stream",message:{id:"stream",role:"assistant",timestamp:new Date(b.message.timestamp).toISOString(),blocks:R(b.message.content)}})),["message_end","agent_start","agent_settled","session_info_changed","entry_appended"].includes(b.type)&&(b.type==="message_end"&&b.message.role==="assistant"&&w({type:"stream",message:null}),w({type:"snapshot",session:this.snapshotOf(k)}))});k.detach=()=>{h(),M()};let c=[],y=!0;if(await v.bindExtensions({mode:"print",shutdownHandler:()=>{},onError:b=>{y&&c.push(b.error),this.diagnostic(k,a.plugins.find(P=>b.extensionPath.startsWith(P.root+"/"))?.id??b.extensionPath,b.event??"runtime",b.error)}}),y=!1,c.length)throw new Error(c.join("; "));if(this.ensureAvailable(),s&&await this.close(s,n),this.disposed)throw new Error("\u5DE5\u4F5C\u533A\u670D\u52A1\u5DF2\u5173\u95ED");this.active=k,d=null,this.publish({type:"stream",message:null}),this.publish({type:"snapshot",session:this.snapshot()})}catch(f){throw d?await this.close(d,"quit"):(u.clear(),await p.release()),f}}async close(e,t){e.closing||(e.closing=!0,e.waitController.abort(),e.interactions.dispose(),await it(e.session,t,n=>this.diagnostic(e,"host","shutdown",n),5e3,()=>{e.detach(),e.bus.clear()}),await e.releasePaths())}snapshotOf(e){let{session:t,cwd:n,catalog:s}=e,a=t.sessionManager.getBranch().flatMap(u=>{let p=ae(u);return p?[p]:[]});return{schemaVersion:1,sessionId:t.sessionManager.getSessionId(),cwd:n,name:ce(t.sessionManager.getSessionName(),a),model:t.model?`${t.model.provider}/${t.model.id}`:null,thinkingLevel:t.thinkingLevel,thinkingLevels:t.getAvailableThinkingLevels(),idle:t.isIdle,paused:U(t.sessionManager.getBranch()),contextUsage:t.getContextUsage()??null,messages:a,interactions:e.interactions.pending(t.sessionManager.getSessionId()),pluginEntries:oe(t.sessionManager.getBranch(),s.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 n=t.session.extensionRunner,s=await q(t.bus,e,15e3,t.waitController.signal);if(this.active!==t||t.closing||n!==t.session.extensionRunner)throw new Error("\u4F1A\u8BDD\u8FD0\u884C\u5B9E\u4F8B\u5DF2\u5207\u6362");return this.publish({type:"snapshot",session:this.snapshot()}),s}resolveInteraction(e,t,n,s){if(this.disposed||!this.active||this.active.closing)throw new Error("Interaction host unavailable");this.active.interactions.resolve(e,t,n,s)}async send(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 n=this.session,s=!1,a,u,p=new Promise((o,d)=>{a=o,u=d});n.prompt(e,{images:t,preflightResult:o=>{o&&(s=!0,a())}}).then(()=>{s||a()}).catch(o=>{s?this.publish({type:"error",message:o instanceof Error?o.message:"Pi \u8BF7\u6C42\u5931\u8D25"}):u(o)}),await p}async stop(){let e=this.active;!e||e.session.isIdle||(e.session.sessionManager.appendCustomEntry(O),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(!U(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(!U(t.sessionManager.getBranch()))throw new Error("\u5F53\u524D\u4F1A\u8BDD\u6CA1\u6709\u6682\u505C\u7684\u4EFB\u52A1");let s=K(this.snapshotOf(e).messages);t.sendCustomMessage(s,{triggerTurn:!0}).catch(a=>{this.active===e&&!e.closing&&this.publish({type:"error",message:a instanceof Error?a.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 n=this.session.modelRuntime.getModel(e,t);if(!n)throw new Error("\u6A21\u578B\u4E0D\u53EF\u7528");await this.session.setModel(n),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 ue,dirname as oi}from"node:path";function ot(r,e){let t=n=>e[n].map(s=>({name:n==="skills"&&ue(s.path).toLowerCase()==="skill.md"?ue(oi(s.path)):ue(s.path),path:s.path,source:s.metadata.source,scope:s.metadata.scope,enabled:s.enabled}));return{packages:r.map(n=>({name:n.source,path:n.installedPath??"",source:n.source,scope:n.scope,enabled:!!n.installedPath})),extensions:t("extensions"),skills:t("skills")}}import{execFile as ai}from"node:child_process";var ci=(r,e)=>new Promise((t,n)=>{ai(r,[...e],{windowsHide:!0},s=>{s?n(s):t()})});async function fe(r,e=process.platform,t=process.env,n=ci){if(t.SSH_CONNECTION||t.SSH_TTY||t.SSH_CLIENT||e==="linux"&&!t.DISPLAY&&!t.WAYLAND_DISPLAY)return!1;let s=e==="darwin"?"open":e==="linux"?"xdg-open":e==="win32"?"explorer.exe":null;return s===null?!1:(await n(s,[r]),!0)}import{execFile as li}from"node:child_process";import{randomUUID as di}from"node:crypto";import{existsSync as at}from"node:fs";import{access as pi,mkdir as ui,readFile as ct,rename as fi,rm as ge,writeFile as lt}from"node:fs/promises";import{join as C}from"node:path";import{promisify as gi}from"node:util";var mi=gi(li),Q=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/;function wi(r,e){let t=Q.exec(r),n=Q.exec(e);if(!t||!n)throw new Error("\u7248\u672C\u53F7\u65E0\u6548");for(let s=1;s<=3;s++){let a=Number(t[s])-Number(n[s]);if(a)return a}return!t[4]&&n[4]?1:t[4]&&!n[4]?-1:(t[4]??"").localeCompare(n[4]??"",void 0,{numeric:!0})}async function hi(r){try{let{stdout:e}=await mi("npm",r,{timeout:18e4,maxBuffer:1048576,encoding:"utf8"});return e}catch(e){let t=e;throw new Error(t.stderr?.trim()||t.message)}}var Z=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??hi}async current(){let e=JSON.parse(await ct(C(this.packageRoot,"package.json"),"utf8"));if(e.name!=="pi-webapp"||typeof e.version!="string"||!Q.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=at(C(this.packageRoot,".git")),n={current:e,latest:null,available:!1,canRestart:!!this.launcherNonce&&!t};t?n.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":n.canRestart||(n.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 s=JSON.parse((await this.runNpm(["view","pi-webapp","dist-tags.latest","--json","--prefer-online"])).trim());if(typeof s!="string"||!Q.test(s))throw new Error("npm \u8FD4\u56DE\u7684\u7248\u672C\u53F7\u65E0\u6548");n.latest=s,n.available=wi(s,e)>0}catch(s){throw new Error(`\u68C0\u67E5 npm \u66F4\u65B0\u5931\u8D25\uFF1A${s instanceof Error?s.message:String(s)}`)}return n}async prepare(){if(!this.launcherNonce)throw new Error("\u5F53\u524D\u9875\u9762\u65E0\u6CD5\u81EA\u52A8\u91CD\u542F Pi");if(at(C(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=C(this.agentDir,"pi-web","releases",e.latest);await ge(t,{recursive:!0,force:!0}),await ui(t,{recursive:!0});try{await this.runNpm(["install",`pi-webapp@${e.latest}`,"--prefix",t,"--ignore-scripts","--no-save","--no-audit","--no-fund"]);let n=C(t,"node_modules","pi-webapp"),s=JSON.parse(await ct(C(n,"package.json"),"utf8"));if(s.name!=="pi-webapp"||s.version!==e.latest)throw new Error("\u4E0B\u8F7D\u7684\u5305\u4E0E\u76EE\u6807\u7248\u672C\u4E0D\u7B26");let a=C(n,"bin","pi-webapp.mjs");await Promise.all([a,C(n,"dist","extension.js"),C(n,"web","dist","index.html")].map(o=>pi(o)));let u=C(this.agentDir,"pi-web"),p=C(u,`update.${di()}.tmp`);try{await lt(p,JSON.stringify({version:e.latest,launcher:a}),{mode:384}),await fi(p,C(u,"update.json"))}finally{await ge(p,{force:!0})}return this.restartPending=!0,{version:e.latest,launcher:a}}catch(n){throw await ge(t,{recursive:!0,force:!0}),n}}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 lt(C(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 xi}from"node:crypto";var dt=we(vi(Pi(import.meta.url)),"../web/dist"),Ci=Symbol.for(`pi-web.bridge-state:${import.meta.url}`),i=globalThis[Ci]??={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 _,tuiGeneration:0,stopChanged:null,tuiWaitController:new AbortController};i.lifecycle??=new _;i.tuiGeneration??=0;i.stopChanged??=null;i.tuiWaitController??=new AbortController;function $(){return i.selected==="sdk"?i.workspaceSessions?.catalog??null:i.tuiCatalog}var Ai=null;function Mi(){return Ai??=Ei.create({refreshOnCreate:!1})}var te=new Map;async function L(){let r=await Mi(),e=i.selected==="tui"?i.current?.modelRegistry:void 0,t=new Set(e?.getRegisteredProviderIds()??[]);for(let n of te.keys())t.has(n)||(r.unregisterProvider(n),te.delete(n));for(let n of t){let s=e?.getRegisteredNativeProvider(n),a=e?.getRegisteredProviderConfig(n),u=s??a;!u||te.get(n)===u||(s?r.registerNativeProvider(s):a&&r.registerProvider(n,a),te.set(n,u))}return await r.refresh({allowNetwork:!1}),r}function I(){if(i.selected==="sdk")return i.workspaceSessions?.snapshot()??(()=>{throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD")})();if(i.current===null)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");return{...De(i.current,i.current.sessionManager.getSessionName(),$()?.ids()??[]),interactions:i.interactions?.pending(i.current.sessionManager.getSessionId())??[]}}function E(r){if(I().sessionId!==r)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362")}async function ft(){let r=i.workspaces?.list()??[],e=I(),t=await re(e.cwd).catch(()=>e.cwd),n=await ut.listAll(),s=(await Promise.all(r.map(async a=>{let p=(await V(a.path,n).catch(()=>[])).map(o=>({id:o.id,workspaceId:a.id,path:o.path,name:o.name||o.firstMessage?.slice(0,50)||"\u5F53\u524D\u4F1A\u8BDD",modified:o.modified.toISOString()}));return a.path===t&&!p.some(o=>o.id===e.sessionId)&&p.unshift({id:e.sessionId,workspaceId:a.id,path:null,name:e.name,modified:new Date().toISOString()}),p}))).flat();return{items:r,activeId:i.activeWorkspaceId,sessions:s}}async function W(){i.bridge&&i.bridge.publish({type:"workspaces",value:await ft()})}async function me(r,e=!1){let t=i.workspaces?.get(r);if(!t)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");if(await re(t.path),!e&&i.current&&t.path===await re(i.current.cwd)){if(i.selected==="sdk"&&i.workspaceSessions?.session&&!i.workspaceSessions.session.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u518D\u5207\u6362\u5DE5\u4F5C\u533A");i.selected="tui",i.activeWorkspaceId=r,i.bridge?.publish({type:"stream",message:null}),i.bridge?.publish({type:"snapshot",session:I()})}else{if(!i.workspaceSessions)throw new Error("Pi \u5DE5\u4F5C\u533A\u670D\u52A1\u4E0D\u53EF\u7528");await i.workspaceSessions.open(t.path,e?"new":"continue"),i.selected="sdk",i.activeWorkspaceId=r,i.bridge?.publish({type:"snapshot",session:I()})}await W()}function A(r){let e=i.current;if(e===null||e.sessionManager.getSessionId()!==r)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362");return e}function S(r){i.current=r,i.selected==="tui"&&i.bridge?.publish({type:"snapshot",session:I()})}function gt(){if(i.current===null)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");let r=i.selected==="sdk"?i.workspaceSessions?.path:i.current.cwd;if(!r)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u5DE5\u4F5C\u533A");let e=i.selected==="tui"?i.current.isProjectTrusted():i.workspaceSessions?.session?.settingsManager.isProjectTrusted()??!1;return Si.create(r,void 0,{projectTrusted:e})}async function mt(){let r=gt(),e=s=>({packages:(s.packages??[]).map(a=>typeof a=="string"?a:a.source),extensions:s.extensions??[],skills:s.skills??[]}),t=new pt({cwd:I().cwd,agentDir:j(),settingsManager:r}),n=ot(t.listConfiguredPackages(),await t.resolve(async()=>"skip"));return{projectTrusted:r.isProjectTrusted(),global:e(r.getGlobalSettings()),project:e(r.getProjectSettings()),installed:n}}async function Wi(r){E(r.sessionId);let e=i.selected==="tui"?A(r.sessionId):null;if(e?!e.isIdle():!i.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let t=gt();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 n=r.value.trim(),s=r.scope==="project"?t.getProjectSettings():t.getGlobalSettings();if(r.kind==="packages"){let a=new pt({cwd:I().cwd,agentDir:j(),settingsManager:t});r.action==="add"?await a.installAndPersist(n,{local:r.scope==="project"}):await a.removeAndPersist(n,{local:r.scope==="project"})}else if(r.kind==="extensions"){let a=s.extensions??[],u=r.action==="add"?[...new Set([...a,n])]:a.filter(p=>p!==n);r.scope==="project"?t.setProjectExtensionPaths(u):t.setExtensionPaths(u)}else{let a=s.skills??[],u=r.action==="add"?[...new Set([...a,n])]:a.filter(p=>p!==n);r.scope==="project"?t.setProjectSkillPaths(u):t.setSkillPaths(u)}return await t.flush(),i.selected==="tui"?(i.commandContext&&await i.commandContext.reload(),i.current&&S(i.current)):(await i.workspaceSessions?.reload(),i.bridge?.publish({type:"plugins_changed"})),await mt()}function Ti(r,e=fe){i.pi=r,i.interactions?.dispose(),i.interactions=new B(r.events,s=>!!i.bridge&&i.selected==="tui"&&s.sessionId===i.current?.sessionManager.getSessionId()&&!!i.tuiCatalog?.has(s.pluginId),()=>{i.current&&i.selected==="tui"&&S(i.current)});let t=()=>{i.stopChanged?.(),i.stopChanged=r.events.on(z,()=>{i.selected==="tui"&&i.current&&S(i.current)})};t(),r.on("session_start",async(s,a)=>{if(i.tuiWaitController.abort(),i.tuiWaitController=new AbortController,i.tuiGeneration++,t(),i.current=a,i.bridge){let u=await N.discover(a.cwd,a.isProjectTrusted?.()??!1);if(i.current!==a)return;i.tuiCatalog=u}i.replacementSessionId!==a.sessionManager.getSessionId()&&(i.replacementContext=null,i.replacementSessionId=null),S(a),i.bridge&&i.bridge.publish({type:"plugins_changed"}),i.selected==="tui"&&i.workspaces&&i.workspaces.add(a.cwd).then(async u=>{i.selected!=="tui"||i.current?.sessionManager.getSessionId()!==a.sessionManager.getSessionId()||(i.activeWorkspaceId=u.id,await W())}).catch(u=>{i.bridge?.publish({type:"error",message:u instanceof Error?u.message:"\u65E0\u6CD5\u6CE8\u518C\u5F53\u524D\u5DE5\u4F5C\u533A"})}),process.env.PI_WEBAPP_AUTO_OPEN==="1"&&a.mode==="tui"&&!i.autoOpened&&(i.autoOpened=!0,n(a).catch(u=>{a.ui.notify(u instanceof Error?u.message:"Web \u542F\u52A8\u5931\u8D25","error")}))}),r.on("agent_start",(s,a)=>S(a)),r.on("agent_end",(s,a)=>S(a)),r.on("agent_settled",(s,a)=>S(a)),r.on("model_select",(s,a)=>S(a)),r.on("thinking_level_select",(s,a)=>S(a)),r.on("message_end",(s,a)=>{i.selected==="tui"&&s.message.role==="assistant"&&i.bridge?.publish({type:"stream",message:null}),S(a),i.selected==="tui"&&W()}),r.on("session_info_changed",(s,a)=>S(a)),r.on("message_update",(s,a)=>{if(i.current=a,i.selected!=="tui"||s.message.role!=="assistant"||i.bridge===null)return;let u=Date.now();u-i.lastStreamAt<60||(i.lastStreamAt=u,i.bridge.publish({type:"stream",message:{id:"stream",role:"assistant",timestamp:new Date(s.message.timestamp).toISOString(),blocks:R(s.message.content)}}))}),r.on("session_shutdown",async s=>{if(i.tuiWaitController.abort(),i.tuiGeneration++,i.stopChanged?.(),i.stopChanged=null,i.interactions?.cancelAll(),i.current=null,s.reason==="new"||s.reason==="resume"||s.reason==="fork"||s.reason==="reload")return;let a=i.bridge;i.bridge=null,i.commandContext=null,i.replacementContext=null,i.replacementSessionId=null,i.pi=null;let u=i.workspaceSessions;i.workspaceSessions=null,await u?.dispose(),i.selected="tui",i.activeWorkspaceId=null,i.autoOpened=!1,i.tuiCatalog=null,i.stopPluginWatch?.(),i.stopPluginWatch=null,a&&await a.close()});let n=async s=>{i.current=s,i.commandContext="newSession"in s?s:null,i.pi=r,i.tuiCatalog=await N.discover(s.cwd,s.isProjectTrusted?.()??!1),i.workspaces===null&&(i.workspaces=new J(ze(j())),await i.workspaces.load());try{await i.workspaces.discover((await ut.listAll()).map(p=>p.cwd))}catch(p){s.ui.notify(`\u65E0\u6CD5\u8BFB\u53D6\u90E8\u5206 Pi \u5386\u53F2\u5DE5\u4F5C\u533A\uFF1A${p instanceof Error?p.message:String(p)}`,"warning")}let a=await i.workspaces.add(s.cwd);if(i.selected==="tui"&&(i.activeWorkspaceId=a.id),i.bridge&&i.bridge.protocolVersion!==7){let p=i.bridge;i.bridge=null,await p.close()}if(i.bridge===null){i.workspaceSessions=new X(o=>{i.selected==="sdk"&&(i.bridge?.publish(o),o.type==="snapshot"&&o.session.idle&&W())},()=>i.current?.model,o=>{try{return!!i.current&&ki(i.current.cwd)===o&&(i.current.isProjectTrusted?.()??!1)}catch{return!1}});let p={selfUpdate:new Z({agentDir:j(),packageRoot:we(dt,"../.."),launcherNonce:process.env.PI_WEBAPP_LAUNCHER_NONCE}),snapshot:I,plugins:async()=>{let o=$();return await o?.refreshAssets(),o?.view()??{plugins:[],errors:[]}},pluginAsset:async o=>$()?.asset(o)??null,async invokePluginAction(o,d,f,m){if(E(o),!$()?.has(d))throw new Error("\u63D2\u4EF6\u672A\u542F\u7528");let v=i.selected,k=i.tuiGeneration,w=i.workspaceSessions?.session,l={requestId:xi(),sessionId:o,pluginId:d,action:f,input:m},h=i.selected==="sdk"?await i.workspaceSessions.invokePluginAction(l):await q(i.pi.events,l,15e3,i.tuiWaitController.signal);if(E(o),v!==i.selected||(v==="tui"?k!==i.tuiGeneration:w!==i.workspaceSessions?.session))throw new Error("\u4F1A\u8BDD\u8FD0\u884C\u5B9E\u4F8B\u5DF2\u5207\u6362");return i.selected==="tui"&&i.current&&S(i.current),h},async resolvePluginInteraction(o,d,f,m){if(E(o),!$()?.has(d))throw new Error("\u63D2\u4EF6\u672A\u542F\u7528");i.selected==="sdk"?i.workspaceSessions.resolveInteraction(o,d,f,m):i.interactions.resolve(o,d,f,m)},image(o,d,f){E(o);let v=(i.selected==="sdk"?i.workspaceSessions?.session?.sessionManager.getBranch():i.current?.sessionManager.getBranch())?.find(w=>w.id===d);if(v?.type!=="message"||v.message.role!=="user"||!Array.isArray(v.message.content))return null;let k=v.message.content[f];return k?.type!=="image"?null:{data:Buffer.from(k.data,"base64"),mimeType:k.mimeType}},async workspaces(){return ft()},async addWorkspace(o,d){let f=await i.workspaces.add(o,d);try{await me(f.id,!0)}catch(m){throw await W(),m}},async selectWorkspace(o){await me(o)},async newSessionInWorkspace(o){await me(o,!0)},async removeWorkspace(o){if(o===i.activeWorkspaceId)throw new Error("\u8BF7\u5148\u5207\u6362\u5230\u5176\u4ED6\u5DE5\u4F5C\u533A");await i.workspaces.remove(o),await W()},async selectSession(o,d,f){let m=i.workspaces?.get(o);if(!m)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");if(d===i.current?.sessionManager.getSessionId()&&m.path===await re(i.current.cwd)){if(i.selected==="sdk"&&i.workspaceSessions?.session&&!i.workspaceSessions.session.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u518D\u5207\u6362\u4F1A\u8BDD");i.selected="tui",i.activeWorkspaceId=o,i.bridge?.publish({type:"snapshot",session:I()})}else{if(i.selected==="sdk"&&i.workspaceSessions?.session?.sessionManager.getSessionId()===d&&i.workspaceSessions.path===m.path)return;if(!(await V(m.path)).some(k=>k.id===d&&k.path===f))throw new Error("\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A");await i.workspaceSessions.open(m.path,{sessionFile:f}),i.selected="sdk",i.activeWorkspaceId=o,i.bridge?.publish({type:"snapshot",session:I()})}await W()},async models(){if(i.selected==="sdk")return i.workspaceSessions?.models()??[];let o=i.current;if(!o)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");let d=o.scopedModels?.map(f=>`${f.model.provider}/${f.model.id}`)??[];return o.modelRegistry.getAvailable().filter(f=>d.length===0||d.includes(`${f.provider}/${f.id}`)).map(f=>({provider:f.provider,id:f.id,name:f.name}))},async providers(){let o=await L(),d=new Set((await o.listCredentials()).map(f=>f.providerId));return o.getProviders().map(f=>({id:f.id,name:f.name,configured:o.getProviderAuthStatus(f.id).configured,storedCredential:d.has(f.id),methods:[f.auth.apiKey?.login?"api_key":null,f.auth.oauth?"oauth":null].filter(m=>m!==null)}))},async providerModels(o){let d=await L();return je(ee(j(),"models.json"),o,d)},async updateProviderModel(o,d,f){if(E(o),i.selected==="tui"?!A(o).isIdle():!i.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let m=I().model;if(f.action==="remove"&&m===`${d}/${f.id}`)throw new Error("\u8BF7\u5148\u5207\u6362\u5F53\u524D\u4F7F\u7528\u7684\u6A21\u578B");if(f.action==="save"&&f.originalId&&f.originalId!==f.model.id&&m===`${d}/${f.originalId}`)throw new Error("\u8BF7\u5148\u5207\u6362\u5F53\u524D\u4F7F\u7528\u7684\u6A21\u578B");let v=await L();await Be(ee(j(),"models.json"),d,f,v),await v.refresh({providers:[d],allowNetwork:!1}),await i.current?.modelRegistry.refresh({providers:[d],allowNetwork:!1}),await i.workspaceSessions?.session?.modelRuntime.refresh({providers:[d],allowNetwork:!1});let k=f.action==="save"?f.model.id:f.action==="base_url"&&m?.startsWith(`${d}/`)?m.slice(d.length+1):null;if(k&&m===`${d}/${k}`)if(i.selected==="sdk")try{await i.workspaceSessions.setModel(d,k)}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 w=A(o),l=w.modelRegistry.find(d,k);if(!l||!i.pi||!await i.pi.setModel(l))throw new Error("\u6A21\u578B\u5DF2\u4FDD\u5B58\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u8BE5\u6A21\u578B\u4EE5\u5E94\u7528\u65B0\u53C2\u6570");S(w)}},async logoutProvider(o,d){if(E(o),i.selected==="tui"?!A(o).isIdle():!i.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let f=await L();if(!(await f.listCredentials()).some(m=>m.providerId===d))throw new Error("\u8BE5\u63D0\u4F9B\u65B9\u6CA1\u6709\u5DF2\u4FDD\u5B58\u7684\u8BA4\u8BC1");await f.logout(d),await i.current?.modelRegistry.refresh({providers:[d],allowNetwork:!1}),await i.workspaceSessions?.session?.modelRuntime.refresh({providers:[d],allowNetwork:!1})},async loginProvider(o,d,f){let m=await L();await m.login(o,d,Me(o,d,f)),await m.refresh({providers:[o],allowNetwork:!1}),await i.current?.modelRegistry.refresh({providers:[o],allowNetwork:!1}),await i.workspaceSessions?.session?.modelRuntime.refresh({providers:[o],allowNetwork:!1})},async addCustomProvider(o,d){if(E(o),i.selected==="tui"?!A(o).isIdle():!i.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let f=await L();if(f.getProvider(d.id))throw new Error("\u63D0\u4F9B\u65B9\u5DF2\u5B58\u5728");await We(ee(j(),"models.json"),d),await f.refresh({allowNetwork:!1}),await i.current?.modelRegistry.refresh({allowNetwork:!1}),await i.workspaceSessions?.session?.modelRuntime.refresh({allowNetwork:!1})},commands(){return i.selected==="tui"?(i.pi?.getCommands()??[]).filter(o=>o.name!=="web"&&o.name!=="web-dev-reload").map(o=>({name:o.name,description:o.description})):[]},async compact(o){if(E(o),i.selected==="sdk"){let f=i.workspaceSessions?.session;if(!f||!f.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");await f.compact(),i.bridge?.publish({type:"snapshot",session:I()});return}let d=A(o);if(!d.isIdle())throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");d.compact()},async setModel(o,d,f){if(E(o),i.selected==="sdk"){await i.workspaceSessions.setModel(d,f);return}let m=A(o);if(!m.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let v=m.modelRegistry.find(d,f);if(!v||!m.modelRegistry.getAvailable().some(k=>k.provider===d&&k.id===f))throw new Error("\u6A21\u578B\u4E0D\u53EF\u7528");if(!i.pi||!await i.pi.setModel(v))throw new Error("\u6A21\u578B\u63D0\u4F9B\u65B9\u672A\u914D\u7F6E\u8BA4\u8BC1");S(m)},async setThinkingLevel(o,d){if(E(o),!["off","minimal","low","medium","high","xhigh"].includes(d))throw new Error("\u63A8\u7406\u5F3A\u5EA6\u65E0\u6548");if(i.selected==="sdk"){let v=i.workspaceSessions?.session;if(!v||!v.isIdle||!v.getAvailableThinkingLevels().includes(d))throw new Error("\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u6B64\u63A8\u7406\u5F3A\u5EA6");v.setThinkingLevel(d),i.bridge?.publish({type:"snapshot",session:I()});return}let m=A(o);if(!m.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!m.model||!Ii(m.model).includes(d))throw new Error("\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u6B64\u63A8\u7406\u5F3A\u5EA6");if(!i.pi)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");i.pi.setThinkingLevel(d),S(m)},config:mt,updateConfig:Wi,async send(o,d,f=[]){if(E(o),i.selected==="sdk"){await i.workspaceSessions.send(d,f);return}if(!A(o).isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(i.replacementContext!==null&&i.replacementSessionId===o){await i.replacementContext.sendUserMessage(f.length?[{type:"text",text:d},...f]:d,{expandPromptTemplates:!0});return}if(i.pi===null)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");i.pi.sendUserMessage(f.length?[{type:"text",text:d},...f]:d,{expandPromptTemplates:!0})},async abort(o){if(E(o),i.selected==="sdk")await i.workspaceSessions.stop();else{let d=A(o);if(d.isIdle())return;if(!i.pi)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");i.pi.appendEntry(O),d.abort()}},async resume(o){if(E(o),i.selected==="sdk"){await i.workspaceSessions.resume();return}let d=A(o);if(!d.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!d.model||!i.pi)throw new Error("\u8BF7\u5148\u9009\u62E9\u6A21\u578B");if(!d.modelRegistry.hasConfiguredAuth(d.model))throw new Error("\u8BF7\u5148\u8FDE\u63A5\u5F53\u524D\u6A21\u578B");i.pi.sendMessage(K(I().messages),{triggerTurn:!0})},async newSession(o){if(E(o),i.selected==="sdk"){let m=i.workspaces?.get(i.activeWorkspaceId??"");if(!m)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");await i.workspaceSessions.open(m.path,"new"),await W();return}let d=A(o);if(!d.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(i.commandContext===null){await i.workspaceSessions.open(d.cwd,"new"),i.selected="sdk",i.bridge?.publish({type:"snapshot",session:I()}),await W();return}if((await i.commandContext.newSession({withSession:async m=>{i.commandContext=m,i.replacementContext=m,i.replacementSessionId=m.sessionManager.getSessionId(),i.current=m}})).cancelled)throw new Error("\u65B0\u4F1A\u8BDD\u5DF2\u53D6\u6D88");await W()}};p.addWorkspace=i.lifecycle.wrap(p.addWorkspace),p.selectWorkspace=i.lifecycle.wrap(p.selectWorkspace),p.newSessionInWorkspace=i.lifecycle.wrap(p.newSessionInWorkspace),p.removeWorkspace=i.lifecycle.wrap(p.removeWorkspace),p.selectSession=i.lifecycle.wrap(p.selectSession),p.newSession=i.lifecycle.wrap(p.newSession),p.updateConfig=i.lifecycle.wrap(p.updateConfig),i.bridge=await Ue(p,dt)}if(i.stopPluginWatch===null&&process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS){let p=[],o=null;for(let d of(process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS??"").split(yi).filter(Boolean))try{p.push(bi(ee(we(d),"dist"),(f,m)=>{let v=String(m??"");["client.js","client.css"].includes(v)&&(o&&clearTimeout(o),o=setTimeout(()=>i.bridge?.publish({type:"plugins_changed"}),180))}))}catch(f){i.bridge?.publish({type:"error",message:`\u63D2\u4EF6\u76D1\u542C\u5931\u8D25\uFF1A${d}: ${String(f)}`})}i.stopPluginWatch=()=>{for(let d of p)d.close();o&&clearTimeout(o)}}let u=await e(i.bridge.url).catch(()=>!1);s.ui.notify(`pi-webapp: ${i.bridge.url}`,u?"info":"warning"),s.ui.setStatus("pi-webapp","Web \u5DF2\u542F\u52A8 \xB7 /web \u91CD\u65B0\u6253\u5F00")};r.registerCommand("web",{description:"Open the current Pi session in a local web interface",handler:async(s,a)=>n(a)}),r.registerCommand("web-dev-reload",{description:"Reload local pi-webapp plugins during development",handler:async(s,a)=>{process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS&&(await a.waitForIdle(),await i.lifecycle.run(async()=>{let u=i.workspaceSessions?.session;u&&(await u.waitForIdle(),await i.workspaceSessions.reload()),await a.reload()}))}})}export{Ti as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-webapp",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "type": "module",
5
5
  "description": "A browser interface for Pi with live chat, workspaces, models, and attachments",
6
6
  "repository": {
@@ -15,7 +15,7 @@
15
15
  "pi-webapp": "./bin/pi-webapp.mjs"
16
16
  },
17
17
  "pi": {
18
- "image": "https://cdn.jsdelivr.net/npm/pi-webapp@0.1.6/assets/cover-webapp.png",
18
+ "image": "https://cdn.jsdelivr.net/npm/pi-webapp@0.1.7/assets/cover-webapp.png",
19
19
  "extensions": [
20
20
  "./dist/extension.js"
21
21
  ]
@@ -27,7 +27,8 @@
27
27
  "web/dist",
28
28
  "README.md",
29
29
  "README.zh-CN.md",
30
- "LICENSE"
30
+ "LICENSE",
31
+ "THIRD_PARTY_LICENSE.txt"
31
32
  ],
32
33
  "scripts": {
33
34
  "start": "npm run build && node bin/pi-webapp.mjs",
@@ -37,7 +38,7 @@
37
38
  "test": "node --experimental-strip-types --test test/*.test.ts",
38
39
  "build": "npm run build:web && npm run build:extension",
39
40
  "build:web": "vite build",
40
- "build:extension": "esbuild extension/index.ts --bundle --platform=node --format=esm --target=node22 --packages=external --minify --outfile=dist/extension.js",
41
+ "build:extension": "node scripts/build-extension.mjs",
41
42
  "prepack": "npm run build",
42
43
  "prepublishOnly": "npm run check && npm run build && npm run test"
43
44
  },
@@ -49,12 +50,16 @@
49
50
  "@earendil-works/pi-coding-agent": "*"
50
51
  },
51
52
  "devDependencies": {
53
+ "@chengzhiyi/pi-web-protocol": "0.1.0",
52
54
  "@earendil-works/pi-ai": "0.87.1",
53
55
  "@earendil-works/pi-coding-agent": "0.87.1",
56
+ "@types/katex": "^0.16.7",
57
+ "@types/mdast": "^4.0.4",
54
58
  "@types/node": "22.19.19",
55
59
  "@types/react": "^18.3.1",
56
60
  "@types/react-dom": "^18.3.0",
57
61
  "esbuild": "^0.28.2",
62
+ "micromark-util-types": "^2.0.2",
58
63
  "typescript": "7.0.2",
59
64
  "vite": "^6.4.3"
60
65
  },
@@ -62,12 +67,30 @@
62
67
  "node": ">=22.19.0"
63
68
  },
64
69
  "dependencies": {
70
+ "@lexical/history": "0.49.0",
71
+ "@lexical/plain-text": "0.49.0",
72
+ "@shikijs/langs": "^4.3.1",
65
73
  "anser": "^2.3.5",
66
74
  "clsx": "^2.1.1",
67
75
  "cross-spawn": "^7.0.6",
76
+ "katex": "^0.16.47",
77
+ "lexical": "0.49.0",
78
+ "mdast-util-from-markdown": "^2.0.3",
79
+ "mdast-util-gfm": "^3.1.0",
80
+ "mdast-util-math": "^3.0.0",
81
+ "micromark-core-commonmark": "^2.0.3",
82
+ "micromark-extension-gfm": "^3.0.0",
83
+ "micromark-extension-math": "^3.1.0",
84
+ "micromark-factory-space": "^2.0.1",
85
+ "micromark-util-character": "^2.1.1",
86
+ "micromark-util-classify-character": "^2.0.1",
87
+ "micromark-util-sanitize-uri": "^2.0.1",
88
+ "micromark-util-symbol": "^2.0.1",
68
89
  "react": "^18.3.1",
69
90
  "react-dom": "^18.3.1",
70
91
  "react-markdown": "^10.1.0",
71
- "remark-gfm": "^4.0.1"
92
+ "remark-gfm": "^4.0.1",
93
+ "shiki": "^4.3.1",
94
+ "simple-icons": "^16.31.0"
72
95
  }
73
96
  }