pi-webapp 0.1.5 → 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 +16 -3
  2. package/README.zh-CN.md +14 -3
  3. package/THIRD_PARTY_LICENSE.txt +24 -0
  4. package/bin/pi-webapp.mjs +93 -5
  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 Xt,join as K,resolve as Qt}from"node:path";import{realpath as O}from"node:fs/promises";import{fileURLToPath as Zt}from"node:url";import{DefaultPackageManager as Me,getAgentDir as T,ModelRuntime as qt,SessionManager as Ae,SettingsManager as ei}from"@earendil-works/pi-coding-agent";import{getSupportedThinkingLevels as ti}from"@earendil-works/pi-ai";import{randomBytes as Et,timingSafeEqual as Ct}from"node:crypto";import{readFile as Mt}from"node:fs/promises";import{createServer as At}from"node:http";import{join as Tt}from"node:path";import{mkdir as je,opendir as Re,stat as Ve}from"node:fs/promises";import{homedir as _e}from"node:os";import{basename as Be,dirname as Y,join as X,posix as Oe,resolve as Q,win32 as Ue}from"node:path";function Z(t){return process.platform==="win32"?Ue.isAbsolute(t)&&/^(?:[A-Za-z]:[\\/]|[\\/]{2}[^\\/]+[\\/]+[^\\/]+)/.test(t):Oe.isAbsolute(t)}function De(t,e,i){if(t.length===i&&e.name.localeCompare(t[t.length-1].name)>=0)return!0;let r=0,n=t.length;for(;r<n;){let p=r+n>>>1;e.name.localeCompare(t[p].name)<0?n=p:r=p+1}return t.splice(r,0,e),t.length<=i?!1:(t.pop(),!0)}async function q(t){if(t!==void 0&&!Z(t))throw new Error("\u76EE\u5F55\u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");let e=_e(),i=Q(t??e),r=[];for(let a=i;;a=Y(a)){let u=Y(a);if(r.unshift({name:u===a?a:Be(a),path:a,hidden:!1}),u===a)break}let n=[],p=!1,o=await Re(i);for await(let a of o)!a.isDirectory()&&!a.isSymbolicLink()||De(n,{name:a.name,isDirectory:a.isDirectory(),isSymbolicLink:a.isSymbolicLink()},1001)&&(p=!0);let l=[];for(let a of n){let u=X(i,a.name);if(!a.isDirectory&&a.isSymbolicLink)try{if(!(await Ve(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:i,home:e,crumbs:r,entries:l,truncated:p}}async function ee(t,e){if(!Z(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 i=X(Q(t),e);return await je(i),i}import{execFile as $e}from"node:child_process";import{accessSync as Fe,constants as He}from"node:fs";import{delimiter as Je,join as Ge}from"node:path";var Ke=(t,e,i)=>new Promise((r,n)=>{$e(t,[...e],{encoding:"utf8",signal:i,windowsHide:!0},(p,o,l)=>{p?n(Object.assign(new Error(p.message,{cause:p}),{code:p.code,stdout:o,stderr:l})):r({stdout:o,stderr:l})})});function ze(t){for(let e of(t??"").split(Je))if(e)for(let i of["zenity","kdialog"])try{return Fe(Ge(e,i),He.X_OK),!0}catch{}return!1}function te(t=process.platform,e=process.env){return e.SSH_CONNECTION||e.SSH_TTY?"browse":t==="darwin"||t==="linux"&&(e.DISPLAY||e.WAYLAND_DISPLAY)&&ze(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 Ye(t){return typeof t=="object"&&t!==null&&"stderr"in t&&typeof t.stderr=="string"?t.stderr:""}function U(t){return t.replace(/[\r\n]+$/,"")||null}async function ie(t,e=process.platform,i=Ke){if(e==="darwin")try{let r=await i("osascript",["-e",'set selectedFolder to choose folder with prompt "Select Workspace Directory"',"-e","POSIX path of selectedFolder"],t);return U(r.stdout)}catch(r){if(!t.aborted&&L(r)===1&&/(?:User canceled|-128)/i.test(Ye(r)))return null;throw r}if(e==="linux"){try{return U((await i("zenity",["--file-selection","--directory","--title=Select Workspace Directory"],t)).stdout)}catch(r){if(t.aborted)throw r;if(L(r)===1)return null;if(L(r)!=="ENOENT")throw r}try{return U((await i("kdialog",["--getexistingdirectory",".","--title","Select Workspace Directory"],t)).stdout)}catch(r){if(t.aborted)throw r;if(L(r)===1)return null;throw r}}throw new Error(`\u5F53\u524D\u7CFB\u7EDF\u4E0D\u652F\u6301\u672C\u5730\u76EE\u5F55\u9009\u62E9\u5668\uFF1A${e}`)}import{createHash as Xe,randomUUID as Qe}from"node:crypto";import{mkdir as Ze,readFile as qe,writeFile as et}from"node:fs/promises";import{join as re}from"node:path";import{getAgentDir as tt}from"@earendil-works/pi-coding-agent";var N=20*1024*1024,se=20,it=/^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])$/iu;function rt(t){let e=t.indexOf("."),i=(e<0?t:t.slice(0,e)).replace(/[. ]+$/u,"");return it.test(i)}function st(t,e){let i=0,r="";for(let n of Buffer.from(t).toString("utf8")){let p=Buffer.byteLength(n);if(i+p>e)break;r+=n,i+=p}return r}function nt(t){if(t===void 0)return"file";let i=t.slice(Math.max(t.lastIndexOf("/"),t.lastIndexOf("\\"))+1).replace(/[\u0000-\u001f\u007f]/g,"").replace(/[<>:"|?*]/g,"_").trim().replace(/[. ]+$/u,"");return rt(i)&&(i=`_${i}`),i=st(i,255).replace(/[. ]+$/u,""),i===""||i==="."||i===".."?"file":i}function ot(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 ne(t,e,i,r){if(r.byteLength===0||r.byteLength>N)throw new Error("\u6587\u4EF6\u4E3A\u7A7A\u6216\u8D85\u8FC7 20 MB");let n=nt(e),p=Xe("sha256").update(r).digest("hex"),o=re(tt(),"pi-web","attachments",p);await Ze(o,{recursive:!0});let l=re(o,n);try{await et(l,r,{flag:"wx",mode:384})}catch(a){if(!(a instanceof Error&&"code"in a&&a.code==="EEXIST"))throw a}return{id:Qe(),name:n,bytes:r.byteLength,path:l,mediaType:ot(r)??i.replace(/^image\//,"application/"),sessionId:t}}async function oe(t){return{type:"image",data:(await qe(t.path)).toString("base64"),mimeType:t.mediaType}}import{randomBytes as at}from"node:crypto";function ae(t,e,i){return t!=="openai-codex"||e!=="oauth"?i:{...i,prompt:r=>r.type==="select"&&r.options.some(n=>n.id==="browser")&&r.options.some(n=>n.id==="device_code")?Promise.resolve("browser"):i.prompt(r)}}var j=class{flows=new Map;start(e,i,r,n){let p=this.getActive();if(p){if(p.providerId===e&&p.method===i&&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=at(18).toString("base64url"),l={view:{id:o,providerId:e,method:i,status:"running"},controller:new AbortController};return this.flows.set(o,l),r(e,i,{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:g,...c}=a;l.answer=u,l.reject=h,l.view={...l.view,status:"waiting",prompt:c},g?.aborted?h(new Error("\u767B\u5F55\u8F93\u5165\u5DF2\u53D6\u6D88")):g?.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:i,status:"done"})}).catch(()=>{l.view.status!=="cancelled"&&(l.view={id:o,providerId:e,method:i,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 i=this.flows.get(e)?.view;return i?{...i}:void 0}getActive(){let e=[...this.flows.values()].find(({view:i})=>i.status==="running"||i.status==="waiting")?.view;return e?{...e}:void 0}respond(e,i){let r=this.flows.get(e);if(!r?.answer||r.view.status!=="waiting"||r.view.prompt?.type==="select"&&!r.view.prompt.options.some(p=>p.id===i))return!1;let n=r.answer;return r.answer=void 0,r.reject=void 0,r.view={...r.view,status:"running",prompt:void 0},n(i),!0}cancel(e){let i=this.flows.get(e);return!i||i.view.status==="done"||i.view.status==="error"?!1:(i.view={...i.view,status:"cancelled",prompt:void 0},i.controller.abort(),i.reject?.(new Error("\u767B\u5F55\u5DF2\u53D6\u6D88")),i.answer=void 0,i.reject=void 0,!0)}close(){for(let e of this.flows.keys())this.cancel(e);this.flows.clear()}};import{randomBytes as dt}from"node:crypto";import{readFile as lt,rename as ct,rm as pt,stat as ut,writeFile as mt,mkdir as ft}from"node:fs/promises";import{dirname as gt}from"node:path";var wt=["openai-completions","openai-responses","anthropic-messages"];function D(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||!wt.includes(e.api)||typeof e.baseUrl!="string"||e.baseUrl.length>2048)return!1;try{let i=new URL(e.baseUrl);return(i.protocol==="https:"||i.protocol==="http:")&&!!i.hostname&&!i.username&&!i.password&&!i.hash}catch{return!1}}async function de(t,e){if(!D(e))throw new Error("\u81EA\u5B9A\u4E49\u63D0\u4F9B\u65B9\u540D\u79F0\u3001\u5730\u5740\u6216\u6A21\u578B\u65E0\u6548");let i;try{i=await lt(t,"utf8")}catch(l){if(l.code!=="ENOENT")throw l}let r;if(i===void 0)r={providers:{}};else{try{r=JSON.parse(i)}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(!r||typeof r!="object"||!r.providers||typeof r.providers!="object"||Array.isArray(r.providers))throw new Error("models.json \u7ED3\u6784\u65E0\u6548")}if(Object.hasOwn(r.providers,e.id))throw new Error("\u63D0\u4F9B\u65B9\u5DF2\u5B58\u5728");let n={...r,providers:{...r.providers,[e.id]:{name:e.name.trim(),baseUrl:e.baseUrl,api:e.api,models:[{id:e.modelId.trim()}]}}};await ft(gt(t),{recursive:!0});let p=i===void 0?384:(await ut(t)).mode&511,o=`${t}.pi-web-${dt(6).toString("hex")}.tmp`;try{await mt(o,`${JSON.stringify(n,null,2)}
2
- `,{mode:p,flag:"wx"}),await ct(o,t)}finally{await pt(o,{force:!0})}}import{randomBytes as ht}from"node:crypto";import{mkdir as yt,readFile as vt,rename as kt,rm as bt,stat as Pt,writeFile as St}from"node:fs/promises";import{dirname as xt}from"node:path";function le(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 ce(t){if(!t||typeof t!="object")return!1;let e=t;return e.action==="save"?(e.originalId===void 0||typeof e.originalId=="string")&&pe(e.model):e.action==="base_url"?e.baseUrl===null||typeof e.baseUrl=="string"&&le(e.baseUrl):e.action==="remove"&&typeof e.id=="string"&&e.id.length>0&&e.id.length<=200}function pe(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 i of[e.contextWindow,e.maxTokens])if(i!==void 0&&(!Number.isSafeInteger(i)||i<=0))return!1;return e.input===void 0||Array.isArray(e.input)&&e.input.length>0&&e.input.every(i=>i==="text"||i==="image")&&new Set(e.input).size===e.input.length}async function ue(t){let e;try{e=await vt(t,"utf8")}catch(r){if(r.code!=="ENOENT")throw r}if(e===void 0)return{config:{providers:{}}};let i;try{i=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(!i||typeof i!="object"||!i.providers||typeof i.providers!="object"||Array.isArray(i.providers))throw new Error("models.json \u7ED3\u6784\u65E0\u6548");return{config:i,existing:e}}async function It(t,e,i){await yt(xt(t),{recursive:!0});let r=i===void 0?384:(await Pt(t)).mode&511,n=`${t}.pi-web-${ht(6).toString("hex")}.tmp`;try{await St(n,`${JSON.stringify(e,null,2)}
3
- `,{mode:r,flag:"wx"}),await kt(n,t)}finally{await bt(n,{force:!0})}}async function me(t,e,i){if(!i.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:r}=await ue(t),n=r.providers[e],p=new Set(n?.models?.map(o=>o.id)??[]);return{providerId:e,baseUrl:n?.baseUrl,models:i.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 fe(t,e,i,r){if(!r.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:n,existing:p}=await ue(t),o={...n.providers[e]??{}},l=[...o.models??[]],a={...o.modelOverrides??{}};if(i.action==="base_url"){if(i.baseUrl!==null&&!le(i.baseUrl))throw new Error("API \u5730\u5740\u65E0\u6548");i.baseUrl===null?delete o.baseUrl:o.baseUrl=i.baseUrl}else if(i.action==="save"){if(!pe(i.model))throw new Error("\u6A21\u578B\u53C2\u6570\u65E0\u6548");let u={id:i.model.id.trim(),...i.model.name===void 0?{}:{name:i.model.name},...i.model.contextWindow===void 0?{}:{contextWindow:i.model.contextWindow},...i.model.maxTokens===void 0?{}:{maxTokens:i.model.maxTokens},...i.model.input===void 0?{}:{input:i.model.input}},h=i.originalId,g=h===void 0?-1:l.findIndex(c=>c.id===h);if(h===void 0&&(l.some(c=>c.id===u.id)||r.getModel(e,u.id)))throw new Error("\u6A21\u578B ID \u5DF2\u5B58\u5728");if(g>=0){if(u.id!==h&&(l.some(f=>f.id===u.id)||r.getModel(e,u.id)))throw new Error("\u6A21\u578B ID \u5DF2\u5B58\u5728");let c={...l[g],...u};for(let f of["name","contextWindow","maxTokens","input"])u[f]===void 0&&delete c[f];l[g]=c}else if(h!==void 0&&r.getModel(e,h)){if(u.id!==h)throw new Error("\u5185\u7F6E\u6A21\u578B ID \u4E0D\u53EF\u4FEE\u6539");let{id:c,...f}=u;a[h]={...a[h],...f};for(let C of["name","contextWindow","maxTokens","input"])u[C]===void 0&&delete a[h][C]}else{if(h!==void 0)throw new Error("\u6A21\u578B\u4E0D\u5B58\u5728");l.push(u)}}else{let u=l.findIndex(h=>h.id===i.id);if(u>=0)l.splice(u,1);else if(Object.hasOwn(a,i.id))delete a[i.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 It(t,n,p)}function ge(t){return/^(?:npm:|git:|https?:\/\/|ssh:\/\/|git@)/i.test(t.trim())}var Wt={"/":{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,i){t.writeHead(e,{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}),t.end(JSON.stringify(i))}function Lt(t,e){let i=t.headers.authorization;if(typeof i!="string"||!i.startsWith("Bearer "))return!1;let r=Buffer.from(i.slice(7),"utf8");return r.length===e.length&&Ct(r,e)}async function Nt(t){let e=0,i=[];for await(let r of t){let n=Buffer.isBuffer(r)?r:Buffer.from(r);if(e+=n.length,e>64*1024)throw new Error("\u8BF7\u6C42\u5185\u5BB9\u8FC7\u5927");i.push(n)}return JSON.parse(Buffer.concat(i).toString("utf8"))}async function jt(t){let e=0,i=[];for await(let r of t){let n=Buffer.isBuffer(r)?r:Buffer.from(r);if(e+=n.length,e>N)throw new Error("\u6587\u4EF6\u8D85\u8FC7 20 MB");i.push(n)}return Buffer.concat(i)}async function Rt(t){await new Promise((i,r)=>{t.once("error",r),t.listen(0,"127.0.0.1",()=>{t.off("error",r),i()})});let e=t.address();if(e===null||typeof e=="string")throw new Error("\u65E0\u6CD5\u786E\u5B9A\u76D1\u542C\u7AEF\u53E3");return e.port}async function we(t,e){let i=Et(24).toString("base64url"),r=Buffer.from(i),n=te(),p=new Set,o=new Map,l=new j,a="",u=At(async(g,c)=>{c.setHeader("X-Content-Type-Options","nosniff"),c.setHeader("Referrer-Policy","no-referrer"),c.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??"/",a).pathname}catch{m(c,400,{error:"\u8BF7\u6C42\u5730\u5740\u65E0\u6548"});return}let C=Wt[f];if(g.method==="GET"&&C){try{let d=await Mt(Tt(e,C.path));c.writeHead(200,{"Content-Type":C.type,"Cache-Control":"no-store"}),c.end(d)}catch{m(c,500,{error:"\u9875\u9762\u6587\u4EF6\u4E0D\u53EF\u7528"})}return}if(!f.startsWith("/api/")){m(c,404,{error:"\u672A\u627E\u5230"});return}if(!Lt(g,r)){m(c,401,{error:"\u8BBF\u95EE\u4EE4\u724C\u65E0\u6548"});return}if(g.method==="GET"&&f==="/api/image"){let d=new URL(g.url??f,a),w=d.searchParams.get("sessionId")??"",v=d.searchParams.get("messageId")??"",y=Number(d.searchParams.get("index"));if(!w||w!==t.snapshot().sessionId||!v||!Number.isInteger(y)||y<0||y>100){m(c,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u56FE\u7247\u5730\u5740\u65E0\u6548"});return}let E=t.image?.(w,v,y);if(!E||!["image/png","image/jpeg","image/webp","image/gif"].includes(E.mimeType)){m(c,404,{error:"\u56FE\u7247\u4E0D\u53EF\u7528"});return}c.writeHead(200,{"Content-Type":E.mimeType,"Cache-Control":"private, no-store"}),c.end(E.data);return}if(g.method==="POST"&&f==="/api/attachment"){if(g.headers.origin!==void 0&&g.headers.origin!==a){m(c,403,{error:"\u6765\u6E90\u4E0D\u5339\u914D"});return}let d=new URL(g.url??f,a),w=d.searchParams.get("sessionId"),v=d.searchParams.get("name");try{if(!w||!v||v.length>1024||w!==t.snapshot().sessionId){m(c,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u6587\u4EF6\u540D\u65E0\u6548"});return}if(Number(g.headers["content-length"]??0)>N){m(c,413,{error:"\u6587\u4EF6\u8D85\u8FC7 20 MB"});return}let y=await ne(w,v,g.headers["content-type"]??"application/octet-stream",await jt(g));if(w!==t.snapshot().sessionId){m(c,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}o.set(y.id,y),m(c,201,{id:y.id,name:y.name,bytes:y.bytes})}catch(y){m(c,400,{error:y instanceof Error?y.message:"\u4E0A\u4F20\u5931\u8D25"})}return}if(g.method==="GET"&&f==="/api/session"){try{m(c,200,t.snapshot())}catch{m(c,503,{error:"\u5F53\u524D\u4F1A\u8BDD\u4E0D\u53EF\u7528"})}return}if(g.method==="GET"&&f==="/api/providers"){try{m(c,200,await t.providers?.()??[])}catch{m(c,503,{error:"\u6A21\u578B\u63D0\u4F9B\u65B9\u4E0D\u53EF\u7528"})}return}if(g.method==="GET"&&f==="/api/provider/models"){let d=new URL(g.url??f,a).searchParams.get("providerId")??"";try{if(!d||!t.providerModels){m(c,400,{error:"\u63D0\u4F9B\u65B9\u65E0\u6548"});return}m(c,200,await t.providerModels(d))}catch(w){m(c,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(c,200,{active:l.getActive()??null});return}if(g.method==="GET"&&f==="/api/provider/login"){let d=new URL(g.url??f,a).searchParams.get("id")??"",w=l.get(d);m(c,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(c,200,f==="/api/models"?await t.models():f==="/api/config"?await t.config():f==="/api/commands"?t.commands?.()??[]:await t.workspaces())}catch{m(c,503,{error:"Pi \u914D\u7F6E\u4E0D\u53EF\u7528"})}return}if(g.method==="GET"&&f==="/api/directory/capability"){m(c,200,{kind:n});return}if(g.method==="GET"&&f==="/api/events"){let d;try{d=t.snapshot()}catch{m(c,503,{error:"\u5F53\u524D\u4F1A\u8BDD\u4E0D\u53EF\u7528"});return}c.writeHead(200,{"Content-Type":"application/x-ndjson; charset=utf-8","Cache-Control":"no-store",Connection:"keep-alive","X-Accel-Buffering":"no"}),p.add(c),c.write(`${JSON.stringify({type:"snapshot",session:d})}
4
- `),c.on("close",()=>p.delete(c));return}if(g.method==="POST"&&["/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!==a){m(c,403,{error:"\u6765\u6E90\u4E0D\u5339\u914D"});return}if(!g.headers["content-type"]?.startsWith("application/json")){m(c,415,{error:"\u9700\u8981 JSON \u8BF7\u6C42"});return}try{let d=await Nt(g);if(typeof d!="object"||d===null||!("sessionId"in d)||typeof d.sessionId!="string"){m(c,400,{error:"\u7F3A\u5C11\u4F1A\u8BDD\u6807\u8BC6"});return}if(f==="/api/provider/custom"){if(d.sessionId!==t.snapshot().sessionId){m(c,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("provider"in d)||!D(d.provider)||!t.addCustomProvider){m(c,400,{error:"\u81EA\u5B9A\u4E49\u63D0\u4F9B\u65B9\u65E0\u6548"});return}await t.addCustomProvider(d.sessionId,d.provider),m(c,201,{accepted:!0});return}if(f==="/api/provider/models"||f==="/api/provider/logout"){if(d.sessionId!==t.snapshot().sessionId){m(c,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("providerId"in d)||typeof d.providerId!="string"){m(c,400,{error:"\u63D0\u4F9B\u65B9\u65E0\u6548"});return}if(f==="/api/provider/models"){if(!("change"in d)||!ce(d.change)||!t.updateProviderModel){m(c,400,{error:"\u6A21\u578B\u53C2\u6570\u65E0\u6548"});return}await t.updateProviderModel(d.sessionId,d.providerId,d.change)}else{if(!t.logoutProvider){m(c,400,{error:"\u65E0\u6CD5\u79FB\u9664\u8BA4\u8BC1"});return}await t.logoutProvider(d.sessionId,d.providerId)}m(c,200,{accepted:!0});return}if(f.startsWith("/api/provider/login")){if(d.sessionId!==t.snapshot().sessionId){m(c,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(f==="/api/provider/login"){if(!("providerId"in d)||typeof d.providerId!="string"||!("method"in d)||d.method!=="api_key"&&d.method!=="oauth"||!t.loginProvider||!t.providers){m(c,400,{error:"\u767B\u5F55\u65B9\u5F0F\u65E0\u6548"});return}if(!(await t.providers()).some(E=>E.id===d.providerId&&E.methods.includes(d.method))){m(c,400,{error:"\u63D0\u4F9B\u65B9\u4E0D\u652F\u6301\u6B64\u767B\u5F55\u65B9\u5F0F"});return}let v="initialSecret"in d?d.initialSecret:void 0;if(v!==void 0&&(d.method!=="api_key"||typeof v!="string"||!v.trim()||v.length>16384)){m(c,400,{error:"API Key \u65E0\u6548"});return}let y=l.start(d.providerId,d.method,t.loginProvider,v);m(c,202,{id:y.id});return}if(!("id"in d)||typeof d.id!="string"){m(c,400,{error:"\u767B\u5F55\u6D41\u7A0B\u65E0\u6548"});return}if(f==="/api/provider/login/cancel"){m(c,l.cancel(d.id)?202:404,{accepted:!0});return}if(!("value"in d)||typeof d.value!="string"||d.value.length>16384||!l.respond(d.id,d.value)){m(c,400,{error:"\u767B\u5F55\u8F93\u5165\u65E0\u6548"});return}m(c,202,{accepted:!0});return}if(f==="/api/attachment/remove"){if(!("id"in d)||typeof d.id!="string"||d.sessionId!==t.snapshot().sessionId){m(c,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u9644\u4EF6\u65E0\u6548"});return}o.get(d.id)?.sessionId===d.sessionId&&o.delete(d.id),m(c,202,{accepted:!0});return}if(f==="/api/directory/pick"){if(n!=="native"){m(c,409,{error:"\u672C\u5730\u76EE\u5F55\u9009\u62E9\u5668\u4E0D\u53EF\u7528"});return}let w=new AbortController;c.once("close",()=>w.abort()),m(c,200,{path:await ie(w.signal)});return}if(f==="/api/directory/list"){if("path"in d&&(typeof d.path!="string"||d.path.length>4096)){m(c,400,{error:"\u76EE\u5F55\u8DEF\u5F84\u65E0\u6548"});return}m(c,200,await q("path"in d?d.path:void 0));return}if(f==="/api/directory/create"){if(!("path"in d)||typeof d.path!="string"||d.path.length>4096||!("name"in d)||typeof d.name!="string"||d.name.length>255){m(c,400,{error:"\u6587\u4EF6\u5939\u540D\u79F0\u6216\u8DEF\u5F84\u65E0\u6548"});return}m(c,200,{path:await ee(d.path,d.name)});return}if(f==="/api/workspace/add"){if(!("path"in d)||typeof d.path!="string"||d.path.length>4096||!("create"in d)||typeof d.create!="boolean"){m(c,400,{error:"\u5DE5\u4F5C\u533A\u8DEF\u5F84\u65E0\u6548"});return}await t.addWorkspace(d.path,d.create),m(c,202,{accepted:!0});return}if(f==="/api/workspace/select"||f==="/api/workspace/remove"||f==="/api/workspace/new-session"){if(!("id"in d)||typeof d.id!="string"){m(c,400,{error:"\u5DE5\u4F5C\u533A\u65E0\u6548"});return}f==="/api/workspace/select"?await t.selectWorkspace(d.id):f==="/api/workspace/new-session"?await t.newSessionInWorkspace(d.id):await t.removeWorkspace(d.id),m(c,202,{accepted:!0});return}if(f==="/api/session/select"){if(!("workspaceId"in d)||typeof d.workspaceId!="string"||!("id"in d)||typeof d.id!="string"||!("path"in d)||typeof d.path!="string"){m(c,400,{error:"\u4F1A\u8BDD\u65E0\u6548"});return}await t.selectSession(d.workspaceId,d.id,d.path),m(c,202,{accepted:!0});return}if(f==="/api/thinking-level"){if(!("level"in d)||typeof d.level!="string"){m(c,400,{error:"\u63A8\u7406\u5F3A\u5EA6\u65E0\u6548"});return}await t.setThinkingLevel(d.sessionId,d.level)}else if(f==="/api/model"){if(!("provider"in d)||typeof d.provider!="string"||!("id"in d)||typeof d.id!="string"){m(c,400,{error:"\u6A21\u578B\u65E0\u6548"});return}await t.setModel(d.sessionId,d.provider,d.id)}else if(f==="/api/config"){let w=d;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(c,400,{error:"\u914D\u7F6E\u9879\u65E0\u6548"});return}if(w.action==="add"&&w.kind!=="packages"&&ge(w.value)){m(c,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(c,200,await t.updateConfig(w));return}else if(f==="/api/message"){let w="attachments"in d?d.attachments:[];if(!Array.isArray(w)||w.length>se||w.some(b=>typeof b!="string")||new Set(w).size!==w.length){m(c,400,{error:"\u9644\u4EF6\u65E0\u6548\u6216\u8FC7\u591A"});return}let v=w.map(b=>o.get(b));if(v.some(b=>!b||b.sessionId!==d.sessionId)){m(c,400,{error:"\u9644\u4EF6\u4E0D\u53EF\u7528"});return}if(!("text"in d)||typeof d.text!="string"||!d.text.trim()&&w.length===0||d.text.length>32e3){m(c,400,{error:"\u6D88\u606F\u65E0\u6548\u6216\u8FC7\u957F"});return}let y=v,E=[d.text.trim(),...y.map(b=>`\u9644\u4EF6 ${JSON.stringify(b.name)}\uFF1A${b.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
- `),Ne=await Promise.all(y.filter(b=>["image/png","image/jpeg","image/webp","image/gif"].includes(b.mediaType)).map(oe));await t.send(d.sessionId,E,Ne);for(let b of w)o.delete(b)}else if(f==="/api/compact"){if(!t.compact)throw new Error("\u5F53\u524D\u4F1A\u8BDD\u4E0D\u652F\u6301\u538B\u7F29");await t.compact(d.sessionId)}else f==="/api/abort"?t.abort(d.sessionId):await t.newSession(d.sessionId);m(c,202,{accepted:!0})}catch(d){let w=d instanceof Error?d.message:"\u8BF7\u6C42\u5931\u8D25";m(c,w==="\u4F1A\u8BDD\u5DF2\u5207\u6362"?409:400,{error:w})}return}m(c,404,{error:"\u672A\u627E\u5230"})});return a=`http://127.0.0.1:${await Rt(u)}`,{protocolVersion:3,url:`${a}/#${i}`,publish(g){if(g.type==="snapshot")for(let[f,C]of o)C.sessionId!==g.session.sessionId&&o.delete(f);let c=`${JSON.stringify(g)}
7
- `;for(let f of p)f.write(c)},async close(){l.close();for(let g of p)g.end();p.clear(),await new Promise((g,c)=>u.close(f=>f?c(f):g()))}}}import{getSupportedThinkingLevels as Vt}from"@earendil-works/pi-ai";function he(t){let e=[],i=t;for(;;){let r=/(^|\n\n)附件 ("(?:\\.|[^"\\])*"):([^\n]+)$/u.exec(i);if(!r||!/[\\/]pi-web[\\/]attachments[\\/][a-f0-9]{64}[\\/]/u.test(r[3]))break;let n;try{n=JSON.parse(r[2])}catch{break}e.unshift({name:n,image:/\.(?:png|jpe?g|webp|gif)$/iu.test(n)}),i=i.slice(0,r.index)}return{text:i,attachments:e}}function M(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 $(t){if(t.type==="custom_message")return t.display?{id:t.id,role:"notice",timestamp:t.timestamp,blocks:M(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:M(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:M(e.content),isError:e.isError,toolCallId:e.toolCallId,toolName:e.toolName}:null}function F(t,e){let i=t?.trim();if(i)return i;let r=e.find(p=>p.role==="user"),n=he(r?.blocks.find(p=>p.kind==="text")?.text??"").text.replace(/\s+/g," ").trim();return n?n.slice(0,50):"\u5F53\u524D\u4F1A\u8BDD"}function ye(t,e){let i=t.sessionManager.getBranch().flatMap(r=>{let n=$(r);return n?[n]:[]});return{schemaVersion:1,sessionId:t.sessionManager.getSessionId(),cwd:t.cwd,name:F(e,i),model:t.model?`${t.model.provider}/${t.model.id}`:null,thinkingLevel:t.thinkingLevel??null,thinkingLevels:t.model?Vt(t.model):["off"],idle:t.isIdle(),contextUsage:t.getContextUsage()??null,messages:i}}import{randomUUID as H}from"node:crypto";import{mkdir as ve,readFile as _t,realpath as ke,rename as Bt,rm as Ot,stat as be,writeFile as Ut}from"node:fs/promises";import{basename as Pe,dirname as Dt,isAbsolute as Se,join as $t}from"node:path";var R=class{items=[];hiddenPaths=[];mutationChain=Promise.resolve();file;constructor(e){this.file=e}async load(){try{let e=JSON.parse(await _t(this.file,"utf8")),i,r=[];if(Array.isArray(e)?i=e:e&&typeof e=="object"&&"version"in e&&e.version===2&&"items"in e&&"hiddenPaths"in e&&(i=e.items,r=e.hiddenPaths),!Array.isArray(i)||!Array.isArray(r))throw new Error("\u5DE5\u4F5C\u533A\u8BB0\u5F55\u65E0\u6548");this.items=i.filter(n=>typeof n=="object"&&n!==null&&typeof n.id=="string"&&typeof n.path=="string"&&typeof n.title=="string"),this.hiddenPaths=r.filter(n=>typeof n=="string")}catch(e){if(e.code!=="ENOENT")throw e}}list(){return[...this.items]}get(e){return this.items.find(i=>i.id===e)}async add(e,i=!1){if(!Se(e)||e.includes("\0"))throw new Error("\u8BF7\u8F93\u5165\u5B8C\u6574\u7684\u76EE\u5F55\u8DEF\u5F84");i&&await ve(e,{recursive:!0});let r=await ke(e);if(!(await be(r)).isDirectory())throw new Error("\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55");return this.mutate(async()=>{let n=this.hiddenPaths.filter(a=>a!==r),p=this.items.find(a=>a.path===r);if(p)return n.length!==this.hiddenPaths.length&&(await this.save(this.items,n),this.hiddenPaths=n),p;let o={id:H(),path:r,title:Pe(r)||r},l=[o,...this.items];return await this.save(l,n),this.items=l,this.hiddenPaths=n,o})}async discover(e){let i=(await Promise.all([...new Set(e)].filter(Se).map(async r=>{try{let n=await ke(r);return(await be(n)).isDirectory()?n:null}catch{return null}}))).filter(r=>r!==null);await this.mutate(async()=>{let r=new Set([...this.items.map(o=>o.path),...this.hiddenPaths]),n=[];for(let o of i)r.has(o)||(r.add(o),n.push({id:H(),path:o,title:Pe(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 i=this.get(e);if(!i)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");let r=this.items.filter(p=>p.id!==e),n=[...new Set([...this.hiddenPaths,i.path])];await this.save(r,n),this.items=r,this.hiddenPaths=n})}mutate(e){let i=this.mutationChain.then(e,e);return this.mutationChain=i.then(()=>{},()=>{}),i}async save(e,i){await ve(Dt(this.file),{recursive:!0});let r=`${this.file}.${H()}.tmp`;try{await Ut(r,JSON.stringify({version:2,items:e,hiddenPaths:i},null,2),{mode:384}),await Bt(r,this.file)}catch(n){throw await Ot(r,{force:!0}),n}}};function xe(t){return $t(t,"pi-web","workspaces.json")}import{createAgentSession as Ht,DefaultResourceLoader as Jt,getAgentDir as Gt,SessionManager as V}from"@earendil-works/pi-coding-agent";import{realpath as Ee}from"node:fs/promises";import{realpath as Ie}from"node:fs/promises";import{SessionManager as Ft}from"@earendil-works/pi-coding-agent";async function W(t,e){let i=await Ie(t),r=e??await Ft.listAll(),n=await Promise.all(r.map(async p=>p.cwd!==""&&await Ie(p.cwd).catch(()=>null)===i));return r.filter((p,o)=>n[o])}var _=class{active=null;detach=null;cwd=null;lastStreamAt=0;publish;fallbackModel;constructor(e,i){this.publish=e,this.fallbackModel=i}get session(){return this.active}get path(){return this.cwd}async open(e,i){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 r=await Ee(e),n;if(i==="new")n=V.create(r);else if(i==="continue"){let a=(await W(r))[0];n=a?V.open(a.path):V.create(r)}else n=V.open(i.sessionFile);if(await Ee(n.getCwd())!==r)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 Jt({cwd:r,agentDir:Gt(),noExtensions:!0});await o.reload();let{session:l}=await Ht({cwd:r,sessionManager:n,model:p,resourceLoader:o});this.detach?.(),this.active?.dispose(),this.active=l,this.cwd=r,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:M(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 i=e.sessionManager.getBranch().flatMap(r=>{let n=$(r);return n?[n]:[]});return{schemaVersion:1,sessionId:e.sessionManager.getSessionId(),cwd:this.cwd,name:F(e.sessionManager.getSessionName(),i),model:e.model?`${e.model.provider}/${e.model.id}`:null,thinkingLevel:e.thinkingLevel,thinkingLevels:e.getAvailableThinkingLevels(),idle:e.isIdle,contextUsage:e.getContextUsage()??null,messages:i}}async send(e,i=[]){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 r=this.active,n=!1,p,o,l=new Promise((a,u)=>{p=a,o=u});r.prompt(e,{images:i,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(i=>({provider:i.provider,id:i.id,name:i.name}))}async setModel(e,i){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 r=this.active.modelRuntime.getModel(e,i);if(!r)throw new Error("\u6A21\u578B\u4E0D\u53EF\u7528");await this.active.setModel(r),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 J,dirname as Kt}from"node:path";function Ce(t,e){let i=r=>e[r].map(n=>({name:r==="skills"&&J(n.path).toLowerCase()==="skill.md"?J(Kt(n.path)):J(n.path),path:n.path,source:n.metadata.source,scope:n.metadata.scope,enabled:n.enabled}));return{packages:t.map(r=>({name:r.source,path:r.installedPath??"",source:r.source,scope:r.scope,enabled:!!r.installedPath})),extensions:i("extensions"),skills:i("skills")}}import{execFile as zt}from"node:child_process";var Yt=(t,e)=>new Promise((i,r)=>{zt(t,[...e],{windowsHide:!0},n=>{n?r(n):i()})});async function G(t,e=process.platform,i=process.env,r=Yt){if(i.SSH_CONNECTION||i.SSH_TTY||i.SSH_CLIENT||e==="linux"&&!i.DISPLAY&&!i.WAYLAND_DISPLAY)return!1;let n=e==="darwin"?"open":e==="linux"?"xdg-open":e==="win32"?"explorer.exe":null;return n===null?!1:(await r(n,[t]),!0)}var ii=Qt(Xt(Zt(import.meta.url)),"../web/dist"),ri=Symbol.for("pi-web.bridge-state"),s=globalThis[ri]??={bridge:null,current:null,commandContext:null,pi:null,replacementContext:null,replacementSessionId:null,lastStreamAt:0,workspaces:null,workspaceSessions:null,selected:"tui",activeWorkspaceId:null,autoOpened:!1},si=null;function ni(){return si??=qt.create({refreshOnCreate:!1})}var B=new Map;async function A(){let t=await ni(),e=s.selected==="tui"?s.current?.modelRegistry:void 0,i=new Set(e?.getRegisteredProviderIds()??[]);for(let r of B.keys())i.has(r)||(t.unregisterProvider(r),B.delete(r));for(let r of i){let n=e?.getRegisteredNativeProvider(r),p=e?.getRegisteredProviderConfig(r),o=n??p;!o||B.get(r)===o||(n?t.registerNativeProvider(n):p&&t.registerProvider(r,p),B.set(r,o))}return await t.refresh({allowNetwork:!1}),t}function k(){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 ye(s.current,s.current.sessionManager.getSessionName())}function S(t){if(k().sessionId!==t)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362")}async function Te(){let t=s.workspaces?.list()??[],e=k(),i=await O(e.cwd).catch(()=>e.cwd),r=await Ae.listAll(),n=(await Promise.all(t.map(async p=>{let l=(await W(p.path,r).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===i&&!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 I(){s.bridge&&s.bridge.publish({type:"workspaces",value:await Te()})}async function z(t,e=!1){let i=s.workspaces?.get(t);if(!i)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");if(await O(i.path),!e&&s.current&&i.path===await O(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:k()})}else{if(!s.workspaceSessions)throw new Error("Pi \u5DE5\u4F5C\u533A\u670D\u52A1\u4E0D\u53EF\u7528");await s.workspaceSessions.open(i.path,e?"new":"continue"),s.selected="sdk",s.activeWorkspaceId=t,s.bridge?.publish({type:"snapshot",session:k()})}await I()}function x(t){let e=s.current;if(e===null||e.sessionManager.getSessionId()!==t)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362");return e}function P(t){s.current=t,s.selected==="tui"&&s.bridge?.publish({type:"snapshot",session:k()})}function We(){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 ei.create(t,void 0,{projectTrusted:e})}async function Le(){let t=We(),e=n=>({packages:(n.packages??[]).map(p=>typeof p=="string"?p:p.source),extensions:n.extensions??[],skills:n.skills??[]}),i=new Me({cwd:k().cwd,agentDir:T(),settingsManager:t}),r=Ce(i.listConfiguredPackages(),await i.resolve(async()=>"skip"));return{projectTrusted:t.isProjectTrusted(),global:e(t.getGlobalSettings()),project:e(t.getProjectSettings()),installed:r}}async function oi(t){S(t.sessionId);let e=s.selected==="tui"?x(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 i=We();if(t.scope==="project"&&!i.isProjectTrusted())throw new Error("\u5F53\u524D\u9879\u76EE\u5C1A\u672A\u53D7\u4FE1\u4EFB\uFF0C\u65E0\u6CD5\u4FEE\u6539\u9879\u76EE\u8BBE\u7F6E");let r=t.value.trim(),n=t.scope==="project"?i.getProjectSettings():i.getGlobalSettings();if(t.kind==="packages"){let p=new Me({cwd:k().cwd,agentDir:T(),settingsManager:i});t.action==="add"?await p.installAndPersist(r,{local:t.scope==="project"}):await p.removeAndPersist(r,{local:t.scope==="project"})}else if(t.kind==="extensions"){let p=n.extensions??[],o=t.action==="add"?[...new Set([...p,r])]:p.filter(l=>l!==r);t.scope==="project"?i.setProjectExtensionPaths(o):i.setExtensionPaths(o)}else{let p=n.skills??[],o=t.action==="add"?[...new Set([...p,r])]:p.filter(l=>l!==r);t.scope==="project"?i.setProjectSkillPaths(o):i.setSkillPaths(o)}return await i.flush(),s.selected==="tui"?(s.commandContext&&await s.commandContext.reload(),s.current&&P(s.current)):(await s.workspaceSessions?.session?.resourceLoader.reload(),s.workspaceSessions?.session?.refreshContext()),await Le()}function ai(t,e=G){s.pi=t,t.on("session_start",(r,n)=>{s.replacementSessionId!==n.sessionManager.getSessionId()&&(s.replacementContext=null,s.replacementSessionId=null),P(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 I())}).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,i(n).catch(p=>{n.ui.notify(p instanceof Error?p.message:"Web \u542F\u52A8\u5931\u8D25","error")}))}),t.on("agent_start",(r,n)=>P(n)),t.on("agent_end",(r,n)=>P(n)),t.on("agent_settled",(r,n)=>P(n)),t.on("model_select",(r,n)=>P(n)),t.on("thinking_level_select",(r,n)=>P(n)),t.on("message_end",(r,n)=>{s.selected==="tui"&&r.message.role==="assistant"&&s.bridge?.publish({type:"stream",message:null}),P(n),s.selected==="tui"&&I()}),t.on("session_info_changed",(r,n)=>P(n)),t.on("message_update",(r,n)=>{if(s.current=n,s.selected!=="tui"||r.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(r.message.timestamp).toISOString(),blocks:M(r.message.content)}}))}),t.on("session_shutdown",r=>{if(s.current=null,r.reason==="new"||r.reason==="resume"||r.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 i=async r=>{s.current=r,s.commandContext="newSession"in r?r:null,s.pi=t,s.workspaces===null&&(s.workspaces=new R(xe(T())),await s.workspaces.load());try{await s.workspaces.discover((await Ae.listAll()).map(o=>o.cwd))}catch(o){r.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(r.cwd);if(s.selected==="tui"&&(s.activeWorkspaceId=n.id),s.bridge&&s.bridge.protocolVersion!==3){let o=s.bridge;s.bridge=null,await o.close()}s.bridge===null&&(s.workspaceSessions=new _(o=>{s.selected==="sdk"&&(s.bridge?.publish(o),o.type==="snapshot"&&o.session.idle&&I())},()=>s.current?.model),s.bridge=await we({snapshot:k,image(o,l,a){S(o);let h=(s.selected==="sdk"?s.workspaceSessions?.session?.sessionManager.getBranch():s.current?.sessionManager.getBranch())?.find(c=>c.id===l);if(h?.type!=="message"||h.message.role!=="user"||!Array.isArray(h.message.content))return null;let g=h.message.content[a];return g?.type!=="image"?null:{data:Buffer.from(g.data,"base64"),mimeType:g.mimeType}},async workspaces(){return Te()},async addWorkspace(o,l){let a=await s.workspaces.add(o,l);try{await z(a.id,!0)}catch(u){throw await I(),u}},async selectWorkspace(o){await z(o)},async newSessionInWorkspace(o){await z(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 I()},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 O(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:k()})}else{if(s.selected==="sdk"&&s.workspaceSessions?.session?.sessionManager.getSessionId()===l&&s.workspaceSessions.path===u.path)return;if(!(await W(u.path)).some(g=>g.id===l&&g.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:k()})}await I()},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 A(),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 A();return me(K(T(),"models.json"),o,l)},async updateProviderModel(o,l,a){if(S(o),s.selected==="tui"?!x(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=k().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 A();await fe(K(T(),"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 g=a.action==="save"?a.model.id:a.action==="base_url"&&u?.startsWith(`${l}/`)?u.slice(l.length+1):null;if(g&&u===`${l}/${g}`)if(s.selected==="sdk")try{await s.workspaceSessions.setModel(l,g)}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 c=x(o),f=c.modelRegistry.find(l,g);if(!f||!s.pi||!await s.pi.setModel(f))throw new Error("\u6A21\u578B\u5DF2\u4FDD\u5B58\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u8BE5\u6A21\u578B\u4EE5\u5E94\u7528\u65B0\u53C2\u6570");P(c)}},async logoutProvider(o,l){if(S(o),s.selected==="tui"?!x(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 A();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 A();await u.login(o,l,ae(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(S(o),s.selected==="tui"?!x(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 A();if(a.getProvider(l.id))throw new Error("\u63D0\u4F9B\u65B9\u5DF2\u5B58\u5728");await de(K(T(),"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(S(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:k()});return}let l=x(o);if(!l.isIdle())throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");l.compact()},async setModel(o,l,a){if(S(o),s.selected==="sdk"){await s.workspaceSessions.setModel(l,a);return}let u=x(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(g=>g.provider===l&&g.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");P(u)},async setThinkingLevel(o,l){if(S(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:k()});return}let u=x(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||!ti(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),P(u)},config:Le,updateConfig:oi,async send(o,l,a=[]){if(S(o),s.selected==="sdk"){await s.workspaceSessions.send(l,a);return}if(!x(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){S(o),s.selected==="sdk"?s.workspaceSessions.stop():x(o).abort()},async newSession(o){if(S(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 I();return}let l=x(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:k()}),await I();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 I()}},ii));let p=await e(s.bridge.url).catch(()=>!1);r.ui.notify(`pi-webapp: ${s.bridge.url}`,p?"info":"warning"),r.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(r,n)=>i(n)})}export{ai 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.5",
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.5/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
  }