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