pi-webapp 0.1.20 → 0.1.21
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 +12 -0
- package/README.zh-CN.md +12 -0
- package/dist/extension.js +16 -16
- package/docs/desktop.md +78 -7
- package/package.json +2 -2
- package/web/dist/assets/app.js +2 -2
package/README.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
[简体中文](README.zh-CN.md)
|
|
4
4
|
|
|
5
|
+
## Download pi desktop
|
|
6
|
+
|
|
7
|
+
### [⬇ Download for macOS Apple Silicon (.dmg)](https://github.com/chengzhiyi/pi-webapp/releases/download/desktop-v0.1.20-b5/pi-0.1.20-desktop.5-mac-arm64.dmg)
|
|
8
|
+
|
|
9
|
+
**Test release · v0.1.20 / desktop build 5 · Apple M-series only**
|
|
10
|
+
|
|
11
|
+
[Release notes and SHA-256 checksums](https://github.com/chengzhiyi/pi-webapp/releases/tag/desktop-v0.1.20-b5) · [All desktop releases](https://github.com/chengzhiyi/pi-webapp/releases) · [Use the Web/npm version instead](#install-and-open)
|
|
12
|
+
|
|
13
|
+
> Open the DMG and drag **pi.app** into Applications. This test build is unsigned/unnotarized; do not globally disable macOS security. Windows/Linux/Intel Mac installers are not yet validated. Node and a tested, pinned Pi runtime are bundled; you do not need to install them separately.
|
|
14
|
+
|
|
5
15
|

|
|
6
16
|
|
|
7
17
|
**pi-webapp** opens the active Pi coding agent session in a local browser. Pi continues to run the agent, tools, and session storage; the browser provides a live interface for conversation and control.
|
|
@@ -57,6 +67,8 @@ On startup, the app discovers workspaces from Pi's saved sessions, so conversati
|
|
|
57
67
|
|
|
58
68
|
## Optional desktop application
|
|
59
69
|
|
|
70
|
+
**[Download pi desktop test releases](https://github.com/chengzhiyi/pi-webapp/releases)** — macOS Apple Silicon (arm64) only for now. Download the DMG from a `desktop-v...` prerelease; compare `SHA256SUMS`, install **pi.app**, and check the build in **pi → 关于 pi**. These builds are unsigned/unnotarized; do not globally disable macOS security. Windows/Linux are not yet validated release downloads.
|
|
71
|
+
|
|
60
72
|
The same UI can run in the **pi** Electron desktop application while the browser and `/web` entry points remain available. Desktop packages include Node/Pi, reuse compatible running services, and let you open the same service in a browser or choose whether to keep background tasks running on exit.
|
|
61
73
|
|
|
62
74
|
From source: `npm ci` → `npm run desktop:prepare` → `npm run desktop:start`. Run `npm run desktop:package` to create a host-native installer under `desktop-release/`. Local QA targets macOS arm64; Windows/Linux configurations need verification on their respective systems. Initial packages are unsigned and do not auto-update. Installers include a desktop build number; check **pi → 关于 pi** for the running build and executable location. Quit the old desktop before replacing it; an external compatible Web backend need not be stopped. Finish tasks and stop an owned runtime before replacing that runtime.
|
package/README.zh-CN.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md)
|
|
4
4
|
|
|
5
|
+
## 下载 pi 桌面版
|
|
6
|
+
|
|
7
|
+
### [⬇ 下载 macOS Apple 芯片版(DMG)](https://github.com/chengzhiyi/pi-webapp/releases/download/desktop-v0.1.20-b5/pi-0.1.20-desktop.5-mac-arm64.dmg)
|
|
8
|
+
|
|
9
|
+
**测试版 · v0.1.20 / 桌面构建 5 · 仅支持 Apple M 系列芯片**
|
|
10
|
+
|
|
11
|
+
[版本说明与 SHA-256 校验和](https://github.com/chengzhiyi/pi-webapp/releases/tag/desktop-v0.1.20-b5) · [所有桌面版本](https://github.com/chengzhiyi/pi-webapp/releases) · [改用 Web/npm 方式](#安装与打开)
|
|
12
|
+
|
|
13
|
+
> 打开 DMG,将 **pi.app** 拖入“应用程序”即可。此测试版未签名、未公证,请勿全局关闭 macOS 安全保护。Windows/Linux/Intel Mac 安装包尚未验收。安装包已内置 Node 与经过验证、锁定版本的 Pi,无需另行安装。
|
|
14
|
+
|
|
5
15
|

|
|
6
16
|
|
|
7
17
|
**pi-webapp** 可以在本地浏览器中打开当前活跃的 Pi 编程 Agent 会话。Agent、工具和会话存储仍由 Pi 运行和管理;浏览器提供实时的对话与控制界面。
|
|
@@ -57,6 +67,8 @@ pi
|
|
|
57
67
|
|
|
58
68
|
## 桌面端(可选)
|
|
59
69
|
|
|
70
|
+
**[下载 pi 桌面测试版](https://github.com/chengzhiyi/pi-webapp/releases)** — 目前仅发布已验收的 macOS Apple 芯片(arm64)版本。在 `desktop-v...` 预发布版本中下载 DMG,核对 `SHA256SUMS` 后安装 **pi.app**,在“pi → 关于 pi”查看构建号。测试版未签名、未公证,请勿全局关闭系统安全保护;Windows/Linux 暂不提供已验收的发行包。
|
|
71
|
+
|
|
60
72
|
同一套界面也可在名为 **pi** 的 Electron 桌面程序中使用,现有浏览器与 `/web` 方式保持不变。桌面包自带 Node/Pi,支持独立窗口、已有服务复用、在浏览器打开同一服务,以及退出时选择保留或停止后台任务。
|
|
61
73
|
|
|
62
74
|
源码构建:`npm ci` → `npm run desktop:prepare` → `npm run desktop:start`。运行 `npm run desktop:package` 生成当前系统/架构的安装包,输出到 `desktop-release/`。当前本地验证目标为 macOS arm64;Windows/Linux 打包配置需在对应系统验证。首版安装包未签名,尚无桌面自动更新。安装包文件名包含桌面构建号;“pi → 关于 pi”显示实际运行的构建号和应用位置。替换前先退出旧桌面,外部兼容 Web 后台无需停止;若替换桌面自有运行时,请先结束任务并停止该自有后台。
|
package/dist/extension.js
CHANGED
|
@@ -1,4 +1,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]="530d2cd3-3a4b-42ac-8c36-ccb76e37b66c",r._sentryDebugIdIdentifier="sentry-dbid-530d2cd3-3a4b-42ac-8c36-ccb76e37b66c")}catch{}})();import{delimiter as go,dirname as ho,join as ze,resolve as vt}from"node:path";import{realpathSync as ti,watch as wo}from"node:fs";import{fileURLToPath as yo}from"node:url";import{DefaultPackageManager as ni,getAgentDir as oe,ModelRuntime as bo,SessionManager as si,SettingsManager as vo,VERSION as He}from"@earendil-works/pi-coding-agent";import{getSupportedThinkingLevels as ko}from"@earendil-works/pi-ai";import{randomBytes as Ir,randomUUID as st,timingSafeEqual as Hn}from"node:crypto";import{readFile as Jn,readdir as Kn}from"node:fs/promises";import{createServer as qn}from"node:http";import{isAbsolute as Xn,join as Cr,relative as Yn}from"node:path";import{mkdir as ui,opendir as fi,stat as mi}from"node:fs/promises";import{homedir as gi}from"node:os";import{basename as hi,dirname as xt,join as Pt,posix as wi,resolve as St,win32 as yi}from"node:path";function It(r){return process.platform==="win32"?yi.isAbsolute(r)&&/^(?:[A-Za-z]:[\\/]|[\\/]{2}[^\\/]+[\\/]+[^\\/]+)/.test(r):wi.isAbsolute(r)}function bi(r,e,t){if(r.length===t&&e.name.localeCompare(r[r.length-1].name)>=0)return!0;let i=0,n=r.length;for(;i<n;){let s=i+n>>>1;e.name.localeCompare(r[s].name)<0?n=s:i=s+1}return r.splice(i,0,e),r.length<=t?!1:(r.pop(),!0)}async function Ct(r){if(r!==void 0&&!It(r))throw new Error("\u76EE\u5F55\u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");let e=gi(),t=St(r??e),i=[];for(let p=t;;p=xt(p)){let w=xt(p);if(i.unshift({name:w===p?p:hi(p),path:p,hidden:!1}),w===p)break}let n=[],s=!1,a=await fi(t);for await(let p of a)!p.isDirectory()&&!p.isSymbolicLink()||bi(n,{name:p.name,isDirectory:p.isDirectory(),isSymbolicLink:p.isSymbolicLink()},1001)&&(s=!0);let l=[];for(let p of n){let w=Pt(t,p.name);if(!p.isDirectory&&p.isSymbolicLink)try{if(!(await mi(w)).isDirectory())continue}catch{continue}if(l.length===1e3){s=!0;break}l.push({name:p.name,path:w,hidden:p.name.startsWith(".")})}return{path:t,home:e,crumbs:i,entries:l,truncated:s}}async function _t(r,e){if(!It(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=Pt(St(r),e);return await ui(t),t}import{constants as Ke}from"node:fs";import{open as vi,opendir as ki,realpath as Tt,stat as Rt}from"node:fs/promises";import{isAbsolute as Nt,relative as Ei,resolve as xi,sep as Pi,win32 as Si}from"node:path";var Ii=1e3,Ci=512*1024,_i=8*1024*1024,At=1e4,Ti=new Intl.Collator("en",{numeric:!0,sensitivity:"base"}),j=class extends Error{status;constructor(e,t=400){super(e),this.name="WorkspaceFileError",this.status=t}};function Mt(r,e){let t=Ei(r,e);return t!==".."&&!t.startsWith(`..${Pi}`)&&!Nt(t)}async function qe(r,e){if(typeof e!="string"||e.length>4096||e.includes("\0")||e.includes("\\")||Nt(e)||Si.isAbsolute(e))throw new j("\u5DE5\u4F5C\u533A\u6587\u4EF6\u8DEF\u5F84\u65E0\u6548");let t=await Tt(r),i=xi(t,e);if(!Mt(t,i))throw new j("\u6587\u4EF6\u4F4D\u4E8E\u5DE5\u4F5C\u533A\u4E4B\u5916",403);let n=await Tt(i);if(!Mt(t,n))throw new j("\u6587\u4EF6\u4F4D\u4E8E\u5DE5\u4F5C\u533A\u4E4B\u5916",403);return n}async function Wt(r){try{return await r()}catch(e){if(e instanceof j)throw e;let t=e.code;throw t==="ENOENT"||t==="ENOTDIR"?new j("\u6587\u4EF6\u6216\u76EE\u5F55\u5DF2\u4E0D\u5B58\u5728",404):t==="EACCES"||t==="EPERM"?new j("\u6CA1\u6709\u6743\u9650\u8BFB\u53D6\u6587\u4EF6\u6216\u76EE\u5F55",403):e}}async function Dt(r,e){return Wt(async()=>{let t=await qe(r,e),i=[],n=!1;for await(let s of await ki(t)){if(i.length===Ii){n=!0;break}let a=e?`${e}/${s.name}`:s.name,l=s.isDirectory()?"directory":s.isFile()?"file":"other";if(s.isSymbolicLink())try{let p=await Rt(await qe(r,a));l=p.isDirectory()?"directory":p.isFile()?"file":"other"}catch{}i.push({name:s.name,path:a,kind:l})}return i.sort((s,a)=>+(a.kind==="directory")-+(s.kind==="directory")||Ti.compare(s.name,a.name)||s.name.localeCompare(a.name)),{path:e,entries:i,truncated:n}})}function Ai(r){if(r.subarray(0,8).equals(Buffer.from([137,80,78,71,13,10,26,10])))return"image/png";if(r[0]===255&&r[1]===216&&r[2]===255)return"image/jpeg";if(["GIF87a","GIF89a"].includes(r.subarray(0,6).toString("ascii")))return"image/gif";if(r.subarray(0,4).toString("ascii")==="RIFF"&&r.subarray(8,12).toString("ascii")==="WEBP")return"image/webp"}async function Se(r,e){return Wt(async()=>{let t=await qe(r,e);if(!(await Rt(t)).isFile())throw new j("\u8FD9\u4E0D\u662F\u53EF\u9884\u89C8\u7684\u666E\u901A\u6587\u4EF6");let i=await vi(t,Ke.O_RDONLY|Ke.O_NONBLOCK|(Ke.O_NOFOLLOW??0));try{let n=await i.stat();if(!n.isFile())throw new j("\u8FD9\u4E0D\u662F\u53EF\u9884\u89C8\u7684\u666E\u901A\u6587\u4EF6");let s={path:e,size:n.size},a=Buffer.alloc(16);await i.read(a,0,a.length,0);let l=Ai(a),p=l?_i:Ci;if(n.size>p)return{...s,kind:"too-large",limit:p,unit:"bytes"};let w=Buffer.alloc(Math.min(n.size+1,p+1)),m=0;for(;m<w.length;){let{bytesRead:f}=await i.read(w,m,w.length-m,m);if(!f)break;m+=f}if(m>n.size)throw new j("\u6587\u4EF6\u6B63\u5728\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6",409);let c=w.subarray(0,m);if(l)return{...s,kind:"image",mimeType:l,data:c.toString("base64")};if(c.some(f=>f===0||f<32&&![9,10,12,13,27].includes(f)))return{...s,kind:"unsupported"};let u=1;for(let f=0;f<c.length-1;f++)if(c[f]===10&&++u>At)return{...s,kind:"too-large",limit:At,unit:"lines"};try{return{...s,kind:"text",text:new TextDecoder("utf-8",{fatal:!0}).decode(c)}}catch{return{...s,kind:"unsupported"}}}finally{await i.close()}})}import{execFile as Mi}from"node:child_process";import{realpath as Ri}from"node:fs/promises";import{isAbsolute as Ot,relative as Ni,sep as Wi,win32 as Di}from"node:path";var P=class extends Error{status;reason;constructor(e,t=400,i="git_failed"){super(e),this.name="WorkspaceGitError",this.status=t,this.reason=i}};function T(r,e,t=2*1024*1024,i={}){let n=Object.fromEntries(Object.entries(process.env).filter(([s])=>!s.startsWith("GIT_")));return new Promise((s,a)=>{let l=Mi("git",["--no-pager","--literal-pathspecs","-c","core.fsmonitor=false",...e],{cwd:r,env:{...n,LC_ALL:"C",GIT_OPTIONAL_LOCKS:"0",GIT_TERMINAL_PROMPT:"0",GIT_NO_REPLACE_OBJECTS:"1"},encoding:"utf8",timeout:i.write?3e4:1e4,maxBuffer:t,windowsHide:!0},(p,w,m)=>{if(!p){s(w);return}if(i.write){let u=p.killed||p.code==="ERR_CHILD_PROCESS_STDIO_MAXBUFFER"?"outcome_unknown":/index\.lock|cannot lock ref|could not lock/i.test(m)?"index_locked":/already exists/i.test(m)?"branch_exists":/already checked out|used by worktree/i.test(m)?"branch_in_use":/would be overwritten|local changes/i.test(m)?"dirty_worktree":/identity unknown|unable to auto-detect email|empty ident/i.test(m)?"identity_missing":"git_failed";a(new P("Git \u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u5237\u65B0\u68C0\u67E5\u4ED3\u5E93\u72B6\u6001\u3001\u8EAB\u4EFD\u6216 hooks \u914D\u7F6E",u==="outcome_unknown"?503:409,u));return}let c=p.code;c==="ENOENT"?a(new P("Git \u672A\u5B89\u88C5\u6216\u5DE5\u4F5C\u533A\u4E0D\u53EF\u7528",503)):c==="ERR_CHILD_PROCESS_STDIO_MAXBUFFER"?a(new P("Git \u8F93\u51FA\u8FC7\u5927\uFF0C\u8BF7\u7F29\u5C0F\u8BFB\u53D6\u8303\u56F4",413)):/not a git repository/.test(m)?a(new P("\u5F53\u524D\u76EE\u5F55\u4E0D\u662F Git \u4ED3\u5E93",404)):a(new P(p.killed?"Git \u8BFB\u53D6\u8D85\u65F6\uFF0C\u8BF7\u91CD\u8BD5":"Git \u8BFB\u53D6\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u4ED3\u5E93\u72B6\u6001\u548C\u76EE\u5F55\u6743\u9650",503))});i.input!==void 0&&l.stdin?.end(i.input)})}async function q(r){let e=await Ri(r),t;try{t=(await T(e,["rev-parse","--show-toplevel"])).replace(/\n$/,"")}catch(n){if(n instanceof P&&n.status===404)return{kind:"not-repository"};if(n instanceof P&&n.message==="Git \u672A\u5B89\u88C5\u6216\u5DE5\u4F5C\u533A\u4E0D\u53EF\u7528")return{kind:"unavailable"};throw n}let i=Ni(t,e).split(Wi).join("/");if(i===".."||i.startsWith("../")||Ot(i))throw new P("\u4ED3\u5E93\u4F4D\u4E8E\u5DE5\u4F5C\u533A\u4E4B\u5916",403);return{kind:"repository",cwd:e,root:t,scope:i?`${i}/`:""}}function Q(r){if(typeof r!="string"||!r||r.length>4096||r.includes("\0")||r.includes("\\")||Ot(r)||Di.isAbsolute(r)||r.split("/").some(e=>!e||e==="."||e===".."))throw new P("\u5DE5\u4F5C\u533A\u6587\u4EF6\u8DEF\u5F84\u65E0\u6548",403)}import{createHash as ji}from"node:crypto";import{lstat as Ye,realpath as Gt}from"node:fs/promises";import{dirname as Lt,isAbsolute as $i,relative as Li,resolve as me}from"node:path";import{lstat as Oi}from"node:fs/promises";import{resolve as Fi}from"node:path";var Bi=1e3,Ft=512*1024,Bt=1e4;function jt(r,e){return e.startsWith(r)&&e.slice(r.length)||void 0}async function ae(r){let e=await q(r);if(e.kind!=="repository")return e;let{root:t,scope:i}=e,n=await T(e.cwd,["status","--porcelain=v2","--branch","-z","--untracked-files=all","--","."]),s={kind:"repository",root:t,scope:i,branch:null,head:null,upstream:null,ahead:null,behind:null,entries:[],truncated:!1},a=n.split("\0");for(let l=0;l<a.length;l++){let p=a[l];if(p.startsWith("# branch.oid ")){let C=p.slice(13);s.head=C==="(initial)"?null:C;continue}if(p.startsWith("# branch.head ")){let C=p.slice(14);s.branch=C==="(detached)"?null:C;continue}if(p.startsWith("# branch.upstream ")){s.upstream=p.slice(18);continue}if(p.startsWith("# branch.ab ")){let C=p.match(/\+(\d+) -(\d+)/);C&&(s.ahead=Number(C[1]),s.behind=Number(C[2]));continue}let w=p[0];if(!["1","2","u","?"].includes(w??""))continue;let m=w==="?"?1:w==="1"?8:w==="2"?9:10,c=0;for(let C=0;C<m;C++)c=p.indexOf(" ",c)+1;let u=jt(i,p.slice(c)),f=w==="2"?a[++l]:void 0;if(!u)continue;if(s.entries.length===Bi){s.truncated=!0;continue}let g=p.slice(0,c).split(" "),x={path:u,index:w==="?"?"?":g[1][0],worktree:w==="?"?"?":g[1][1],conflict:w==="u",untracked:w==="?",submodule:w!=="?"&&g[2]!=="N..."},I=f===void 0?void 0:jt(i,f);I&&(x.originalPath=I),s.entries.push(x)}return s}async function $t(r,e,t){if(Q(e),!["staged","unstaged","untracked"].includes(t))throw new P("Git \u5DEE\u5F02\u8303\u56F4\u65E0\u6548");let i=await ae(r);if(i.kind!=="repository")throw new P("\u5F53\u524D\u5DE5\u4F5C\u533A\u6CA1\u6709\u53EF\u8BFB\u53D6\u7684 Git \u4ED3\u5E93",404);let n={path:e,area:t},s=i.entries.find(l=>l.path===e);if(!s)return{...n,kind:"empty"};if(s.conflict)return{...n,kind:"conflict"};if(s.submodule)return{...n,kind:"submodule"};if(t==="untracked"){if(!s.untracked)return{...n,kind:"empty"};if(!(await Oi(Fi(r,e))).isFile())return{...n,kind:"unsupported"};let l=await Se(r,e);if(l.kind==="too-large")return{...n,kind:"too-large"};if(l.kind!=="text")return{...n,kind:"binary"};if(!l.text)return{...n,kind:"empty"};let p=l.text.split(`
|
|
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]="8f4a3bff-f5ed-41fe-801f-ba54d279cfbe",r._sentryDebugIdIdentifier="sentry-dbid-8f4a3bff-f5ed-41fe-801f-ba54d279cfbe")}catch{}})();import{delimiter as go,dirname as ho,join as ze,resolve as vt}from"node:path";import{realpathSync as ti,watch as wo}from"node:fs";import{fileURLToPath as yo}from"node:url";import{DefaultPackageManager as ni,getAgentDir as oe,ModelRuntime as bo,SessionManager as si,SettingsManager as vo,VERSION as He}from"@earendil-works/pi-coding-agent";import{getSupportedThinkingLevels as ko}from"@earendil-works/pi-ai";import{randomBytes as Ir,randomUUID as st,timingSafeEqual as Hn}from"node:crypto";import{readFile as Jn,readdir as Kn}from"node:fs/promises";import{createServer as qn}from"node:http";import{isAbsolute as Xn,join as Cr,relative as Yn}from"node:path";import{mkdir as ui,opendir as fi,stat as mi}from"node:fs/promises";import{homedir as gi}from"node:os";import{basename as hi,dirname as xt,join as Pt,posix as wi,resolve as St,win32 as yi}from"node:path";function It(r){return process.platform==="win32"?yi.isAbsolute(r)&&/^(?:[A-Za-z]:[\\/]|[\\/]{2}[^\\/]+[\\/]+[^\\/]+)/.test(r):wi.isAbsolute(r)}function bi(r,e,t){if(r.length===t&&e.name.localeCompare(r[r.length-1].name)>=0)return!0;let i=0,n=r.length;for(;i<n;){let s=i+n>>>1;e.name.localeCompare(r[s].name)<0?n=s:i=s+1}return r.splice(i,0,e),r.length<=t?!1:(r.pop(),!0)}async function Ct(r){if(r!==void 0&&!It(r))throw new Error("\u76EE\u5F55\u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");let e=gi(),t=St(r??e),i=[];for(let p=t;;p=xt(p)){let w=xt(p);if(i.unshift({name:w===p?p:hi(p),path:p,hidden:!1}),w===p)break}let n=[],s=!1,a=await fi(t);for await(let p of a)!p.isDirectory()&&!p.isSymbolicLink()||bi(n,{name:p.name,isDirectory:p.isDirectory(),isSymbolicLink:p.isSymbolicLink()},1001)&&(s=!0);let l=[];for(let p of n){let w=Pt(t,p.name);if(!p.isDirectory&&p.isSymbolicLink)try{if(!(await mi(w)).isDirectory())continue}catch{continue}if(l.length===1e3){s=!0;break}l.push({name:p.name,path:w,hidden:p.name.startsWith(".")})}return{path:t,home:e,crumbs:i,entries:l,truncated:s}}async function _t(r,e){if(!It(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=Pt(St(r),e);return await ui(t),t}import{constants as Ke}from"node:fs";import{open as vi,opendir as ki,realpath as Tt,stat as Rt}from"node:fs/promises";import{isAbsolute as Nt,relative as Ei,resolve as xi,sep as Pi,win32 as Si}from"node:path";var Ii=1e3,Ci=512*1024,_i=8*1024*1024,At=1e4,Ti=new Intl.Collator("en",{numeric:!0,sensitivity:"base"}),j=class extends Error{status;constructor(e,t=400){super(e),this.name="WorkspaceFileError",this.status=t}};function Mt(r,e){let t=Ei(r,e);return t!==".."&&!t.startsWith(`..${Pi}`)&&!Nt(t)}async function qe(r,e){if(typeof e!="string"||e.length>4096||e.includes("\0")||e.includes("\\")||Nt(e)||Si.isAbsolute(e))throw new j("\u5DE5\u4F5C\u533A\u6587\u4EF6\u8DEF\u5F84\u65E0\u6548");let t=await Tt(r),i=xi(t,e);if(!Mt(t,i))throw new j("\u6587\u4EF6\u4F4D\u4E8E\u5DE5\u4F5C\u533A\u4E4B\u5916",403);let n=await Tt(i);if(!Mt(t,n))throw new j("\u6587\u4EF6\u4F4D\u4E8E\u5DE5\u4F5C\u533A\u4E4B\u5916",403);return n}async function Wt(r){try{return await r()}catch(e){if(e instanceof j)throw e;let t=e.code;throw t==="ENOENT"||t==="ENOTDIR"?new j("\u6587\u4EF6\u6216\u76EE\u5F55\u5DF2\u4E0D\u5B58\u5728",404):t==="EACCES"||t==="EPERM"?new j("\u6CA1\u6709\u6743\u9650\u8BFB\u53D6\u6587\u4EF6\u6216\u76EE\u5F55",403):e}}async function Dt(r,e){return Wt(async()=>{let t=await qe(r,e),i=[],n=!1;for await(let s of await ki(t)){if(i.length===Ii){n=!0;break}let a=e?`${e}/${s.name}`:s.name,l=s.isDirectory()?"directory":s.isFile()?"file":"other";if(s.isSymbolicLink())try{let p=await Rt(await qe(r,a));l=p.isDirectory()?"directory":p.isFile()?"file":"other"}catch{}i.push({name:s.name,path:a,kind:l})}return i.sort((s,a)=>+(a.kind==="directory")-+(s.kind==="directory")||Ti.compare(s.name,a.name)||s.name.localeCompare(a.name)),{path:e,entries:i,truncated:n}})}function Ai(r){if(r.subarray(0,8).equals(Buffer.from([137,80,78,71,13,10,26,10])))return"image/png";if(r[0]===255&&r[1]===216&&r[2]===255)return"image/jpeg";if(["GIF87a","GIF89a"].includes(r.subarray(0,6).toString("ascii")))return"image/gif";if(r.subarray(0,4).toString("ascii")==="RIFF"&&r.subarray(8,12).toString("ascii")==="WEBP")return"image/webp"}async function Se(r,e){return Wt(async()=>{let t=await qe(r,e);if(!(await Rt(t)).isFile())throw new j("\u8FD9\u4E0D\u662F\u53EF\u9884\u89C8\u7684\u666E\u901A\u6587\u4EF6");let i=await vi(t,Ke.O_RDONLY|Ke.O_NONBLOCK|(Ke.O_NOFOLLOW??0));try{let n=await i.stat();if(!n.isFile())throw new j("\u8FD9\u4E0D\u662F\u53EF\u9884\u89C8\u7684\u666E\u901A\u6587\u4EF6");let s={path:e,size:n.size},a=Buffer.alloc(16);await i.read(a,0,a.length,0);let l=Ai(a),p=l?_i:Ci;if(n.size>p)return{...s,kind:"too-large",limit:p,unit:"bytes"};let w=Buffer.alloc(Math.min(n.size+1,p+1)),m=0;for(;m<w.length;){let{bytesRead:u}=await i.read(w,m,w.length-m,m);if(!u)break;m+=u}if(m>n.size)throw new j("\u6587\u4EF6\u6B63\u5728\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6",409);let c=w.subarray(0,m);if(l)return{...s,kind:"image",mimeType:l,data:c.toString("base64")};if(c.some(u=>u===0||u<32&&![9,10,12,13,27].includes(u)))return{...s,kind:"unsupported"};let f=1;for(let u=0;u<c.length-1;u++)if(c[u]===10&&++f>At)return{...s,kind:"too-large",limit:At,unit:"lines"};try{return{...s,kind:"text",text:new TextDecoder("utf-8",{fatal:!0}).decode(c)}}catch{return{...s,kind:"unsupported"}}}finally{await i.close()}})}import{execFile as Mi}from"node:child_process";import{realpath as Ri}from"node:fs/promises";import{isAbsolute as Ot,relative as Ni,sep as Wi,win32 as Di}from"node:path";var P=class extends Error{status;reason;constructor(e,t=400,i="git_failed"){super(e),this.name="WorkspaceGitError",this.status=t,this.reason=i}};function T(r,e,t=2*1024*1024,i={}){let n=Object.fromEntries(Object.entries(process.env).filter(([s])=>!s.startsWith("GIT_")));return new Promise((s,a)=>{let l,p=Mi("git",["--no-pager","--literal-pathspecs","-c","core.fsmonitor=false",...e],{cwd:r,env:{...n,LC_ALL:"C",GIT_OPTIONAL_LOCKS:"0",GIT_TERMINAL_PROMPT:"0",GIT_NO_REPLACE_OBJECTS:"1"},encoding:"utf8",timeout:i.write?3e4:1e4,maxBuffer:t,windowsHide:!0},(w,m,c)=>{if(!w){if(l){a(new P("Git \u8F93\u5165\u4F20\u8F93\u5931\u8D25\uFF0C\u64CD\u4F5C\u7ED3\u679C\u672A\u786E\u8BA4\uFF0C\u8BF7\u5237\u65B0\u68C0\u67E5\u4ED3\u5E93\u72B6\u6001\uFF1B\u4E0D\u8981\u81EA\u52A8\u91CD\u8BD5",503,i.write?"outcome_unknown":"git_failed"));return}s(m);return}if(i.write){let u=w.killed||w.code==="ERR_CHILD_PROCESS_STDIO_MAXBUFFER"?"outcome_unknown":/index\.lock|cannot lock ref|could not lock/i.test(c)?"index_locked":/already exists/i.test(c)?"branch_exists":/already checked out|used by worktree/i.test(c)?"branch_in_use":/would be overwritten|local changes/i.test(c)?"dirty_worktree":/identity unknown|unable to auto-detect email|empty ident/i.test(c)?"identity_missing":"git_failed";a(new P("Git \u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u5237\u65B0\u68C0\u67E5\u4ED3\u5E93\u72B6\u6001\u3001\u8EAB\u4EFD\u6216 hooks \u914D\u7F6E",u==="outcome_unknown"?503:409,u));return}let f=w.code;f==="ENOENT"?a(new P("Git \u672A\u5B89\u88C5\u6216\u5DE5\u4F5C\u533A\u4E0D\u53EF\u7528",503)):f==="ERR_CHILD_PROCESS_STDIO_MAXBUFFER"?a(new P("Git \u8F93\u51FA\u8FC7\u5927\uFF0C\u8BF7\u7F29\u5C0F\u8BFB\u53D6\u8303\u56F4",413)):/not a git repository/.test(c)?a(new P("\u5F53\u524D\u76EE\u5F55\u4E0D\u662F Git \u4ED3\u5E93",404)):a(new P(w.killed?"Git \u8BFB\u53D6\u8D85\u65F6\uFF0C\u8BF7\u91CD\u8BD5":"Git \u8BFB\u53D6\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u4ED3\u5E93\u72B6\u6001\u548C\u76EE\u5F55\u6743\u9650",503))});p.stdin?.on("error",w=>{l=w}),i.input!==void 0&&p.stdin?.end(i.input)})}async function q(r){let e=await Ri(r),t;try{t=(await T(e,["rev-parse","--show-toplevel"])).replace(/\n$/,"")}catch(n){if(n instanceof P&&n.status===404)return{kind:"not-repository"};if(n instanceof P&&n.message==="Git \u672A\u5B89\u88C5\u6216\u5DE5\u4F5C\u533A\u4E0D\u53EF\u7528")return{kind:"unavailable"};throw n}let i=Ni(t,e).split(Wi).join("/");if(i===".."||i.startsWith("../")||Ot(i))throw new P("\u4ED3\u5E93\u4F4D\u4E8E\u5DE5\u4F5C\u533A\u4E4B\u5916",403);return{kind:"repository",cwd:e,root:t,scope:i?`${i}/`:""}}function Q(r){if(typeof r!="string"||!r||r.length>4096||r.includes("\0")||r.includes("\\")||Ot(r)||Di.isAbsolute(r)||r.split("/").some(e=>!e||e==="."||e===".."))throw new P("\u5DE5\u4F5C\u533A\u6587\u4EF6\u8DEF\u5F84\u65E0\u6548",403)}import{createHash as ji}from"node:crypto";import{lstat as Ye,realpath as Gt}from"node:fs/promises";import{dirname as Lt,isAbsolute as $i,relative as Li,resolve as me}from"node:path";import{lstat as Oi}from"node:fs/promises";import{resolve as Fi}from"node:path";var Bi=1e3,Ft=512*1024,Bt=1e4;function jt(r,e){return e.startsWith(r)&&e.slice(r.length)||void 0}async function ae(r){let e=await q(r);if(e.kind!=="repository")return e;let{root:t,scope:i}=e,n=await T(e.cwd,["status","--porcelain=v2","--branch","-z","--untracked-files=all","--","."]),s={kind:"repository",root:t,scope:i,branch:null,head:null,upstream:null,ahead:null,behind:null,entries:[],truncated:!1},a=n.split("\0");for(let l=0;l<a.length;l++){let p=a[l];if(p.startsWith("# branch.oid ")){let C=p.slice(13);s.head=C==="(initial)"?null:C;continue}if(p.startsWith("# branch.head ")){let C=p.slice(14);s.branch=C==="(detached)"?null:C;continue}if(p.startsWith("# branch.upstream ")){s.upstream=p.slice(18);continue}if(p.startsWith("# branch.ab ")){let C=p.match(/\+(\d+) -(\d+)/);C&&(s.ahead=Number(C[1]),s.behind=Number(C[2]));continue}let w=p[0];if(!["1","2","u","?"].includes(w??""))continue;let m=w==="?"?1:w==="1"?8:w==="2"?9:10,c=0;for(let C=0;C<m;C++)c=p.indexOf(" ",c)+1;let f=jt(i,p.slice(c)),u=w==="2"?a[++l]:void 0;if(!f)continue;if(s.entries.length===Bi){s.truncated=!0;continue}let g=p.slice(0,c).split(" "),x={path:f,index:w==="?"?"?":g[1][0],worktree:w==="?"?"?":g[1][1],conflict:w==="u",untracked:w==="?",submodule:w!=="?"&&g[2]!=="N..."},I=u===void 0?void 0:jt(i,u);I&&(x.originalPath=I),s.entries.push(x)}return s}async function $t(r,e,t){if(Q(e),!["staged","unstaged","untracked"].includes(t))throw new P("Git \u5DEE\u5F02\u8303\u56F4\u65E0\u6548");let i=await ae(r);if(i.kind!=="repository")throw new P("\u5F53\u524D\u5DE5\u4F5C\u533A\u6CA1\u6709\u53EF\u8BFB\u53D6\u7684 Git \u4ED3\u5E93",404);let n={path:e,area:t},s=i.entries.find(l=>l.path===e);if(!s)return{...n,kind:"empty"};if(s.conflict)return{...n,kind:"conflict"};if(s.submodule)return{...n,kind:"submodule"};if(t==="untracked"){if(!s.untracked)return{...n,kind:"empty"};if(!(await Oi(Fi(r,e))).isFile())return{...n,kind:"unsupported"};let l=await Se(r,e);if(l.kind==="too-large")return{...n,kind:"too-large"};if(l.kind!=="text")return{...n,kind:"binary"};if(!l.text)return{...n,kind:"empty"};let p=l.text.split(`
|
|
2
2
|
`),w=p.at(-1)==="";w&&p.pop();let m=`--- /dev/null
|
|
3
3
|
+++ b/${e.replace(/[\r\n]/g," ")}
|
|
4
4
|
@@ -0,0 +1,${p.length} @@
|
|
@@ -6,36 +6,36 @@ ${p.map(c=>`+${c}`).join(`
|
|
|
6
6
|
`)}
|
|
7
7
|
${w?"":`\
|
|
8
8
|
`}`;return Buffer.byteLength(m)>Ft||p.length>Bt?{...n,kind:"too-large"}:{...n,kind:"text",patch:m}}if(s.untracked||(t==="staged"?s.index:s.worktree)===".")return{...n,kind:"empty"};let a=t==="staged"&&s.originalPath?[e,s.originalPath]:[e];try{let l=await T(r,["diff","--no-ext-diff","--no-textconv","--no-color","--no-renames","--relative","--src-prefix=a/","--dst-prefix=b/",...t==="staged"?["--cached"]:[],"--",...a],Ft);return l?l.split(`
|
|
9
|
-
`).length>Bt?{...n,kind:"too-large"}:/^Binary files /m.test(l)?{...n,kind:"binary"}:{...n,kind:"text",patch:l}:{...n,kind:"empty"}}catch(l){if(l instanceof P&&l.status===413)return{...n,kind:"too-large"};throw l}}var Xe=new Set,A=(r,e=409)=>{throw new P("Git \u72B6\u6001\u4E0D\u5141\u8BB8\u6B64\u64CD\u4F5C\uFF0C\u8BF7\u5237\u65B0\u540E\u68C0\u67E5",e,r)};async function Gi(r){return Gt(me(r,(await T(r,["rev-parse","--git-common-dir"])).replace(/\n$/,"")))}async function ce(r,e,t=!1){let i=null;try{let n=await q(r);n.kind==="repository"&&(i=await Gi(n.cwd))}catch(n){if(!t)throw n}if(!i)return e();if(Xe.has(i))return A("busy");Xe.add(i);try{return await e()}finally{Xe.delete(i)}}async function Ie(r){let e=await q(r),t={kind:e.kind,root:null,scope:"",head:null,branch:null,version:"",staged:0,dirty:!1,blocked:null,branches:[]};if(e.kind!=="repository")return t;let i=await ae(e.root);if(i.kind!=="repository")return t;let[n,s,a]=await Promise.all([T(e.cwd,["ls-files","--stage","-z"]),T(e.cwd,["for-each-ref","--format=%(refname:short)%00%(objectname)%00%(worktreepath)","refs/heads"]),T(e.cwd,["rev-parse","--absolute-git-dir"])]),l=["MERGE_HEAD","CHERRY_PICK_HEAD","REVERT_HEAD","rebase-merge","rebase-apply","sequencer","BISECT_LOG","index.lock"],p=(await Promise.all(l.map(async
|
|
10
|
-
`).filter(Boolean).map(
|
|
11
|
-
`).filter(Boolean)){let[p,w,m,c,
|
|
12
|
-
`).length>1e4?{...l,kind:"too-large"}:p?{...l,kind:"text",patch:p}:{...l,kind:"empty"}}catch(p){if(p instanceof P&&p.status===413)return{...l,kind:"too-large"};throw p}}var Ze=["/api/workspace/git/control","/api/workspace/git/write","/api/workspace/git/status","/api/workspace/git/diff","/api/workspace/git/history","/api/workspace/git/commit-detail","/api/workspace/git/commit-diff"];function er(r,e,t){if(r.endsWith("/control"))return Ie(e);if(r.endsWith("/status"))return ae(e);if(r.endsWith("/history")){if(t.limit!==void 0&&typeof t.limit!="number"||t.cursor!==void 0&&typeof t.cursor!="string")throw new P("\u5386\u53F2\u5206\u9875\u53C2\u6570\u65E0\u6548");return Kt(e,{limit:t.limit,cursor:t.cursor})}if(r.endsWith("/diff")){if(typeof t.path!="string"||!["staged","unstaged","untracked"].includes(t.area))throw new P("Git \u5DEE\u5F02\u53C2\u6570\u65E0\u6548");return $t(e,t.path,t.area)}if(typeof t.hash!="string"||t.parentIndex!==void 0&&(!Number.isInteger(t.parentIndex)||t.parentIndex<0))throw new P("\u63D0\u4EA4\u53C2\u6570\u65E0\u6548");let i=t.parentIndex;if(r.endsWith("/commit-detail"))return Zt(e,t.hash,i);if(r.endsWith("/commit-diff")&&typeof t.path=="string")return Qt(e,t.hash,t.path,i);throw new P("Git \u5DEE\u5F02\u53C2\u6570\u65E0\u6548")}import{execFile as zi}from"node:child_process";import{accessSync as Hi,constants as Ji}from"node:fs";import{delimiter as Ki,join as qi}from"node:path";var Xi=(r,e,t)=>new Promise((i,n)=>{zi(r,[...e],{encoding:"utf8",signal:t,windowsHide:!0},(s,a,l)=>{s?n(Object.assign(new Error(s.message,{cause:s}),{code:s.code,stdout:a,stderr:l})):i({stdout:a,stderr:l})})});function Yi(r){for(let e of(r??"").split(Ki))if(e)for(let t of["zenity","kdialog"])try{return Hi(qi(e,t),Ji.X_OK),!0}catch{}return!1}function tr(r=process.platform,e=process.env){return e.SSH_CONNECTION||e.SSH_TTY?"browse":r==="darwin"||r==="linux"&&(e.DISPLAY||e.WAYLAND_DISPLAY)&&Yi(e.PATH)?"native":"browse"}function Ce(r){if(!(typeof r!="object"||r===null||!("code"in r)))return typeof r.code=="string"||typeof r.code=="number"?r.code:void 0}function Zi(r){return typeof r=="object"&&r!==null&&"stderr"in r&&typeof r.stderr=="string"?r.stderr:""}function Qe(r){return r.replace(/[\r\n]+$/,"")||null}async function rr(r,e=process.platform,t=Xi){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 Qe(i.stdout)}catch(i){if(!r.aborted&&Ce(i)===1&&/(?:User canceled|-128)/i.test(Zi(i)))return null;throw i}if(e==="linux"){try{return Qe((await t("zenity",["--file-selection","--directory","--title=Select Workspace Directory"],r)).stdout)}catch(i){if(r.aborted)throw i;if(Ce(i)===1)return null;if(Ce(i)!=="ENOENT")throw i}try{return Qe((await t("kdialog",["--getexistingdirectory",".","--title","Select Workspace Directory"],r)).stdout)}catch(i){if(r.aborted)throw i;if(Ce(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 Qi,randomUUID as en}from"node:crypto";import{mkdir as tn,readFile as rn,writeFile as nn}from"node:fs/promises";import{join as ir}from"node:path";import{getAgentDir as sn}from"@earendil-works/pi-coding-agent";var _e=20*1024*1024,nr=20,on=/^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])$/iu;function an(r){let e=r.indexOf("."),t=(e<0?r:r.slice(0,e)).replace(/[. ]+$/u,"");return on.test(t)}function cn(r,e){let t=0,i="";for(let n of Buffer.from(r).toString("utf8")){let s=Buffer.byteLength(n);if(t+s>e)break;i+=n,t+=s}return i}function ln(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 an(t)&&(t=`_${t}`),t=cn(t,255).replace(/[. ]+$/u,""),t===""||t==="."||t===".."?"file":t}function dn(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 sr(r,e,t,i){if(i.byteLength===0||i.byteLength>_e)throw new Error("\u6587\u4EF6\u4E3A\u7A7A\u6216\u8D85\u8FC7 20 MB");let n=ln(e),s=Qi("sha256").update(i).digest("hex"),a=ir(sn(),"pi-web","attachments",s);await tn(a,{recursive:!0});let l=ir(a,n);try{await nn(l,i,{flag:"wx",mode:384})}catch(p){if(!(p instanceof Error&&"code"in p&&p.code==="EEXIST"))throw p}return{id:en(),name:n,bytes:i.byteLength,path:l,mediaType:dn(i)??t.replace(/^image\//,"application/"),sessionId:r}}async function or(r){return{type:"image",data:(await rn(r.path)).toString("base64"),mimeType:r.mediaType}}import{randomBytes as pn}from"node:crypto";function ar(r,e,t){return r!=="openai-codex"||e!=="oauth"?t:{...t,prompt:i=>i.type==="select"&&i.options.some(n=>n.id==="browser")&&i.options.some(n=>n.id==="device_code")?Promise.resolve("browser"):t.prompt(i)}}var Te=class{flows=new Map;reportError;constructor(e=()=>{}){this.reportError=e}start(e,t,i,n,s){let a=this.getActive();if(a){if(a.providerId===e&&a.method===t&&n===void 0)return a;throw new Error("\u5176\u4ED6\u63D0\u4F9B\u65B9\u7684\u767B\u5F55\u6B63\u5728\u8FDB\u884C\uFF0C\u8BF7\u5148\u5B8C\u6210\u6216\u53D6\u6D88\u5F53\u524D\u767B\u5F55")}this.flows.clear();let l=pn(18).toString("base64url"),p={view:{id:l,providerId:e,method:t,status:"running"},controller:new AbortController};return this.flows.set(l,p),i(e,t,{signal:p.controller.signal,notify:w=>{p.view={...p.view,event:w,...w.type==="auth_url"||w.type==="device_code"?{authorization:w}:{}}},prompt:w=>{if(w.type==="secret"&&n!==void 0){let m=n;return n=void 0,Promise.resolve(m)}return new Promise((m,c)=>{let{signal:u
|
|
9
|
+
`).length>Bt?{...n,kind:"too-large"}:/^Binary files /m.test(l)?{...n,kind:"binary"}:{...n,kind:"text",patch:l}:{...n,kind:"empty"}}catch(l){if(l instanceof P&&l.status===413)return{...n,kind:"too-large"};throw l}}var Xe=new Set,A=(r,e=409)=>{throw new P("Git \u72B6\u6001\u4E0D\u5141\u8BB8\u6B64\u64CD\u4F5C\uFF0C\u8BF7\u5237\u65B0\u540E\u68C0\u67E5",e,r)};async function Gi(r){return Gt(me(r,(await T(r,["rev-parse","--git-common-dir"])).replace(/\n$/,"")))}async function ce(r,e,t=!1){let i=null;try{let n=await q(r);n.kind==="repository"&&(i=await Gi(n.cwd))}catch(n){if(!t)throw n}if(!i)return e();if(Xe.has(i))return A("busy");Xe.add(i);try{return await e()}finally{Xe.delete(i)}}async function Ie(r){let e=await q(r),t={kind:e.kind,root:null,scope:"",head:null,branch:null,version:"",staged:0,dirty:!1,blocked:null,branches:[]};if(e.kind!=="repository")return t;let i=await ae(e.root);if(i.kind!=="repository")return t;let[n,s,a]=await Promise.all([T(e.cwd,["ls-files","--stage","-z"]),T(e.cwd,["for-each-ref","--format=%(refname:short)%00%(objectname)%00%(worktreepath)","refs/heads"]),T(e.cwd,["rev-parse","--absolute-git-dir"])]),l=["MERGE_HEAD","CHERRY_PICK_HEAD","REVERT_HEAD","rebase-merge","rebase-apply","sequencer","BISECT_LOG","index.lock"],p=(await Promise.all(l.map(async u=>{try{return await Ye(me(a.replace(/\n$/,""),u)),u}catch(g){if(g.code==="ENOENT")return null;throw g}}))).filter(Boolean),w=await Promise.all(i.entries.map(async u=>{try{let g=await Ye(me(e.root,u.path));return[u.path,g.size,g.mtimeMs,g.ctimeMs,g.ino,g.mode]}catch(g){if(["ENOENT","ENOTDIR"].includes(g.code??""))return[u.path,"missing"];throw g}})),m=s.split(`
|
|
10
|
+
`).filter(Boolean).map(u=>{let[g,,x]=u.split("\0");return{name:g,current:g===i.branch,occupied:!!x&&g!==i.branch}}),c=i.truncated||m.length>512?"too_many_changes":p.includes("index.lock")?"index_locked":p.length||i.entries.some(u=>u.conflict)?"operation_in_progress":null,f=ji("sha256").update(JSON.stringify({head:i.head,branch:i.branch,index:n,refs:s,entries:i.entries,files:w,present:p})).digest("hex");return{kind:"repository",root:e.root,scope:e.scope,head:i.head,branch:i.branch,version:f,staged:i.entries.filter(u=>!u.untracked&&u.index!==".").length,dirty:i.entries.length>0,blocked:c,branches:m.slice(0,512)}}async function Vi(r,e){Q(e);let t=Lt(me(r.cwd,e));for(;;)try{let s=await Gt(t),a=Li(r.cwd,s);if(a===".."||a.startsWith(`..${process.platform==="win32"?"\\":"/"}`)||$i(a))return A("invalid_path",403);break}catch(s){if(s.code!=="ENOENT")throw s;t=Lt(t)}let i=await ae(r.cwd),n=i.kind==="repository"?i.entries.find(s=>s.path===e):void 0;if(!n||n.submodule||n.conflict)return A("invalid_path",400);try{let s=await Ye(me(r.cwd,e));if(!s.isFile()&&!s.isSymbolicLink())return A("invalid_path",400)}catch(s){if(s.code!=="ENOENT")throw s}return n}async function Vt(r,e,t){let i=e.action;if(!["stage","unstage","commit","create-branch","switch-branch"].includes(i)||typeof e.expected!="string"||!/^[a-f0-9]{64}$/.test(e.expected))throw new P("Git \u64CD\u4F5C\u53C2\u6570\u65E0\u6548");return ce(r,async()=>{let n=await q(r);if(n.kind!=="repository")return A("invalid_path",404);t(n.root);let s=await Ie(n.cwd);if(s.version!==e.expected)return A("state_changed");if(s.blocked)return A(s.blocked);let a,l;if(i==="stage"||i==="unstage"){if(typeof e.path!="string")return A("invalid_path",400);let m=await Vi(n,e.path);if(i==="stage"&&!m.untracked&&m.worktree==="."||i==="unstage"&&(m.untracked||m.index==="."))return A("state_changed");let c=[e.path];i==="unstage"&&m.originalPath&&(Q(m.originalPath),c.push(m.originalPath)),a=i==="stage"?["add","--",...c]:s.head?["restore","--staged","--",...c]:["rm","--cached","-f","--ignore-unmatch","--",...c]}else if(i==="commit"){if(n.scope)return A("root_required",400);if(typeof e.message!="string"||!e.message.trim()||e.message.includes("\0")||Buffer.byteLength(e.message)>8192)return A("invalid_message",400);if(!s.staged)return A("nothing_staged",400);l=e.message,a=["commit","--file=-","--cleanup=verbatim"]}else{if(!s.head)return A("no_commits",400);if(typeof e.branch!="string"||!e.branch||e.branch.length>256||e.branch.startsWith("-")||e.branch.startsWith("refs/")||["HEAD","@"].includes(e.branch)||/[\0\r\n]|@\{/.test(e.branch))return A("invalid_branch",400);try{await T(n.cwd,["check-ref-format","--branch",e.branch])}catch{return A("invalid_branch",400)}if(e.checkout!==void 0&&typeof e.checkout!="boolean")return A("invalid_branch",400);let m=s.branches.find(f=>f.name===e.branch),c=i==="switch-branch"||e.checkout===!0;if(i==="create-branch"&&m)return A("branch_exists");if(i==="switch-branch"&&(!m||m.current))return A("invalid_branch",400);if(c&&n.scope)return A("root_required",400);if(c&&s.dirty)return A("dirty_worktree");if(m?.occupied)return A("branch_in_use");a=i==="switch-branch"?["switch","--no-guess","--no-overwrite-ignore","--",e.branch]:c?["switch","--no-guess","--no-overwrite-ignore","-c",e.branch,"--","HEAD"]:["branch","--",e.branch,"HEAD"]}let p=await Ie(n.cwd);if(p.version!==e.expected||p.blocked)return A(p.blocked??"state_changed");t(n.root),await T(n.cwd,a,2*1024*1024,{write:!0,input:l});let w=(await T(n.cwd,["rev-parse","--verify","--quiet","HEAD"]).catch(()=>"")).trim()||null;return{action:i,head:w}})}import{createHash as Ui}from"node:crypto";var ge=/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/,Ut="%H%x00%P%x00%an%x00%aI%x00%s",zt=["--no-ext-diff","--no-textconv","--no-renames","--no-color","--relative"];async function Ht(r){let[e,t,i]=await Promise.all([T(r,["for-each-ref","--format=%(refname)%00%(objecttype)%00%(objectname)%00%(*objecttype)%00%(*objectname)","refs/heads","refs/remotes","refs/tags"]),T(r,["rev-parse","--verify","--quiet","HEAD"]).then(l=>l.trim(),()=>null),T(r,["symbolic-ref","-q","HEAD"]).then(l=>l.trim(),()=>null)]),n=[];for(let l of e.split(`
|
|
11
|
+
`).filter(Boolean)){let[p,w,m,c,f]=l.split("\0"),u=w==="commit"?m:c==="commit"?f:void 0;if(!u||!ge.test(u))continue;let g=p.startsWith("refs/heads/")?"branch":p.startsWith("refs/remotes/")?"remote":"tag";n.push({name:p.replace(/^refs\/(?:heads|remotes|tags)\//,""),hash:u,kind:g})}if(n.length>512)throw new P("\u4ED3\u5E93\u5F15\u7528\u8FC7\u591A\uFF0C\u6682\u4E0D\u652F\u6301\u8BFB\u53D6\u5386\u53F2",413);let s=[...new Set([...n.map(l=>l.hash),...t&&ge.test(t)?[t]:[]])].sort(),a=Ui("sha256").update(JSON.stringify({refs:n,head:t,symbolic:i})).digest("hex");return{refs:n,tips:s,head:t,snapshot:a}}function Jt(r){let[e,t,i,n,s]=r;if(!e||!ge.test(e)||!t?.split(" ").filter(Boolean).every(a=>ge.test(a)))throw new P("\u63D0\u4EA4\u683C\u5F0F\u65E0\u6548",422);return{hash:e,parents:t.split(" ").filter(Boolean),author:i,authoredAt:n,subject:s}}async function Kt(r,e={}){let t=e.limit??50;if(!Number.isInteger(t)||t<1||t>100||e.cursor!==void 0&&(typeof e.cursor!="string"||e.cursor.length>256))throw new P("\u5386\u53F2\u5206\u9875\u53C2\u6570\u65E0\u6548");let i=await q(r),n={kind:i.kind,root:null,scope:"",head:null,snapshot:"",refs:[],commits:[],nextCursor:null};if(i.kind!=="repository")return n;let s=await Ht(i.cwd),a=0;if(e.cursor!==void 0){let c;try{c=JSON.parse(Buffer.from(e.cursor,"base64url").toString("utf8"))}catch{throw new P("\u5386\u53F2\u5206\u9875\u53C2\u6570\u65E0\u6548")}if(!c||typeof c.snapshot!="string"||!/^[a-f0-9]{64}$/.test(c.snapshot)||!Number.isInteger(c.offset)||c.offset<1||c.offset>1e4)throw new P("\u5386\u53F2\u5206\u9875\u53C2\u6570\u65E0\u6548");if(c.snapshot!==s.snapshot)throw new P("\u4ED3\u5E93\u5F15\u7528\u5DF2\u53D8\u5316\uFF0C\u8BF7\u5237\u65B0\u5386\u53F2",409);a=c.offset}let l={...n,root:i.root,scope:i.scope,head:s.head,snapshot:s.snapshot,refs:s.refs};if(!s.tips.length)return l;let w=(await T(i.cwd,["log","--no-notes","--no-show-signature","--encoding=UTF-8","--topo-order","-z",`--format=${Ut}`,`--max-count=${t+1}`,`--skip=${a}`,...s.tips,"--"])).split("\0");if(w.at(-1)===""&&w.pop(),w.length%5)throw new P("\u63D0\u4EA4\u683C\u5F0F\u65E0\u6548",422);let m=[];for(let c=0;c<w.length;c+=5)m.push(Jt(w.slice(c,c+5)));return l.commits=m.slice(0,t),m.length>t&&a+t<=1e4&&(l.nextCursor=Buffer.from(JSON.stringify({snapshot:s.snapshot,offset:a+t})).toString("base64url")),l}async function qt(r,e){if(typeof e!="string"||!ge.test(e))throw new P("\u63D0\u4EA4\u6807\u8BC6\u65E0\u6548");let t=await q(r);if(t.kind!=="repository")throw new P("\u5F53\u524D\u5DE5\u4F5C\u533A\u6CA1\u6709\u53EF\u8BFB\u53D6\u7684 Git \u4ED3\u5E93",404);let i=await Ht(t.cwd);if(!i.tips.length)throw new P("\u63D0\u4EA4\u4E0D\u5B58\u5728\u6216\u5DF2\u4E0D\u53EF\u8FBE",404);if((await T(t.cwd,["cat-file","-t",e]).catch(()=>"")).trim()!=="commit"||(await T(t.cwd,["rev-list","--max-count=1",e,"--not",...i.tips,"--"])).trim())throw new P("\u63D0\u4EA4\u4E0D\u5B58\u5728\u6216\u5DF2\u4E0D\u53EF\u8FBE",404);return t}function Xt(r,e,t){if(!Number.isInteger(t)||t<0||t>=Math.max(1,e.length))throw new P("\u7236\u63D0\u4EA4\u9009\u62E9\u65E0\u6548");return e.length?[e[t],r]:[r]}async function Yt(r,e,t){let n=(await T(r.cwd,["show","-s","--no-notes","--no-show-signature","--encoding=UTF-8","-z",`--format=${Ut}%x00%ae%x00%cn%x00%ce%x00%cI%x00%B`,e,"--"],262144)).split("\0");if(n.at(-1)===""&&n.pop(),n.length!==10)throw new P("\u63D0\u4EA4\u683C\u5F0F\u65E0\u6548",422);let s=Jt(n.slice(0,5)),a=Xt(e,s.parents,t),l=["diff-tree","--root","-r","--no-commit-id",...zt],[p,w]=await Promise.all([T(r.cwd,[...l,"--name-status","-z",...a,"--","."]),T(r.cwd,[...l,"--numstat","-z",...a,"--","."])]),m=new Map;for(let u of w.split("\0").filter(Boolean)){let g=u.match(/^(\d+|-)\t(\d+|-)\t([\s\S]+)$/);g&&m.set(g[3],[g[1]==="-"?null:Number(g[1]),g[2]==="-"?null:Number(g[2])])}let c=p.split("\0");if(c.at(-1)===""&&c.pop(),c.length%2)throw new P("\u63D0\u4EA4\u6587\u4EF6\u683C\u5F0F\u65E0\u6548",422);let f=[];for(let u=0;u<c.length&&f.length<1e3;u+=2){let g=c[u+1],[x,I]=m.get(g)??[null,null];f.push({path:g,status:c[u],additions:x,deletions:I})}return{...s,email:n[5],committer:n[6],committerEmail:n[7],committedAt:n[8],message:n[9],root:r.root,scope:r.scope,parentIndex:t,files:f,truncated:c.length>2e3}}async function Zt(r,e,t=0){return Yt(await qt(r,e),e,t)}async function Qt(r,e,t,i=0){Q(t);let n=await qt(r,e),s=await Yt(n,e,i),a=s.files.find(p=>p.path===t);if(!a)throw new P("\u6587\u4EF6\u4E0D\u5728\u5F53\u524D\u76EE\u5F55\u7684\u63D0\u4EA4\u6539\u52A8\u4E2D",404);let l={hash:e,path:t,parentIndex:i,parentHash:s.parents[i]??null};if(a.additions===null)return{...l,kind:"binary"};try{let p=await T(n.cwd,["diff-tree","--root","-r","--no-commit-id",...zt,"--src-prefix=a/","--dst-prefix=b/","-p",...Xt(e,s.parents,i),"--",t],524288);return p.split(`
|
|
12
|
+
`).length>1e4?{...l,kind:"too-large"}:p?{...l,kind:"text",patch:p}:{...l,kind:"empty"}}catch(p){if(p instanceof P&&p.status===413)return{...l,kind:"too-large"};throw p}}var Ze=["/api/workspace/git/control","/api/workspace/git/write","/api/workspace/git/status","/api/workspace/git/diff","/api/workspace/git/history","/api/workspace/git/commit-detail","/api/workspace/git/commit-diff"];function er(r,e,t){if(r.endsWith("/control"))return Ie(e);if(r.endsWith("/status"))return ae(e);if(r.endsWith("/history")){if(t.limit!==void 0&&typeof t.limit!="number"||t.cursor!==void 0&&typeof t.cursor!="string")throw new P("\u5386\u53F2\u5206\u9875\u53C2\u6570\u65E0\u6548");return Kt(e,{limit:t.limit,cursor:t.cursor})}if(r.endsWith("/diff")){if(typeof t.path!="string"||!["staged","unstaged","untracked"].includes(t.area))throw new P("Git \u5DEE\u5F02\u53C2\u6570\u65E0\u6548");return $t(e,t.path,t.area)}if(typeof t.hash!="string"||t.parentIndex!==void 0&&(!Number.isInteger(t.parentIndex)||t.parentIndex<0))throw new P("\u63D0\u4EA4\u53C2\u6570\u65E0\u6548");let i=t.parentIndex;if(r.endsWith("/commit-detail"))return Zt(e,t.hash,i);if(r.endsWith("/commit-diff")&&typeof t.path=="string")return Qt(e,t.hash,t.path,i);throw new P("Git \u5DEE\u5F02\u53C2\u6570\u65E0\u6548")}import{execFile as zi}from"node:child_process";import{accessSync as Hi,constants as Ji}from"node:fs";import{delimiter as Ki,join as qi}from"node:path";var Xi=(r,e,t)=>new Promise((i,n)=>{zi(r,[...e],{encoding:"utf8",signal:t,windowsHide:!0},(s,a,l)=>{s?n(Object.assign(new Error(s.message,{cause:s}),{code:s.code,stdout:a,stderr:l})):i({stdout:a,stderr:l})})});function Yi(r){for(let e of(r??"").split(Ki))if(e)for(let t of["zenity","kdialog"])try{return Hi(qi(e,t),Ji.X_OK),!0}catch{}return!1}function tr(r=process.platform,e=process.env){return e.SSH_CONNECTION||e.SSH_TTY?"browse":r==="darwin"||r==="linux"&&(e.DISPLAY||e.WAYLAND_DISPLAY)&&Yi(e.PATH)?"native":"browse"}function Ce(r){if(!(typeof r!="object"||r===null||!("code"in r)))return typeof r.code=="string"||typeof r.code=="number"?r.code:void 0}function Zi(r){return typeof r=="object"&&r!==null&&"stderr"in r&&typeof r.stderr=="string"?r.stderr:""}function Qe(r){return r.replace(/[\r\n]+$/,"")||null}async function rr(r,e=process.platform,t=Xi){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 Qe(i.stdout)}catch(i){if(!r.aborted&&Ce(i)===1&&/(?:User canceled|-128)/i.test(Zi(i)))return null;throw i}if(e==="linux"){try{return Qe((await t("zenity",["--file-selection","--directory","--title=Select Workspace Directory"],r)).stdout)}catch(i){if(r.aborted)throw i;if(Ce(i)===1)return null;if(Ce(i)!=="ENOENT")throw i}try{return Qe((await t("kdialog",["--getexistingdirectory",".","--title","Select Workspace Directory"],r)).stdout)}catch(i){if(r.aborted)throw i;if(Ce(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 Qi,randomUUID as en}from"node:crypto";import{mkdir as tn,readFile as rn,writeFile as nn}from"node:fs/promises";import{join as ir}from"node:path";import{getAgentDir as sn}from"@earendil-works/pi-coding-agent";var _e=20*1024*1024,nr=20,on=/^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])$/iu;function an(r){let e=r.indexOf("."),t=(e<0?r:r.slice(0,e)).replace(/[. ]+$/u,"");return on.test(t)}function cn(r,e){let t=0,i="";for(let n of Buffer.from(r).toString("utf8")){let s=Buffer.byteLength(n);if(t+s>e)break;i+=n,t+=s}return i}function ln(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 an(t)&&(t=`_${t}`),t=cn(t,255).replace(/[. ]+$/u,""),t===""||t==="."||t===".."?"file":t}function dn(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 sr(r,e,t,i){if(i.byteLength===0||i.byteLength>_e)throw new Error("\u6587\u4EF6\u4E3A\u7A7A\u6216\u8D85\u8FC7 20 MB");let n=ln(e),s=Qi("sha256").update(i).digest("hex"),a=ir(sn(),"pi-web","attachments",s);await tn(a,{recursive:!0});let l=ir(a,n);try{await nn(l,i,{flag:"wx",mode:384})}catch(p){if(!(p instanceof Error&&"code"in p&&p.code==="EEXIST"))throw p}return{id:en(),name:n,bytes:i.byteLength,path:l,mediaType:dn(i)??t.replace(/^image\//,"application/"),sessionId:r}}async function or(r){return{type:"image",data:(await rn(r.path)).toString("base64"),mimeType:r.mediaType}}import{randomBytes as pn}from"node:crypto";function ar(r,e,t){return r!=="openai-codex"||e!=="oauth"?t:{...t,prompt:i=>i.type==="select"&&i.options.some(n=>n.id==="browser")&&i.options.some(n=>n.id==="device_code")?Promise.resolve("browser"):t.prompt(i)}}var Te=class{flows=new Map;reportError;constructor(e=()=>{}){this.reportError=e}start(e,t,i,n,s){let a=this.getActive();if(a){if(a.providerId===e&&a.method===t&&n===void 0)return a;throw new Error("\u5176\u4ED6\u63D0\u4F9B\u65B9\u7684\u767B\u5F55\u6B63\u5728\u8FDB\u884C\uFF0C\u8BF7\u5148\u5B8C\u6210\u6216\u53D6\u6D88\u5F53\u524D\u767B\u5F55")}this.flows.clear();let l=pn(18).toString("base64url"),p={view:{id:l,providerId:e,method:t,status:"running"},controller:new AbortController};return this.flows.set(l,p),i(e,t,{signal:p.controller.signal,notify:w=>{p.view={...p.view,event:w,...w.type==="auth_url"||w.type==="device_code"?{authorization:w}:{}}},prompt:w=>{if(w.type==="secret"&&n!==void 0){let m=n;return n=void 0,Promise.resolve(m)}return new Promise((m,c)=>{let{signal:f,...u}=w;p.answer=m,p.reject=c,p.view={...p.view,status:"waiting",prompt:u},f?.aborted?c(new Error("\u767B\u5F55\u8F93\u5165\u5DF2\u53D6\u6D88")):f?.addEventListener("abort",()=>c(new Error("\u767B\u5F55\u8F93\u5165\u5DF2\u53D6\u6D88")),{once:!0})})}}).then(()=>{p.view.status!=="cancelled"&&(p.view={id:l,providerId:e,method:t,status:"done"})}).catch(w=>{if(p.view.status!=="cancelled"){let m=new Error("Provider login failed");w instanceof Error&&w.stack&&(m.stack=`${m.message}
|
|
13
13
|
${w.stack.split(`
|
|
14
14
|
`).slice(1).join(`
|
|
15
15
|
`)}`);let c=this.reportError(m,{...s,stage:"provider_login"});p.view={id:l,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:c}}}),{...p.view}}get(e){let t=this.flows.get(e)?.view;return t?{...t}:void 0}getActive(){let e=[...this.flows.values()].find(({view:t})=>t.status==="running"||t.status==="waiting")?.view;return e?{...e}:void 0}respond(e,t){let i=this.flows.get(e);if(!i?.answer||i.view.status!=="waiting"||i.view.prompt?.type==="select"&&!i.view.prompt.options.some(s=>s.id===t))return!1;let n=i.answer;return i.answer=void 0,i.reject=void 0,i.view={...i.view,status:"running",prompt:void 0},n(t),!0}cancel(e){let t=this.flows.get(e);return!t||t.view.status==="done"||t.view.status==="error"?!1:(t.view={...t.view,status:"cancelled",prompt:void 0},t.controller.abort(),t.reject?.(new Error("\u767B\u5F55\u5DF2\u53D6\u6D88")),t.answer=void 0,t.reject=void 0,!0)}close(){for(let e of this.flows.keys())this.cancel(e);this.flows.clear()}};import{randomBytes as un}from"node:crypto";import{readFile as fn,rename as mn,rm as gn,stat as hn,writeFile as wn,mkdir as yn}from"node:fs/promises";import{dirname as bn}from"node:path";var vn=["openai-completions","openai-responses","anthropic-messages"];function et(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||!vn.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 cr(r,e){if(!et(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 fn(r,"utf8")}catch(l){if(l.code!=="ENOENT")throw l}let i;if(t===void 0)i={providers:{}};else{try{i=JSON.parse(t)}catch{throw new Error("models.json \u542B\u6CE8\u91CA\u6216\u683C\u5F0F\u9519\u8BEF\uFF0C\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u624B\u52A8\u6DFB\u52A0\u63D0\u4F9B\u65B9")}if(!i||typeof i!="object"||!i.providers||typeof i.providers!="object"||Array.isArray(i.providers))throw new Error("models.json \u7ED3\u6784\u65E0\u6548")}if(Object.hasOwn(i.providers,e.id))throw new Error("\u63D0\u4F9B\u65B9\u5DF2\u5B58\u5728");let n={...i,providers:{...i.providers,[e.id]:{name:e.name.trim(),baseUrl:e.baseUrl,api:e.api,models:[{id:e.modelId.trim()}]}}};await yn(bn(r),{recursive:!0});let s=t===void 0?384:(await hn(r)).mode&511,a=`${r}.pi-web-${un(6).toString("hex")}.tmp`;try{await wn(a,`${JSON.stringify(n,null,2)}
|
|
16
16
|
`,{mode:s,flag:"wx"}),await mn(a,r)}finally{await gn(a,{force:!0})}}import{randomBytes as kn}from"node:crypto";import{mkdir as En,readFile as xn,rename as Pn,rm as Sn,stat as In,writeFile as Cn}from"node:fs/promises";import{dirname as _n}from"node:path";function lr(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 dr(r){if(!r||typeof r!="object")return!1;let e=r;return e.action==="save"?(e.originalId===void 0||typeof e.originalId=="string")&&pr(e.model):e.action==="base_url"?e.baseUrl===null||typeof e.baseUrl=="string"&&lr(e.baseUrl):e.action==="remove"&&typeof e.id=="string"&&e.id.length>0&&e.id.length<=200}function pr(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 ur(r){let e;try{e=await xn(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 Tn(r,e,t){await En(_n(r),{recursive:!0});let i=t===void 0?384:(await In(r)).mode&511,n=`${r}.pi-web-${kn(6).toString("hex")}.tmp`;try{await Cn(n,`${JSON.stringify(e,null,2)}
|
|
17
|
-
`,{mode:i,flag:"wx"}),await Pn(n,r)}finally{await Sn(n,{force:!0})}}async function fr(r,e,t){if(!t.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:i}=await ur(r),n=i.providers[e],s=new Set(n?.models?.map(a=>a.id)??[]);return{providerId:e,baseUrl:n?.baseUrl,models:t.getModels(e).map(a=>({id:a.id,name:a.name,contextWindow:a.contextWindow,maxTokens:a.maxTokens,input:[...a.input],source:s.has(a.id)?"custom":"builtin",overridden:!!n?.modelOverrides?.[a.id]}))}}async function mr(r,e,t,i){if(!i.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:n,existing:s}=await ur(r),a={...n.providers[e]??{}},l=[...a.models??[]],p={...a.modelOverrides??{}};if(t.action==="base_url"){if(t.baseUrl!==null&&!lr(t.baseUrl))throw new Error("API \u5730\u5740\u65E0\u6548");t.baseUrl===null?delete a.baseUrl:a.baseUrl=t.baseUrl}else if(t.action==="save"){if(!pr(t.model))throw new Error("\u6A21\u578B\u53C2\u6570\u65E0\u6548");let w={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}},m=t.originalId,c=m===void 0?-1:l.findIndex(
|
|
17
|
+
`,{mode:i,flag:"wx"}),await Pn(n,r)}finally{await Sn(n,{force:!0})}}async function fr(r,e,t){if(!t.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:i}=await ur(r),n=i.providers[e],s=new Set(n?.models?.map(a=>a.id)??[]);return{providerId:e,baseUrl:n?.baseUrl,models:t.getModels(e).map(a=>({id:a.id,name:a.name,contextWindow:a.contextWindow,maxTokens:a.maxTokens,input:[...a.input],source:s.has(a.id)?"custom":"builtin",overridden:!!n?.modelOverrides?.[a.id]}))}}async function mr(r,e,t,i){if(!i.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:n,existing:s}=await ur(r),a={...n.providers[e]??{}},l=[...a.models??[]],p={...a.modelOverrides??{}};if(t.action==="base_url"){if(t.baseUrl!==null&&!lr(t.baseUrl))throw new Error("API \u5730\u5740\u65E0\u6548");t.baseUrl===null?delete a.baseUrl:a.baseUrl=t.baseUrl}else if(t.action==="save"){if(!pr(t.model))throw new Error("\u6A21\u578B\u53C2\u6570\u65E0\u6548");let w={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}},m=t.originalId,c=m===void 0?-1:l.findIndex(f=>f.id===m);if(m===void 0&&(l.some(f=>f.id===w.id)||i.getModel(e,w.id)))throw new Error("\u6A21\u578B ID \u5DF2\u5B58\u5728");if(c>=0){if(w.id!==m&&(l.some(u=>u.id===w.id)||i.getModel(e,w.id)))throw new Error("\u6A21\u578B ID \u5DF2\u5B58\u5728");let f={...l[c],...w};for(let u of["name","contextWindow","maxTokens","input"])w[u]===void 0&&delete f[u];l[c]=f}else if(m!==void 0&&i.getModel(e,m)){if(w.id!==m)throw new Error("\u5185\u7F6E\u6A21\u578B ID \u4E0D\u53EF\u4FEE\u6539");let{id:f,...u}=w;p[m]={...p[m],...u};for(let g of["name","contextWindow","maxTokens","input"])w[g]===void 0&&delete p[m][g]}else{if(m!==void 0)throw new Error("\u6A21\u578B\u4E0D\u5B58\u5728");l.push(w)}}else{let w=l.findIndex(m=>m.id===t.id);if(w>=0)l.splice(w,1);else if(Object.hasOwn(p,t.id))delete p[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")}l.length?a.models=l:delete a.models,Object.keys(p).length?a.modelOverrides=p:delete a.modelOverrides,Object.keys(a).length?n.providers[e]=a:delete n.providers[e],await Tn(r,n,s)}function gr(r){return/^(?:npm:|git:|https?:\/\/|ssh:\/\/|git@)/i.test(r.trim())}import{randomBytes as kr,createHash as On}from"node:crypto";import{fileURLToPath as Fn}from"node:url";var Ae="pi-webapp@0.1.21+c6b0921cd1db2811f3fc",J="c6b0921cd1db2811f3fc";var Re=new Set(["bash","powershell","read","write","edit","grep","find","ls"]),An=new Set(["cancelled","blocked","validation","not_found","permission","timeout","process_exit","unknown"]),hr={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},Mn=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","toolName","toolId","toolCallId","failureKind","errorCode","exitCode","timeoutMs","diagnosticSource","originalStackAvailable","errorSummary","summaryOmitted","summaryOmittedReason","level"]),Rn=new Set(["/api/workspace/git/control","/api/workspace/git/write","/api/workspace/git/status","/api/workspace/git/diff","/api/workspace/git/history","/api/workspace/git/commit-detail","/api/workspace/git/commit-diff","/api/workspace/files/list","/api/workspace/files/preview","/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 wr(r){return r==="/api/message"||r.startsWith("/api/provider/")||r.startsWith("/api/workspace/files/")||r.startsWith("/api/workspace/git/")||["/api/plugin-action","/api/plugin-interaction","/api/resume","/api/compact"].includes(r)}function L(r){return r.slice(0,8192).replace(/-----BEGIN [^-\n]+-----[\s\S]*?(?:-----END [^-\n]+-----|$)/g,"[redacted]").replace(/(["'`])[\s\S]*?\1/g,"[quoted]").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(/(?:^|\s)(?:\.\.?[\\/]|~[\\/])[^\s)]+/g," [path]").replace(/\b(?:[\w.-]+[\\/])+[\w.-]+/g,"[path]").replace(/\{[^\n]*\}/g,"[object]").replace(/\b[A-Za-z0-9_-]{24,}\b/g,"[redacted]").slice(0,1024)}function z(r){let e={};for(let t of Mn){let i=r[t];t==="toolName"?typeof i=="string"&&(Re.has(i)||i==="custom")&&(e[t]=i):t==="failureKind"?An.has(i)&&(e[t]=i):t==="level"?(i==="warning"||i==="error")&&(e[t]=i):t==="diagnosticSource"?(i==="tool_execution_end"||i==="message_end")&&(e[t]=i):t==="errorCode"?typeof i=="string"&&/^(?:E[A-Z0-9]{1,20}|nonzero_exit|timeout|cancelled|blocked|invalid_arguments|tool_not_found|unknown)$/.test(i)&&(e[t]=i):t==="toolId"?typeof i=="string"&&/^[a-f0-9]{16}$/.test(i)&&(e[t]=i):t==="route"&&typeof i=="string"?e[t]=Rn.has(i.split("?")[0])?i.split("?")[0]:"[route]":t==="model"&&typeof i=="string"&&/^[\w.-]+\/[\w.-]+$/.test(i)?e[t]=i.split("/").map(L).join("/"):typeof i=="string"?e[t]=["requestId","operationId","errorId","session","buildId","toolId","toolCallId"].includes(t)&&/^[\w-]{1,80}$/.test(i)?i:L(i).slice(0,t==="errorSummary"?512:1024):(typeof i=="boolean"||typeof i=="number"&&Number.isFinite(i)||i===null)&&(e[t]=i)}return e}function tt(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 le(r,e=0){let t=r instanceof Error?r:new Error(typeof r=="string"?r:"Non-Error rejection"),i=new Error(L(t.message));if(i.name=L(t.name).slice(0,100),t.stack){let n=t.stack.split(`
|
|
18
18
|
`).slice(1,31).map(s=>{let a=s.match(/((?:file:\/\/|https?:\/\/|\/|[A-Za-z]:\\)[^\s()]+):(\d+):(\d+)(\)?)$/);return a?`${L(s.slice(0,a.index))}${a[1]}:${a[2]}:${a[3]}${a[4]}`:L(s)});i.stack=`${i.name}: ${i.message}
|
|
19
19
|
${n.join(`
|
|
20
20
|
`)}`}else i.stack=void 0;return e<3&&t.cause!==void 0&&(i.cause=le(t.cause,e+1)),i}function ee(r,e){let t=new Error(e);return r instanceof Error&&(t.name=r.name,r.stack&&(t.stack=`${t.name}: ${e}
|
|
21
21
|
${r.stack.split(`
|
|
22
22
|
`).slice(1).join(`
|
|
23
23
|
`)}`)),t}function Nn(r){return{...r.filename?{filename:tt(r.filename)}:{},...r.abs_path?{abs_path:tt(r.abs_path)}:{},...r.function?{function:L(r.function)}:{},lineno:r.lineno,colno:r.colno,in_app:r.in_app}}function Wn(r){let e=z(r.contexts?.diagnostic??{}),t=yr(e);return{event_id:r.event_id,timestamp:r.timestamp,platform:r.platform,level:r.level,release:r.release,dist:r.dist,environment:L(r.environment??"production"),...r.message?{message:L(r.message)}:{},exception:r.exception?{values:r.exception.values?.slice(0,4).map(i=>({type:L(i.type??"Error"),value:L(i.value??""),...i.stacktrace?{stacktrace:{frames:i.stacktrace.frames?.slice(-30).map(Nn)}}:{},...i.mechanism?{mechanism:{type:i.mechanism.type,handled:i.mechanism.handled}}:{}}))}:void 0,tags:{side:r.tags?.side,buildId:r.tags?.buildId,...e.toolName?{toolName:e.toolName}:{},...e.failureKind?{failureKind:e.failureKind}:{},...e.errorCode?{errorCode:e.errorCode}:{}},...t?{fingerprint:t}:{},contexts:{diagnostic:e},breadcrumbs:r.breadcrumbs?.slice(-100).map(i=>({timestamp:i.timestamp,category:L(i.category??"app"),data:z(i.data??{})})),debug_meta:r.debug_meta?{images:r.debug_meta.images?.slice(0,10).map(i=>({type:i.type,debug_id:i.debug_id,...i.code_file?{code_file:tt(i.code_file)}:{}}))}:void 0}}function yr(r){if(!(r.stage!=="tool"||r.originalStackAvailable!==!1||!r.toolName||!r.failureKind))return["pi-webapp-tool-result",String(r.toolName),String(r.toolId??"builtin"),String(r.failureKind),String(r.errorCode??"unknown")]}function br(r,e){return e.attachments=[],Wn(r)}var he=class{items=[];bytes=0;encoder=new TextEncoder;add(e,t={}){let i={timestamp:Date.now()/1e3,category:L(e),data:z(t)},n=this.encoder.encode(JSON.stringify(i)).byteLength+1;for(this.items.push({item:i,size:n}),this.bytes+=n;this.items.length>100||this.bytes>64*1024-2;)this.bytes-=this.items.shift().size}snapshot(){return this.items.map(({item:e})=>e)}},rt=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}}},Dn=new Set(["\u76EE\u5F55\u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84","\u7236\u76EE\u5F55\u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84","\u6587\u4EF6\u5939\u540D\u79F0\u65E0\u6548","\u5DE5\u4F5C\u533A\u76EE\u5F55\u4E0D\u53EF\u7528\uFF0C\u8BF7\u6062\u590D\u76EE\u5F55\u6216\u4ECE\u5217\u8868\u79FB\u9664\u540E\u91CD\u65B0\u6DFB\u52A0","\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 te(r){return r instanceof Error&&(r.name==="AbortError"||Dn.has(r.message))}var Me=class{budget=new rt;breadcrumbs;scopeClass;seen=new WeakSet;state={};client;side;buildId;constructor(e,t,i,n,s=new he){this.client=e,this.side=t,this.buildId=i,this.scopeClass=n.Scope,this.breadcrumbs=s,e.addIntegration(n.linkedErrorsIntegration({limit:4}))}setState(e){this.state=z(e)}capture(e,t={},i){try{if(te(e))return;if(typeof e=="object"&&e!==null){if(this.seen.has(e))return;this.seen.add(e)}let n=le(e),s=z({...this.state,...t}),a=yr(s),l=a?JSON.stringify(a):`${n.name}:${n.message}:${n.stack?.split(`
|
|
24
|
-
`)[1]??""}:${t.stage??""}`,p=this.budget.take(l);if(!p)return;let w=new this.scopeClass;w.setClient(this.client),w.setTags({side:this.side,buildId:this.buildId}),s.level==="warning"&&w.setLevel("warning"),a&&w.setFingerprint(a),w.setContext("diagnostic",{...s,repeats:p.repeats});for(let m of this.breadcrumbs.snapshot())w.addBreadcrumb(m,100);return w.captureException(n,i?{event_id:i}:void 0)}catch{return}}ignore(e){this.seen.add(e)}};function vr(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 Bn="https://070c0b7c5ac18d940c294e63ecfa0793@o4506663318716416.ingest.us.sentry.io/4512191040716800";function jn(r=process.env,e=console.warn){let t=i=>{let n={enabled:!1,environment:r.PI_WEB_SENTRY_ENVIRONMENT||"production",release:Ae,buildId:J},s=r[`PI_WEB_SENTRY_${i}_DSN`]??r.PI_WEB_SENTRY_DSN??Bn;if(r.PI_WEB_SENTRY_ENABLED==="false"||!s)return n;try{let a=new URL(s);if(a.protocol!=="https:"||!/^[\w-]+$/.test(a.username)||a.password||a.search||a.hash||!/\/(?:[\w-]+\/)*\d+$/.test(a.pathname))throw new Error;return{...n,enabled:!0,dsn:s}}catch{return e(`pi-webapp: invalid ${i.toLowerCase()} Sentry DSN; error reporting disabled for this side.`),n}};return{browser:t("BROWSER"),node:t("NODE")}}var X=class{config;ready;reporter;client;salt=kr(16);breadcrumbs=new he;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=jn(e.env),!this.config.node.enabled){this.ready=Promise.resolve();return}if(e.monitor!==!1){let t=Fn(import.meta.url).replace(/\\/g,"/"),i=t.slice(0,t.lastIndexOf("/")+1);this.fatal=n=>{n.stack?.replace(/\\/g,"/").includes(t.endsWith("extension.js")?t:i)&&this.capture(n,{stage:"fatal"})},process.on("uncaughtExceptionMonitor",this.fatal)}this.ready=import("@sentry/node").then(t=>{if(!this.closed){this.client=new t.NodeClient({...this.config.node,dist:J,integrations:[],transport:e.transport??(i=>vr(t.createTransport,i)),stackParser:t.defaultStackParser,beforeSend:br,sendClientReports:!1,dataCollection:{...hr,httpBodies:[]},includeServerName:!1,enableRuntimeChannelInjection:!1,beforeSendLog:()=>null,beforeSendMetric:()=>null,enableOpenTelemetrySetup:!1,maxBreadcrumbs:100}),this.reporter=new Me(this.client,"node",J,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||te(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=kr(16).toString("hex");return this.early.push({error:le(e),context:z(t),eventId:i}),i}catch{return}}setState(e){this.state=z({...this.state,...e}),this.reporter?.setState(this.state)}breadcrumb(e,t={}){this.enabled&&this.breadcrumbs.add(e,t)}session(e){return On("sha256").update(this.salt).update(e).digest("hex").slice(0,16)}async flush(e=3e3){await this.ready;try{return this.enabled&&!!await this.client?.flush(e)}catch{return!1}}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 Zn}from"@earendil-works/pi-coding-agent";import{accessSync as $n,constants as Ln,statSync as Gn}from"node:fs";import{createRequire as Vn}from"node:module";import{execFile as Er}from"node:child_process";var it=Vn(import.meta.url),nt=class{pid;pty;screen;serializer;followers=new Set;pending=Promise.resolve();exit;disposed=!1;done;expire;closing;sessionId;abandoned;graceMs;constructor(e,t,i,n,s,a,l,p){this.sessionId=e,this.abandoned=l,this.graceMs=p;let{Terminal:w}=it("@xterm/headless"),{SerializeAddon:m}=it("@xterm/addon-serialize");this.screen=new w({cols:i,rows:n,scrollback:2e3,allowProposedApi:!0}),this.serializer=new m,this.screen.loadAddon(this.serializer);let c=Object.fromEntries(Object.entries(process.env).filter(([u
|
|
25
|
-
`).map(n=>n.trim().split(/\s+/).map(Number)),i=n=>t.filter(([,s])=>s===n).flatMap(([s])=>[...i(s),s]);for(let n of[...i(this.pid),this.pid])try{process.kill(n,"SIGKILL")}catch{}}this.pty.kill(),this.pty.resume(),await this.done}await this.pending,this.followers.clear(),this.screen.dispose()}},Ne=class{terminals=new Map;stopped=!1;options;constructor(e={}){this.options=e}create(e,t,i,n,s){if(this.stopped)throw new Error("\u7EC8\u7AEF\u670D\u52A1\u5DF2\u505C\u6B62");if(this.terminals.has(e))return this.get(e,t);if(this.terminals.size>=32||[...this.terminals.values()].filter(w=>w.sessionId===t).length>=8)throw new Error("\u7EC8\u7AEF\u6570\u91CF\u5DF2\u8FBE\u4E0A\u9650\uFF0C\u8BF7\u5173\u95ED\u4E0D\u7528\u7684\u7EC8\u7AEF");let a=this.options.shell??(process.platform==="win32"?process.env.COMSPEC||"cmd.exe":process.env.SHELL||"/bin/sh");if($n(a,Ln.X_OK),!Gn(i).isDirectory())throw new Error("\u5DE5\u4F5C\u533A\u76EE\u5F55\u4E0D\u53EF\u7528");let l=this.options.shellArgs??(process.platform==="win32"?[]:["-i"]),p=new nt(t,i,n,s,a,l,()=>{this.remove(e,t)},this.options.graceMs??5*6e4);return this.terminals.set(e,p),p}get(e,t){let i=this.terminals.get(e);if(!i||i.sessionId!==t)throw new Error("\u7EC8\u7AEF\u4E0D\u5B58\u5728\u6216\u4E0D\u5C5E\u4E8E\u6B64\u4F1A\u8BDD");return i}async remove(e,t){let i=this.terminals.get(e);if(i){if(i.sessionId!==t)throw new Error("\u7EC8\u7AEF\u4E0D\u5C5E\u4E8E\u6B64\u4F1A\u8BDD");await i.close(),this.terminals.get(e)===i&&this.terminals.delete(e)}}async close(){this.stopped=!0,await Promise.all([...this.terminals.values()].map(e=>e.close())),this.terminals.clear()}};var xr=(r,e)=>Number.isInteger(r)&&Number.isInteger(e)&&Number(r)>=2&&Number(r)<=500&&Number(e)>=1&&Number(e)<=300;async function Pr(r,e,t,i,n,s){let a=(w,m)=>{t.writeHead(w,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(m))};if(typeof e.id!="string"||!/^[a-f0-9-]{36}$/i.test(e.id)){a(400,{error:"\u7EC8\u7AEF\u6807\u8BC6\u65E0\u6548"});return}let l=r.slice(14),p=i();if(l!=="close"&&e.sessionId!==p.sessionId){a(409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if((l==="create"||l==="resize")&&!xr(e.cols,e.rows)){a(400,{error:"\u7EC8\u7AEF\u5C3A\u5BF8\u65E0\u6548"});return}if(l==="input"&&(typeof e.data!="string"||Buffer.byteLength(e.data)>16384)){a(400,{error:"\u7EC8\u7AEF\u8F93\u5165\u65E0\u6548\u6216\u8FC7\u5927"});return}try{if(l==="create"){n.create(e.id,e.sessionId,p.cwd,e.cols,e.rows),a(201,{id:e.id});return}if(l==="close"){await n.remove(e.id,e.sessionId),a(200,{closed:!0});return}let w=n.get(e.id,e.sessionId);if(l==="attach"){let m=!1,c;t.once("close",()=>{m=!0,c?.(),s.delete(t)}),c=await w.attach(
|
|
26
|
-
`),!0))),m?c():s.add(t);return}if(l==="input")w.write(e.data);else if(l==="resize")w.resize(e.cols,e.rows);else{a(404,{error:"\u672A\u77E5\u7EC8\u7AEF\u64CD\u4F5C"});return}a(200,{accepted:!0})}catch{t.headersSent?t.end():a(400,{error:l==="create"?"\u7EC8\u7AEF\u542F\u52A8\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u9ED8\u8BA4 shell\u3001\u5DE5\u4F5C\u533A\u76EE\u5F55\u6216\u7EC8\u7AEF\u6570\u91CF\u4E0A\u9650":"\u7EC8\u7AEF\u4E0D\u53EF\u7528\u6216\u4E0D\u5C5E\u4E8E\u6B64\u4F1A\u8BDD\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u7EC8\u7AEF"})}}import{readFile as Un}from"node:fs/promises";import{join as zn}from"node:path";async function Sr(r){try{let e=JSON.parse(await Un(zn(r,".vite/manifest.json"),"utf8"));if(!e||typeof e!="object")return{};let t=new Set;for(let n of Object.values(e))if(!(!n||typeof n!="object"))for(let s of[n.file,...Array.isArray(n.css)?n.css:[],...Array.isArray(n.assets)?n.assets:[]])typeof s=="string"&&/^assets\/[\w.-]+\.(?:js|css|woff2?|ttf|png|jpe?g|svg|webp)$/.test(s)&&t.add(s);let i={js:"text/javascript; charset=utf-8",css:"text/css; charset=utf-8",svg:"image/svg+xml",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",webp:"image/webp",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf"};return Object.fromEntries([...t].map(n=>[`/${n}`,{path:n,type:i[n.split(".").pop()]}]))}catch{return{}}}var Qn={"/":{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 y(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 es(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&&Hn(i,e)}async function ts(r){let e=0,t=[];for await(let i of r){let n=Buffer.isBuffer(i)?i:Buffer.from(i);if(e+=n.length,e>64*1024)throw new Error("\u8BF7\u6C42\u5185\u5BB9\u8FC7\u5927");t.push(n)}return JSON.parse(Buffer.concat(t).toString("utf8"))}async function rs(r){let e=0,t=[];for await(let i of r){let n=Buffer.isBuffer(i)?i:Buffer.from(i);if(e+=n.length,e>_e)throw new Error("\u6587\u4EF6\u8D85\u8FC7 20 MB");t.push(n)}return Buffer.concat(t)}async function is(r,e=0){await new Promise((i,n)=>{r.once("error",n),r.listen(e,"127.0.0.1",()=>{r.off("error",n),i()})});let t=r.address();if(t===null||typeof t=="string")throw new Error("\u65E0\u6CD5\u786E\u5B9A\u76D1\u542C\u7AEF\u53E3");return t.port}async function _r(r,e,t=new X){t.setState({piVersion:Zn});let i=process.env.PI_WEBAPP_RESTART_TOKEN,n=i&&/^[A-Za-z0-9_-]{32}$/.test(i)?i:Ir(24).toString("base64url"),s=Buffer.from(n),a=tr(),l=new Set,p=new Ne,w=new Set,m=new Map,c=new Te((b,h)=>t.capture(b,h)),
|
|
27
|
-
`),h.on("close",()=>l.delete(h));return}if(b.method==="POST"&&["/api/terminal/create","/api/terminal/attach","/api/terminal/input","/api/terminal/resize","/api/terminal/close",...Ze,"/api/workspace/files/list","/api/workspace/files/preview","/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(k)){if(b.headers.origin!==void 0&&b.headers.origin!==f){y(h,403,{error:"\u6765\u6E90\u4E0D\u5339\u914D"});return}if(!b.headers["content-type"]?.startsWith("application/json")){y(h,415,{error:"\u9700\u8981 JSON \u8BF7\u6C42"});return}try{let d;try{d=await ts(b)}catch(v){if(v instanceof SyntaxError||te(v)){y(h,400,{error:"\u8BF7\u6C42\u5185\u5BB9\u65E0\u6548"});return}throw v}if(typeof d!="object"||d===null||!("sessionId"in d)||typeof d.sessionId!="string"){y(h,400,{error:"\u7F3A\u5C11\u4F1A\u8BDD\u6807\u8BC6"});return}if(k.startsWith("/api/terminal/")){await Pr(k,d,h,()=>r.snapshot(),p,w);return}if(Ze.includes(k)){let v=r.snapshot();if(d.sessionId!==v.sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}try{let S=M=>!r.snapshot().idle||(r.busyGitWorkspaces?.()??[]).some(K=>{let Et=(di,pi)=>{let Pe=Yn(di,pi);return Pe!==".."&&!Pe.startsWith("../")&&!Pe.startsWith("..\\")&&!Xn(Pe)};return Et(M,K)||Et(K,M)}),_=M=>{let K=r.snapshot();if(K.sessionId!==v.sessionId||K.cwd!==v.cwd)throw new P("\u4F1A\u8BDD\u5DF2\u5207\u6362",409,"session_changed");if(S(M))throw new P("\u5171\u7528\u6B64\u5DE5\u4F5C\u6811\u7684\u804A\u5929\u6B63\u5728\u8FD0\u884C",409,"agent_busy")},B=k.endsWith("/write"),xe=B?await Vt(v.cwd,d,_):await er(k,v.cwd,d);if(!B){let M=r.snapshot();if(M.sessionId!==v.sessionId||M.cwd!==v.cwd){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(k.endsWith("/control")){let K=xe;K.root&&S(K.root)&&(K.blocked??="agent_busy")}}y(h,200,xe)}catch(S){if(S instanceof P||S instanceof j)y(h,S.status,{error:S.message,errorCode:"validation_error",...S instanceof P?{reason:S.reason}:{}});else throw ee(S,"Git \u64CD\u4F5C\u5931\u8D25")}return}if(k==="/api/workspace/files/list"||k==="/api/workspace/files/preview"){let v=r.snapshot();if(d.sessionId!==v.sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("path"in d)||typeof d.path!="string"||d.path.length>4096){y(h,400,{error:"\u5DE5\u4F5C\u533A\u6587\u4EF6\u8DEF\u5F84\u65E0\u6548"});return}try{let S=k.endsWith("/list")?await Dt(v.cwd,d.path):await Se(v.cwd,d.path),_=r.snapshot();if(_.sessionId!==v.sessionId||_.cwd!==v.cwd){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}y(h,200,S)}catch(S){if(S instanceof j)y(h,S.status,{error:S.message,errorCode:"validation_error"});else throw ee(S,"\u5DE5\u4F5C\u533A\u6587\u4EF6\u8BFB\u53D6\u5931\u8D25")}return}if(k==="/api/plugin-interaction"){if(d.sessionId!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("pluginId"in d)||typeof d.pluginId!="string"||d.pluginId.length>200||!("requestId"in d)||typeof d.requestId!="string"||d.requestId.length>200||!r.resolvePluginInteraction||!("value"in d)){y(h,400,{error:"\u63D2\u4EF6\u4EA4\u4E92\u54CD\u5E94\u65E0\u6548"});return}await ce(r.snapshot().cwd,async()=>r.resolvePluginInteraction(d.sessionId,d.pluginId,d.requestId,d.value),!0),y(h,200,{accepted:!0});return}if(k==="/api/plugin-action"){if(d.sessionId!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("pluginId"in d)||typeof d.pluginId!="string"||d.pluginId.length>200||!("action"in d)||typeof d.action!="string"||d.action.length>100||!r.invokePluginAction){y(h,400,{error:"\u63D2\u4EF6\u52A8\u4F5C\u65E0\u6548"});return}let v=await ce(r.snapshot().cwd,async()=>r.invokePluginAction(d.sessionId,d.pluginId,d.action,"input"in d?d.input:void 0),!0);y(h,200,{value:v});return}if(k==="/api/update"){if(d.sessionId!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!r.snapshot().idle){y(h,409,{error:"\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u540E\u518D\u5347\u7EA7"});return}if(!r.selfUpdate){y(h,409,{error:"\u5F53\u524D\u6269\u5C55\u4E0D\u652F\u6301\u5728\u7EBF\u5347\u7EA7"});return}let v=await r.selfUpdate.prepare();g=!0,y(h,202,{accepted:!0,version:v.version}),setTimeout(()=>{r.selfUpdate?.requestRestart(v).catch(S=>{g=!1,t.capture(S,{stage:"restart"}),console.error("pi-webapp restart:",S)})},500).unref();return}if(k==="/api/provider/custom"){if(d.sessionId!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("provider"in d)||!et(d.provider)||!r.addCustomProvider){y(h,400,{error:"\u81EA\u5B9A\u4E49\u63D0\u4F9B\u65B9\u65E0\u6548"});return}await r.addCustomProvider(d.sessionId,d.provider),y(h,201,{accepted:!0});return}if(k==="/api/provider/models"||k==="/api/provider/logout"){if(d.sessionId!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("providerId"in d)||typeof d.providerId!="string"){y(h,400,{error:"\u63D0\u4F9B\u65B9\u65E0\u6548"});return}if(k==="/api/provider/models"){if(!("change"in d)||!dr(d.change)||!r.updateProviderModel){y(h,400,{error:"\u6A21\u578B\u53C2\u6570\u65E0\u6548"});return}await r.updateProviderModel(d.sessionId,d.providerId,d.change)}else{if(!r.logoutProvider){y(h,400,{error:"\u65E0\u6CD5\u79FB\u9664\u8BA4\u8BC1"});return}await r.logoutProvider(d.sessionId,d.providerId)}y(h,200,{accepted:!0});return}if(k.startsWith("/api/provider/login")){if(d.sessionId!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(k==="/api/provider/login"){if(!("providerId"in d)||typeof d.providerId!="string"||!("method"in d)||d.method!=="api_key"&&d.method!=="oauth"||!r.loginProvider||!r.providers){y(h,400,{error:"\u767B\u5F55\u65B9\u5F0F\u65E0\u6548"});return}if(!(await r.providers()).some(B=>B.id===d.providerId&&B.methods.includes(d.method))){y(h,400,{error:"\u63D0\u4F9B\u65B9\u4E0D\u652F\u6301\u6B64\u767B\u5F55\u65B9\u5F0F"});return}let S="initialSecret"in d?d.initialSecret:void 0;if(S!==void 0&&(d.method!=="api_key"||typeof S!="string"||!S.trim()||S.length>16384)){y(h,400,{error:"API Key \u65E0\u6548"});return}let _=c.start(d.providerId,d.method,r.loginProvider,S,O);y(h,202,{id:_.id});return}if(!("id"in d)||typeof d.id!="string"){y(h,400,{error:"\u767B\u5F55\u6D41\u7A0B\u65E0\u6548"});return}if(k==="/api/provider/login/cancel"){y(h,c.cancel(d.id)?202:404,{accepted:!0});return}if(!("value"in d)||typeof d.value!="string"||d.value.length>16384||!c.respond(d.id,d.value)){y(h,400,{error:"\u767B\u5F55\u8F93\u5165\u65E0\u6548"});return}y(h,202,{accepted:!0});return}if(k==="/api/attachment/remove"){if(!("id"in d)||typeof d.id!="string"||d.sessionId!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u9644\u4EF6\u65E0\u6548"});return}m.get(d.id)?.sessionId===d.sessionId&&m.delete(d.id),y(h,202,{accepted:!0});return}if(k==="/api/directory/pick"){if(a!=="native"){y(h,409,{error:"\u672C\u5730\u76EE\u5F55\u9009\u62E9\u5668\u4E0D\u53EF\u7528"});return}let v=new AbortController;h.once("close",()=>v.abort()),y(h,200,{path:await rr(v.signal)});return}if(k==="/api/directory/list"){if("path"in d&&(typeof d.path!="string"||d.path.length>4096)){y(h,400,{error:"\u76EE\u5F55\u8DEF\u5F84\u65E0\u6548"});return}y(h,200,await Ct("path"in d?d.path:void 0));return}if(k==="/api/directory/create"){if(!("path"in d)||typeof d.path!="string"||d.path.length>4096||!("name"in d)||typeof d.name!="string"||d.name.length>255){y(h,400,{error:"\u6587\u4EF6\u5939\u540D\u79F0\u6216\u8DEF\u5F84\u65E0\u6548"});return}y(h,200,{path:await _t(d.path,d.name)});return}if(k==="/api/workspace/add"){if(!("path"in d)||typeof d.path!="string"||d.path.length>4096||!("create"in d)||typeof d.create!="boolean"){y(h,400,{error:"\u5DE5\u4F5C\u533A\u8DEF\u5F84\u65E0\u6548"});return}await r.addWorkspace(d.path,d.create),y(h,202,{accepted:!0});return}if(k==="/api/workspace/select"||k==="/api/workspace/remove"||k==="/api/workspace/new-session"){if(!("id"in d)||typeof d.id!="string"){y(h,400,{error:"\u5DE5\u4F5C\u533A\u65E0\u6548"});return}k==="/api/workspace/select"?await r.selectWorkspace(d.id):k==="/api/workspace/new-session"?await r.newSessionInWorkspace(d.id):await r.removeWorkspace(d.id),y(h,202,{accepted:!0});return}if(k==="/api/session/select"){if(!("workspaceId"in d)||typeof d.workspaceId!="string"||!("id"in d)||typeof d.id!="string"||!("path"in d)||typeof d.path!="string"){y(h,400,{error:"\u4F1A\u8BDD\u65E0\u6548"});return}await r.selectSession(d.workspaceId,d.id,d.path),y(h,202,{accepted:!0});return}if(k==="/api/thinking-level"){if(!("level"in d)||typeof d.level!="string"){y(h,400,{error:"\u63A8\u7406\u5F3A\u5EA6\u65E0\u6548"});return}await r.setThinkingLevel(d.sessionId,d.level)}else if(k==="/api/model"){if(!("provider"in d)||typeof d.provider!="string"||!("id"in d)||typeof d.id!="string"){y(h,400,{error:"\u6A21\u578B\u65E0\u6548"});return}await r.setModel(d.sessionId,d.provider,d.id)}else if(k==="/api/config"){let v=d;if(!["packages","extensions","skills"].includes(v.kind)||!["global","project"].includes(v.scope)||!["add","remove"].includes(v.action)||typeof v.value!="string"||!v.value.trim()||v.value.length>2048){y(h,400,{error:"\u914D\u7F6E\u9879\u65E0\u6548"});return}if(v.action==="add"&&v.kind!=="packages"&&gr(v.value)){y(h,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}y(h,200,await r.updateConfig(v));return}else if(k==="/api/message"){let v="attachments"in d?d.attachments:[];if(!Array.isArray(v)||v.length>nr||v.some(M=>typeof M!="string")||new Set(v).size!==v.length){y(h,400,{error:"\u9644\u4EF6\u65E0\u6548\u6216\u8FC7\u591A"});return}let S=v.map(M=>m.get(M));if(S.some(M=>!M||M.sessionId!==d.sessionId)){y(h,400,{error:"\u9644\u4EF6\u4E0D\u53EF\u7528"});return}if(!("text"in d)||typeof d.text!="string"||!d.text.trim()&&v.length===0||d.text.length>32e3){y(h,400,{error:"\u6D88\u606F\u65E0\u6548\u6216\u8FC7\u957F"});return}let _=S,B=[d.text.trim(),..._.map(M=>`\u9644\u4EF6 ${JSON.stringify(M.name)}\uFF1A${M.path}`)].filter(Boolean).join(`
|
|
24
|
+
`)[1]??""}:${t.stage??""}`,p=this.budget.take(l);if(!p)return;let w=new this.scopeClass;w.setClient(this.client),w.setTags({side:this.side,buildId:this.buildId}),s.level==="warning"&&w.setLevel("warning"),a&&w.setFingerprint(a),w.setContext("diagnostic",{...s,repeats:p.repeats});for(let m of this.breadcrumbs.snapshot())w.addBreadcrumb(m,100);return w.captureException(n,i?{event_id:i}:void 0)}catch{return}}ignore(e){this.seen.add(e)}};function vr(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 Bn="https://070c0b7c5ac18d940c294e63ecfa0793@o4506663318716416.ingest.us.sentry.io/4512191040716800";function jn(r=process.env,e=console.warn){let t=i=>{let n={enabled:!1,environment:r.PI_WEB_SENTRY_ENVIRONMENT||"production",release:Ae,buildId:J},s=r[`PI_WEB_SENTRY_${i}_DSN`]??r.PI_WEB_SENTRY_DSN??Bn;if(r.PI_WEB_SENTRY_ENABLED==="false"||!s)return n;try{let a=new URL(s);if(a.protocol!=="https:"||!/^[\w-]+$/.test(a.username)||a.password||a.search||a.hash||!/\/(?:[\w-]+\/)*\d+$/.test(a.pathname))throw new Error;return{...n,enabled:!0,dsn:s}}catch{return e(`pi-webapp: invalid ${i.toLowerCase()} Sentry DSN; error reporting disabled for this side.`),n}};return{browser:t("BROWSER"),node:t("NODE")}}var X=class{config;ready;reporter;client;salt=kr(16);breadcrumbs=new he;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=jn(e.env),!this.config.node.enabled){this.ready=Promise.resolve();return}if(e.monitor!==!1){let t=Fn(import.meta.url).replace(/\\/g,"/"),i=t.slice(0,t.lastIndexOf("/")+1);this.fatal=n=>{n.stack?.replace(/\\/g,"/").includes(t.endsWith("extension.js")?t:i)&&this.capture(n,{stage:"fatal"})},process.on("uncaughtExceptionMonitor",this.fatal)}this.ready=import("@sentry/node").then(t=>{if(!this.closed){this.client=new t.NodeClient({...this.config.node,dist:J,integrations:[],transport:e.transport??(i=>vr(t.createTransport,i)),stackParser:t.defaultStackParser,beforeSend:br,sendClientReports:!1,dataCollection:{...hr,httpBodies:[]},includeServerName:!1,enableRuntimeChannelInjection:!1,beforeSendLog:()=>null,beforeSendMetric:()=>null,enableOpenTelemetrySetup:!1,maxBreadcrumbs:100}),this.reporter=new Me(this.client,"node",J,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||te(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=kr(16).toString("hex");return this.early.push({error:le(e),context:z(t),eventId:i}),i}catch{return}}setState(e){this.state=z({...this.state,...e}),this.reporter?.setState(this.state)}breadcrumb(e,t={}){this.enabled&&this.breadcrumbs.add(e,t)}session(e){return On("sha256").update(this.salt).update(e).digest("hex").slice(0,16)}async flush(e=3e3){await this.ready;try{return this.enabled&&!!await this.client?.flush(e)}catch{return!1}}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 Zn}from"@earendil-works/pi-coding-agent";import{accessSync as $n,constants as Ln,statSync as Gn}from"node:fs";import{createRequire as Vn}from"node:module";import{execFile as Er}from"node:child_process";var it=Vn(import.meta.url),nt=class{pid;pty;screen;serializer;followers=new Set;pending=Promise.resolve();exit;disposed=!1;done;expire;closing;sessionId;abandoned;graceMs;constructor(e,t,i,n,s,a,l,p){this.sessionId=e,this.abandoned=l,this.graceMs=p;let{Terminal:w}=it("@xterm/headless"),{SerializeAddon:m}=it("@xterm/addon-serialize");this.screen=new w({cols:i,rows:n,scrollback:2e3,allowProposedApi:!0}),this.serializer=new m,this.screen.loadAddon(this.serializer);let c=Object.fromEntries(Object.entries(process.env).filter(([f,u])=>u!==void 0&&!/^PI_WEBAPP_RESTART_/.test(f)));try{this.pty=it("node-pty").spawn(s,a,{name:"xterm-256color",cwd:t,cols:i,rows:n,env:{...c,TERM:"xterm-256color",COLORTERM:"truecolor"}})}catch(f){throw this.screen.dispose(),f}this.pid=this.pty.pid,this.pty.onData(f=>{this.disposed||(this.pty.pause(),this.pending=this.pending.then(()=>new Promise(u=>{if(this.disposed){u();return}this.screen.write(f,()=>{this.broadcast({type:"output",data:f}),u()})})).finally(()=>{!this.exit&&!this.disposed&&this.pty.resume()}))}),this.done=new Promise(f=>this.pty.onExit(({exitCode:u,signal:g})=>{this.exit={type:"exit",exitCode:u,signal:g},this.pending.then(()=>{this.broadcast(this.exit),f()})})),this.scheduleExpiry()}broadcast(e){for(let t of this.followers)t(e)||this.followers.delete(t);this.followers.size||this.scheduleExpiry()}scheduleExpiry(){this.expire||this.disposed||(this.expire=setTimeout(this.abandoned,this.graceMs).unref())}async attach(e){if(await this.pending,this.disposed)throw new Error("\u7EC8\u7AEF\u5DF2\u5173\u95ED");return clearTimeout(this.expire),this.expire=void 0,e({type:"snapshot",screen:this.serializer.serialize(),cols:this.screen.cols,rows:this.screen.rows})?(this.exit&&e(this.exit),this.followers.add(e)):this.scheduleExpiry(),()=>{this.followers.delete(e),this.followers.size||this.scheduleExpiry()}}write(e){if(this.exit||this.disposed)throw new Error("\u7EC8\u7AEF\u5DF2\u9000\u51FA");this.pty.write(e)}resize(e,t){this.exit||this.disposed||(this.pty.resize(e,t),this.pending=this.pending.then(()=>{this.disposed||(this.screen.resize(e,t),this.broadcast({type:"resize",cols:e,rows:t}))}))}close(){return this.closing??=this.dispose()}async dispose(){if(this.disposed=!0,clearTimeout(this.expire),!this.exit){if(process.platform==="win32")await new Promise(e=>Er("taskkill",["/pid",String(this.pid),"/T","/F"],()=>e()));else{let t=(await new Promise(n=>Er("ps",["-axo","pid=,ppid="],(s,a)=>n(s?"":a)))).trim().split(`
|
|
25
|
+
`).map(n=>n.trim().split(/\s+/).map(Number)),i=n=>t.filter(([,s])=>s===n).flatMap(([s])=>[...i(s),s]);for(let n of[...i(this.pid),this.pid])try{process.kill(n,"SIGKILL")}catch{}}this.pty.kill(),this.pty.resume(),await this.done}await this.pending,this.followers.clear(),this.screen.dispose()}},Ne=class{terminals=new Map;stopped=!1;options;constructor(e={}){this.options=e}create(e,t,i,n,s){if(this.stopped)throw new Error("\u7EC8\u7AEF\u670D\u52A1\u5DF2\u505C\u6B62");if(this.terminals.has(e))return this.get(e,t);if(this.terminals.size>=32||[...this.terminals.values()].filter(w=>w.sessionId===t).length>=8)throw new Error("\u7EC8\u7AEF\u6570\u91CF\u5DF2\u8FBE\u4E0A\u9650\uFF0C\u8BF7\u5173\u95ED\u4E0D\u7528\u7684\u7EC8\u7AEF");let a=this.options.shell??(process.platform==="win32"?process.env.COMSPEC||"cmd.exe":process.env.SHELL||"/bin/sh");if($n(a,Ln.X_OK),!Gn(i).isDirectory())throw new Error("\u5DE5\u4F5C\u533A\u76EE\u5F55\u4E0D\u53EF\u7528");let l=this.options.shellArgs??(process.platform==="win32"?[]:["-i"]),p=new nt(t,i,n,s,a,l,()=>{this.remove(e,t)},this.options.graceMs??5*6e4);return this.terminals.set(e,p),p}get(e,t){let i=this.terminals.get(e);if(!i||i.sessionId!==t)throw new Error("\u7EC8\u7AEF\u4E0D\u5B58\u5728\u6216\u4E0D\u5C5E\u4E8E\u6B64\u4F1A\u8BDD");return i}async remove(e,t){let i=this.terminals.get(e);if(i){if(i.sessionId!==t)throw new Error("\u7EC8\u7AEF\u4E0D\u5C5E\u4E8E\u6B64\u4F1A\u8BDD");await i.close(),this.terminals.get(e)===i&&this.terminals.delete(e)}}async close(){this.stopped=!0,await Promise.all([...this.terminals.values()].map(e=>e.close())),this.terminals.clear()}};var xr=(r,e)=>Number.isInteger(r)&&Number.isInteger(e)&&Number(r)>=2&&Number(r)<=500&&Number(e)>=1&&Number(e)<=300;async function Pr(r,e,t,i,n,s){let a=(w,m)=>{t.writeHead(w,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(m))};if(typeof e.id!="string"||!/^[a-f0-9-]{36}$/i.test(e.id)){a(400,{error:"\u7EC8\u7AEF\u6807\u8BC6\u65E0\u6548"});return}let l=r.slice(14),p=i();if(l!=="close"&&e.sessionId!==p.sessionId){a(409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if((l==="create"||l==="resize")&&!xr(e.cols,e.rows)){a(400,{error:"\u7EC8\u7AEF\u5C3A\u5BF8\u65E0\u6548"});return}if(l==="input"&&(typeof e.data!="string"||Buffer.byteLength(e.data)>16384)){a(400,{error:"\u7EC8\u7AEF\u8F93\u5165\u65E0\u6548\u6216\u8FC7\u5927"});return}try{if(l==="create"){n.create(e.id,e.sessionId,p.cwd,e.cols,e.rows),a(201,{id:e.id});return}if(l==="close"){await n.remove(e.id,e.sessionId),a(200,{closed:!0});return}let w=n.get(e.id,e.sessionId);if(l==="attach"){let m=!1,c;t.once("close",()=>{m=!0,c?.(),s.delete(t)}),c=await w.attach(f=>m?!1:(t.headersSent||t.writeHead(200,{"Content-Type":"application/x-ndjson","Cache-Control":"no-store","X-Accel-Buffering":"no"}),t.writableLength>1024*1024?(t.destroy(),!1):(t.write(`${JSON.stringify(f)}
|
|
26
|
+
`),!0))),m?c():s.add(t);return}if(l==="input")w.write(e.data);else if(l==="resize")w.resize(e.cols,e.rows);else{a(404,{error:"\u672A\u77E5\u7EC8\u7AEF\u64CD\u4F5C"});return}a(200,{accepted:!0})}catch{t.headersSent?t.end():a(400,{error:l==="create"?"\u7EC8\u7AEF\u542F\u52A8\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u9ED8\u8BA4 shell\u3001\u5DE5\u4F5C\u533A\u76EE\u5F55\u6216\u7EC8\u7AEF\u6570\u91CF\u4E0A\u9650":"\u7EC8\u7AEF\u4E0D\u53EF\u7528\u6216\u4E0D\u5C5E\u4E8E\u6B64\u4F1A\u8BDD\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u7EC8\u7AEF"})}}import{readFile as Un}from"node:fs/promises";import{join as zn}from"node:path";async function Sr(r){try{let e=JSON.parse(await Un(zn(r,".vite/manifest.json"),"utf8"));if(!e||typeof e!="object")return{};let t=new Set;for(let n of Object.values(e))if(!(!n||typeof n!="object"))for(let s of[n.file,...Array.isArray(n.css)?n.css:[],...Array.isArray(n.assets)?n.assets:[]])typeof s=="string"&&/^assets\/[\w.-]+\.(?:js|css|woff2?|ttf|png|jpe?g|svg|webp)$/.test(s)&&t.add(s);let i={js:"text/javascript; charset=utf-8",css:"text/css; charset=utf-8",svg:"image/svg+xml",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",webp:"image/webp",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf"};return Object.fromEntries([...t].map(n=>[`/${n}`,{path:n,type:i[n.split(".").pop()]}]))}catch{return{}}}var Qn={"/":{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 y(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 es(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&&Hn(i,e)}async function ts(r){let e=0,t=[];for await(let i of r){let n=Buffer.isBuffer(i)?i:Buffer.from(i);if(e+=n.length,e>64*1024)throw new Error("\u8BF7\u6C42\u5185\u5BB9\u8FC7\u5927");t.push(n)}return JSON.parse(Buffer.concat(t).toString("utf8"))}async function rs(r){let e=0,t=[];for await(let i of r){let n=Buffer.isBuffer(i)?i:Buffer.from(i);if(e+=n.length,e>_e)throw new Error("\u6587\u4EF6\u8D85\u8FC7 20 MB");t.push(n)}return Buffer.concat(t)}async function is(r,e=0){await new Promise((i,n)=>{r.once("error",n),r.listen(e,"127.0.0.1",()=>{r.off("error",n),i()})});let t=r.address();if(t===null||typeof t=="string")throw new Error("\u65E0\u6CD5\u786E\u5B9A\u76D1\u542C\u7AEF\u53E3");return t.port}async function _r(r,e,t=new X){t.setState({piVersion:Zn});let i=process.env.PI_WEBAPP_RESTART_TOKEN,n=i&&/^[A-Za-z0-9_-]{32}$/.test(i)?i:Ir(24).toString("base64url"),s=Buffer.from(n),a=tr(),l=new Set,p=new Ne,w=new Set,m=new Map,c=new Te((b,h)=>t.capture(b,h)),f=b=>t.setState({nodeVersion:process.version,platform:process.platform,session:t.session(b.sessionId),idle:b.idle,model:b.model,thinkingLevel:b.thinkingLevel,messageCount:b.messages.length}),u="",g=!1,x={...Qn,...await Sr(e)};for(let b of await Kn(Cr(e,"assets")).catch(()=>[])){let h=/^[\w.-]+\.(js|css|woff2?|ttf)$/.exec(b);if(!h)continue;let E={js:"text/javascript; charset=utf-8",css:"text/css; charset=utf-8",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf"};x[`/assets/${b}`]={path:`assets/${b}`,type:E[h[1]]}}let I=qn(async(b,h)=>{let E=Ir(18).toString("base64"),R=F=>typeof F=="string"&&/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(F),Z=R(b.headers["x-request-id"])?b.headers["x-request-id"]:st(),O={requestId:Z,operationId:R(b.headers["x-operation-id"])?b.headers["x-operation-id"]:void 0};h.setHeader("X-Request-ID",Z),O.operationId&&h.setHeader("X-Operation-ID",O.operationId);let k="/",li=performance.now(),$=(F,d,v)=>{let _=!te(F)&&wr(k)?ee(F,"Agent or provider operation failed"):F,B=t.capture(_,{...O,route:k,method:b.method,status:d,stage:"http"});y(h,d,{error:v,errorId:B,errorReported:t.enabled,errorCode:te(F)?"validation_error":"unexpected_error"})};h.once("finish",()=>{k.startsWith("/api/telemetry/")||t.breadcrumb("request",{...O,route:k,method:b.method,status:h.statusCode,durationMs:Math.round(performance.now()-li)})});try{h.setHeader("X-Content-Type-Options","nosniff"),h.setHeader("Referrer-Policy","no-referrer"),h.setHeader("Content-Security-Policy",`default-src 'self'; script-src 'self'; style-src 'self' 'nonce-${E}'; style-src-attr 'unsafe-inline'; font-src 'self' data:; 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{k=new URL(b.url??"/",u).pathname}catch{y(h,400,{error:"\u8BF7\u6C42\u5730\u5740\u65E0\u6548"});return}let F=x[k];if(b.method==="GET"&&F){try{let d=await Jn(Cr(e,F.path));h.writeHead(200,{"Content-Type":F.type,"Cache-Control":"no-store"}),h.end(k==="/"?d.toString("utf8").replace("<head>",`<head><meta name="pi-style-nonce" content="${E}">`):d)}catch(d){$(d,500,"\u9875\u9762\u6587\u4EF6\u4E0D\u53EF\u7528")}return}if(b.method==="GET"&&k.startsWith("/plugins/")){try{let d=await r.pluginAsset?.(b.url??k);if(!d){y(h,404,{error:"\u63D2\u4EF6\u8D44\u6E90\u4E0D\u5B58\u5728"});return}h.writeHead(200,{"Content-Type":d.type,"Cache-Control":"no-store"}),h.end(d.bytes)}catch(d){$(d,404,"\u63D2\u4EF6\u8D44\u6E90\u4E0D\u53EF\u7528")}return}if(!k.startsWith("/api/")){y(h,404,{error:"\u672A\u627E\u5230"});return}if(!es(b,s)){y(h,401,{error:"\u8BBF\u95EE\u4EE4\u724C\u65E0\u6548"});return}if(b.method==="GET"&&k==="/api/telemetry/config"){y(h,200,t.config.browser);return}if(b.method==="GET"&&k==="/api/update/version"){try{y(h,200,{current:await r.selfUpdate?.runningVersion()??null})}catch(d){$(d,503,d instanceof Error?d.message:"\u65E0\u6CD5\u8BFB\u53D6\u7248\u672C")}return}if(b.method==="GET"&&k==="/api/update"){try{y(h,200,await r.selfUpdate?.check()??{canRestart:!1,reason:"\u5F53\u524D\u6269\u5C55\u4E0D\u652F\u6301\u5728\u7EBF\u5347\u7EA7"})}catch(d){$(d,503,d instanceof Error?d.message:"\u68C0\u67E5\u66F4\u65B0\u5931\u8D25")}return}if(b.method==="GET"&&k==="/api/image"){let d=new URL(b.url??k,u),v=d.searchParams.get("sessionId")??"",S=d.searchParams.get("messageId")??"",_=Number(d.searchParams.get("index"));if(!v||v!==r.snapshot().sessionId||!S||!Number.isInteger(_)||_<0||_>100){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u56FE\u7247\u5730\u5740\u65E0\u6548"});return}let B=r.image?.(v,S,_);if(!B||!["image/png","image/jpeg","image/webp","image/gif"].includes(B.mimeType)){y(h,404,{error:"\u56FE\u7247\u4E0D\u53EF\u7528"});return}h.writeHead(200,{"Content-Type":B.mimeType,"Cache-Control":"private, no-store"}),h.end(B.data);return}if(b.method==="POST"&&k==="/api/attachment"){if(b.headers.origin!==void 0&&b.headers.origin!==u){y(h,403,{error:"\u6765\u6E90\u4E0D\u5339\u914D"});return}let d=new URL(b.url??k,u),v=d.searchParams.get("sessionId"),S=d.searchParams.get("name");try{if(!v||!S||S.length>1024||v!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u6587\u4EF6\u540D\u65E0\u6548"});return}if(Number(b.headers["content-length"]??0)>_e){y(h,413,{error:"\u6587\u4EF6\u8D85\u8FC7 20 MB"});return}let _=await sr(v,S,b.headers["content-type"]??"application/octet-stream",await rs(b));if(v!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}m.set(_.id,_),y(h,201,{id:_.id,name:_.name,bytes:_.bytes})}catch(_){$(_,400,_ instanceof Error?_.message:"\u4E0A\u4F20\u5931\u8D25")}return}if(b.method==="GET"&&k==="/api/session"){try{let d=r.snapshot();f(d),y(h,200,d)}catch(d){$(d,503,"\u5F53\u524D\u4F1A\u8BDD\u4E0D\u53EF\u7528")}return}if(b.method==="GET"&&k==="/api/plugins"){try{y(h,200,await r.plugins?.()??{plugins:[],errors:[]})}catch(d){$(d,503,"\u63D2\u4EF6\u76EE\u5F55\u4E0D\u53EF\u7528")}return}if(b.method==="GET"&&k==="/api/providers"){try{y(h,200,await r.providers?.()??[])}catch(d){$(d,503,"\u6A21\u578B\u63D0\u4F9B\u65B9\u4E0D\u53EF\u7528")}return}if(b.method==="GET"&&k==="/api/provider/models"){let d=new URL(b.url??k,u).searchParams.get("providerId")??"";try{if(!d||!r.providerModels){y(h,400,{error:"\u63D0\u4F9B\u65B9\u65E0\u6548"});return}y(h,200,await r.providerModels(d))}catch(v){$(v,400,v instanceof Error?v.message:"\u6A21\u578B\u76EE\u5F55\u4E0D\u53EF\u7528")}return}if(b.method==="GET"&&k==="/api/provider/login/active"){y(h,200,{active:c.getActive()??null});return}if(b.method==="GET"&&k==="/api/provider/login"){let d=new URL(b.url??k,u).searchParams.get("id")??"",v=c.get(d);y(h,v?200:404,v??{error:"\u767B\u5F55\u6D41\u7A0B\u4E0D\u5B58\u5728"});return}if(b.method==="GET"&&(k==="/api/models"||k==="/api/config"||k==="/api/workspaces"||k==="/api/commands")){try{y(h,200,k==="/api/models"?await r.models():k==="/api/config"?await r.config():k==="/api/commands"?r.commands?.()??[]:await r.workspaces())}catch(d){$(d,503,"Pi \u914D\u7F6E\u4E0D\u53EF\u7528")}return}if(b.method==="GET"&&k==="/api/directory/capability"){y(h,200,{kind:a});return}if(b.method==="GET"&&k==="/api/events"){let d;try{d=r.snapshot(),f(d)}catch(v){$(v,503,"\u5F53\u524D\u4F1A\u8BDD\u4E0D\u53EF\u7528");return}h.writeHead(200,{"Content-Type":"application/x-ndjson; charset=utf-8","Cache-Control":"no-store",Connection:"keep-alive","X-Accel-Buffering":"no"}),l.add(h),h.write(`${JSON.stringify({type:"snapshot",session:d})}
|
|
27
|
+
`),h.on("close",()=>l.delete(h));return}if(b.method==="POST"&&["/api/terminal/create","/api/terminal/attach","/api/terminal/input","/api/terminal/resize","/api/terminal/close",...Ze,"/api/workspace/files/list","/api/workspace/files/preview","/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(k)){if(b.headers.origin!==void 0&&b.headers.origin!==u){y(h,403,{error:"\u6765\u6E90\u4E0D\u5339\u914D"});return}if(!b.headers["content-type"]?.startsWith("application/json")){y(h,415,{error:"\u9700\u8981 JSON \u8BF7\u6C42"});return}try{let d;try{d=await ts(b)}catch(v){if(v instanceof SyntaxError||te(v)){y(h,400,{error:"\u8BF7\u6C42\u5185\u5BB9\u65E0\u6548"});return}throw v}if(typeof d!="object"||d===null||!("sessionId"in d)||typeof d.sessionId!="string"){y(h,400,{error:"\u7F3A\u5C11\u4F1A\u8BDD\u6807\u8BC6"});return}if(k.startsWith("/api/terminal/")){await Pr(k,d,h,()=>r.snapshot(),p,w);return}if(Ze.includes(k)){let v=r.snapshot();if(d.sessionId!==v.sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}try{let S=M=>!r.snapshot().idle||(r.busyGitWorkspaces?.()??[]).some(K=>{let Et=(di,pi)=>{let Pe=Yn(di,pi);return Pe!==".."&&!Pe.startsWith("../")&&!Pe.startsWith("..\\")&&!Xn(Pe)};return Et(M,K)||Et(K,M)}),_=M=>{let K=r.snapshot();if(K.sessionId!==v.sessionId||K.cwd!==v.cwd)throw new P("\u4F1A\u8BDD\u5DF2\u5207\u6362",409,"session_changed");if(S(M))throw new P("\u5171\u7528\u6B64\u5DE5\u4F5C\u6811\u7684\u804A\u5929\u6B63\u5728\u8FD0\u884C",409,"agent_busy")},B=k.endsWith("/write"),xe=B?await Vt(v.cwd,d,_):await er(k,v.cwd,d);if(!B){let M=r.snapshot();if(M.sessionId!==v.sessionId||M.cwd!==v.cwd){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(k.endsWith("/control")){let K=xe;K.root&&S(K.root)&&(K.blocked??="agent_busy")}}y(h,200,xe)}catch(S){if(S instanceof P||S instanceof j)y(h,S.status,{error:S.message,errorCode:"validation_error",...S instanceof P?{reason:S.reason}:{}});else throw ee(S,"Git \u64CD\u4F5C\u5931\u8D25")}return}if(k==="/api/workspace/files/list"||k==="/api/workspace/files/preview"){let v=r.snapshot();if(d.sessionId!==v.sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("path"in d)||typeof d.path!="string"||d.path.length>4096){y(h,400,{error:"\u5DE5\u4F5C\u533A\u6587\u4EF6\u8DEF\u5F84\u65E0\u6548"});return}try{let S=k.endsWith("/list")?await Dt(v.cwd,d.path):await Se(v.cwd,d.path),_=r.snapshot();if(_.sessionId!==v.sessionId||_.cwd!==v.cwd){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}y(h,200,S)}catch(S){if(S instanceof j)y(h,S.status,{error:S.message,errorCode:"validation_error"});else throw ee(S,"\u5DE5\u4F5C\u533A\u6587\u4EF6\u8BFB\u53D6\u5931\u8D25")}return}if(k==="/api/plugin-interaction"){if(d.sessionId!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("pluginId"in d)||typeof d.pluginId!="string"||d.pluginId.length>200||!("requestId"in d)||typeof d.requestId!="string"||d.requestId.length>200||!r.resolvePluginInteraction||!("value"in d)){y(h,400,{error:"\u63D2\u4EF6\u4EA4\u4E92\u54CD\u5E94\u65E0\u6548"});return}await ce(r.snapshot().cwd,async()=>r.resolvePluginInteraction(d.sessionId,d.pluginId,d.requestId,d.value),!0),y(h,200,{accepted:!0});return}if(k==="/api/plugin-action"){if(d.sessionId!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("pluginId"in d)||typeof d.pluginId!="string"||d.pluginId.length>200||!("action"in d)||typeof d.action!="string"||d.action.length>100||!r.invokePluginAction){y(h,400,{error:"\u63D2\u4EF6\u52A8\u4F5C\u65E0\u6548"});return}let v=await ce(r.snapshot().cwd,async()=>r.invokePluginAction(d.sessionId,d.pluginId,d.action,"input"in d?d.input:void 0),!0);y(h,200,{value:v});return}if(k==="/api/update"){if(d.sessionId!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!r.snapshot().idle){y(h,409,{error:"\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u540E\u518D\u5347\u7EA7"});return}if(!r.selfUpdate){y(h,409,{error:"\u5F53\u524D\u6269\u5C55\u4E0D\u652F\u6301\u5728\u7EBF\u5347\u7EA7"});return}let v=await r.selfUpdate.prepare();g=!0,y(h,202,{accepted:!0,version:v.version}),setTimeout(()=>{r.selfUpdate?.requestRestart(v).catch(S=>{g=!1,t.capture(S,{stage:"restart"}),console.error("pi-webapp restart:",S)})},500).unref();return}if(k==="/api/provider/custom"){if(d.sessionId!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("provider"in d)||!et(d.provider)||!r.addCustomProvider){y(h,400,{error:"\u81EA\u5B9A\u4E49\u63D0\u4F9B\u65B9\u65E0\u6548"});return}await r.addCustomProvider(d.sessionId,d.provider),y(h,201,{accepted:!0});return}if(k==="/api/provider/models"||k==="/api/provider/logout"){if(d.sessionId!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!("providerId"in d)||typeof d.providerId!="string"){y(h,400,{error:"\u63D0\u4F9B\u65B9\u65E0\u6548"});return}if(k==="/api/provider/models"){if(!("change"in d)||!dr(d.change)||!r.updateProviderModel){y(h,400,{error:"\u6A21\u578B\u53C2\u6570\u65E0\u6548"});return}await r.updateProviderModel(d.sessionId,d.providerId,d.change)}else{if(!r.logoutProvider){y(h,400,{error:"\u65E0\u6CD5\u79FB\u9664\u8BA4\u8BC1"});return}await r.logoutProvider(d.sessionId,d.providerId)}y(h,200,{accepted:!0});return}if(k.startsWith("/api/provider/login")){if(d.sessionId!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(k==="/api/provider/login"){if(!("providerId"in d)||typeof d.providerId!="string"||!("method"in d)||d.method!=="api_key"&&d.method!=="oauth"||!r.loginProvider||!r.providers){y(h,400,{error:"\u767B\u5F55\u65B9\u5F0F\u65E0\u6548"});return}if(!(await r.providers()).some(B=>B.id===d.providerId&&B.methods.includes(d.method))){y(h,400,{error:"\u63D0\u4F9B\u65B9\u4E0D\u652F\u6301\u6B64\u767B\u5F55\u65B9\u5F0F"});return}let S="initialSecret"in d?d.initialSecret:void 0;if(S!==void 0&&(d.method!=="api_key"||typeof S!="string"||!S.trim()||S.length>16384)){y(h,400,{error:"API Key \u65E0\u6548"});return}let _=c.start(d.providerId,d.method,r.loginProvider,S,O);y(h,202,{id:_.id});return}if(!("id"in d)||typeof d.id!="string"){y(h,400,{error:"\u767B\u5F55\u6D41\u7A0B\u65E0\u6548"});return}if(k==="/api/provider/login/cancel"){y(h,c.cancel(d.id)?202:404,{accepted:!0});return}if(!("value"in d)||typeof d.value!="string"||d.value.length>16384||!c.respond(d.id,d.value)){y(h,400,{error:"\u767B\u5F55\u8F93\u5165\u65E0\u6548"});return}y(h,202,{accepted:!0});return}if(k==="/api/attachment/remove"){if(!("id"in d)||typeof d.id!="string"||d.sessionId!==r.snapshot().sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u9644\u4EF6\u65E0\u6548"});return}m.get(d.id)?.sessionId===d.sessionId&&m.delete(d.id),y(h,202,{accepted:!0});return}if(k==="/api/directory/pick"){if(a!=="native"){y(h,409,{error:"\u672C\u5730\u76EE\u5F55\u9009\u62E9\u5668\u4E0D\u53EF\u7528"});return}let v=new AbortController;h.once("close",()=>v.abort()),y(h,200,{path:await rr(v.signal)});return}if(k==="/api/directory/list"){if("path"in d&&(typeof d.path!="string"||d.path.length>4096)){y(h,400,{error:"\u76EE\u5F55\u8DEF\u5F84\u65E0\u6548"});return}y(h,200,await Ct("path"in d?d.path:void 0));return}if(k==="/api/directory/create"){if(!("path"in d)||typeof d.path!="string"||d.path.length>4096||!("name"in d)||typeof d.name!="string"||d.name.length>255){y(h,400,{error:"\u6587\u4EF6\u5939\u540D\u79F0\u6216\u8DEF\u5F84\u65E0\u6548"});return}y(h,200,{path:await _t(d.path,d.name)});return}if(k==="/api/workspace/add"){if(!("path"in d)||typeof d.path!="string"||d.path.length>4096||!("create"in d)||typeof d.create!="boolean"){y(h,400,{error:"\u5DE5\u4F5C\u533A\u8DEF\u5F84\u65E0\u6548"});return}await r.addWorkspace(d.path,d.create),y(h,202,{accepted:!0});return}if(k==="/api/workspace/select"||k==="/api/workspace/remove"||k==="/api/workspace/new-session"){if(!("id"in d)||typeof d.id!="string"){y(h,400,{error:"\u5DE5\u4F5C\u533A\u65E0\u6548"});return}k==="/api/workspace/select"?await r.selectWorkspace(d.id):k==="/api/workspace/new-session"?await r.newSessionInWorkspace(d.id):await r.removeWorkspace(d.id),y(h,202,{accepted:!0});return}if(k==="/api/session/select"){if(!("workspaceId"in d)||typeof d.workspaceId!="string"||!("id"in d)||typeof d.id!="string"||!("path"in d)||typeof d.path!="string"){y(h,400,{error:"\u4F1A\u8BDD\u65E0\u6548"});return}await r.selectSession(d.workspaceId,d.id,d.path),y(h,202,{accepted:!0});return}if(k==="/api/thinking-level"){if(!("level"in d)||typeof d.level!="string"){y(h,400,{error:"\u63A8\u7406\u5F3A\u5EA6\u65E0\u6548"});return}await r.setThinkingLevel(d.sessionId,d.level)}else if(k==="/api/model"){if(!("provider"in d)||typeof d.provider!="string"||!("id"in d)||typeof d.id!="string"){y(h,400,{error:"\u6A21\u578B\u65E0\u6548"});return}await r.setModel(d.sessionId,d.provider,d.id)}else if(k==="/api/config"){let v=d;if(!["packages","extensions","skills"].includes(v.kind)||!["global","project"].includes(v.scope)||!["add","remove"].includes(v.action)||typeof v.value!="string"||!v.value.trim()||v.value.length>2048){y(h,400,{error:"\u914D\u7F6E\u9879\u65E0\u6548"});return}if(v.action==="add"&&v.kind!=="packages"&&gr(v.value)){y(h,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}y(h,200,await r.updateConfig(v));return}else if(k==="/api/message"){let v="attachments"in d?d.attachments:[];if(!Array.isArray(v)||v.length>nr||v.some(M=>typeof M!="string")||new Set(v).size!==v.length){y(h,400,{error:"\u9644\u4EF6\u65E0\u6548\u6216\u8FC7\u591A"});return}let S=v.map(M=>m.get(M));if(S.some(M=>!M||M.sessionId!==d.sessionId)){y(h,400,{error:"\u9644\u4EF6\u4E0D\u53EF\u7528"});return}if(!("text"in d)||typeof d.text!="string"||!d.text.trim()&&v.length===0||d.text.length>32e3){y(h,400,{error:"\u6D88\u606F\u65E0\u6548\u6216\u8FC7\u957F"});return}let _=S,B=[d.text.trim(),..._.map(M=>`\u9644\u4EF6 ${JSON.stringify(M.name)}\uFF1A${M.path}`)].filter(Boolean).join(`
|
|
28
28
|
|
|
29
|
-
`),xe=await Promise.all(_.filter(M=>["image/png","image/jpeg","image/webp","image/gif"].includes(M.mediaType)).map(or));O.operationId??=st(),h.setHeader("X-Operation-ID",O.operationId),t.breadcrumb("send",{...O,attachmentCount:_.length}),await ce(r.snapshot().cwd,async()=>r.send(d.sessionId,B,xe,O),!0);for(let M of v)m.delete(M)}else if(k==="/api/compact"){if(!r.compact)throw new Error("\u5F53\u524D\u4F1A\u8BDD\u4E0D\u652F\u6301\u538B\u7F29");await r.compact(d.sessionId)}else if(k==="/api/resume"){let v=r.snapshot();if(d.sessionId!==v.sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!v.idle){y(h,409,{error:"Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F"});return}if(!v.paused){y(h,409,{error:"\u5F53\u524D\u4F1A\u8BDD\u6CA1\u6709\u6682\u505C\u7684\u4EFB\u52A1"});return}if(v.interactions?.length){y(h,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");O.operationId??=st(),h.setHeader("X-Operation-ID",O.operationId),t.breadcrumb("resume",{...O}),await ce(v.cwd,async()=>r.resume(d.sessionId,O),!0)}else k==="/api/abort"?await r.abort(d.sessionId):await r.newSession(d.sessionId);y(h,202,{accepted:!0})}catch(d){if(d instanceof P){y(h,d.status,{error:d.message,errorCode:"validation_error",reason:d.reason});return}let v=d instanceof Error?d.message:"\u8BF7\u6C42\u5931\u8D25";$(d,v==="\u4F1A\u8BDD\u5DF2\u5207\u6362"?409:400,v)}return}y(h,404,{error:"\u672A\u627E\u5230"})}catch(F){h.headersSent?(t.capture(F,{...O,route:k,stage:"http_stream"}),h.end()):$(F,500,"\u8BF7\u6C42\u5931\u8D25")}}),C=Number(process.env.PI_WEBAPP_RESTART_PORT),H;try{H=await is(I,Number.isInteger(C)&&C>0&&C<65536&&i===n?C:0)}catch(b){throw t.capture(b,{stage:"listen"}),await t.close(),b}return
|
|
29
|
+
`),xe=await Promise.all(_.filter(M=>["image/png","image/jpeg","image/webp","image/gif"].includes(M.mediaType)).map(or));O.operationId??=st(),h.setHeader("X-Operation-ID",O.operationId),t.breadcrumb("send",{...O,attachmentCount:_.length}),await ce(r.snapshot().cwd,async()=>r.send(d.sessionId,B,xe,O),!0);for(let M of v)m.delete(M)}else if(k==="/api/compact"){if(!r.compact)throw new Error("\u5F53\u524D\u4F1A\u8BDD\u4E0D\u652F\u6301\u538B\u7F29");await r.compact(d.sessionId)}else if(k==="/api/resume"){let v=r.snapshot();if(d.sessionId!==v.sessionId){y(h,409,{error:"\u4F1A\u8BDD\u5DF2\u5207\u6362"});return}if(!v.idle){y(h,409,{error:"Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F"});return}if(!v.paused){y(h,409,{error:"\u5F53\u524D\u4F1A\u8BDD\u6CA1\u6709\u6682\u505C\u7684\u4EFB\u52A1"});return}if(v.interactions?.length){y(h,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");O.operationId??=st(),h.setHeader("X-Operation-ID",O.operationId),t.breadcrumb("resume",{...O}),await ce(v.cwd,async()=>r.resume(d.sessionId,O),!0)}else k==="/api/abort"?await r.abort(d.sessionId):await r.newSession(d.sessionId);y(h,202,{accepted:!0})}catch(d){if(d instanceof P){y(h,d.status,{error:d.message,errorCode:"validation_error",reason:d.reason});return}let v=d instanceof Error?d.message:"\u8BF7\u6C42\u5931\u8D25";$(d,v==="\u4F1A\u8BDD\u5DF2\u5207\u6362"?409:400,v)}return}y(h,404,{error:"\u672A\u627E\u5230"})}catch(F){h.headersSent?(t.capture(F,{...O,route:k,stage:"http_stream"}),h.end()):$(F,500,"\u8BF7\u6C42\u5931\u8D25")}}),C=Number(process.env.PI_WEBAPP_RESTART_PORT),H;try{H=await is(I,Number.isInteger(C)&&C>0&&C<65536&&i===n?C:0)}catch(b){throw t.capture(b,{stage:"listen"}),await t.close(),b}return u=`http://127.0.0.1:${H}`,{protocolVersion:7,buildId:J,reportError(b,h){return t.capture(b,h)},breadcrumb(b,h){t.breadcrumb(b,h)},url:`${u}/#${n}`,publish(b){if(b.type==="snapshot"&&f(b.session),b.type==="error"&&!b.errorCode&&(b={...b,errorCode:"unexpected_error",errorId:t.capture(new Error("Agent execution failed"),{stage:"agent",requestId:b.requestId,operationId:b.operationId})}),b.type==="error"&&(b={...b,errorReported:b.errorReported??t.enabled}),b.type==="snapshot")for(let[E,R]of m)R.sessionId!==b.session.sessionId&&m.delete(E);let h=`${JSON.stringify(b)}
|
|
30
30
|
`;for(let E of l)E.write(h)},async close(b){c.close();for(let E of w)E.end();w.clear(),await p.close();for(let E of l)E.end(`${JSON.stringify({type:"shutdown",reconnect:b?.reconnect??g})}
|
|
31
|
-
`);l.clear();let h;try{await new Promise((E,R)=>{I.close(Z=>Z?R(Z):E()),h=setTimeout(()=>I.closeAllConnections(),50).unref()})}finally{clearTimeout(h),await t.close()}}}}import{getSupportedThinkingLevels as ns}from"@earendil-works/pi-ai";function Tr(r){let e=[],t=r;for(;;){let i=/(^|\n\n)附件 ("(?:\\.|[^"\\])*"):([^\n]+)$/u.exec(t);if(!i||!/[\\/]pi-web[\\/]attachments[\\/][a-f0-9]{64}[\\/]/u.test(i[3]))break;let n;try{n=JSON.parse(i[2])}catch{break}e.unshift({name:n,image:/\.(?:png|jpe?g|webp|gif)$/iu.test(n)}),t=t.slice(0,i.index)}return{text:t,attachments:e}}var we="pi-webapp/paused",ot="pi-webapp/resume";function ye(r){for(let e=r.length-1;e>=0;e--){let t=r[e];if(t.type==="custom_message"&&t.customType===ot)return!1;if(t.type==="custom"&&t.customType===we)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 at(r,e){let t=[],i;for(let n of r){if(n.type==="message"&&(i=n.id),n.type!=="custom")continue;let s=e.find(a=>n.customType.startsWith(`${a}/`));if(s){try{if(JSON.stringify(n.data).length>128*1024)continue}catch{continue}t.push({id:n.id,pluginId:s,kind:n.customType,data:n.data,timestamp:n.timestamp,...i?{afterMessageId:i}:{}})}}return t}function re(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 We(r){if(r.type==="custom_message")return r.display?{id:r.id,role:"notice",timestamp:r.timestamp,blocks:re(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:re(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:re(e.content),isError:e.isError,toolCallId:e.toolCallId,toolName:e.toolName}:null}function De(r,e){let t=r?.trim();if(t)return t;let i=e.find(s=>s.role==="user"),n=Tr(i?.blocks.find(s=>s.kind==="text")?.text??"").text.replace(/\s+/g," ").trim();return n?n.slice(0,50):"\u5F53\u524D\u4F1A\u8BDD"}function ct(r,e,t=[]){let i=r.sessionManager.getBranch().flatMap(n=>{let s=We(n);return s?[s]:[]});return{schemaVersion:1,sessionId:r.sessionManager.getSessionId(),cwd:r.cwd,name:De(e,i),model:r.model?`${r.model.provider}/${r.model.id}`:null,thinkingLevel:r.thinkingLevel??null,thinkingLevels:r.model?ns(r.model):["off"],idle:r.isIdle(),paused:ye(r.sessionManager.getBranch()),contextUsage:r.getContextUsage()??null,messages:i,pluginEntries:at(r.sessionManager.getBranch(),t)}}import{randomUUID as lt}from"node:crypto";import{mkdir as Ar,readFile as ss,realpath as dt,rename as os,rm as as,stat as pt,writeFile as cs}from"node:fs/promises";import{basename as Mr,dirname as ls,isAbsolute as Rr,join as ds}from"node:path";var be=class extends Error{constructor(){super("\u5DE5\u4F5C\u533A\u76EE\u5F55\u4E0D\u53EF\u7528\uFF0C\u8BF7\u6062\u590D\u76EE\u5F55\u6216\u4ECE\u5217\u8868\u79FB\u9664\u540E\u91CD\u65B0\u6DFB\u52A0")}};async function de(r){try{let e=await dt(r);return(await pt(e)).isDirectory()?e:null}catch(e){let t=e.code;if(t==="ENOENT"||t==="ENOTDIR")return null;throw e}}async function ie(r){let e=await de(r);if(e===null)throw new be;return e}var Oe=class{items=[];hiddenPaths=[];mutationChain=Promise.resolve();file;constructor(e){this.file=e}async load(){try{let e=JSON.parse(await ss(this.file,"utf8")),t,i=[];if(Array.isArray(e)?t=e:e&&typeof e=="object"&&"version"in e&&e.version===2&&"items"in e&&"hiddenPaths"in e&&(t=e.items,i=e.hiddenPaths),!Array.isArray(t)||!Array.isArray(i))throw new Error("\u5DE5\u4F5C\u533A\u8BB0\u5F55\u65E0\u6548");this.items=t.filter(n=>typeof n=="object"&&n!==null&&typeof n.id=="string"&&typeof n.path=="string"&&typeof n.title=="string"),this.hiddenPaths=i.filter(n=>typeof n=="string")}catch(e){if(e.code!=="ENOENT")throw e}}list(){return[...this.items]}get(e){return this.items.find(t=>t.id===e)}async add(e,t=!1){if(!Rr(e)||e.includes("\0"))throw new Error("\u8BF7\u8F93\u5165\u5B8C\u6574\u7684\u76EE\u5F55\u8DEF\u5F84");t&&await Ar(e,{recursive:!0});let i=await dt(e);if(!(await pt(i)).isDirectory())throw new Error("\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55");return this.mutate(async()=>{let n=this.hiddenPaths.filter(p=>p!==i),s=this.items.find(p=>p.path===i);if(s)return n.length!==this.hiddenPaths.length&&(await this.save(this.items,n),this.hiddenPaths=n),s;let a={id:lt(),path:i,title:Mr(i)||i},l=[a,...this.items];return await this.save(l,n),this.items=l,this.hiddenPaths=n,a})}async discover(e){let t=(await Promise.all([...new Set(e)].filter(Rr).map(async i=>{try{let n=await dt(i);return(await pt(n)).isDirectory()?n:null}catch{return null}}))).filter(i=>i!==null);await this.mutate(async()=>{let i=new Set([...this.items.map(a=>a.path),...this.hiddenPaths]),n=[];for(let a of t)i.has(a)||(i.add(a),n.push({id:lt(),path:a,title:Mr(a)||a}));if(n.length===0)return;let s=[...this.items,...n];await this.save(s,this.hiddenPaths),this.items=s})}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(s=>s.id!==e),n=[...new Set([...this.hiddenPaths,t.path])];await this.save(i,n),this.items=i,this.hiddenPaths=n})}mutate(e){let t=this.mutationChain.then(e,e);return this.mutationChain=t.then(()=>{},()=>{}),t}async save(e,t){await Ar(ls(this.file),{recursive:!0});let i=`${this.file}.${lt()}.tmp`;try{await cs(i,JSON.stringify({version:2,items:e,hiddenPaths:t},null,2),{mode:384}),await os(i,this.file)}catch(n){throw await as(i,{force:!0}),n}}};function Nr(r){return ds(r,"pi-web","workspaces.json")}import{createAgentSession as zs,createEventBus as Hs,DefaultResourceLoader as Js,getAgentDir as Ks,SessionManager as $e,VERSION as Le}from"@earendil-works/pi-coding-agent";var ps="pi-webapp:interaction-open:v1",us="pi-webapp:interaction-accept:v1",Wr="pi-webapp:interaction-settle:v1",fs="pi-webapp:interaction-cancel:v1";var pe=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(ps,n=>{!ms(n)||!t(n)||this.requests.has(n.requestId)||(this.requests.set(n.requestId,n),e.emit(us,{requestId:n.requestId}),i())}),e.on(fs,n=>{let s=n,a=this.requests.get(s?.requestId);a&&a.sessionId===s.sessionId&&a.pluginId===s.pluginId&&(this.requests.delete(s.requestId),i())})]}pending(e){return[...this.requests.values()].filter(t=>t.sessionId===e)}resolve(e,t,i,n){let s=this.requests.get(i);if(!s||s.sessionId!==e||s.pluginId!==t||!this.accepts(s))throw new Error("Interaction expired or session changed");this.requests.delete(i),this.bus.emit(Wr,{requestId:i,value:n}),this.changed()}cancelAll(e="Session changed"){for(let t of this.requests.values())this.bus.emit(Wr,{requestId:t.requestId,error:e});this.requests.clear(),this.changed()}dispose(){for(let e of this.detach)e();this.cancelAll("Interaction host unloaded")}};function ms(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 gs=1,hs="pi-webapp:action:v1",ws="pi-webapp:action-response:v1",Fe="pi-webapp:plugin-changed:v1";function Dr(r){if(!r||typeof r!="object")return!1;let e=r;return e.apiVersion===gs&&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 Be(r,e,t=15e3,i){return new Promise((n,s)=>{let a=!1,l=(c,u)=>{a||(a=!0,clearTimeout(w),p(),i?.removeEventListener("abort",m),c?s(c):n(u))},p=r.on(ws,c=>{let u=c;u?.requestId===e.requestId&&l(u.ok?null:new Error(u.error??"Plugin action failed"),u.value)}),w=setTimeout(()=>l(new Error(`Plugin action timed out: ${e.pluginId}/${e.action}`)),t),m=()=>l(new Error("Plugin action runtime unloaded"));if(i?.addEventListener("abort",m,{once:!0}),i?.aborted)m();else try{r.emit(hs,e)}catch(c){l(c instanceof Error?c:new Error(String(c)))}})}import{realpath as qs}from"node:fs/promises";import{readFile as ut,realpath as jr,stat as $r}from"node:fs/promises";import{createHash as ys}from"node:crypto";import{dirname as Or,isAbsolute as bs,join as ft,parse as vs,resolve as ks,sep as Es,delimiter as xs}from"node:path";import{DefaultPackageManager as Ps,getAgentDir as Ss,SettingsManager as Is}from"@earendil-works/pi-coding-agent";async function Fr(r,e){let t=await ut(r),i=e?await ut(e):void 0;if(t.length>8*1024*1024||(i?.length??0)>8*1024*1024)throw new Error("Plugin asset exceeds 8 MB");let n=ys("sha256").update(t).update("\0").update(i??"").digest("hex");return{clientBytes:t,styleBytes:i,revision:n}}function Cs(){return(process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS??"").split(xs).filter(Boolean).map(r=>ks(r))}async function _s(r){let e=Or(r);for(;e!==vs(e).root;)try{return await $r(ft(e,"package.json")),e}catch{e=Or(e)}return null}async function Br(r,e){let t=await jr(ft(r,e));if(!t.startsWith(r+Es))throw new Error("Asset escapes package root");let i=await $r(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 ne=class r{plugins;errors;extensionRoots;constructor(e,t,i){this.plugins=e,this.errors=t,this.extensionRoots=i}static async discover(e,t,i=Cs()){let n=Is.create(e,void 0,{projectTrusted:t}),s=new Ps({cwd:e,agentDir:Ss(),settingsManager:n}),a=await s.resolve(async()=>"skip"),l=i.length?await s.resolveExtensionSources(i,{temporary:!0}):{extensions:[]},p=new Set;for(let f of[...a.extensions,...l.extensions]){if(!f.enabled)continue;let g=await _s(f.path);g&&p.add(g)}for(let f of i)bs(f)&&p.add(f);let w=[],m=[],c=[],u=new Set;for(let f of p)try{let g=await jr(f),x=JSON.parse(await ut(ft(g,"package.json"),"utf8"));if(x.piWebapp===void 0)continue;if(typeof x.name!="string"||!x.name)throw new Error("Missing package name");if(!Dr(x.piWebapp))throw new Error("Unsupported piWebapp manifest or asset path");if(u.has(x.name))throw new Error(`Duplicate plugin id: ${x.name}`);let I=await Br(g,x.piWebapp.client),C=x.piWebapp.style?await Br(g,x.piWebapp.style):void 0;u.add(x.name),w.push({id:x.name,root:g,manifest:x.piWebapp,clientPath:I,stylePath:C,...await Fr(I,C)}),c.push(g)}catch(g){m.push(`${f}: ${g instanceof Error?g.message:String(g)}`)}return w.sort((f,g)=>f.id.localeCompare(g.id)),new r(w,m,c)}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 Fr(e.clientPath,e.stylePath))}view(){return{plugins:this.plugins.map(e=>({id:e.id,client:`/plugins/${encodeURIComponent(e.id)}/client.js?v=${e.revision}`,...e.stylePath?{style:`/plugins/${encodeURIComponent(e.id)}/client.css?v=${e.revision}`}:{}})),errors:this.errors}}async asset(e){let t=new URL(e,"http://localhost"),i=/^\/plugins\/([^/]+)\/(client\.js|client\.css)$/.exec(t.pathname);if(!i)return null;let n;try{n=decodeURIComponent(i[1])}catch{return null}let s=this.plugins.find(l=>l.id===n);if(!s||t.searchParams.has("v")&&t.searchParams.get("v")!==s.revision)return null;let a=i[2]==="client.js"?s.clientBytes:s.styleBytes;return a?{bytes:a,type:i[2]==="client.js"?"text/javascript; charset=utf-8":"text/css; charset=utf-8"}:null}};import{realpath as Ts}from"node:fs/promises";import{SessionManager as As}from"@earendil-works/pi-coding-agent";async function ve(r,e){let t=await ie(r),i=e??await As.listAll(),n=await Promise.all(i.map(async s=>s.cwd!==""&&await Ts(s.cwd).catch(()=>null)===t));return i.filter((s,a)=>n[a])}var se=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))}},Lr=new WeakMap;function Gr(r,e,t,i=5e3,n=()=>{}){let s=Lr.get(r);if(s)return s;let a=(async()=>{let l;try{await Promise.race([r.extensionRunner.emit({type:"session_shutdown",reason:e}),new Promise((p,w)=>{l=setTimeout(()=>w(new Error("Plugin shutdown timed out")),i)})])}catch(p){t(p instanceof Error?p.message:String(p))}finally{clearTimeout(l);try{n()}finally{r.dispose()}}})();return Lr.set(r,a),a}function je(r){let t=[...r].reverse().find(i=>i.role==="assistant")?.blocks.filter(i=>i.kind==="text").map(i=>i.text).join(`
|
|
31
|
+
`);l.clear();let h;try{await new Promise((E,R)=>{I.close(Z=>Z?R(Z):E()),h=setTimeout(()=>I.closeAllConnections(),50).unref()})}finally{clearTimeout(h),await t.close()}}}}import{getSupportedThinkingLevels as ns}from"@earendil-works/pi-ai";function Tr(r){let e=[],t=r;for(;;){let i=/(^|\n\n)附件 ("(?:\\.|[^"\\])*"):([^\n]+)$/u.exec(t);if(!i||!/[\\/]pi-web[\\/]attachments[\\/][a-f0-9]{64}[\\/]/u.test(i[3]))break;let n;try{n=JSON.parse(i[2])}catch{break}e.unshift({name:n,image:/\.(?:png|jpe?g|webp|gif)$/iu.test(n)}),t=t.slice(0,i.index)}return{text:t,attachments:e}}var we="pi-webapp/paused",ot="pi-webapp/resume";function ye(r){for(let e=r.length-1;e>=0;e--){let t=r[e];if(t.type==="custom_message"&&t.customType===ot)return!1;if(t.type==="custom"&&t.customType===we)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 at(r,e){let t=[],i;for(let n of r){if(n.type==="message"&&(i=n.id),n.type!=="custom")continue;let s=e.find(a=>n.customType.startsWith(`${a}/`));if(s){try{if(JSON.stringify(n.data).length>128*1024)continue}catch{continue}t.push({id:n.id,pluginId:s,kind:n.customType,data:n.data,timestamp:n.timestamp,...i?{afterMessageId:i}:{}})}}return t}function re(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 We(r){if(r.type==="custom_message")return r.display?{id:r.id,role:"notice",timestamp:r.timestamp,blocks:re(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:re(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:re(e.content),isError:e.isError,toolCallId:e.toolCallId,toolName:e.toolName}:null}function De(r,e){let t=r?.trim();if(t)return t;let i=e.find(s=>s.role==="user"),n=Tr(i?.blocks.find(s=>s.kind==="text")?.text??"").text.replace(/\s+/g," ").trim();return n?n.slice(0,50):"\u5F53\u524D\u4F1A\u8BDD"}function ct(r,e,t=[]){let i=r.sessionManager.getBranch().flatMap(n=>{let s=We(n);return s?[s]:[]});return{schemaVersion:1,sessionId:r.sessionManager.getSessionId(),cwd:r.cwd,name:De(e,i),model:r.model?`${r.model.provider}/${r.model.id}`:null,thinkingLevel:r.thinkingLevel??null,thinkingLevels:r.model?ns(r.model):["off"],idle:r.isIdle(),paused:ye(r.sessionManager.getBranch()),contextUsage:r.getContextUsage()??null,messages:i,pluginEntries:at(r.sessionManager.getBranch(),t)}}import{randomUUID as lt}from"node:crypto";import{mkdir as Ar,readFile as ss,realpath as dt,rename as os,rm as as,stat as pt,writeFile as cs}from"node:fs/promises";import{basename as Mr,dirname as ls,isAbsolute as Rr,join as ds}from"node:path";var be=class extends Error{constructor(){super("\u5DE5\u4F5C\u533A\u76EE\u5F55\u4E0D\u53EF\u7528\uFF0C\u8BF7\u6062\u590D\u76EE\u5F55\u6216\u4ECE\u5217\u8868\u79FB\u9664\u540E\u91CD\u65B0\u6DFB\u52A0")}};async function de(r){try{let e=await dt(r);return(await pt(e)).isDirectory()?e:null}catch(e){let t=e.code;if(t==="ENOENT"||t==="ENOTDIR")return null;throw e}}async function ie(r){let e=await de(r);if(e===null)throw new be;return e}var Oe=class{items=[];hiddenPaths=[];mutationChain=Promise.resolve();file;constructor(e){this.file=e}async load(){try{let e=JSON.parse(await ss(this.file,"utf8")),t,i=[];if(Array.isArray(e)?t=e:e&&typeof e=="object"&&"version"in e&&e.version===2&&"items"in e&&"hiddenPaths"in e&&(t=e.items,i=e.hiddenPaths),!Array.isArray(t)||!Array.isArray(i))throw new Error("\u5DE5\u4F5C\u533A\u8BB0\u5F55\u65E0\u6548");this.items=t.filter(n=>typeof n=="object"&&n!==null&&typeof n.id=="string"&&typeof n.path=="string"&&typeof n.title=="string"),this.hiddenPaths=i.filter(n=>typeof n=="string")}catch(e){if(e.code!=="ENOENT")throw e}}list(){return[...this.items]}get(e){return this.items.find(t=>t.id===e)}async add(e,t=!1){if(!Rr(e)||e.includes("\0"))throw new Error("\u8BF7\u8F93\u5165\u5B8C\u6574\u7684\u76EE\u5F55\u8DEF\u5F84");t&&await Ar(e,{recursive:!0});let i=await dt(e);if(!(await pt(i)).isDirectory())throw new Error("\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55");return this.mutate(async()=>{let n=this.hiddenPaths.filter(p=>p!==i),s=this.items.find(p=>p.path===i);if(s)return n.length!==this.hiddenPaths.length&&(await this.save(this.items,n),this.hiddenPaths=n),s;let a={id:lt(),path:i,title:Mr(i)||i},l=[a,...this.items];return await this.save(l,n),this.items=l,this.hiddenPaths=n,a})}async discover(e){let t=(await Promise.all([...new Set(e)].filter(Rr).map(async i=>{try{let n=await dt(i);return(await pt(n)).isDirectory()?n:null}catch{return null}}))).filter(i=>i!==null);await this.mutate(async()=>{let i=new Set([...this.items.map(a=>a.path),...this.hiddenPaths]),n=[];for(let a of t)i.has(a)||(i.add(a),n.push({id:lt(),path:a,title:Mr(a)||a}));if(n.length===0)return;let s=[...this.items,...n];await this.save(s,this.hiddenPaths),this.items=s})}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(s=>s.id!==e),n=[...new Set([...this.hiddenPaths,t.path])];await this.save(i,n),this.items=i,this.hiddenPaths=n})}mutate(e){let t=this.mutationChain.then(e,e);return this.mutationChain=t.then(()=>{},()=>{}),t}async save(e,t){await Ar(ls(this.file),{recursive:!0});let i=`${this.file}.${lt()}.tmp`;try{await cs(i,JSON.stringify({version:2,items:e,hiddenPaths:t},null,2),{mode:384}),await os(i,this.file)}catch(n){throw await as(i,{force:!0}),n}}};function Nr(r){return ds(r,"pi-web","workspaces.json")}import{createAgentSession as zs,createEventBus as Hs,DefaultResourceLoader as Js,getAgentDir as Ks,SessionManager as $e,VERSION as Le}from"@earendil-works/pi-coding-agent";var ps="pi-webapp:interaction-open:v1",us="pi-webapp:interaction-accept:v1",Wr="pi-webapp:interaction-settle:v1",fs="pi-webapp:interaction-cancel:v1";var pe=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(ps,n=>{!ms(n)||!t(n)||this.requests.has(n.requestId)||(this.requests.set(n.requestId,n),e.emit(us,{requestId:n.requestId}),i())}),e.on(fs,n=>{let s=n,a=this.requests.get(s?.requestId);a&&a.sessionId===s.sessionId&&a.pluginId===s.pluginId&&(this.requests.delete(s.requestId),i())})]}pending(e){return[...this.requests.values()].filter(t=>t.sessionId===e)}resolve(e,t,i,n){let s=this.requests.get(i);if(!s||s.sessionId!==e||s.pluginId!==t||!this.accepts(s))throw new Error("Interaction expired or session changed");this.requests.delete(i),this.bus.emit(Wr,{requestId:i,value:n}),this.changed()}cancelAll(e="Session changed"){for(let t of this.requests.values())this.bus.emit(Wr,{requestId:t.requestId,error:e});this.requests.clear(),this.changed()}dispose(){for(let e of this.detach)e();this.cancelAll("Interaction host unloaded")}};function ms(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 gs=1,hs="pi-webapp:action:v1",ws="pi-webapp:action-response:v1",Fe="pi-webapp:plugin-changed:v1";function Dr(r){if(!r||typeof r!="object")return!1;let e=r;return e.apiVersion===gs&&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 Be(r,e,t=15e3,i){return new Promise((n,s)=>{let a=!1,l=(c,f)=>{a||(a=!0,clearTimeout(w),p(),i?.removeEventListener("abort",m),c?s(c):n(f))},p=r.on(ws,c=>{let f=c;f?.requestId===e.requestId&&l(f.ok?null:new Error(f.error??"Plugin action failed"),f.value)}),w=setTimeout(()=>l(new Error(`Plugin action timed out: ${e.pluginId}/${e.action}`)),t),m=()=>l(new Error("Plugin action runtime unloaded"));if(i?.addEventListener("abort",m,{once:!0}),i?.aborted)m();else try{r.emit(hs,e)}catch(c){l(c instanceof Error?c:new Error(String(c)))}})}import{realpath as qs}from"node:fs/promises";import{readFile as ut,realpath as jr,stat as $r}from"node:fs/promises";import{createHash as ys}from"node:crypto";import{dirname as Or,isAbsolute as bs,join as ft,parse as vs,resolve as ks,sep as Es,delimiter as xs}from"node:path";import{DefaultPackageManager as Ps,getAgentDir as Ss,SettingsManager as Is}from"@earendil-works/pi-coding-agent";async function Fr(r,e){let t=await ut(r),i=e?await ut(e):void 0;if(t.length>8*1024*1024||(i?.length??0)>8*1024*1024)throw new Error("Plugin asset exceeds 8 MB");let n=ys("sha256").update(t).update("\0").update(i??"").digest("hex");return{clientBytes:t,styleBytes:i,revision:n}}function Cs(){return(process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS??"").split(xs).filter(Boolean).map(r=>ks(r))}async function _s(r){let e=Or(r);for(;e!==vs(e).root;)try{return await $r(ft(e,"package.json")),e}catch{e=Or(e)}return null}async function Br(r,e){let t=await jr(ft(r,e));if(!t.startsWith(r+Es))throw new Error("Asset escapes package root");let i=await $r(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 ne=class r{plugins;errors;extensionRoots;constructor(e,t,i){this.plugins=e,this.errors=t,this.extensionRoots=i}static async discover(e,t,i=Cs()){let n=Is.create(e,void 0,{projectTrusted:t}),s=new Ps({cwd:e,agentDir:Ss(),settingsManager:n}),a=await s.resolve(async()=>"skip"),l=i.length?await s.resolveExtensionSources(i,{temporary:!0}):{extensions:[]},p=new Set;for(let u of[...a.extensions,...l.extensions]){if(!u.enabled)continue;let g=await _s(u.path);g&&p.add(g)}for(let u of i)bs(u)&&p.add(u);let w=[],m=[],c=[],f=new Set;for(let u of p)try{let g=await jr(u),x=JSON.parse(await ut(ft(g,"package.json"),"utf8"));if(x.piWebapp===void 0)continue;if(typeof x.name!="string"||!x.name)throw new Error("Missing package name");if(!Dr(x.piWebapp))throw new Error("Unsupported piWebapp manifest or asset path");if(f.has(x.name))throw new Error(`Duplicate plugin id: ${x.name}`);let I=await Br(g,x.piWebapp.client),C=x.piWebapp.style?await Br(g,x.piWebapp.style):void 0;f.add(x.name),w.push({id:x.name,root:g,manifest:x.piWebapp,clientPath:I,stylePath:C,...await Fr(I,C)}),c.push(g)}catch(g){m.push(`${u}: ${g instanceof Error?g.message:String(g)}`)}return w.sort((u,g)=>u.id.localeCompare(g.id)),new r(w,m,c)}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 Fr(e.clientPath,e.stylePath))}view(){return{plugins:this.plugins.map(e=>({id:e.id,client:`/plugins/${encodeURIComponent(e.id)}/client.js?v=${e.revision}`,...e.stylePath?{style:`/plugins/${encodeURIComponent(e.id)}/client.css?v=${e.revision}`}:{}})),errors:this.errors}}async asset(e){let t=new URL(e,"http://localhost"),i=/^\/plugins\/([^/]+)\/(client\.js|client\.css)$/.exec(t.pathname);if(!i)return null;let n;try{n=decodeURIComponent(i[1])}catch{return null}let s=this.plugins.find(l=>l.id===n);if(!s||t.searchParams.has("v")&&t.searchParams.get("v")!==s.revision)return null;let a=i[2]==="client.js"?s.clientBytes:s.styleBytes;return a?{bytes:a,type:i[2]==="client.js"?"text/javascript; charset=utf-8":"text/css; charset=utf-8"}:null}};import{realpath as Ts}from"node:fs/promises";import{SessionManager as As}from"@earendil-works/pi-coding-agent";async function ve(r,e){let t=await ie(r),i=e??await As.listAll(),n=await Promise.all(i.map(async s=>s.cwd!==""&&await Ts(s.cwd).catch(()=>null)===t));return i.filter((s,a)=>n[a])}var se=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))}},Lr=new WeakMap;function Gr(r,e,t,i=5e3,n=()=>{}){let s=Lr.get(r);if(s)return s;let a=(async()=>{let l;try{await Promise.race([r.extensionRunner.emit({type:"session_shutdown",reason:e}),new Promise((p,w)=>{l=setTimeout(()=>w(new Error("Plugin shutdown timed out")),i)})])}catch(p){t(p instanceof Error?p.message:String(p))}finally{clearTimeout(l);try{n()}finally{r.dispose()}}})();return Lr.set(r,a),a}function je(r){let t=[...r].reverse().find(i=>i.role==="assistant")?.blocks.filter(i=>i.kind==="text").map(i=>i.text).join(`
|
|
32
32
|
`);return{customType:ot,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?`
|
|
33
33
|
Already displayed assistant text (reference data):
|
|
34
|
-
${JSON.stringify(t)}`:"")}}import{createHash as Ms}from"node:crypto";import{readFile as Rs,writeFile as Ns,unlink as Ws}from"node:fs/promises";import{basename as Ds,dirname as Os,extname as Fs,join as Bs}from"node:path";import{DefaultPackageManager as js,getAgentDir as $s,SettingsManager as Ls}from"@earendil-works/pi-coding-agent";var ke=new Map;async function Vr(r,e){let i=await new js({cwd:r,agentDir:$s(),settingsManager:Ls.create(r)}).resolveExtensionSources([...e],{temporary:!0}),n=[],s=[],a=async()=>{for(let l of n.splice(0)){let p=(ke.get(l)??1)-1;p?ke.set(l,p):(ke.delete(l),await Ws(l).catch(()=>{}))}};try{for(let l of i.extensions){if(!l.enabled)continue;let p=Fs(l.path);if(![".js",".mjs"].includes(p)){s.push(l.path);continue}let w=await Rs(l.path),m=Ms("sha256").update(w).digest("hex"),c=Bs(Os(l.path),`.pi-web-runtime-${Ds(l.path,p)}-${m}${p}`);await Ns(c,w,{flag:"wx"}).catch(
|
|
34
|
+
${JSON.stringify(t)}`:"")}}import{createHash as Ms}from"node:crypto";import{readFile as Rs,writeFile as Ns,unlink as Ws}from"node:fs/promises";import{basename as Ds,dirname as Os,extname as Fs,join as Bs}from"node:path";import{DefaultPackageManager as js,getAgentDir as $s,SettingsManager as Ls}from"@earendil-works/pi-coding-agent";var ke=new Map;async function Vr(r,e){let i=await new js({cwd:r,agentDir:$s(),settingsManager:Ls.create(r)}).resolveExtensionSources([...e],{temporary:!0}),n=[],s=[],a=async()=>{for(let l of n.splice(0)){let p=(ke.get(l)??1)-1;p?ke.set(l,p):(ke.delete(l),await Ws(l).catch(()=>{}))}};try{for(let l of i.extensions){if(!l.enabled)continue;let p=Fs(l.path);if(![".js",".mjs"].includes(p)){s.push(l.path);continue}let w=await Rs(l.path),m=Ms("sha256").update(w).digest("hex"),c=Bs(Os(l.path),`.pi-web-runtime-${Ds(l.path,p)}-${m}${p}`);await Ns(c,w,{flag:"wx"}).catch(f=>{if(f.code!=="EEXIST")throw f}),ke.set(c,(ke.get(c)??0)+1),n.push(c),s.push(c)}return{paths:s,release:a}}catch(l){throw await a(),l}}import{createHash as Gs}from"node:crypto";var mt={ENOENT:{kind:"not_found",summary:"no such file or directory"},ENOTDIR:{kind:"not_found",summary:"not a directory"},EACCES:{kind:"permission",summary:"permission denied"},EPERM:{kind:"permission",summary:"operation not permitted"},ETIMEDOUT:{kind:"timeout",summary:"operation timed out"},EINVAL:{kind:"validation",summary:"invalid argument"}},Y=r=>r!==null&&typeof r=="object"?r:void 0,Vs=[{pattern:/^Could not find (?:the exact text in [^\r\n]+\. The old text|edits\[\d+\] in [^\r\n]+\. The oldText) must match exactly including all whitespace and newlines\.$/,code:"edit_text_not_found",summary:"Edit text does not match the file"},{pattern:/^Found \d+ occurrences of (?:the text in [^\r\n]+\. The text|edits\[\d+\] in [^\r\n]+\. Each oldText) must be unique\. Please provide more context to make it unique\.$/,code:"edit_text_ambiguous",summary:"Edit text matches multiple locations"},{pattern:/^(?:edits\[\d+\]\.)?oldText must not be empty in [^\r\n]+\.$/,code:"invalid_arguments",summary:"Edit oldText must not be empty"},{pattern:/^No changes made to [^\r\n]+\. (?:The replacement produced identical content\. This might indicate an issue with special characters or the text not existing as expected\.|The replacements produced identical content\.)$/,code:"edit_no_change",summary:"Edit replacement produced no changes"},{pattern:/^edits\[\d+\] and edits\[\d+\] overlap in [^\r\n]+\. Merge them into one edit or target disjoint regions\.$/,code:"edit_overlap",summary:"Edit replacements overlap"}];function zr(r,e){let t=r instanceof Error?r:Y(r)?.error instanceof Error?Y(r).error:void 0,i={failureKind:"unknown",summaryOmitted:!0,summaryOmittedReason:"unrecognized_diagnostic",originalStackAvailable:!!t?.stack,level:"error"},n=(m,c,f)=>{Object.assign(i,{failureKind:m,errorCode:c,errorSummary:f.slice(0,512),summaryOmitted:!1,level:t?"error":"warning"}),delete i.summaryOmittedReason},s=Y(t)?.code;if(typeof s=="string"&&mt[s]){let m=mt[s];return n(m.kind,s,`${s}: ${m.summary}`),i}let a=t?.message??"";if(!t){let m=Y(r)?.content;Array.isArray(m)&&(a=m.slice(0,8).flatMap(c=>{let f=Y(c);return f?.type==="text"&&typeof f.text=="string"?[f.text.length>16384?`${f.text.slice(0,8192)}
|
|
35
35
|
[truncated]
|
|
36
|
-
${
|
|
36
|
+
${f.text.slice(-8192)}`:f.text]:[]}).join(`
|
|
37
37
|
`))}let l=e==="bash"||e==="powershell",p=a.slice(-8192).trimEnd().split(/\r?\n/).at(-1)??"";if(l){let m=p.match(/^Command exited with code (-?\d{1,10})$/),c=p.match(/^Command timed out after (\d+(?:\.\d+)?) seconds$/);if(m&&Number.isSafeInteger(Number(m[1]))&&Number(m[1])!==0)return n("process_exit","nonzero_exit",p),i.exitCode=Number(m[1]),i;if(c&&Number.isFinite(Number(c[1]))&&Number(c[1])>0)return n("timeout","timeout",p),i.timeoutMs=Number(c[1])*1e3,i;if(p==="Command aborted")return n("cancelled","cancelled",p),i}let w=a.slice(0,8192).split(/\r?\n/,1)[0]??"";if(a==="Operation aborted"||t?.name==="AbortError")n("cancelled","cancelled","Operation aborted");else if(a==="Tool execution was blocked")n("blocked","blocked",a);else if(/^Working directory does not exist: [^\n]+\nCannot execute (?:bash|powershell) commands\.$/.test(a))n("not_found","ENOENT","Working directory does not exist");else if(!l||!a.includes(`
|
|
38
|
-
`)||/^Validation failed for tool\b/.test(w)){let m=w.match(/^(ENOENT|ENOTDIR|EACCES|EPERM|ETIMEDOUT|EINVAL):/);if(m){let c=mt[m[1]],
|
|
38
|
+
`)||/^Validation failed for tool\b/.test(w)){let m=w.match(/^(ENOENT|ENOTDIR|EACCES|EPERM|ETIMEDOUT|EINVAL):/);if(m){let c=mt[m[1]],f=w.match(/, (open|access|stat|lstat|scandir|spawn|read|write|rename|mkdir|unlink)\s/);n(c.kind,m[1],`${m[1]}: ${c.summary}${f?`; operation=${f[1]}`:""}`)}else if(/^Tool [^\r\n]+ not found$/.test(a))n("not_found","tool_not_found","Tool not found");else if(/^Validation failed for tool\b/.test(w)||w==="Edit tool input is invalid. edits must contain at least one replacement."||/^Invalid timeout:/.test(w))n("validation","invalid_arguments",w.startsWith("Invalid timeout:")?"Invalid timeout argument":"Invalid tool arguments");else if(/^Offset \d+ is beyond end of file \(\d+ lines total\)$/.test(a))n("validation","invalid_arguments","Read offset is beyond end of file");else if(e==="edit"){let c=Vs.find(f=>f.pattern.test(a));c&&n("validation",c.code,c.summary)}}return i}var Us=256;function Ur(r,e,t){r.delete(e),r.set(e,t),r.size>Us&&r.delete(r.keys().next().value)}var ue=class{options;pending=new Map;completed=new Map;constructor(e){this.options=e}enabled(){return this.options.enabled()?!0:(this.clear(),!1)}identity(e){return{toolName:Re.has(e.toolName)?e.toolName:"custom",...Re.has(e.toolName)?{}:{toolId:Gs("sha256").update(e.toolName).digest("hex").slice(0,16)},toolCallId:this.options.anonymize(`tool-call:${e.toolCallId}`)}}breadcrumb(e,t){try{this.options.breadcrumb(e,t)}catch{}}start(e,t={}){try{if(!this.enabled()||this.pending.has(e.toolCallId)||this.completed.has(e.toolCallId))return;let i=e.toolName==="bash"||e.toolName==="powershell"?Y(e.args)?.timeout:void 0,n=typeof i=="number"&&i>0&&Number.isFinite(i*1e3)?i*1e3:void 0,s={...z(t),...this.identity(e),stage:"tool"};Ur(this.pending,e.toolCallId,{context:s,started:(this.options.now??performance.now.bind(performance))(),cancelled:!1,timeoutMs:n}),this.breadcrumb("tool_start",s)}catch{}}end(e,t={}){this.finish(e,t,"tool_execution_end")}message(e,t={}){try{if(!this.enabled()||!e.isError)return;this.finish({toolCallId:e.toolCallId,toolName:e.toolName,isError:e.isError,result:{content:e.content}},t,"message_end")}catch{}}finish(e,t,i){try{if(!this.enabled()||this.completed.has(e.toolCallId))return;let n=this.pending.get(e.toolCallId);this.pending.delete(e.toolCallId),Ur(this.completed,e.toolCallId,!0);let s={...n?.context??{...z(t),...this.identity(e),stage:"tool"},diagnosticSource:i};if(n&&(s.durationMs=Math.max(0,Math.round((this.options.now??performance.now.bind(performance))()-n.started)),n.timeoutMs!==void 0&&(s.timeoutMs=n.timeoutMs)),!e.isError){this.breadcrumb("tool_end",s);return}let a=e.result instanceof Error?e.result:Y(e.result)?.error instanceof Error?Y(e.result).error:void 0,l=n?.cancelled&&!a?{failureKind:"cancelled",errorCode:"cancelled",level:"warning",originalStackAvailable:!1,summaryOmitted:!0,summaryOmittedReason:"cancelled"}:zr(e.result,e.toolName);if(Object.assign(s,l,{code:"tool_failed"}),this.breadcrumb(l.failureKind==="cancelled"?"tool_cancelled":l.failureKind==="blocked"?"tool_blocked":"tool_failed",s),l.failureKind==="cancelled"||l.failureKind==="blocked")return;let p;a?p=Hr(a,e.toolName):(p=new Error(`${s.toolName}: ${l.failureKind} (${l.errorCode??"unknown"})`),p.name="ToolResultFailure",p.stack=void 0),this.options.capture(p,s)}catch{}}cancel(){try{if(!this.enabled())return;for(let e of this.pending.values())e.cancelled=!0}catch{}}clear(){this.pending.clear(),this.completed.clear()}};function Hr(r,e,t=0){let i=zr(r,e),n=new Error(i.errorSummary??"Tool exception (diagnostic text unavailable)");return n.name=r.name,n.stack=r.stack?`${n.name}: ${n.message}
|
|
39
39
|
${r.stack.split(`
|
|
40
40
|
`).slice(1).join(`
|
|
41
|
-
`)}`:void 0,t<3&&r.cause instanceof Error&&(n.cause=Hr(r.cause,e,t+1)),le(n)}var Ge=class{telemetryVersion=2;runtimeVersion=1;active=null;runtimes=new Map;selectedByWorkspace=new Map;queue=new se;generation=0;disposed=!1;publish;fallbackModel;isProjectTrusted;reportError;telemetry;onSessionsChanged;constructor(e,t,i=()=>!1,n=()=>{},s={enabled:()=>!1,breadcrumb:()=>{},anonymize:()=>"unavailable"},a=()=>{}){this.publish=e,this.fallbackModel=t,this.isProjectTrusted=i,this.reportError=n,this.onSessionsChanged=a,this.telemetry={enabled:()=>{try{return s.enabled()}catch{return!1}},breadcrumb:(l,p)=>{try{s.enabled()&&s.breadcrumb(l,p)}catch{}},anonymize:l=>{try{return s.enabled()?s.anonymize(l):"unavailable"}catch{return"unavailable"}}}}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 ie(e),n=t==="continue"?this.selectedByWorkspace.get(i):typeof t=="object"&&"sessionId"in t?this.runtimes.get(t.sessionId):void 0;if(n){if(n.cwd!==i)throw new Error("\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A");this.activate(n);return}if(typeof t=="object"&&"sessionId"in t)throw new Error("\u4F1A\u8BDD\u4E0D\u5B58\u5728");let s;if(t==="new")s=$e.create(i);else if(t==="continue"){let l=(await ve(i))[0];s=l?$e.open(l.path):$e.create(i)}else s="sessionManager"in t?t.sessionManager:$e.open(t.sessionFile);if(await qs(s.getCwd())!==i)throw new Error("\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A");let a=this.runtimes.get(s.getSessionId());if(a){if(a.cwd!==i)throw new Error("\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A");this.activate(a);return}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");if(!e.session.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");await this.replace(e.cwd,e.session.sessionManager,"reload")})}ensureAvailable(){if(this.disposed)throw new Error("\u5DE5\u4F5C\u533A\u670D\u52A1\u5DF2\u5173\u95ED")}hasSession(e,t){return this.runtimes.get(t)?.cwd===e}hasWorkspace(e){return this.selectedByWorkspace.has(e)}retainedSessions(){return[...this.runtimes.values()].map(({session:e,cwd:t})=>{let i=e.sessionManager.getBranch(),n=i.flatMap(s=>{let a=We(s);return a?[a]:[]});return{sessionId:e.sessionManager.getSessionId(),cwd:t,path:e.sessionManager.getSessionFile()??null,idle:e.isIdle,name:De(e.sessionManager.getSessionName(),n),modified:i.at(-1)?.timestamp??new Date().toISOString()}})}activate(e){this.ensureAvailable(),this.active=e,this.selectedByWorkspace.set(e.cwd,e),this.publish({type:"snapshot",session:this.snapshotOf(e)}),this.onSessionsChanged()}publishFor(e,t){!this.disposed&&this.active===e&&!e.closing&&this.publish(t)}diagnostic(e,t,i,n){let s=`plugin=${t} session=${e.session.sessionManager.getSessionId()} generation=${e.generation} stage=${i}: ${n}`;console.error(s),this.publishFor(e,{type:"error",message:s})}async replace(e,t,i){let n=this.runtimes.get(t.getSessionId()),s=await ne.discover(e,this.isProjectTrusted(e)),a=Hs(),l=await Vr(e,s.extensionRoots),p=new Js({cwd:e,agentDir:Ks(),noExtensions:!0,additionalExtensionPaths:l.paths,eventBus:a}),w=null;try{await p.reload();let m=p.getExtensions().errors;if(m.length)throw new Error(m.map(E=>`${E.path}: ${E.error}`).join("; "));let c=t.buildSessionProjection().model?void 0:this.active?.session.model??this.fallbackModel(),{session:u}=await zs({cwd:e,sessionManager:t,model:c,resourceLoader:p}),f=new ue({enabled:()=>this.telemetry.enabled(),capture:this.reportError,breadcrumb:(E,R)=>this.telemetry.breadcrumb(E,R),anonymize:E=>this.telemetry.anonymize(E)}),g={session:u,cwd:e,catalog:s,bus:a,generation:++this.generation,closing:!1,waitController:new AbortController,interactions:null,detach:()=>{},releasePaths:l.release,tools:f,streaming:null};w=g;let x=E=>this.publishFor(g,E);g.interactions=new pe(a,E=>!g.closing&&E.sessionId===u.sessionManager.getSessionId()&&s.has(E.pluginId),()=>x({type:"snapshot",session:this.snapshotOf(g)}));let I=0,C=a.on(Fe,()=>x({type:"snapshot",session:this.snapshotOf(g)})),H=u.subscribe(E=>{if(!this.disposed&&!g.closing){let R={...g.operation,session:this.telemetry.anonymize(u.sessionManager.getSessionId()),piVersion:Le,model:u.model?`${u.model.provider}/${u.model.id}`:null,thinkingLevel:u.thinkingLevel};if(E.type==="agent_start"&&this.telemetry.breadcrumb("agent_start",R),E.type==="tool_execution_start"&&f.start(E,R),E.type==="tool_execution_end"&&f.end(E,R),E.type==="message_end"&&E.message.role==="assistant"&&E.message.stopReason==="error"){g.agentErrorReported=!0;let Z=this.reportError(new Error("Agent response failed"),{...g.operation,stage:"agent",code:"agent_failed",piVersion:Le});x({type:"error",message:E.message.errorMessage??"Agent response failed",errorCode:"unexpected_error",errorId:Z,...g.operation})}E.type==="message_end"&&E.message.role==="toolResult"&&f.message(E.message,R),E.type==="agent_settled"&&(this.telemetry.breadcrumb("agent_end",R),f.clear(),g.operation=void 0)}E.type==="message_update"&&E.message.role==="assistant"&&(g.streaming={id:"stream",role:"assistant",timestamp:new Date(E.message.timestamp).toISOString(),blocks:re(E.message.content)},Date.now()-I>=60&&(I=Date.now(),x({type:"stream",message:g.streaming}))),["message_end","agent_start","agent_settled","session_info_changed","entry_appended"].includes(E.type)&&((E.type==="message_end"&&E.message.role==="assistant"||E.type==="agent_settled")&&(g.streaming=null,x({type:"stream",message:null})),x({type:"snapshot",session:this.snapshotOf(g)}),!this.disposed&&!g.closing&&["message_end","agent_start","agent_settled","session_info_changed"].includes(E.type)&&this.onSessionsChanged())});g.detach=()=>{C(),H()};let b=[],h=!0;if(await u.bindExtensions({mode:"print",shutdownHandler:()=>{},onError:E=>{h&&b.push(E.error),this.diagnostic(g,s.plugins.find(R=>E.extensionPath.startsWith(R.root+"/"))?.id??E.extensionPath,E.event??"runtime",E.error)}}),h=!1,b.length)throw new Error(b.join("; "));if(this.ensureAvailable(),n&&!n.session.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(n&&await this.close(n,i),this.disposed)throw new Error("\u5DE5\u4F5C\u533A\u670D\u52A1\u5DF2\u5173\u95ED");this.runtimes.set(u.sessionManager.getSessionId(),g),w=null,this.activate(g)}catch(m){throw w?await this.close(w,"quit"):(a.clear(),await l.release()),m}}async close(e,t){e.closing||(e.closing=!0,e.tools.clear(),e.waitController.abort(),e.interactions.dispose(),await Gr(e.session,t,i=>this.diagnostic(e,"host","shutdown",i),5e3,()=>{e.detach(),e.bus.clear()}),await e.releasePaths())}snapshotOf(e){let{session:t,cwd:i,catalog:n}=e,s=t.sessionManager.getBranch().flatMap(a=>{let l=We(a);return l?[l]:[]});return{schemaVersion:1,sessionId:t.sessionManager.getSessionId(),cwd:i,name:De(t.sessionManager.getSessionName(),s),model:t.model?`${t.model.provider}/${t.model.id}`:null,thinkingLevel:t.thinkingLevel,thinkingLevels:t.getAvailableThinkingLevels(),idle:t.isIdle,paused:ye(t.sessionManager.getBranch()),contextUsage:t.getContextUsage()??null,messages:s,streaming:e.streaming,interactions:e.interactions.pending(t.sessionManager.getSessionId()),pluginEntries:at(t.sessionManager.getBranch(),n.ids())}}snapshot(){if(!this.active)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u5DE5\u4F5C\u533A\u4F1A\u8BDD");return this.snapshotOf(this.active)}async invokePluginAction(e){let t=this.active;if(this.disposed||!t||t.closing||e.sessionId!==t.session.sessionManager.getSessionId())throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362");if(!t.catalog.has(e.pluginId))throw new Error("\u63D2\u4EF6\u672A\u542F\u7528");let i=t.session.extensionRunner,n=await Be(t.bus,e,15e3,t.waitController.signal);if(this.active!==t||t.closing||i!==t.session.extensionRunner)throw new Error("\u4F1A\u8BDD\u8FD0\u884C\u5B9E\u4F8B\u5DF2\u5207\u6362");return this.publish({type:"snapshot",session:this.snapshot()}),n}resolveInteraction(e,t,i,n){if(this.disposed||!this.active||this.active.closing)throw new Error("Interaction host unavailable");this.active.interactions.resolve(e,t,i,n)}async send(e,t=[],i){if(this.disposed||!this.session||this.active?.closing||!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=this.active;s.operation=i,this.telemetry.breadcrumb("send",{...i,piVersion:Le}),s.agentErrorReported=!1;let a=!1,l,p,w=new Promise((m,c)=>{l=m,p=c});n.prompt(e,{images:t,preflightResult:m=>{m&&(a=!0,l())}}).then(()=>{a||l()}).catch(m=>{if(!a)p(m);else if(!this.disposed&&!s.closing&&!s.agentErrorReported){let c=this.reportError(ee(m,"Agent response failed"),{...i,stage:"agent",code:"agent_failed",piVersion:Le});this.publishFor(s,{type:"error",message:m instanceof Error?m.message:"Pi \u8BF7\u6C42\u5931\u8D25",errorCode:"unexpected_error",errorId:c,...i})}});try{await w}catch(m){throw s.operation=void 0,m}}async stop(){let e=this.active;!e||e.session.isIdle||(e.tools.cancel(),this.telemetry.breadcrumb("cancel",{...e.operation}),e.session.sessionManager.appendCustomEntry(we),await e.session.abort(),this.active===e&&!e.closing&&this.publish({type:"snapshot",session:this.snapshotOf(e)}))}async resume(e){let t=this.active;if(this.disposed||!t||t.closing)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");let i=t.session;if(!i.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!ye(i.sessionManager.getBranch()))throw new Error("\u5F53\u524D\u4F1A\u8BDD\u6CA1\u6709\u6682\u505C\u7684\u4EFB\u52A1");if(!i.model)throw new Error("\u8BF7\u5148\u9009\u62E9\u6A21\u578B");if(!(i.modelRuntime.hasConfiguredAuth(i.model.provider)||await i.modelRuntime.checkAuth(i.model.provider)!==void 0))throw new Error("\u8BF7\u5148\u8FDE\u63A5\u5F53\u524D\u6A21\u578B");if(this.active!==t||t.closing)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362");if(!i.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!ye(i.sessionManager.getBranch()))throw new Error("\u5F53\u524D\u4F1A\u8BDD\u6CA1\u6709\u6682\u505C\u7684\u4EFB\u52A1");let s=je(this.snapshotOf(t).messages);t.operation=e,t.agentErrorReported=!1,this.telemetry.breadcrumb("resume",{...e}),i.sendCustomMessage(s,{triggerTurn:!0}).catch(a=>{if(!this.disposed&&!t.closing&&!t.agentErrorReported){let l=this.reportError(ee(a,"Agent resume failed"),{...e,stage:"agent",code:"agent_failed"});this.publishFor(t,{type:"error",message:a instanceof Error?a.message:"\u7EE7\u7EED\u5931\u8D25",errorId:l,...e})}})}async models(){return(await this.session?.modelRuntime.getAvailable()??[]).map(t=>({provider:t.provider,id:t.id,name:t.name}))}async setModel(e,t){let i=this.active;if(this.disposed||!i||i.closing||!i.session.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let n=i.session.modelRuntime.getModel(e,t);if(!n)throw new Error("\u6A21\u578B\u4E0D\u53EF\u7528");await i.session.setModel(n),this.publishFor(i,{type:"snapshot",session:this.snapshotOf(i)})}dispose(){return this.disposed=!0,this.queue.run(async()=>{let e=[...this.runtimes.values()];this.active=null,this.runtimes.clear(),this.selectedByWorkspace.clear(),await Promise.all(e.map(t=>this.close(t,"quit")))})}};import{basename as gt,dirname as Xs}from"node:path";function Jr(r,e){let t=i=>e[i].map(n=>({name:i==="skills"&>(n.path).toLowerCase()==="skill.md"?gt(Xs(n.path)):gt(n.path),path:n.path,source:n.metadata.source,scope:n.metadata.scope,enabled:n.enabled}));return{packages:r.map(i=>({name:i.source,path:i.installedPath??"",source:i.source,scope:i.scope,enabled:!!i.installedPath})),extensions:t("extensions"),skills:t("skills")}}import{execFile as Ys}from"node:child_process";var Zs=(r,e)=>new Promise((t,i)=>{Ys(r,[...e],{windowsHide:!0},n=>{n?i(n):t()})});async function ht(r,e=process.platform,t=process.env,i=Zs){if(t.SSH_CONNECTION||t.SSH_TTY||t.SSH_CLIENT||e==="linux"&&!t.DISPLAY&&!t.WAYLAND_DISPLAY)return!1;let n=e==="darwin"?"open":e==="linux"?"xdg-open":e==="win32"?"explorer.exe":null;return n===null?!1:(await i(n,[r]),!0)}import{execFile as no}from"node:child_process";import{randomUUID as so}from"node:crypto";import{existsSync as Zr}from"node:fs";import{access as oo,mkdir as ao,readFile as Qr,rename as co,rm as yt,writeFile as ei}from"node:fs/promises";import{join as G}from"node:path";import{promisify as lo}from"node:util";import{realpathSync as Xr,statSync as Qs}from"node:fs";import{basename as eo,delimiter as to,dirname as Kr,join as wt,resolve as ro}from"node:path";function qr(r){if(!r)return null;try{let e=Xr(r);return eo(e)==="npm-cli.js"&&Qs(e).isFile()?e:null}catch{return null}}function io({execPath:r=process.execPath,env:e=process.env}={}){let t=qr(e.npm_execpath);if(t)return t;let i=new Set([Kr(r)]);try{i.add(Kr(Xr(r)))}catch{}let n=Object.entries(e).find(([s])=>s.toLowerCase()==="path")?.[1]??"";for(let s of n.split(to).filter(Boolean))i.add(ro(s));for(let s of i)for(let a of[wt(s,"node_modules","npm","bin","npm-cli.js"),wt(s,"..","lib","node_modules","npm","bin","npm-cli.js"),wt(s,"npm")]){let l=qr(a);if(l)return l}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 Yr(r){return{file:process.execPath,args:[io(),...r]}}var po=lo(no),Ve=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/;function uo(r,e){let t=Ve.exec(r),i=Ve.exec(e);if(!t||!i)throw new Error("\u7248\u672C\u53F7\u65E0\u6548");for(let n=1;n<=3;n++){let s=Number(t[n])-Number(i[n]);if(s)return s}return!t[4]&&i[4]?1:t[4]&&!i[4]?-1:(t[4]??"").localeCompare(i[4]??"",void 0,{numeric:!0})}async function fo(r){try{let e=Yr(r),{stdout:t}=await po(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 Ue=class{agentDir;packageRoot;launcherNonce;runNpm;desktopManaged;preparing=!1;restartPending=!1;constructor(e){this.agentDir=e.agentDir,this.packageRoot=e.packageRoot,this.launcherNonce=e.launcherNonce,this.runNpm=e.runNpm??fo,this.desktopManaged=e.desktopManaged??process.env.PI_WEBAPP_RUNTIME==="desktop"}async current(){let e=JSON.parse(await Qr(G(this.packageRoot,"package.json"),"utf8"));if(e.name!=="pi-webapp"||typeof e.version!="string"||!Ve.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();if(this.desktopManaged)return{current:e,latest:null,available:!1,canRestart:!1,reason:"\u5F53\u524D\u7531\u684C\u9762\u5E94\u7528\u7BA1\u7406\uFF0C\u8BF7\u5B89\u88C5\u65B0\u7248\u684C\u9762\u5E94\u7528\u8FDB\u884C\u5347\u7EA7\uFF1B\u4E0D\u4F1A\u901A\u8FC7 npm \u4FEE\u6539\u968F\u5305\u8FD0\u884C\u73AF\u5883\u3002"};let t=Zr(G(this.packageRoot,".git")),i={current:e,latest:null,available:!1,canRestart:!!this.launcherNonce&&!t};t?i.reason="\u5F53\u524D\u4ECE\u6E90\u7801\u76EE\u5F55\u8FD0\u884C\u3002\u7F51\u9875\u5347\u7EA7\u4EC5\u652F\u6301 npm \u5B89\u88C5\u7684\u7248\u672C\uFF0C\u4EE5\u514D\u8986\u76D6\u672C\u5730\u4EE3\u7801\u3002":i.canRestart||(i.reason="\u5F53\u524D\u9875\u9762\u7531 Pi \u7EC8\u7AEF\u6253\u5F00\uFF0C\u65E0\u6CD5\u4ECE\u7F51\u9875\u81EA\u52A8\u91CD\u542F Pi\uFF1B\u8BF7\u4F7F\u7528 pi-webapp \u542F\u52A8\u5668\u3002");try{let n=JSON.parse((await this.runNpm(["view","pi-webapp","dist-tags.latest","--json","--prefer-online"])).trim()),s=Array.isArray(n)&&n.length===1?n[0]:n;if(typeof s!="string"||!Ve.test(s))throw new Error("npm \u8FD4\u56DE\u7684\u7248\u672C\u53F7\u65E0\u6548");i.latest=s,i.available=uo(s,e)>0}catch(n){throw new Error(`\u68C0\u67E5 npm \u66F4\u65B0\u5931\u8D25\uFF1A${n instanceof Error?n.message:String(n)}`)}return i}async prepare(){if(this.desktopManaged)throw new Error("\u684C\u9762\u5E94\u7528\u7684\u8FD0\u884C\u73AF\u5883\u4E0D\u80FD\u901A\u8FC7\u7F51\u9875\u5347\u7EA7\uFF0C\u8BF7\u5B89\u88C5\u65B0\u7248\u684C\u9762\u5E94\u7528");if(!this.launcherNonce)throw new Error("\u5F53\u524D\u9875\u9762\u65E0\u6CD5\u81EA\u52A8\u91CD\u542F Pi");if(Zr(G(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=G(this.agentDir,"pi-web","releases",e.latest);await yt(t,{recursive:!0,force:!0}),await ao(t,{recursive:!0});try{await this.runNpm(["install",`pi-webapp@${e.latest}`,"--prefix",t,"--ignore-scripts","--no-save","--no-audit","--no-fund"]);let i=G(t,"node_modules","pi-webapp"),n=JSON.parse(await Qr(G(i,"package.json"),"utf8"));if(n.name!=="pi-webapp"||n.version!==e.latest)throw new Error("\u4E0B\u8F7D\u7684\u5305\u4E0E\u76EE\u6807\u7248\u672C\u4E0D\u7B26");let s=G(i,"bin","pi-webapp.mjs");await Promise.all([s,G(i,"dist","extension.js"),G(i,"web","dist","index.html")].map(p=>oo(p)));let a=G(this.agentDir,"pi-web"),l=G(a,`update.${so()}.tmp`);try{await ei(l,JSON.stringify({version:e.latest,launcher:s}),{mode:384}),await co(l,G(a,"update.json"))}finally{await yt(l,{force:!0})}return this.restartPending=!0,{version:e.latest,launcher:s}}catch(i){throw await yt(t,{recursive:!0,force:!0}),i}}finally{this.preparing=!1}}async requestRestart(e){if(this.desktopManaged)throw new Error("\u684C\u9762\u5E94\u7528\u7684\u8FD0\u884C\u73AF\u5883\u4E0D\u80FD\u901A\u8FC7\u7F51\u9875\u91CD\u542F\u5347\u7EA7");if(!this.launcherNonce)throw new Error("\u5F53\u524D\u9875\u9762\u65E0\u6CD5\u81EA\u52A8\u91CD\u542F Pi");try{await ei(G(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 Eo}from"node:crypto";async function mo(){if(process.env.PI_WEB_SENTRY_VERIFY_RELEASE!=="true"||process.env.PI_WEB_SENTRY_ENVIRONMENT!=="sentry-verification")throw new Error("Sentry release verification is not enabled");let r=new X({monitor:!1});try{if(await r.ready,!r.enabled)throw new Error("Sentry verification transport is disabled");let e=r.capture(new Error("Sentry Node release verification"),{stage:"release_verification",code:"sentry_release_probe"});if(!e||!await r.flush(3e3))throw new Error("Sentry verification event was not delivered");return{eventId:e,release:Ae,buildId:J}}finally{await r.close()}}var ri=vt(ho(yo(import.meta.url)),"../web/dist"),xo=Symbol.for(`pi-web.bridge-state:${import.meta.url}`),o=globalThis[xo]??={bridge:null,current:null,commandContext:null,pi:null,replacementContext:null,replacementSessionId:null,lastStreamAt:0,tuiStreaming:null,workspaces:null,workspaceSessions:null,selected:"tui",activeWorkspaceId:null,autoOpened:!1,tuiCatalog:null,stopPluginWatch:null,interactions:null,lifecycle:new se,tuiGeneration:0,stopChanged:null,tuiWaitController:new AbortController};o.lifecycle??=new se;o.tuiGeneration??=0;o.stopChanged??=null;o.tuiWaitController??=new AbortController;o.tuiStreaming??=null;function Ee(){return o.selected==="sdk"?o.workspaceSessions?.catalog??null:o.tuiCatalog}var Po=null;function So(){return Po??=bo.create({refreshOnCreate:!1})}var Je=new Map;async function fe(){let r=await So(),e=o.selected==="tui"?o.current?.modelRegistry:void 0,t=new Set(e?.getRegisteredProviderIds()??[]);for(let i of Je.keys())t.has(i)||(r.unregisterProvider(i),Je.delete(i));for(let i of t){let n=e?.getRegisteredNativeProvider(i),s=e?.getRegisteredProviderConfig(i),a=n??s;!a||Je.get(i)===a||(n?r.registerNativeProvider(n):s&&r.registerProvider(i,s),Je.set(i,a))}return await r.refresh({allowNetwork:!1}),r}function D(){if(o.selected==="sdk")return o.workspaceSessions?.snapshot()??(()=>{throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD")})();if(o.current===null)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");return{...ct(o.current,o.current.sessionManager.getSessionName(),Ee()?.ids()??[]),streaming:o.tuiStreaming,interactions:o.interactions?.pending(o.current.sessionManager.getSessionId())??[]}}function N(r){if(D().sessionId!==r)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362")}async function oi(){let r=(o.workspaces?.list()??[]).map(m=>({...m})),e=o.activeWorkspaceId,t=D(),i=o.current,n=i?ct(i,i.sessionManager.getSessionName(),o.tuiCatalog?.ids()??[]):null,s=await de(t.cwd).catch(m=>(o.bridge?.reportError?.(m,{stage:"workspace_path"}),null)),a=n?await de(n.cwd).catch(m=>(o.bridge?.reportError?.(m,{stage:"workspace_path"}),null)):null,l=await si.listAll(),p=o.workspaceSessions?.retainedSessions()??[];n&&a&&p.push({sessionId:n.sessionId,cwd:a,path:null,name:n.name,modified:n.messages.at(-1)?.timestamp??new Date().toISOString(),idle:n.idle});let w=(await Promise.all(r.map(async m=>{let u=(await ve(m.path,l).catch(f=>(f instanceof be?m.available=!1:o.bridge?.reportError?.(f,{stage:"workspace_sessions"}),[]))).map(f=>({id:f.id,workspaceId:m.id,path:f.path,name:f.name||f.firstMessage?.slice(0,50)||"\u5F53\u524D\u4F1A\u8BDD",modified:f.modified.toISOString(),idle:!0}));for(let f of p.filter(g=>g.cwd===m.path)){let g=u.findIndex(I=>I.id===f.sessionId),x={id:f.sessionId,workspaceId:m.id,path:f.path??u[g]?.path??null,name:f.name,modified:f.modified,idle:f.idle};g<0?u.unshift(x):u[g]=x}return m.path===s&&!u.some(f=>f.id===t.sessionId)&&u.unshift({id:t.sessionId,workspaceId:m.id,path:null,name:t.name,modified:new Date().toISOString(),idle:t.idle}),u}))).flat();return{items:r,activeId:e,sessions:w}}var ii=0;async function V(){if(!o.bridge)return;let r=++ii;try{let e=await oi();r===ii&&o.bridge?.publish({type:"workspaces",value:e})}catch(e){o.bridge?.reportError?.(e,{stage:"workspace_list"})}}async function bt(r,e=!1){let t=o.workspaces?.get(r);if(!t)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");if(await ie(t.path),!e&&o.current&&t.path===await de(o.current.cwd)&&!o.workspaceSessions?.hasWorkspace(t.path))o.selected="tui",o.activeWorkspaceId=r,o.bridge?.publish({type:"stream",message:null}),o.bridge?.publish({type:"snapshot",session:D()});else{if(!o.workspaceSessions)throw new Error("Pi \u5DE5\u4F5C\u533A\u670D\u52A1\u4E0D\u53EF\u7528");await o.workspaceSessions.open(t.path,e?"new":"continue"),o.selected="sdk",o.activeWorkspaceId=r,o.bridge?.publish({type:"snapshot",session:D()})}await V()}function U(r){let e=o.current;if(e===null||e.sessionManager.getSessionId()!==r)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362");return e}function W(r){o.current=r,o.selected==="tui"&&o.bridge?.publish({type:"snapshot",session:D()})}function ai(){if(o.current===null)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");let r=o.selected==="sdk"?o.workspaceSessions?.path:o.current.cwd;if(!r)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u5DE5\u4F5C\u533A");let e=o.selected==="tui"?o.current.isProjectTrusted():o.workspaceSessions?.session?.settingsManager.isProjectTrusted()??!1;return vo.create(r,void 0,{projectTrusted:e})}async function ci(){let r=ai(),e=n=>({packages:(n.packages??[]).map(s=>typeof s=="string"?s:s.source),extensions:n.extensions??[],skills:n.skills??[]}),t=new ni({cwd:D().cwd,agentDir:oe(),settingsManager:r}),i=Jr(t.listConfiguredPackages(),await t.resolve(async()=>"skip"));return{projectTrusted:r.isProjectTrusted(),global:e(r.getGlobalSettings()),project:e(r.getProjectSettings()),installed:i}}async function Io(r){N(r.sessionId);let e=o.selected==="tui"?U(r.sessionId):null;if(e?!e.isIdle():!o.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let t=ai();if(r.scope==="project"&&!t.isProjectTrusted())throw new Error("\u5F53\u524D\u9879\u76EE\u5C1A\u672A\u53D7\u4FE1\u4EFB\uFF0C\u65E0\u6CD5\u4FEE\u6539\u9879\u76EE\u8BBE\u7F6E");let i=r.value.trim(),n=r.scope==="project"?t.getProjectSettings():t.getGlobalSettings();if(r.kind==="packages"){let s=new ni({cwd:D().cwd,agentDir:oe(),settingsManager:t});r.action==="add"?await s.installAndPersist(i,{local:r.scope==="project"}):await s.removeAndPersist(i,{local:r.scope==="project"})}else if(r.kind==="extensions"){let s=n.extensions??[],a=r.action==="add"?[...new Set([...s,i])]:s.filter(l=>l!==i);r.scope==="project"?t.setProjectExtensionPaths(a):t.setExtensionPaths(a)}else{let s=n.skills??[],a=r.action==="add"?[...new Set([...s,i])]:s.filter(l=>l!==i);r.scope==="project"?t.setProjectSkillPaths(a):t.setSkillPaths(a)}return await t.flush(),o.selected==="tui"?(o.commandContext&&await o.commandContext.reload(),o.current&&W(o.current)):(await o.workspaceSessions?.reload(),o.bridge?.publish({type:"plugins_changed"})),await ci()}function kt(r,e=ht){o.pi=r,o.tools?.clear(),o.tools=new ue({enabled:()=>!!o.telemetry?.enabled&&!!o.bridge,capture:(s,a)=>o.bridge?.reportError?.(s,a),breadcrumb:(s,a)=>o.bridge?.breadcrumb?.(s,a),anonymize:s=>o.telemetry?.session(s)??"unavailable"});let t=s=>({...o.operation,session:o.telemetry?.session(s.sessionManager.getSessionId()),piVersion:He,model:s.model?`${s.model.provider}/${s.model.id}`:null,thinkingLevel:s.thinkingLevel});o.interactions?.dispose(),o.interactions=new pe(r.events,s=>!!o.bridge&&s.sessionId===o.current?.sessionManager.getSessionId()&&!!o.tuiCatalog?.has(s.pluginId),()=>{o.current&&o.selected==="tui"&&W(o.current)});let i=()=>{o.stopChanged?.(),o.stopChanged=r.events.on(Fe,()=>{o.selected==="tui"&&o.current&&W(o.current)})};i(),r.on("session_start",async(s,a)=>{if(o.tuiStreaming=null,o.tools?.clear(),o.operation=void 0,o.tuiWaitController.abort(),o.tuiWaitController=new AbortController,o.tuiGeneration++,i(),o.current=a,o.bridge){let l=await ne.discover(a.cwd,a.isProjectTrusted?.()??!1);if(o.current!==a)return;o.tuiCatalog=l}o.replacementSessionId!==a.sessionManager.getSessionId()&&(o.replacementContext=null,o.replacementSessionId=null),W(a),o.bridge&&o.selected==="tui"&&o.bridge.publish({type:"plugins_changed"}),o.selected==="tui"&&o.workspaces&&o.workspaces.add(a.cwd).then(async l=>{o.selected!=="tui"||o.current?.sessionManager.getSessionId()!==a.sessionManager.getSessionId()||(o.activeWorkspaceId=l.id,await V())}).catch(l=>{o.bridge?.publish({type:"error",message:l instanceof Error?l.message:"\u65E0\u6CD5\u6CE8\u518C\u5F53\u524D\u5DE5\u4F5C\u533A",errorCode:"unexpected_error",errorId:o.bridge.reportError?.(l,{stage:"workspace_register"})})}),process.env.PI_WEBAPP_AUTO_OPEN==="1"&&a.mode==="tui"&&!o.autoOpened&&(o.autoOpened=!0,n(a).catch(l=>{a.ui.notify(l instanceof Error?l.message:"Web \u542F\u52A8\u5931\u8D25","error")}))}),r.on("agent_start",(s,a)=>{o.bridge?.breadcrumb?.("agent_start",t(a)),W(a),V()}),r.on("agent_end",(s,a)=>W(a)),r.on("agent_settled",(s,a)=>{o.bridge?.breadcrumb?.("agent_end",t(a)),o.tools?.clear(),o.operation=void 0,o.tuiStreaming=null,W(a),V()}),r.on("tool_execution_start",(s,a)=>{o.tools?.start(s,t(a))}),r.on("tool_execution_end",(s,a)=>{o.tools?.end(s,t(a))}),r.on("model_select",(s,a)=>W(a)),r.on("thinking_level_select",(s,a)=>W(a)),r.on("message_end",(s,a)=>{if(s.message.role==="assistant"&&s.message.stopReason==="error"){let l=o.bridge?.reportError?.(new Error("Agent response failed"),{...o.operation,stage:"agent",code:"agent_failed",piVersion:He});o.selected==="tui"&&o.bridge?.publish({type:"error",message:s.message.errorMessage??"Agent response failed",errorCode:"unexpected_error",errorId:l,...o.operation})}s.message.role==="toolResult"&&o.tools?.message(s.message,t(a)),s.message.role==="assistant"&&(o.tuiStreaming=null),o.selected==="tui"&&s.message.role==="assistant"&&o.bridge?.publish({type:"stream",message:null}),W(a),V()}),r.on("session_info_changed",(s,a)=>W(a)),r.on("message_update",(s,a)=>{if(o.current=a,s.message.role!=="assistant"||(o.tuiStreaming={id:"stream",role:"assistant",timestamp:new Date(s.message.timestamp).toISOString(),blocks:re(s.message.content)},o.selected!=="tui"||o.bridge===null))return;let l=Date.now();l-o.lastStreamAt<60||(o.lastStreamAt=l,o.bridge.publish({type:"stream",message:o.tuiStreaming}))}),r.on("session_shutdown",async s=>{if(o.tuiStreaming=null,o.tools?.clear(),o.operation=void 0,o.tuiWaitController.abort(),o.tuiGeneration++,o.stopChanged?.(),o.stopChanged=null,o.interactions?.cancelAll(),o.current=null,s.reason==="new"||s.reason==="resume"||s.reason==="fork"||s.reason==="reload")return;let a=o.bridge,l=o.telemetry;o.bridge=null,o.commandContext=null,o.replacementContext=null,o.replacementSessionId=null,o.pi=null;let p=o.workspaceSessions;o.workspaceSessions=null,await p?.dispose(),o.selected="tui",o.activeWorkspaceId=null,o.autoOpened=!1,o.tuiCatalog=null,o.stopPluginWatch?.(),o.stopPluginWatch=null,o.operation=void 0,o.telemetry=null,a?await a.close():await l?.close()});let n=async s=>{o.telemetry??=new X;try{o.current=s,o.commandContext="newSession"in s?s:null,o.pi=r,o.tuiCatalog=await ne.discover(s.cwd,s.isProjectTrusted?.()??!1),o.workspaces===null&&(o.workspaces=new Oe(Nr(oe())),await o.workspaces.load());try{await o.workspaces.discover((await si.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 o.workspaces.add(s.cwd);if(o.selected==="tui"&&(o.activeWorkspaceId=a.id),o.bridge&&(o.bridge.protocolVersion!==7||o.bridge.buildId!==J||typeof o.bridge.reportError!="function")){let p=o.bridge;if(o.workspaceSessions&&(o.workspaceSessions.telemetryVersion!==2||o.workspaceSessions.runtimeVersion!==1)&&o.workspaceSessions.session&&!o.workspaceSessions.session.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u518D\u5207\u6362\u5DE5\u4F5C\u533A");o.bridge=null,await p.close(),await o.telemetry.close(),o.telemetry=new X}if(o.bridge===null){let p=o.workspaceSessions&&(o.workspaceSessions.telemetryVersion!==2||o.workspaceSessions.runtimeVersion!==1)?o.workspaceSessions:null,w=p?.session&&p.path?{path:p.path,sessionManager:p.session.sessionManager}:null;p&&(await p.dispose(),o.workspaceSessions=null),o.workspaceSessions??=new Ge(c=>{o.selected==="sdk"&&o.bridge?.publish(c)},()=>o.current?.model,c=>{try{return!!o.current&&ti(o.current.cwd)===c&&(o.current.isProjectTrusted?.()??!1)}catch{return!1}},(c,u)=>o.bridge?.reportError?.(c,u),{enabled:()=>!!o.telemetry?.enabled&&!!o.bridge,breadcrumb:(c,u)=>o.bridge?.breadcrumb?.(c,u),anonymize:c=>o.telemetry?.session(c)??"unavailable"},()=>{V()}),w&&await o.workspaceSessions.open(w.path,{sessionManager:w.sessionManager});let m={selfUpdate:new Ue({agentDir:oe(),packageRoot:vt(ri,"../.."),launcherNonce:process.env.PI_WEBAPP_LAUNCHER_NONCE}),snapshot:D,busyGitWorkspaces:()=>{let c=(o.workspaceSessions?.retainedSessions()??[]).filter(u=>!u.idle).map(u=>u.cwd);if(o.current&&!o.current.isIdle())try{c.push(ti(o.current.cwd))}catch{c.push(o.current.cwd)}return c},plugins:async()=>{let c=Ee();return await c?.refreshAssets(),c?.view()??{plugins:[],errors:[]}},pluginAsset:async c=>Ee()?.asset(c)??null,async invokePluginAction(c,u,f,g){if(N(c),!Ee()?.has(u))throw new Error("\u63D2\u4EF6\u672A\u542F\u7528");let x=o.selected,I=o.tuiGeneration,C=o.workspaceSessions?.session,H={requestId:Eo(),sessionId:c,pluginId:u,action:f,input:g},b=o.selected==="sdk"?await o.workspaceSessions.invokePluginAction(H):await Be(o.pi.events,H,15e3,o.tuiWaitController.signal);if(N(c),x!==o.selected||(x==="tui"?I!==o.tuiGeneration:C!==o.workspaceSessions?.session))throw new Error("\u4F1A\u8BDD\u8FD0\u884C\u5B9E\u4F8B\u5DF2\u5207\u6362");return o.selected==="tui"&&o.current&&W(o.current),b},async resolvePluginInteraction(c,u,f,g){if(N(c),!Ee()?.has(u))throw new Error("\u63D2\u4EF6\u672A\u542F\u7528");o.selected==="sdk"?o.workspaceSessions.resolveInteraction(c,u,f,g):o.interactions.resolve(c,u,f,g)},image(c,u,f){N(c);let x=(o.selected==="sdk"?o.workspaceSessions?.session?.sessionManager.getBranch():o.current?.sessionManager.getBranch())?.find(C=>C.id===u);if(x?.type!=="message"||x.message.role!=="user"||!Array.isArray(x.message.content))return null;let I=x.message.content[f];return I?.type!=="image"?null:{data:Buffer.from(I.data,"base64"),mimeType:I.mimeType}},async workspaces(){return oi()},async addWorkspace(c,u){let f=await o.workspaces.add(c,u);try{await bt(f.id,!0)}catch(g){throw await V(),g}},async selectWorkspace(c){await bt(c)},async newSessionInWorkspace(c){await bt(c,!0)},async removeWorkspace(c){if(c===o.activeWorkspaceId)throw new Error("\u8BF7\u5148\u5207\u6362\u5230\u5176\u4ED6\u5DE5\u4F5C\u533A");await o.workspaces.remove(c),await V()},async selectSession(c,u,f){let g=o.workspaces?.get(c);if(!g)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");if(await ie(g.path),u===o.current?.sessionManager.getSessionId()&&g.path===await de(o.current.cwd))o.selected="tui",o.activeWorkspaceId=c,o.bridge?.publish({type:"stream",message:null}),o.bridge?.publish({type:"snapshot",session:D()});else{if(o.selected==="sdk"&&o.workspaceSessions?.session?.sessionManager.getSessionId()===u&&o.workspaceSessions.path===g.path)return;if(o.workspaceSessions?.hasSession(g.path,u))await o.workspaceSessions.open(g.path,{sessionId:u});else{if(!(await ve(g.path)).some(I=>I.id===u&&I.path===f))throw new Error("\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A");await o.workspaceSessions.open(g.path,{sessionFile:f})}o.selected="sdk",o.activeWorkspaceId=c,o.bridge?.publish({type:"snapshot",session:D()})}await V()},async models(){if(o.selected==="sdk")return o.workspaceSessions?.models()??[];let c=o.current;if(!c)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");let u=c.scopedModels?.map(f=>`${f.model.provider}/${f.model.id}`)??[];return c.modelRegistry.getAvailable().filter(f=>u.length===0||u.includes(`${f.provider}/${f.id}`)).map(f=>({provider:f.provider,id:f.id,name:f.name}))},async providers(){let c=await fe(),u=new Set((await c.listCredentials()).map(f=>f.providerId));return c.getProviders().map(f=>({id:f.id,name:f.name,configured:c.getProviderAuthStatus(f.id).configured,storedCredential:u.has(f.id),methods:[f.auth.apiKey?.login?"api_key":null,f.auth.oauth?"oauth":null].filter(g=>g!==null)}))},async providerModels(c){let u=await fe();return fr(ze(oe(),"models.json"),c,u)},async updateProviderModel(c,u,f){if(N(c),o.selected==="tui"?!U(c).isIdle():!o.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let g=D().model;if(f.action==="remove"&&g===`${u}/${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&&g===`${u}/${f.originalId}`)throw new Error("\u8BF7\u5148\u5207\u6362\u5F53\u524D\u4F7F\u7528\u7684\u6A21\u578B");let x=await fe();await mr(ze(oe(),"models.json"),u,f,x),await x.refresh({providers:[u],allowNetwork:!1}),await o.current?.modelRegistry.refresh({providers:[u],allowNetwork:!1}),await o.workspaceSessions?.session?.modelRuntime.refresh({providers:[u],allowNetwork:!1});let I=f.action==="save"?f.model.id:f.action==="base_url"&&g?.startsWith(`${u}/`)?g.slice(u.length+1):null;if(I&&g===`${u}/${I}`)if(o.selected==="sdk")try{await o.workspaceSessions.setModel(u,I)}catch{throw new Error("\u6A21\u578B\u5DF2\u4FDD\u5B58\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u8BE5\u6A21\u578B\u4EE5\u5E94\u7528\u65B0\u53C2\u6570")}else{let C=U(c),H=C.modelRegistry.find(u,I);if(!H||!o.pi||!await o.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");W(C)}},async logoutProvider(c,u){if(N(c),o.selected==="tui"?!U(c).isIdle():!o.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let f=await fe();if(!(await f.listCredentials()).some(g=>g.providerId===u))throw new Error("\u8BE5\u63D0\u4F9B\u65B9\u6CA1\u6709\u5DF2\u4FDD\u5B58\u7684\u8BA4\u8BC1");await f.logout(u),await o.current?.modelRegistry.refresh({providers:[u],allowNetwork:!1}),await o.workspaceSessions?.session?.modelRuntime.refresh({providers:[u],allowNetwork:!1})},async loginProvider(c,u,f){let g=await fe();await g.login(c,u,ar(c,u,f)),await g.refresh({providers:[c],allowNetwork:!1}),await o.current?.modelRegistry.refresh({providers:[c],allowNetwork:!1}),await o.workspaceSessions?.session?.modelRuntime.refresh({providers:[c],allowNetwork:!1})},async addCustomProvider(c,u){if(N(c),o.selected==="tui"?!U(c).isIdle():!o.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let f=await fe();if(f.getProvider(u.id))throw new Error("\u63D0\u4F9B\u65B9\u5DF2\u5B58\u5728");await cr(ze(oe(),"models.json"),u),await f.refresh({allowNetwork:!1}),await o.current?.modelRegistry.refresh({allowNetwork:!1}),await o.workspaceSessions?.session?.modelRuntime.refresh({allowNetwork:!1})},commands(){return o.selected==="tui"?(o.pi?.getCommands()??[]).filter(c=>c.name!=="web"&&c.name!=="web-dev-reload").map(c=>({name:c.name,description:c.description})):[]},async compact(c){if(N(c),o.selected==="sdk"){let f=o.workspaceSessions?.session;if(!f||!f.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");await f.compact(),o.bridge?.publish({type:"snapshot",session:D()});return}let u=U(c);if(!u.isIdle())throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");u.compact()},async setModel(c,u,f){if(N(c),o.selected==="sdk"){await o.workspaceSessions.setModel(u,f);return}let g=U(c);if(!g.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let x=g.modelRegistry.find(u,f);if(!x||!g.modelRegistry.getAvailable().some(I=>I.provider===u&&I.id===f))throw new Error("\u6A21\u578B\u4E0D\u53EF\u7528");if(!o.pi||!await o.pi.setModel(x))throw new Error("\u6A21\u578B\u63D0\u4F9B\u65B9\u672A\u914D\u7F6E\u8BA4\u8BC1");W(g)},async setThinkingLevel(c,u){if(N(c),!["off","minimal","low","medium","high","xhigh"].includes(u))throw new Error("\u63A8\u7406\u5F3A\u5EA6\u65E0\u6548");if(o.selected==="sdk"){let x=o.workspaceSessions?.session;if(!x||!x.isIdle||!x.getAvailableThinkingLevels().includes(u))throw new Error("\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u6B64\u63A8\u7406\u5F3A\u5EA6");x.setThinkingLevel(u),o.bridge?.publish({type:"snapshot",session:D()});return}let g=U(c);if(!g.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!g.model||!ko(g.model).includes(u))throw new Error("\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u6B64\u63A8\u7406\u5F3A\u5EA6");if(!o.pi)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");o.pi.setThinkingLevel(u),W(g)},config:ci,updateConfig:Io,async send(c,u,f=[],g){if(N(c),o.selected==="sdk"){await o.workspaceSessions.send(u,f,g);return}if(!U(c).isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");o.operation=g;try{if(o.bridge?.breadcrumb?.("send",{...g,piVersion:He}),o.replacementContext!==null&&o.replacementSessionId===c){await o.replacementContext.sendUserMessage(f.length?[{type:"text",text:u},...f]:u,{expandPromptTemplates:!0});return}if(o.pi===null)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");o.pi.sendUserMessage(f.length?[{type:"text",text:u},...f]:u,{expandPromptTemplates:!0})}catch(I){throw o.operation=void 0,I}},async abort(c){if(N(c),o.selected==="sdk")await o.workspaceSessions.stop();else{let u=U(c);if(u.isIdle())return;if(!o.pi)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");o.tools?.cancel(),o.bridge?.breadcrumb?.("cancel",{...o.operation}),o.pi.appendEntry(we),u.abort()}},async resume(c,u){if(N(c),o.selected==="sdk"){await o.workspaceSessions.resume(u);return}let f=U(c);if(!f.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!f.model||!o.pi)throw new Error("\u8BF7\u5148\u9009\u62E9\u6A21\u578B");if(!f.modelRegistry.hasConfiguredAuth(f.model))throw new Error("\u8BF7\u5148\u8FDE\u63A5\u5F53\u524D\u6A21\u578B");o.operation=u;try{o.pi.sendMessage(je(D().messages),{triggerTurn:!0})}catch(g){throw o.operation=void 0,g}},async newSession(c){if(N(c),o.selected==="sdk"){let g=o.workspaces?.get(o.activeWorkspaceId??"");if(!g)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");await o.workspaceSessions.open(g.path,"new"),await V();return}let u=U(c);if(!u.isIdle()||o.commandContext===null){await o.workspaceSessions.open(u.cwd,"new"),o.selected="sdk",o.bridge?.publish({type:"snapshot",session:D()}),await V();return}if((await o.commandContext.newSession({withSession:async g=>{o.commandContext=g,o.replacementContext=g,o.replacementSessionId=g.sessionManager.getSessionId(),o.current=g}})).cancelled)throw new Error("\u65B0\u4F1A\u8BDD\u5DF2\u53D6\u6D88");await V()}};m.addWorkspace=o.lifecycle.wrap(m.addWorkspace),m.selectWorkspace=o.lifecycle.wrap(m.selectWorkspace),m.newSessionInWorkspace=o.lifecycle.wrap(m.newSessionInWorkspace),m.removeWorkspace=o.lifecycle.wrap(m.removeWorkspace),m.selectSession=o.lifecycle.wrap(m.selectSession),m.newSession=o.lifecycle.wrap(m.newSession),m.updateConfig=o.lifecycle.wrap(m.updateConfig),o.bridge=await _r(m,ri,o.telemetry)}if(o.stopPluginWatch===null&&process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS){let p=[],w=null;for(let m of(process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS??"").split(go).filter(Boolean))try{p.push(wo(ze(vt(m),"dist"),(c,u)=>{let f=String(u??"");["client.js","client.css"].includes(f)&&(w&&clearTimeout(w),w=setTimeout(()=>o.bridge?.publish({type:"plugins_changed"}),180))}))}catch(c){o.bridge?.publish({type:"error",message:`\u63D2\u4EF6\u76D1\u542C\u5931\u8D25\uFF1A${m}: ${String(c)}`})}o.stopPluginWatch=()=>{for(let m of p)m.close();w&&clearTimeout(w)}}let l=await e(o.bridge.url).catch(()=>!1);s.ui.notify(`pi-webapp: ${o.bridge.url}`,l?"info":"warning"),s.ui.setStatus("pi-webapp","Web \u5DF2\u542F\u52A8 \xB7 /web \u91CD\u65B0\u6253\u5F00")}catch(a){throw o.telemetry?.capture(a,{stage:"open_web",piVersion:He}),o.bridge||(await o.telemetry?.close(),o.telemetry=null),a}};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 o.lifecycle.run(async()=>{let l=o.workspaceSessions?.session;l&&(await l.waitForIdle(),await o.workspaceSessions.reload()),await a.reload()}))}})}var ql=kt;export{ql as default,mo as verifySentryNodeRelease};
|
|
41
|
+
`)}`:void 0,t<3&&r.cause instanceof Error&&(n.cause=Hr(r.cause,e,t+1)),le(n)}var Ge=class{telemetryVersion=2;runtimeVersion=1;active=null;runtimes=new Map;selectedByWorkspace=new Map;queue=new se;generation=0;disposed=!1;publish;fallbackModel;isProjectTrusted;reportError;telemetry;onSessionsChanged;constructor(e,t,i=()=>!1,n=()=>{},s={enabled:()=>!1,breadcrumb:()=>{},anonymize:()=>"unavailable"},a=()=>{}){this.publish=e,this.fallbackModel=t,this.isProjectTrusted=i,this.reportError=n,this.onSessionsChanged=a,this.telemetry={enabled:()=>{try{return s.enabled()}catch{return!1}},breadcrumb:(l,p)=>{try{s.enabled()&&s.breadcrumb(l,p)}catch{}},anonymize:l=>{try{return s.enabled()?s.anonymize(l):"unavailable"}catch{return"unavailable"}}}}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 ie(e),n=t==="continue"?this.selectedByWorkspace.get(i):typeof t=="object"&&"sessionId"in t?this.runtimes.get(t.sessionId):void 0;if(n){if(n.cwd!==i)throw new Error("\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A");this.activate(n);return}if(typeof t=="object"&&"sessionId"in t)throw new Error("\u4F1A\u8BDD\u4E0D\u5B58\u5728");let s;if(t==="new")s=$e.create(i);else if(t==="continue"){let l=(await ve(i))[0];s=l?$e.open(l.path):$e.create(i)}else s="sessionManager"in t?t.sessionManager:$e.open(t.sessionFile);if(await qs(s.getCwd())!==i)throw new Error("\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A");let a=this.runtimes.get(s.getSessionId());if(a){if(a.cwd!==i)throw new Error("\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A");this.activate(a);return}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");if(!e.session.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");await this.replace(e.cwd,e.session.sessionManager,"reload")})}ensureAvailable(){if(this.disposed)throw new Error("\u5DE5\u4F5C\u533A\u670D\u52A1\u5DF2\u5173\u95ED")}hasSession(e,t){return this.runtimes.get(t)?.cwd===e}hasWorkspace(e){return this.selectedByWorkspace.has(e)}retainedSessions(){return[...this.runtimes.values()].map(({session:e,cwd:t})=>{let i=e.sessionManager.getBranch(),n=i.flatMap(s=>{let a=We(s);return a?[a]:[]});return{sessionId:e.sessionManager.getSessionId(),cwd:t,path:e.sessionManager.getSessionFile()??null,idle:e.isIdle,name:De(e.sessionManager.getSessionName(),n),modified:i.at(-1)?.timestamp??new Date().toISOString()}})}activate(e){this.ensureAvailable(),this.active=e,this.selectedByWorkspace.set(e.cwd,e),this.publish({type:"snapshot",session:this.snapshotOf(e)}),this.onSessionsChanged()}publishFor(e,t){!this.disposed&&this.active===e&&!e.closing&&this.publish(t)}diagnostic(e,t,i,n){let s=`plugin=${t} session=${e.session.sessionManager.getSessionId()} generation=${e.generation} stage=${i}: ${n}`;console.error(s),this.publishFor(e,{type:"error",message:s})}async replace(e,t,i){let n=this.runtimes.get(t.getSessionId()),s=await ne.discover(e,this.isProjectTrusted(e)),a=Hs(),l=await Vr(e,s.extensionRoots),p=new Js({cwd:e,agentDir:Ks(),noExtensions:!0,additionalExtensionPaths:l.paths,eventBus:a}),w=null;try{await p.reload();let m=p.getExtensions().errors;if(m.length)throw new Error(m.map(E=>`${E.path}: ${E.error}`).join("; "));let c=t.buildSessionProjection().model?void 0:this.active?.session.model??this.fallbackModel(),{session:f}=await zs({cwd:e,sessionManager:t,model:c,resourceLoader:p}),u=new ue({enabled:()=>this.telemetry.enabled(),capture:this.reportError,breadcrumb:(E,R)=>this.telemetry.breadcrumb(E,R),anonymize:E=>this.telemetry.anonymize(E)}),g={session:f,cwd:e,catalog:s,bus:a,generation:++this.generation,closing:!1,waitController:new AbortController,interactions:null,detach:()=>{},releasePaths:l.release,tools:u,streaming:null};w=g;let x=E=>this.publishFor(g,E);g.interactions=new pe(a,E=>!g.closing&&E.sessionId===f.sessionManager.getSessionId()&&s.has(E.pluginId),()=>x({type:"snapshot",session:this.snapshotOf(g)}));let I=0,C=a.on(Fe,()=>x({type:"snapshot",session:this.snapshotOf(g)})),H=f.subscribe(E=>{if(!this.disposed&&!g.closing){let R={...g.operation,session:this.telemetry.anonymize(f.sessionManager.getSessionId()),piVersion:Le,model:f.model?`${f.model.provider}/${f.model.id}`:null,thinkingLevel:f.thinkingLevel};if(E.type==="agent_start"&&this.telemetry.breadcrumb("agent_start",R),E.type==="tool_execution_start"&&u.start(E,R),E.type==="tool_execution_end"&&u.end(E,R),E.type==="message_end"&&E.message.role==="assistant"&&E.message.stopReason==="error"){g.agentErrorReported=!0;let Z=this.reportError(new Error("Agent response failed"),{...g.operation,stage:"agent",code:"agent_failed",piVersion:Le});x({type:"error",message:E.message.errorMessage??"Agent response failed",errorCode:"unexpected_error",errorId:Z,...g.operation})}E.type==="message_end"&&E.message.role==="toolResult"&&u.message(E.message,R),E.type==="agent_settled"&&(this.telemetry.breadcrumb("agent_end",R),u.clear(),g.operation=void 0)}E.type==="message_update"&&E.message.role==="assistant"&&(g.streaming={id:"stream",role:"assistant",timestamp:new Date(E.message.timestamp).toISOString(),blocks:re(E.message.content)},Date.now()-I>=60&&(I=Date.now(),x({type:"stream",message:g.streaming}))),["message_end","agent_start","agent_settled","session_info_changed","entry_appended"].includes(E.type)&&((E.type==="message_end"&&E.message.role==="assistant"||E.type==="agent_settled")&&(g.streaming=null,x({type:"stream",message:null})),x({type:"snapshot",session:this.snapshotOf(g)}),!this.disposed&&!g.closing&&["message_end","agent_start","agent_settled","session_info_changed"].includes(E.type)&&this.onSessionsChanged())});g.detach=()=>{C(),H()};let b=[],h=!0;if(await f.bindExtensions({mode:"print",shutdownHandler:()=>{},onError:E=>{h&&b.push(E.error),this.diagnostic(g,s.plugins.find(R=>E.extensionPath.startsWith(R.root+"/"))?.id??E.extensionPath,E.event??"runtime",E.error)}}),h=!1,b.length)throw new Error(b.join("; "));if(this.ensureAvailable(),n&&!n.session.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(n&&await this.close(n,i),this.disposed)throw new Error("\u5DE5\u4F5C\u533A\u670D\u52A1\u5DF2\u5173\u95ED");this.runtimes.set(f.sessionManager.getSessionId(),g),w=null,this.activate(g)}catch(m){throw w?await this.close(w,"quit"):(a.clear(),await l.release()),m}}async close(e,t){e.closing||(e.closing=!0,e.tools.clear(),e.waitController.abort(),e.interactions.dispose(),await Gr(e.session,t,i=>this.diagnostic(e,"host","shutdown",i),5e3,()=>{e.detach(),e.bus.clear()}),await e.releasePaths())}snapshotOf(e){let{session:t,cwd:i,catalog:n}=e,s=t.sessionManager.getBranch().flatMap(a=>{let l=We(a);return l?[l]:[]});return{schemaVersion:1,sessionId:t.sessionManager.getSessionId(),cwd:i,name:De(t.sessionManager.getSessionName(),s),model:t.model?`${t.model.provider}/${t.model.id}`:null,thinkingLevel:t.thinkingLevel,thinkingLevels:t.getAvailableThinkingLevels(),idle:t.isIdle,paused:ye(t.sessionManager.getBranch()),contextUsage:t.getContextUsage()??null,messages:s,streaming:e.streaming,interactions:e.interactions.pending(t.sessionManager.getSessionId()),pluginEntries:at(t.sessionManager.getBranch(),n.ids())}}snapshot(){if(!this.active)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u5DE5\u4F5C\u533A\u4F1A\u8BDD");return this.snapshotOf(this.active)}async invokePluginAction(e){let t=this.active;if(this.disposed||!t||t.closing||e.sessionId!==t.session.sessionManager.getSessionId())throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362");if(!t.catalog.has(e.pluginId))throw new Error("\u63D2\u4EF6\u672A\u542F\u7528");let i=t.session.extensionRunner,n=await Be(t.bus,e,15e3,t.waitController.signal);if(this.active!==t||t.closing||i!==t.session.extensionRunner)throw new Error("\u4F1A\u8BDD\u8FD0\u884C\u5B9E\u4F8B\u5DF2\u5207\u6362");return this.publish({type:"snapshot",session:this.snapshot()}),n}resolveInteraction(e,t,i,n){if(this.disposed||!this.active||this.active.closing)throw new Error("Interaction host unavailable");this.active.interactions.resolve(e,t,i,n)}async send(e,t=[],i){if(this.disposed||!this.session||this.active?.closing||!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=this.active;s.operation=i,this.telemetry.breadcrumb("send",{...i,piVersion:Le}),s.agentErrorReported=!1;let a=!1,l,p,w=new Promise((m,c)=>{l=m,p=c});n.prompt(e,{images:t,preflightResult:m=>{m&&(a=!0,l())}}).then(()=>{a||l()}).catch(m=>{if(!a)p(m);else if(!this.disposed&&!s.closing&&!s.agentErrorReported){let c=this.reportError(ee(m,"Agent response failed"),{...i,stage:"agent",code:"agent_failed",piVersion:Le});this.publishFor(s,{type:"error",message:m instanceof Error?m.message:"Pi \u8BF7\u6C42\u5931\u8D25",errorCode:"unexpected_error",errorId:c,...i})}});try{await w}catch(m){throw s.operation=void 0,m}}async stop(){let e=this.active;!e||e.session.isIdle||(e.tools.cancel(),this.telemetry.breadcrumb("cancel",{...e.operation}),e.session.sessionManager.appendCustomEntry(we),await e.session.abort(),this.active===e&&!e.closing&&this.publish({type:"snapshot",session:this.snapshotOf(e)}))}async resume(e){let t=this.active;if(this.disposed||!t||t.closing)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");let i=t.session;if(!i.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!ye(i.sessionManager.getBranch()))throw new Error("\u5F53\u524D\u4F1A\u8BDD\u6CA1\u6709\u6682\u505C\u7684\u4EFB\u52A1");if(!i.model)throw new Error("\u8BF7\u5148\u9009\u62E9\u6A21\u578B");if(!(i.modelRuntime.hasConfiguredAuth(i.model.provider)||await i.modelRuntime.checkAuth(i.model.provider)!==void 0))throw new Error("\u8BF7\u5148\u8FDE\u63A5\u5F53\u524D\u6A21\u578B");if(this.active!==t||t.closing)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362");if(!i.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!ye(i.sessionManager.getBranch()))throw new Error("\u5F53\u524D\u4F1A\u8BDD\u6CA1\u6709\u6682\u505C\u7684\u4EFB\u52A1");let s=je(this.snapshotOf(t).messages);t.operation=e,t.agentErrorReported=!1,this.telemetry.breadcrumb("resume",{...e}),i.sendCustomMessage(s,{triggerTurn:!0}).catch(a=>{if(!this.disposed&&!t.closing&&!t.agentErrorReported){let l=this.reportError(ee(a,"Agent resume failed"),{...e,stage:"agent",code:"agent_failed"});this.publishFor(t,{type:"error",message:a instanceof Error?a.message:"\u7EE7\u7EED\u5931\u8D25",errorId:l,...e})}})}async models(){return(await this.session?.modelRuntime.getAvailable()??[]).map(t=>({provider:t.provider,id:t.id,name:t.name}))}async setModel(e,t){let i=this.active;if(this.disposed||!i||i.closing||!i.session.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let n=i.session.modelRuntime.getModel(e,t);if(!n)throw new Error("\u6A21\u578B\u4E0D\u53EF\u7528");await i.session.setModel(n),this.publishFor(i,{type:"snapshot",session:this.snapshotOf(i)})}dispose(){return this.disposed=!0,this.queue.run(async()=>{let e=[...this.runtimes.values()];this.active=null,this.runtimes.clear(),this.selectedByWorkspace.clear(),await Promise.all(e.map(t=>this.close(t,"quit")))})}};import{basename as gt,dirname as Xs}from"node:path";function Jr(r,e){let t=i=>e[i].map(n=>({name:i==="skills"&>(n.path).toLowerCase()==="skill.md"?gt(Xs(n.path)):gt(n.path),path:n.path,source:n.metadata.source,scope:n.metadata.scope,enabled:n.enabled}));return{packages:r.map(i=>({name:i.source,path:i.installedPath??"",source:i.source,scope:i.scope,enabled:!!i.installedPath})),extensions:t("extensions"),skills:t("skills")}}import{execFile as Ys}from"node:child_process";var Zs=(r,e)=>new Promise((t,i)=>{Ys(r,[...e],{windowsHide:!0},n=>{n?i(n):t()})});async function ht(r,e=process.platform,t=process.env,i=Zs){if(t.SSH_CONNECTION||t.SSH_TTY||t.SSH_CLIENT||e==="linux"&&!t.DISPLAY&&!t.WAYLAND_DISPLAY)return!1;let n=e==="darwin"?"open":e==="linux"?"xdg-open":e==="win32"?"explorer.exe":null;return n===null?!1:(await i(n,[r]),!0)}import{execFile as no}from"node:child_process";import{randomUUID as so}from"node:crypto";import{existsSync as Zr}from"node:fs";import{access as oo,mkdir as ao,readFile as Qr,rename as co,rm as yt,writeFile as ei}from"node:fs/promises";import{join as G}from"node:path";import{promisify as lo}from"node:util";import{realpathSync as Xr,statSync as Qs}from"node:fs";import{basename as eo,delimiter as to,dirname as Kr,join as wt,resolve as ro}from"node:path";function qr(r){if(!r)return null;try{let e=Xr(r);return eo(e)==="npm-cli.js"&&Qs(e).isFile()?e:null}catch{return null}}function io({execPath:r=process.execPath,env:e=process.env}={}){let t=qr(e.npm_execpath);if(t)return t;let i=new Set([Kr(r)]);try{i.add(Kr(Xr(r)))}catch{}let n=Object.entries(e).find(([s])=>s.toLowerCase()==="path")?.[1]??"";for(let s of n.split(to).filter(Boolean))i.add(ro(s));for(let s of i)for(let a of[wt(s,"node_modules","npm","bin","npm-cli.js"),wt(s,"..","lib","node_modules","npm","bin","npm-cli.js"),wt(s,"npm")]){let l=qr(a);if(l)return l}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 Yr(r){return{file:process.execPath,args:[io(),...r]}}var po=lo(no),Ve=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/;function uo(r,e){let t=Ve.exec(r),i=Ve.exec(e);if(!t||!i)throw new Error("\u7248\u672C\u53F7\u65E0\u6548");for(let n=1;n<=3;n++){let s=Number(t[n])-Number(i[n]);if(s)return s}return!t[4]&&i[4]?1:t[4]&&!i[4]?-1:(t[4]??"").localeCompare(i[4]??"",void 0,{numeric:!0})}async function fo(r){try{let e=Yr(r),{stdout:t}=await po(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 Ue=class{agentDir;packageRoot;launcherNonce;runNpm;desktopManaged;preparing=!1;restartPending=!1;constructor(e){this.agentDir=e.agentDir,this.packageRoot=e.packageRoot,this.launcherNonce=e.launcherNonce,this.runNpm=e.runNpm??fo,this.desktopManaged=e.desktopManaged??process.env.PI_WEBAPP_RUNTIME==="desktop"}async current(){let e=JSON.parse(await Qr(G(this.packageRoot,"package.json"),"utf8"));if(e.name!=="pi-webapp"||typeof e.version!="string"||!Ve.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();if(this.desktopManaged)return{current:e,latest:null,available:!1,canRestart:!1,reason:"\u5F53\u524D\u7531\u684C\u9762\u5E94\u7528\u7BA1\u7406\uFF0C\u8BF7\u5B89\u88C5\u65B0\u7248\u684C\u9762\u5E94\u7528\u8FDB\u884C\u5347\u7EA7\uFF1B\u4E0D\u4F1A\u901A\u8FC7 npm \u4FEE\u6539\u968F\u5305\u8FD0\u884C\u73AF\u5883\u3002"};let t=Zr(G(this.packageRoot,".git")),i={current:e,latest:null,available:!1,canRestart:!!this.launcherNonce&&!t};t?i.reason="\u5F53\u524D\u4ECE\u6E90\u7801\u76EE\u5F55\u8FD0\u884C\u3002\u7F51\u9875\u5347\u7EA7\u4EC5\u652F\u6301 npm \u5B89\u88C5\u7684\u7248\u672C\uFF0C\u4EE5\u514D\u8986\u76D6\u672C\u5730\u4EE3\u7801\u3002":i.canRestart||(i.reason="\u5F53\u524D\u9875\u9762\u7531 Pi \u7EC8\u7AEF\u6253\u5F00\uFF0C\u65E0\u6CD5\u4ECE\u7F51\u9875\u81EA\u52A8\u91CD\u542F Pi\uFF1B\u8BF7\u4F7F\u7528 pi-webapp \u542F\u52A8\u5668\u3002");try{let n=JSON.parse((await this.runNpm(["view","pi-webapp","dist-tags.latest","--json","--prefer-online"])).trim()),s=Array.isArray(n)&&n.length===1?n[0]:n;if(typeof s!="string"||!Ve.test(s))throw new Error("npm \u8FD4\u56DE\u7684\u7248\u672C\u53F7\u65E0\u6548");i.latest=s,i.available=uo(s,e)>0}catch(n){throw new Error(`\u68C0\u67E5 npm \u66F4\u65B0\u5931\u8D25\uFF1A${n instanceof Error?n.message:String(n)}`)}return i}async prepare(){if(this.desktopManaged)throw new Error("\u684C\u9762\u5E94\u7528\u7684\u8FD0\u884C\u73AF\u5883\u4E0D\u80FD\u901A\u8FC7\u7F51\u9875\u5347\u7EA7\uFF0C\u8BF7\u5B89\u88C5\u65B0\u7248\u684C\u9762\u5E94\u7528");if(!this.launcherNonce)throw new Error("\u5F53\u524D\u9875\u9762\u65E0\u6CD5\u81EA\u52A8\u91CD\u542F Pi");if(Zr(G(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=G(this.agentDir,"pi-web","releases",e.latest);await yt(t,{recursive:!0,force:!0}),await ao(t,{recursive:!0});try{await this.runNpm(["install",`pi-webapp@${e.latest}`,"--prefix",t,"--ignore-scripts","--no-save","--no-audit","--no-fund"]);let i=G(t,"node_modules","pi-webapp"),n=JSON.parse(await Qr(G(i,"package.json"),"utf8"));if(n.name!=="pi-webapp"||n.version!==e.latest)throw new Error("\u4E0B\u8F7D\u7684\u5305\u4E0E\u76EE\u6807\u7248\u672C\u4E0D\u7B26");let s=G(i,"bin","pi-webapp.mjs");await Promise.all([s,G(i,"dist","extension.js"),G(i,"web","dist","index.html")].map(p=>oo(p)));let a=G(this.agentDir,"pi-web"),l=G(a,`update.${so()}.tmp`);try{await ei(l,JSON.stringify({version:e.latest,launcher:s}),{mode:384}),await co(l,G(a,"update.json"))}finally{await yt(l,{force:!0})}return this.restartPending=!0,{version:e.latest,launcher:s}}catch(i){throw await yt(t,{recursive:!0,force:!0}),i}}finally{this.preparing=!1}}async requestRestart(e){if(this.desktopManaged)throw new Error("\u684C\u9762\u5E94\u7528\u7684\u8FD0\u884C\u73AF\u5883\u4E0D\u80FD\u901A\u8FC7\u7F51\u9875\u91CD\u542F\u5347\u7EA7");if(!this.launcherNonce)throw new Error("\u5F53\u524D\u9875\u9762\u65E0\u6CD5\u81EA\u52A8\u91CD\u542F Pi");try{await ei(G(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 Eo}from"node:crypto";async function mo(){if(process.env.PI_WEB_SENTRY_VERIFY_RELEASE!=="true"||process.env.PI_WEB_SENTRY_ENVIRONMENT!=="sentry-verification")throw new Error("Sentry release verification is not enabled");let r=new X({monitor:!1});try{if(await r.ready,!r.enabled)throw new Error("Sentry verification transport is disabled");let e=r.capture(new Error("Sentry Node release verification"),{stage:"release_verification",code:"sentry_release_probe"});if(!e||!await r.flush(3e3))throw new Error("Sentry verification event was not delivered");return{eventId:e,release:Ae,buildId:J}}finally{await r.close()}}var ri=vt(ho(yo(import.meta.url)),"../web/dist"),xo=Symbol.for(`pi-web.bridge-state:${import.meta.url}`),o=globalThis[xo]??={bridge:null,current:null,commandContext:null,pi:null,replacementContext:null,replacementSessionId:null,lastStreamAt:0,tuiStreaming:null,workspaces:null,workspaceSessions:null,selected:"tui",activeWorkspaceId:null,autoOpened:!1,tuiCatalog:null,stopPluginWatch:null,interactions:null,lifecycle:new se,tuiGeneration:0,stopChanged:null,tuiWaitController:new AbortController};o.lifecycle??=new se;o.tuiGeneration??=0;o.stopChanged??=null;o.tuiWaitController??=new AbortController;o.tuiStreaming??=null;function Ee(){return o.selected==="sdk"?o.workspaceSessions?.catalog??null:o.tuiCatalog}var Po=null;function So(){return Po??=bo.create({refreshOnCreate:!1})}var Je=new Map;async function fe(){let r=await So(),e=o.selected==="tui"?o.current?.modelRegistry:void 0,t=new Set(e?.getRegisteredProviderIds()??[]);for(let i of Je.keys())t.has(i)||(r.unregisterProvider(i),Je.delete(i));for(let i of t){let n=e?.getRegisteredNativeProvider(i),s=e?.getRegisteredProviderConfig(i),a=n??s;!a||Je.get(i)===a||(n?r.registerNativeProvider(n):s&&r.registerProvider(i,s),Je.set(i,a))}return await r.refresh({allowNetwork:!1}),r}function D(){if(o.selected==="sdk")return o.workspaceSessions?.snapshot()??(()=>{throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD")})();if(o.current===null)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");return{...ct(o.current,o.current.sessionManager.getSessionName(),Ee()?.ids()??[]),streaming:o.tuiStreaming,interactions:o.interactions?.pending(o.current.sessionManager.getSessionId())??[]}}function N(r){if(D().sessionId!==r)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362")}async function oi(){let r=(o.workspaces?.list()??[]).map(m=>({...m})),e=o.activeWorkspaceId,t=D(),i=o.current,n=i?ct(i,i.sessionManager.getSessionName(),o.tuiCatalog?.ids()??[]):null,s=await de(t.cwd).catch(m=>(o.bridge?.reportError?.(m,{stage:"workspace_path"}),null)),a=n?await de(n.cwd).catch(m=>(o.bridge?.reportError?.(m,{stage:"workspace_path"}),null)):null,l=await si.listAll(),p=o.workspaceSessions?.retainedSessions()??[];n&&a&&p.push({sessionId:n.sessionId,cwd:a,path:null,name:n.name,modified:n.messages.at(-1)?.timestamp??new Date().toISOString(),idle:n.idle});let w=(await Promise.all(r.map(async m=>{let f=(await ve(m.path,l).catch(u=>(u instanceof be?m.available=!1:o.bridge?.reportError?.(u,{stage:"workspace_sessions"}),[]))).map(u=>({id:u.id,workspaceId:m.id,path:u.path,name:u.name||u.firstMessage?.slice(0,50)||"\u5F53\u524D\u4F1A\u8BDD",modified:u.modified.toISOString(),idle:!0}));for(let u of p.filter(g=>g.cwd===m.path)){let g=f.findIndex(I=>I.id===u.sessionId),x={id:u.sessionId,workspaceId:m.id,path:u.path??f[g]?.path??null,name:u.name,modified:u.modified,idle:u.idle};g<0?f.unshift(x):f[g]=x}return m.path===s&&!f.some(u=>u.id===t.sessionId)&&f.unshift({id:t.sessionId,workspaceId:m.id,path:null,name:t.name,modified:new Date().toISOString(),idle:t.idle}),f}))).flat();return{items:r,activeId:e,sessions:w}}var ii=0;async function V(){if(!o.bridge)return;let r=++ii;try{let e=await oi();r===ii&&o.bridge?.publish({type:"workspaces",value:e})}catch(e){o.bridge?.reportError?.(e,{stage:"workspace_list"})}}async function bt(r,e=!1){let t=o.workspaces?.get(r);if(!t)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");if(await ie(t.path),!e&&o.current&&t.path===await de(o.current.cwd)&&!o.workspaceSessions?.hasWorkspace(t.path))o.selected="tui",o.activeWorkspaceId=r,o.bridge?.publish({type:"stream",message:null}),o.bridge?.publish({type:"snapshot",session:D()});else{if(!o.workspaceSessions)throw new Error("Pi \u5DE5\u4F5C\u533A\u670D\u52A1\u4E0D\u53EF\u7528");await o.workspaceSessions.open(t.path,e?"new":"continue"),o.selected="sdk",o.activeWorkspaceId=r,o.bridge?.publish({type:"snapshot",session:D()})}await V()}function U(r){let e=o.current;if(e===null||e.sessionManager.getSessionId()!==r)throw new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362");return e}function W(r){o.current=r,o.selected==="tui"&&o.bridge?.publish({type:"snapshot",session:D()})}function ai(){if(o.current===null)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");let r=o.selected==="sdk"?o.workspaceSessions?.path:o.current.cwd;if(!r)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u5DE5\u4F5C\u533A");let e=o.selected==="tui"?o.current.isProjectTrusted():o.workspaceSessions?.session?.settingsManager.isProjectTrusted()??!1;return vo.create(r,void 0,{projectTrusted:e})}async function ci(){let r=ai(),e=n=>({packages:(n.packages??[]).map(s=>typeof s=="string"?s:s.source),extensions:n.extensions??[],skills:n.skills??[]}),t=new ni({cwd:D().cwd,agentDir:oe(),settingsManager:r}),i=Jr(t.listConfiguredPackages(),await t.resolve(async()=>"skip"));return{projectTrusted:r.isProjectTrusted(),global:e(r.getGlobalSettings()),project:e(r.getProjectSettings()),installed:i}}async function Io(r){N(r.sessionId);let e=o.selected==="tui"?U(r.sessionId):null;if(e?!e.isIdle():!o.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let t=ai();if(r.scope==="project"&&!t.isProjectTrusted())throw new Error("\u5F53\u524D\u9879\u76EE\u5C1A\u672A\u53D7\u4FE1\u4EFB\uFF0C\u65E0\u6CD5\u4FEE\u6539\u9879\u76EE\u8BBE\u7F6E");let i=r.value.trim(),n=r.scope==="project"?t.getProjectSettings():t.getGlobalSettings();if(r.kind==="packages"){let s=new ni({cwd:D().cwd,agentDir:oe(),settingsManager:t});r.action==="add"?await s.installAndPersist(i,{local:r.scope==="project"}):await s.removeAndPersist(i,{local:r.scope==="project"})}else if(r.kind==="extensions"){let s=n.extensions??[],a=r.action==="add"?[...new Set([...s,i])]:s.filter(l=>l!==i);r.scope==="project"?t.setProjectExtensionPaths(a):t.setExtensionPaths(a)}else{let s=n.skills??[],a=r.action==="add"?[...new Set([...s,i])]:s.filter(l=>l!==i);r.scope==="project"?t.setProjectSkillPaths(a):t.setSkillPaths(a)}return await t.flush(),o.selected==="tui"?(o.commandContext&&await o.commandContext.reload(),o.current&&W(o.current)):(await o.workspaceSessions?.reload(),o.bridge?.publish({type:"plugins_changed"})),await ci()}function kt(r,e=ht){o.pi=r,o.tools?.clear(),o.tools=new ue({enabled:()=>!!o.telemetry?.enabled&&!!o.bridge,capture:(s,a)=>o.bridge?.reportError?.(s,a),breadcrumb:(s,a)=>o.bridge?.breadcrumb?.(s,a),anonymize:s=>o.telemetry?.session(s)??"unavailable"});let t=s=>({...o.operation,session:o.telemetry?.session(s.sessionManager.getSessionId()),piVersion:He,model:s.model?`${s.model.provider}/${s.model.id}`:null,thinkingLevel:s.thinkingLevel});o.interactions?.dispose(),o.interactions=new pe(r.events,s=>!!o.bridge&&s.sessionId===o.current?.sessionManager.getSessionId()&&!!o.tuiCatalog?.has(s.pluginId),()=>{o.current&&o.selected==="tui"&&W(o.current)});let i=()=>{o.stopChanged?.(),o.stopChanged=r.events.on(Fe,()=>{o.selected==="tui"&&o.current&&W(o.current)})};i(),r.on("session_start",async(s,a)=>{if(o.tuiStreaming=null,o.tools?.clear(),o.operation=void 0,o.tuiWaitController.abort(),o.tuiWaitController=new AbortController,o.tuiGeneration++,i(),o.current=a,o.bridge){let l=await ne.discover(a.cwd,a.isProjectTrusted?.()??!1);if(o.current!==a)return;o.tuiCatalog=l}o.replacementSessionId!==a.sessionManager.getSessionId()&&(o.replacementContext=null,o.replacementSessionId=null),W(a),o.bridge&&o.selected==="tui"&&o.bridge.publish({type:"plugins_changed"}),o.selected==="tui"&&o.workspaces&&o.workspaces.add(a.cwd).then(async l=>{o.selected!=="tui"||o.current?.sessionManager.getSessionId()!==a.sessionManager.getSessionId()||(o.activeWorkspaceId=l.id,await V())}).catch(l=>{o.bridge?.publish({type:"error",message:l instanceof Error?l.message:"\u65E0\u6CD5\u6CE8\u518C\u5F53\u524D\u5DE5\u4F5C\u533A",errorCode:"unexpected_error",errorId:o.bridge.reportError?.(l,{stage:"workspace_register"})})}),process.env.PI_WEBAPP_AUTO_OPEN==="1"&&a.mode==="tui"&&!o.autoOpened&&(o.autoOpened=!0,n(a).catch(l=>{a.ui.notify(l instanceof Error?l.message:"Web \u542F\u52A8\u5931\u8D25","error")}))}),r.on("agent_start",(s,a)=>{o.bridge?.breadcrumb?.("agent_start",t(a)),W(a),V()}),r.on("agent_end",(s,a)=>W(a)),r.on("agent_settled",(s,a)=>{o.bridge?.breadcrumb?.("agent_end",t(a)),o.tools?.clear(),o.operation=void 0,o.tuiStreaming=null,W(a),V()}),r.on("tool_execution_start",(s,a)=>{o.tools?.start(s,t(a))}),r.on("tool_execution_end",(s,a)=>{o.tools?.end(s,t(a))}),r.on("model_select",(s,a)=>W(a)),r.on("thinking_level_select",(s,a)=>W(a)),r.on("message_end",(s,a)=>{if(s.message.role==="assistant"&&s.message.stopReason==="error"){let l=o.bridge?.reportError?.(new Error("Agent response failed"),{...o.operation,stage:"agent",code:"agent_failed",piVersion:He});o.selected==="tui"&&o.bridge?.publish({type:"error",message:s.message.errorMessage??"Agent response failed",errorCode:"unexpected_error",errorId:l,...o.operation})}s.message.role==="toolResult"&&o.tools?.message(s.message,t(a)),s.message.role==="assistant"&&(o.tuiStreaming=null),o.selected==="tui"&&s.message.role==="assistant"&&o.bridge?.publish({type:"stream",message:null}),W(a),V()}),r.on("session_info_changed",(s,a)=>W(a)),r.on("message_update",(s,a)=>{if(o.current=a,s.message.role!=="assistant"||(o.tuiStreaming={id:"stream",role:"assistant",timestamp:new Date(s.message.timestamp).toISOString(),blocks:re(s.message.content)},o.selected!=="tui"||o.bridge===null))return;let l=Date.now();l-o.lastStreamAt<60||(o.lastStreamAt=l,o.bridge.publish({type:"stream",message:o.tuiStreaming}))}),r.on("session_shutdown",async s=>{if(o.tuiStreaming=null,o.tools?.clear(),o.operation=void 0,o.tuiWaitController.abort(),o.tuiGeneration++,o.stopChanged?.(),o.stopChanged=null,o.interactions?.cancelAll(),o.current=null,s.reason==="new"||s.reason==="resume"||s.reason==="fork"||s.reason==="reload")return;let a=o.bridge,l=o.telemetry;o.bridge=null,o.commandContext=null,o.replacementContext=null,o.replacementSessionId=null,o.pi=null;let p=o.workspaceSessions;o.workspaceSessions=null,await p?.dispose(),o.selected="tui",o.activeWorkspaceId=null,o.autoOpened=!1,o.tuiCatalog=null,o.stopPluginWatch?.(),o.stopPluginWatch=null,o.operation=void 0,o.telemetry=null,a?await a.close():await l?.close()});let n=async s=>{o.telemetry??=new X;try{o.current=s,o.commandContext="newSession"in s?s:null,o.pi=r,o.tuiCatalog=await ne.discover(s.cwd,s.isProjectTrusted?.()??!1),o.workspaces===null&&(o.workspaces=new Oe(Nr(oe())),await o.workspaces.load());try{await o.workspaces.discover((await si.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 o.workspaces.add(s.cwd);if(o.selected==="tui"&&(o.activeWorkspaceId=a.id),o.bridge&&(o.bridge.protocolVersion!==7||o.bridge.buildId!==J||typeof o.bridge.reportError!="function")){let p=o.bridge;if(o.workspaceSessions&&(o.workspaceSessions.telemetryVersion!==2||o.workspaceSessions.runtimeVersion!==1)&&o.workspaceSessions.session&&!o.workspaceSessions.session.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F\u518D\u5207\u6362\u5DE5\u4F5C\u533A");o.bridge=null,await p.close(),await o.telemetry.close(),o.telemetry=new X}if(o.bridge===null){let p=o.workspaceSessions&&(o.workspaceSessions.telemetryVersion!==2||o.workspaceSessions.runtimeVersion!==1)?o.workspaceSessions:null,w=p?.session&&p.path?{path:p.path,sessionManager:p.session.sessionManager}:null;p&&(await p.dispose(),o.workspaceSessions=null),o.workspaceSessions??=new Ge(c=>{o.selected==="sdk"&&o.bridge?.publish(c)},()=>o.current?.model,c=>{try{return!!o.current&&ti(o.current.cwd)===c&&(o.current.isProjectTrusted?.()??!1)}catch{return!1}},(c,f)=>o.bridge?.reportError?.(c,f),{enabled:()=>!!o.telemetry?.enabled&&!!o.bridge,breadcrumb:(c,f)=>o.bridge?.breadcrumb?.(c,f),anonymize:c=>o.telemetry?.session(c)??"unavailable"},()=>{V()}),w&&await o.workspaceSessions.open(w.path,{sessionManager:w.sessionManager});let m={selfUpdate:new Ue({agentDir:oe(),packageRoot:vt(ri,"../.."),launcherNonce:process.env.PI_WEBAPP_LAUNCHER_NONCE}),snapshot:D,busyGitWorkspaces:()=>{let c=(o.workspaceSessions?.retainedSessions()??[]).filter(f=>!f.idle).map(f=>f.cwd);if(o.current&&!o.current.isIdle())try{c.push(ti(o.current.cwd))}catch{c.push(o.current.cwd)}return c},plugins:async()=>{let c=Ee();return await c?.refreshAssets(),c?.view()??{plugins:[],errors:[]}},pluginAsset:async c=>Ee()?.asset(c)??null,async invokePluginAction(c,f,u,g){if(N(c),!Ee()?.has(f))throw new Error("\u63D2\u4EF6\u672A\u542F\u7528");let x=o.selected,I=o.tuiGeneration,C=o.workspaceSessions?.session,H={requestId:Eo(),sessionId:c,pluginId:f,action:u,input:g},b=o.selected==="sdk"?await o.workspaceSessions.invokePluginAction(H):await Be(o.pi.events,H,15e3,o.tuiWaitController.signal);if(N(c),x!==o.selected||(x==="tui"?I!==o.tuiGeneration:C!==o.workspaceSessions?.session))throw new Error("\u4F1A\u8BDD\u8FD0\u884C\u5B9E\u4F8B\u5DF2\u5207\u6362");return o.selected==="tui"&&o.current&&W(o.current),b},async resolvePluginInteraction(c,f,u,g){if(N(c),!Ee()?.has(f))throw new Error("\u63D2\u4EF6\u672A\u542F\u7528");o.selected==="sdk"?o.workspaceSessions.resolveInteraction(c,f,u,g):o.interactions.resolve(c,f,u,g)},image(c,f,u){N(c);let x=(o.selected==="sdk"?o.workspaceSessions?.session?.sessionManager.getBranch():o.current?.sessionManager.getBranch())?.find(C=>C.id===f);if(x?.type!=="message"||x.message.role!=="user"||!Array.isArray(x.message.content))return null;let I=x.message.content[u];return I?.type!=="image"?null:{data:Buffer.from(I.data,"base64"),mimeType:I.mimeType}},async workspaces(){return oi()},async addWorkspace(c,f){let u=await o.workspaces.add(c,f);try{await bt(u.id,!0)}catch(g){throw await V(),g}},async selectWorkspace(c){await bt(c)},async newSessionInWorkspace(c){await bt(c,!0)},async removeWorkspace(c){if(c===o.activeWorkspaceId)throw new Error("\u8BF7\u5148\u5207\u6362\u5230\u5176\u4ED6\u5DE5\u4F5C\u533A");await o.workspaces.remove(c),await V()},async selectSession(c,f,u){let g=o.workspaces?.get(c);if(!g)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");if(await ie(g.path),f===o.current?.sessionManager.getSessionId()&&g.path===await de(o.current.cwd))o.selected="tui",o.activeWorkspaceId=c,o.bridge?.publish({type:"stream",message:null}),o.bridge?.publish({type:"snapshot",session:D()});else{if(o.selected==="sdk"&&o.workspaceSessions?.session?.sessionManager.getSessionId()===f&&o.workspaceSessions.path===g.path)return;if(o.workspaceSessions?.hasSession(g.path,f))await o.workspaceSessions.open(g.path,{sessionId:f});else{if(!(await ve(g.path)).some(I=>I.id===f&&I.path===u))throw new Error("\u4F1A\u8BDD\u4E0D\u5C5E\u4E8E\u8BE5\u5DE5\u4F5C\u533A");await o.workspaceSessions.open(g.path,{sessionFile:u})}o.selected="sdk",o.activeWorkspaceId=c,o.bridge?.publish({type:"snapshot",session:D()})}await V()},async models(){if(o.selected==="sdk")return o.workspaceSessions?.models()??[];let c=o.current;if(!c)throw new Error("\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD");let f=c.scopedModels?.map(u=>`${u.model.provider}/${u.model.id}`)??[];return c.modelRegistry.getAvailable().filter(u=>f.length===0||f.includes(`${u.provider}/${u.id}`)).map(u=>({provider:u.provider,id:u.id,name:u.name}))},async providers(){let c=await fe(),f=new Set((await c.listCredentials()).map(u=>u.providerId));return c.getProviders().map(u=>({id:u.id,name:u.name,configured:c.getProviderAuthStatus(u.id).configured,storedCredential:f.has(u.id),methods:[u.auth.apiKey?.login?"api_key":null,u.auth.oauth?"oauth":null].filter(g=>g!==null)}))},async providerModels(c){let f=await fe();return fr(ze(oe(),"models.json"),c,f)},async updateProviderModel(c,f,u){if(N(c),o.selected==="tui"?!U(c).isIdle():!o.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let g=D().model;if(u.action==="remove"&&g===`${f}/${u.id}`)throw new Error("\u8BF7\u5148\u5207\u6362\u5F53\u524D\u4F7F\u7528\u7684\u6A21\u578B");if(u.action==="save"&&u.originalId&&u.originalId!==u.model.id&&g===`${f}/${u.originalId}`)throw new Error("\u8BF7\u5148\u5207\u6362\u5F53\u524D\u4F7F\u7528\u7684\u6A21\u578B");let x=await fe();await mr(ze(oe(),"models.json"),f,u,x),await x.refresh({providers:[f],allowNetwork:!1}),await o.current?.modelRegistry.refresh({providers:[f],allowNetwork:!1}),await o.workspaceSessions?.session?.modelRuntime.refresh({providers:[f],allowNetwork:!1});let I=u.action==="save"?u.model.id:u.action==="base_url"&&g?.startsWith(`${f}/`)?g.slice(f.length+1):null;if(I&&g===`${f}/${I}`)if(o.selected==="sdk")try{await o.workspaceSessions.setModel(f,I)}catch{throw new Error("\u6A21\u578B\u5DF2\u4FDD\u5B58\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u8BE5\u6A21\u578B\u4EE5\u5E94\u7528\u65B0\u53C2\u6570")}else{let C=U(c),H=C.modelRegistry.find(f,I);if(!H||!o.pi||!await o.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");W(C)}},async logoutProvider(c,f){if(N(c),o.selected==="tui"?!U(c).isIdle():!o.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let u=await fe();if(!(await u.listCredentials()).some(g=>g.providerId===f))throw new Error("\u8BE5\u63D0\u4F9B\u65B9\u6CA1\u6709\u5DF2\u4FDD\u5B58\u7684\u8BA4\u8BC1");await u.logout(f),await o.current?.modelRegistry.refresh({providers:[f],allowNetwork:!1}),await o.workspaceSessions?.session?.modelRuntime.refresh({providers:[f],allowNetwork:!1})},async loginProvider(c,f,u){let g=await fe();await g.login(c,f,ar(c,f,u)),await g.refresh({providers:[c],allowNetwork:!1}),await o.current?.modelRegistry.refresh({providers:[c],allowNetwork:!1}),await o.workspaceSessions?.session?.modelRuntime.refresh({providers:[c],allowNetwork:!1})},async addCustomProvider(c,f){if(N(c),o.selected==="tui"?!U(c).isIdle():!o.workspaceSessions?.session?.isIdle)throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let u=await fe();if(u.getProvider(f.id))throw new Error("\u63D0\u4F9B\u65B9\u5DF2\u5B58\u5728");await cr(ze(oe(),"models.json"),f),await u.refresh({allowNetwork:!1}),await o.current?.modelRegistry.refresh({allowNetwork:!1}),await o.workspaceSessions?.session?.modelRuntime.refresh({allowNetwork:!1})},commands(){return o.selected==="tui"?(o.pi?.getCommands()??[]).filter(c=>c.name!=="web"&&c.name!=="web-dev-reload").map(c=>({name:c.name,description:c.description})):[]},async compact(c){if(N(c),o.selected==="sdk"){let u=o.workspaceSessions?.session;if(!u||!u.isIdle)throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");await u.compact(),o.bridge?.publish({type:"snapshot",session:D()});return}let f=U(c);if(!f.isIdle())throw new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");f.compact()},async setModel(c,f,u){if(N(c),o.selected==="sdk"){await o.workspaceSessions.setModel(f,u);return}let g=U(c);if(!g.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");let x=g.modelRegistry.find(f,u);if(!x||!g.modelRegistry.getAvailable().some(I=>I.provider===f&&I.id===u))throw new Error("\u6A21\u578B\u4E0D\u53EF\u7528");if(!o.pi||!await o.pi.setModel(x))throw new Error("\u6A21\u578B\u63D0\u4F9B\u65B9\u672A\u914D\u7F6E\u8BA4\u8BC1");W(g)},async setThinkingLevel(c,f){if(N(c),!["off","minimal","low","medium","high","xhigh"].includes(f))throw new Error("\u63A8\u7406\u5F3A\u5EA6\u65E0\u6548");if(o.selected==="sdk"){let x=o.workspaceSessions?.session;if(!x||!x.isIdle||!x.getAvailableThinkingLevels().includes(f))throw new Error("\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u6B64\u63A8\u7406\u5F3A\u5EA6");x.setThinkingLevel(f),o.bridge?.publish({type:"snapshot",session:D()});return}let g=U(c);if(!g.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!g.model||!ko(g.model).includes(f))throw new Error("\u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u6B64\u63A8\u7406\u5F3A\u5EA6");if(!o.pi)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");o.pi.setThinkingLevel(f),W(g)},config:ci,updateConfig:Io,async send(c,f,u=[],g){if(N(c),o.selected==="sdk"){await o.workspaceSessions.send(f,u,g);return}if(!U(c).isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");o.operation=g;try{if(o.bridge?.breadcrumb?.("send",{...g,piVersion:He}),o.replacementContext!==null&&o.replacementSessionId===c){await o.replacementContext.sendUserMessage(u.length?[{type:"text",text:f},...u]:f,{expandPromptTemplates:!0});return}if(o.pi===null)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");o.pi.sendUserMessage(u.length?[{type:"text",text:f},...u]:f,{expandPromptTemplates:!0})}catch(I){throw o.operation=void 0,I}},async abort(c){if(N(c),o.selected==="sdk")await o.workspaceSessions.stop();else{let f=U(c);if(f.isIdle())return;if(!o.pi)throw new Error("Pi \u4F1A\u8BDD\u4E0D\u53EF\u7528");o.tools?.cancel(),o.bridge?.breadcrumb?.("cancel",{...o.operation}),o.pi.appendEntry(we),f.abort()}},async resume(c,f){if(N(c),o.selected==="sdk"){await o.workspaceSessions.resume(f);return}let u=U(c);if(!u.isIdle())throw new Error("Pi \u6B63\u5728\u8FD0\u884C\uFF0C\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u7ED3\u675F");if(!u.model||!o.pi)throw new Error("\u8BF7\u5148\u9009\u62E9\u6A21\u578B");if(!u.modelRegistry.hasConfiguredAuth(u.model))throw new Error("\u8BF7\u5148\u8FDE\u63A5\u5F53\u524D\u6A21\u578B");o.operation=f;try{o.pi.sendMessage(je(D().messages),{triggerTurn:!0})}catch(g){throw o.operation=void 0,g}},async newSession(c){if(N(c),o.selected==="sdk"){let g=o.workspaces?.get(o.activeWorkspaceId??"");if(!g)throw new Error("\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728");await o.workspaceSessions.open(g.path,"new"),await V();return}let f=U(c);if(!f.isIdle()||o.commandContext===null){await o.workspaceSessions.open(f.cwd,"new"),o.selected="sdk",o.bridge?.publish({type:"snapshot",session:D()}),await V();return}if((await o.commandContext.newSession({withSession:async g=>{o.commandContext=g,o.replacementContext=g,o.replacementSessionId=g.sessionManager.getSessionId(),o.current=g}})).cancelled)throw new Error("\u65B0\u4F1A\u8BDD\u5DF2\u53D6\u6D88");await V()}};m.addWorkspace=o.lifecycle.wrap(m.addWorkspace),m.selectWorkspace=o.lifecycle.wrap(m.selectWorkspace),m.newSessionInWorkspace=o.lifecycle.wrap(m.newSessionInWorkspace),m.removeWorkspace=o.lifecycle.wrap(m.removeWorkspace),m.selectSession=o.lifecycle.wrap(m.selectSession),m.newSession=o.lifecycle.wrap(m.newSession),m.updateConfig=o.lifecycle.wrap(m.updateConfig),o.bridge=await _r(m,ri,o.telemetry)}if(o.stopPluginWatch===null&&process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS){let p=[],w=null;for(let m of(process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS??"").split(go).filter(Boolean))try{p.push(wo(ze(vt(m),"dist"),(c,f)=>{let u=String(f??"");["client.js","client.css"].includes(u)&&(w&&clearTimeout(w),w=setTimeout(()=>o.bridge?.publish({type:"plugins_changed"}),180))}))}catch(c){o.bridge?.publish({type:"error",message:`\u63D2\u4EF6\u76D1\u542C\u5931\u8D25\uFF1A${m}: ${String(c)}`})}o.stopPluginWatch=()=>{for(let m of p)m.close();w&&clearTimeout(w)}}let l=await e(o.bridge.url).catch(()=>!1);s.ui.notify(`pi-webapp: ${o.bridge.url}`,l?"info":"warning"),s.ui.setStatus("pi-webapp","Web \u5DF2\u542F\u52A8 \xB7 /web \u91CD\u65B0\u6253\u5F00")}catch(a){throw o.telemetry?.capture(a,{stage:"open_web",piVersion:He}),o.bridge||(await o.telemetry?.close(),o.telemetry=null),a}};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 o.lifecycle.run(async()=>{let l=o.workspaceSessions?.session;l&&(await l.waitForIdle(),await o.workspaceSessions.reload()),await a.reload()}))}})}var ql=kt;export{ql as default,mo as verifySentryNodeRelease};
|
package/docs/desktop.md
CHANGED
|
@@ -46,7 +46,7 @@ npm run desktop:package -- --dir # unpacked application for QA
|
|
|
46
46
|
|
|
47
47
|
Output is in `desktop-release/`. The macOS bundle is **pi.app**, the native menu
|
|
48
48
|
and window name are **pi**, and installer names include a desktop build number,
|
|
49
|
-
e.g. `pi-0.1.
|
|
49
|
+
e.g. `pi-0.1.20-desktop.5-mac-arm64.dmg`. “pi → 关于 pi” shows the build number
|
|
50
50
|
and executable location, so different desktop rebuilds are distinguishable even
|
|
51
51
|
when their shared backend stays at the same npm version. `desktop/release.json`
|
|
52
52
|
is the single source for the desktop name/build; increment its build number for
|
|
@@ -55,8 +55,9 @@ each delivered rebuild. The CFBundleVersion / Windows file version also changes.
|
|
|
55
55
|
Cross-platform/architecture flags are
|
|
56
56
|
intentionally rejected by the wrapper: using the current machine's Node/native
|
|
57
57
|
modules in another platform's installer would create a broken application. Use
|
|
58
|
-
native runners for each target.
|
|
59
|
-
|
|
58
|
+
native runners for each target. `desktop.yml` remains a manual cross-platform
|
|
59
|
+
packaging/artifact workflow. The separate `desktop-release.yml` below handles
|
|
60
|
+
verified macOS arm64 prereleases, not every main push.
|
|
60
61
|
|
|
61
62
|
The application embeds Node and Pi. Git, SSH, project compilers and other system
|
|
62
63
|
tools are **not** bundled. Missing tools must be installed by the user. Model
|
|
@@ -73,8 +74,9 @@ These are two separate release responsibilities:
|
|
|
73
74
|
- **Safe updates** verify an update's publisher/integrity and replace a compatible
|
|
74
75
|
application/runtime without destroying user data.
|
|
75
76
|
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
The installers remain **unsigned/unnotarized test builds**, with no certificate
|
|
78
|
+
discovery or automatic desktop updater. A GitHub prerelease is a download channel,
|
|
79
|
+
not a claim of formal signed-distribution readiness.
|
|
78
80
|
macOS Gatekeeper / Windows SmartScreen may warn or block an unsigned download.
|
|
79
81
|
Do not disable OS security globally to use it. Public distribution needs a
|
|
80
82
|
separately configured, authorized signing/notarization workflow; local successful
|
|
@@ -82,7 +84,8 @@ packaging is not proof of public-distribution readiness.
|
|
|
82
84
|
|
|
83
85
|
For now, install a newer desktop package to upgrade; if replacing a running
|
|
84
86
|
desktop-owned runtime, first finish tasks and stop that owned service. A desktop
|
|
85
|
-
attached to an external Web service can simply close without stopping the service.
|
|
87
|
+
attached to an external Web service can simply close without stopping the service.
|
|
88
|
+
Desktop-managed backends reject the Web/npm update and restart paths,
|
|
86
89
|
so the UI cannot overwrite the bundled runtime. A desktop window attached to an
|
|
87
90
|
existing npm-managed backend preserves that backend's original update behavior.
|
|
88
91
|
|
|
@@ -95,7 +98,7 @@ existing npm-managed backend preserves that backend's original update behavior.
|
|
|
95
98
|
If pi.app already exists, confirm Replace. The formerly named Pi Webapp.app
|
|
96
99
|
is a separate Finder item and is not silently deleted or overwritten.
|
|
97
100
|
3. Explicitly open `/Applications/pi.app`, not the old Dock shortcut, an older
|
|
98
|
-
mounted disk image, or Pi Webapp.app. Verify **pi → 关于 pi
|
|
101
|
+
mounted disk image, or Pi Webapp.app. Verify the expected build in **pi → 关于 pi**.
|
|
99
102
|
4. Remove the old pinned Dock shortcut and pin the new pi.app. Once verified,
|
|
100
103
|
the old Pi Webapp.app may be removed manually; do not delete `~/.pi`.
|
|
101
104
|
|
|
@@ -106,6 +109,53 @@ preferences or allow a second independent desktop instance. Explicit
|
|
|
106
109
|
sessions still live in their existing directory. The shared Web document/CLI
|
|
107
110
|
keeps its existing name; this rename is for the native desktop application.
|
|
108
111
|
|
|
112
|
+
## GitHub desktop prereleases
|
|
113
|
+
|
|
114
|
+
Download builds from **[GitHub Releases](https://github.com/chengzhiyi/pi-webapp/releases)**,
|
|
115
|
+
not the npm package, source ZIP or an expired Actions artifact. The current
|
|
116
|
+
release channel only offers tested macOS Apple Silicon DMGs; Windows/Linux and
|
|
117
|
+
Intel macOS need their own acceptance before becoming release targets.
|
|
118
|
+
|
|
119
|
+
`.github/workflows/desktop-release.yml` supports:
|
|
120
|
+
|
|
121
|
+
- **Tag push**: `desktop-v<backend-version>-b<desktop-build>`, such as
|
|
122
|
+
`desktop-v0.1.20-b5`. The tag must match package.json and desktop/release.json
|
|
123
|
+
at that exact source commit; mismatches fail before installation/build.
|
|
124
|
+
- **Manual build only** (default): `gh workflow run desktop-release.yml --ref main`.
|
|
125
|
+
This produces checksummed Actions artifacts without a public release.
|
|
126
|
+
- **Explicit manual publication**: add `-f publish=true`. The workflow pins the
|
|
127
|
+
dispatch commit, derives the tag from it, and only creates a missing tag at
|
|
128
|
+
that same commit. Existing tags pointing elsewhere are never moved.
|
|
129
|
+
|
|
130
|
+
For repeatable publication, commit the intended version/build and push a tag
|
|
131
|
+
pointing to that verified source SHA; do not silently follow a moving main while
|
|
132
|
+
its independent npm pipeline may write another version. Increment the desktop
|
|
133
|
+
build number for each delivered rebuild. Tag creation/release is an intentional
|
|
134
|
+
publication action, not part of an ordinary main commit.
|
|
135
|
+
|
|
136
|
+
The build job uses standard `macos-15` arm64, pinned npm lockfiles, standalone
|
|
137
|
+
Node/Pi preparation, icon/config tests and the **packaged** desktop/browser/PTY
|
|
138
|
+
smoke. Sentry reporting and signing discovery are disabled. It produces:
|
|
139
|
+
|
|
140
|
+
- `pi-<version>-desktop.<build>-mac-arm64.dmg`
|
|
141
|
+
- `SHA256SUMS` (DMG SHA-256)
|
|
142
|
+
- `desktop-release.json` (source SHA, backend/build/runtime versions, unsigned
|
|
143
|
+
status, platform/architecture, file size/checksum and smoke checks)
|
|
144
|
+
- `release-notes.md` (used as the Release body, not a separate download asset)
|
|
145
|
+
|
|
146
|
+
A separate Ubuntu job has scoped `contents: write` and no npm installation/app
|
|
147
|
+
execution. It revalidates the source-bound files, creates a **draft prerelease**,
|
|
148
|
+
uploads only the three intended assets, downloads them to verify their bytes,
|
|
149
|
+
and only then publishes the prerelease with `latest=false`. Signing is not
|
|
150
|
+
claimed. An interrupted upload leaves a draft; retrying the same source/tag may
|
|
151
|
+
repair a draft. A published release is never clobbered: a retry only succeeds
|
|
152
|
+
when downloaded assets are byte-identical. A conflicting source/tag or different
|
|
153
|
+
published bytes fails rather than replacing a public download.
|
|
154
|
+
|
|
155
|
+
The packing wrapper deliberately retains `--publish never`: explicit CI Release
|
|
156
|
+
upload owns publication. The manual cross-platform package workflow remains
|
|
157
|
+
artifact-only. npm/Web publishing is unchanged and independent.
|
|
158
|
+
|
|
109
159
|
## Application icon
|
|
110
160
|
|
|
111
161
|
The desktop uses an original deep-teal rounded tile with an ivory **π** monogram
|
|
@@ -203,6 +253,27 @@ may observe that author instead of its fixture author. Run tests with the normal
|
|
|
203
253
|
system Git in PATH in an isolated test environment; do not change global Git
|
|
204
254
|
configuration to make a fixture pass.
|
|
205
255
|
|
|
256
|
+
## Why the bundled Pi may not be the latest upstream version
|
|
257
|
+
|
|
258
|
+
The desktop bundles **Pi 0.87.1** because that is the host project's explicitly
|
|
259
|
+
pinned and tested SDK/runtime pair, not because npm automatically chose its
|
|
260
|
+
latest release. `package.json` and `desktop/runtime-manifest/package-lock.json`
|
|
261
|
+
pin both `@earendil-works/pi-coding-agent` and `@earendil-works/pi-ai` together.
|
|
262
|
+
The standalone Node runtime and native PTY are verified as part of that unit.
|
|
263
|
+
The app version, desktop build number and bundled Pi version are separate.
|
|
264
|
+
|
|
265
|
+
The public npm `latest` for both Pi packages was **1.3.0 when checked on
|
|
266
|
+
2026-10-20**. Thus 0.87.1 is **not** the latest Pi; a validated pin should not be
|
|
267
|
+
misrepresented as one or become an excuse never to maintain the dependency.
|
|
268
|
+
Moving from the tested 0.x SDK to 1.x needs API/type compatibility review, paired
|
|
269
|
+
lockfile updates, authentication/plugin/session regressions, native PTY checks,
|
|
270
|
+
and packaged desktop/Web smoke tests before publishing a new installer.
|
|
271
|
+
|
|
272
|
+
Do not replace the signed/packaged runtime in place or install `latest` on every
|
|
273
|
+
startup. Upgrade it deliberately through a new tested desktop build, recording
|
|
274
|
+
the exact Pi version in `desktop-release.json` and release notes. This preserves
|
|
275
|
+
reproducibility and prevents silently changing a user's running tasks.
|
|
276
|
+
|
|
206
277
|
## Updating runtime dependencies
|
|
207
278
|
|
|
208
279
|
When production dependencies or pinned Pi versions in the root manifest change:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-webapp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.21",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A browser interface for Pi with live chat, workspaces, models, and attachments",
|
|
6
6
|
"repository": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"pi-webapp": "./bin/pi-webapp.mjs"
|
|
16
16
|
},
|
|
17
17
|
"pi": {
|
|
18
|
-
"image": "https://cdn.jsdelivr.net/npm/pi-webapp@0.1.
|
|
18
|
+
"image": "https://cdn.jsdelivr.net/npm/pi-webapp@0.1.21/assets/cover-webapp.png",
|
|
19
19
|
"extensions": [
|
|
20
20
|
"./dist/extension.js"
|
|
21
21
|
]
|
package/web/dist/assets/app.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var O=Object.defineProperty;var x=(e,t,i)=>t in e?O(e,t,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[t]=i;var d=(e,t,i)=>x(e,typeof t!="symbol"?t+"":t,i);(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},t=new e.Error().stack;t&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[t]="
|
|
1
|
+
var O=Object.defineProperty;var x=(e,t,i)=>t in e?O(e,t,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[t]=i;var d=(e,t,i)=>x(e,typeof t!="symbol"?t+"":t,i);(function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},t=new e.Error().stack;t&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[t]="b4ccb35d-2c25-4c71-a83d-ff79175b2fb7",e._sentryDebugIdIdentifier="sentry-dbid-b4ccb35d-2c25-4c71-a83d-ff79175b2fb7")}catch{}})();(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))r(s);new MutationObserver(s=>{for(const n of s)if(n.type==="childList")for(const a of n.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&r(a)}).observe(document,{childList:!0,subtree:!0});function i(s){const n={};return s.integrity&&(n.integrity=s.integrity),s.referrerPolicy&&(n.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?n.credentials="include":s.crossOrigin==="anonymous"?n.credentials="omit":n.credentials="same-origin",n}function r(s){if(s.ep)return;s.ep=!0;const n=i(s);fetch(s.href,n)}})();const B="modulepreload",D=function(e){return"/"+e},I={},A=function(t,i,r){let s=Promise.resolve();if(i&&i.length>0){let a=function(o){return Promise.all(o.map(l=>Promise.resolve(l).then(g=>({status:"fulfilled",value:g}),g=>({status:"rejected",reason:g}))))};document.getElementsByTagName("link");const c=document.querySelector("meta[property=csp-nonce]"),m=(c==null?void 0:c.nonce)||(c==null?void 0:c.getAttribute("nonce"));s=a(i.map(o=>{if(o=D(o),o in I)return;I[o]=!0;const l=o.endsWith(".css"),g=l?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${o}"]${g}`))return;const u=document.createElement("link");if(u.rel=l?"stylesheet":B,l||(u.as="script"),u.crossOrigin="",u.href=o,m&&u.setAttribute("nonce",m),document.head.appendChild(u),l)return new Promise((T,N)=>{u.addEventListener("load",T),u.addEventListener("error",()=>N(new Error(`Unable to preload CSS for ${o}`)))})}))}function n(a){const c=new Event("vite:preloadError",{cancelable:!0});if(c.payload=a,window.dispatchEvent(c),!c.defaultPrevented)throw a}return s.then(a=>{for(const c of a||[])c.status==="rejected"&&n(c.reason);return t().catch(n)})},j=new Set(["bash","powershell","read","write","edit","grep","find","ls"]),R=new Set(["cancelled","blocked","validation","not_found","permission","timeout","process_exit","unknown"]),ee={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},U=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","toolName","toolId","toolCallId","failureKind","errorCode","exitCode","timeoutMs","diagnosticSource","originalStackAvailable","errorSummary","summaryOmitted","summaryOmittedReason","level"]),q=new Set(["/api/workspace/git/control","/api/workspace/git/write","/api/workspace/git/status","/api/workspace/git/diff","/api/workspace/git/history","/api/workspace/git/commit-detail","/api/workspace/git/commit-diff","/api/workspace/files/list","/api/workspace/files/preview","/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 te(e){return e==="/api/message"||e.startsWith("/api/provider/")||e.startsWith("/api/workspace/files/")||e.startsWith("/api/workspace/git/")||["/api/plugin-action","/api/plugin-interaction","/api/resume","/api/compact"].includes(e)}function p(e){return e.slice(0,8192).replace(/-----BEGIN [^-\n]+-----[\s\S]*?(?:-----END [^-\n]+-----|$)/g,"[redacted]").replace(/(["'`])[\s\S]*?\1/g,"[quoted]").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(/(?:^|\s)(?:\.\.?[\\/]|~[\\/])[^\s)]+/g," [path]").replace(/\b(?:[\w.-]+[\\/])+[\w.-]+/g,"[path]").replace(/\{[^\n]*\}/g,"[object]").replace(/\b[A-Za-z0-9_-]{24,}\b/g,"[redacted]").slice(0,1024)}function h(e){const t={};for(const i of U){const r=e[i];i==="toolName"?typeof r=="string"&&(j.has(r)||r==="custom")&&(t[i]=r):i==="failureKind"?R.has(r)&&(t[i]=r):i==="level"?(r==="warning"||r==="error")&&(t[i]=r):i==="diagnosticSource"?(r==="tool_execution_end"||r==="message_end")&&(t[i]=r):i==="errorCode"?typeof r=="string"&&/^(?:E[A-Z0-9]{1,20}|nonzero_exit|timeout|cancelled|blocked|invalid_arguments|tool_not_found|unknown)$/.test(r)&&(t[i]=r):i==="toolId"?typeof r=="string"&&/^[a-f0-9]{16}$/.test(r)&&(t[i]=r):i==="route"&&typeof r=="string"?t[i]=q.has(r.split("?")[0])?r.split("?")[0]:"[route]":i==="model"&&typeof r=="string"&&/^[\w.-]+\/[\w.-]+$/.test(r)?t[i]=r.split("/").map(p).join("/"):typeof r=="string"?t[i]=["requestId","operationId","errorId","session","buildId","toolId","toolCallId"].includes(i)&&/^[\w-]{1,80}$/.test(r)?r:p(r).slice(0,i==="errorSummary"?512:1024):(typeof r=="boolean"||typeof r=="number"&&Number.isFinite(r)||r===null)&&(t[i]=r)}return t}function v(e){var r;const t=e.replace(/\\/g,"/").split(/[?#]/)[0];return t.startsWith("node:")?t.slice(0,150):`app:///${(((r=t.match(/(?:^|\/)((?:web\/src|extension|shared|dist|assets)\/[^\s:)]+)$/))==null?void 0:r[1])??t.split("/").pop()??"unknown").replace(/[^\w./-]/g,"_").slice(-200)}`}function S(e,t=0){const i=e instanceof Error?e:new Error(typeof e=="string"?e:"Non-Error rejection"),r=new Error(p(i.message));if(r.name=p(i.name).slice(0,100),i.stack){const s=i.stack.split(`
|
|
2
2
|
`).slice(1,31).map(n=>{const a=n.match(/((?:file:\/\/|https?:\/\/|\/|[A-Za-z]:\\)[^\s()]+):(\d+):(\d+)(\)?)$/);return a?`${p(n.slice(0,a.index))}${a[1]}:${a[2]}:${a[3]}${a[4]}`:p(n)});r.stack=`${r.name}: ${r.message}
|
|
3
3
|
${s.join(`
|
|
4
4
|
`)}`}else r.stack=void 0;return t<3&&i.cause!==void 0&&(r.cause=S(i.cause,t+1)),r}function re(e,t){const i=new Error(t);return e instanceof Error&&(i.name=e.name,e.stack&&(i.stack=`${i.name}: ${t}
|
|
5
5
|
${e.stack.split(`
|
|
6
6
|
`).slice(1).join(`
|
|
7
7
|
`)}`)),i}function F(e){return{...e.filename?{filename:v(e.filename)}:{},...e.abs_path?{abs_path:v(e.abs_path)}:{},...e.function?{function:p(e.function)}:{},lineno:e.lineno,colno:e.colno,in_app:e.in_app}}function K(e){var r,s,n,a,c,m;const t=h(((r=e.contexts)==null?void 0:r.diagnostic)??{}),i=C(t);return{event_id:e.event_id,timestamp:e.timestamp,platform:e.platform,level:e.level,release:e.release,dist:e.dist,environment:p(e.environment??"production"),...e.message?{message:p(e.message)}:{},exception:e.exception?{values:(s=e.exception.values)==null?void 0:s.slice(0,4).map(o=>{var l;return{type:p(o.type??"Error"),value:p(o.value??""),...o.stacktrace?{stacktrace:{frames:(l=o.stacktrace.frames)==null?void 0:l.slice(-30).map(F)}}:{},...o.mechanism?{mechanism:{type:o.mechanism.type,handled:o.mechanism.handled}}:{}}})}:void 0,tags:{side:(n=e.tags)==null?void 0:n.side,buildId:(a=e.tags)==null?void 0:a.buildId,...t.toolName?{toolName:t.toolName}:{},...t.failureKind?{failureKind:t.failureKind}:{},...t.errorCode?{errorCode:t.errorCode}:{}},...i?{fingerprint:i}:{},contexts:{diagnostic:t},breadcrumbs:(c=e.breadcrumbs)==null?void 0:c.slice(-100).map(o=>({timestamp:o.timestamp,category:p(o.category??"app"),data:h(o.data??{})})),debug_meta:e.debug_meta?{images:(m=e.debug_meta.images)==null?void 0:m.slice(0,10).map(o=>({type:o.type,debug_id:o.debug_id,...o.code_file?{code_file:v(o.code_file)}:{}}))}:void 0}}function C(e){if(!(e.stage!=="tool"||e.originalStackAvailable!==!1||!e.toolName||!e.failureKind))return["pi-webapp-tool-result",String(e.toolName),String(e.toolId??"builtin"),String(e.failureKind),String(e.errorCode??"unknown")]}function ie(e,t){return t.attachments=[],K(e)}class Z{constructor(){d(this,"items",[]);d(this,"bytes",0);d(this,"encoder",new TextEncoder)}add(t,i={}){const r={timestamp:Date.now()/1e3,category:p(t),data:h(i)},s=this.encoder.encode(JSON.stringify(r)).byteLength+1;for(this.items.push({item:r,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:t})=>t)}}class V{constructor(){d(this,"windowAt",-1);d(this,"total",0);d(this,"seen",new Map)}take(t,i=Date.now()){(this.windowAt<0||i-this.windowAt>=6e4)&&(this.windowAt=i,this.total=0);const r=this.seen.get(t);if(r&&i-r.at<6e4){r.repeats++;return}if(!(this.total>=20))return this.total++,this.seen.size>=64&&!r&&this.seen.delete(this.seen.keys().next().value),this.seen.set(t,{at:i,repeats:0}),{repeats:(r==null?void 0:r.repeats)??0}}}const W=new Set(["目录路径必须是绝对路径","父目录路径必须是绝对路径","文件夹名称无效","工作区目录不可用,请恢复目录或从列表移除后重新添加","会话已切换","Pi 正在运行,请等待当前回复结束","请等待当前回复结束","请等待当前回复结束再切换工作区","请等待当前回复结束再切换会话","请先切换到其他工作区","新会话已取消","已有登录正在进行","模型不可用","模型提供方未配置认证","当前模型不支持此推理强度","其他提供方的登录正在进行,请先完成或取消当前登录","当前会话没有暂停的任务","请先完成当前交互或审批","请先选择模型","请先连接当前模型","插件未启用","会话运行实例已切换","提供方已存在","文件超过 20 MB","请求内容过大","会话不属于该工作区","推理强度无效"]);function L(e){return e instanceof Error&&(e.name==="AbortError"||W.has(e.message))}class se{constructor(t,i,r,s,n=new Z){d(this,"budget",new V);d(this,"breadcrumbs");d(this,"scopeClass");d(this,"seen",new WeakSet);d(this,"state",{});d(this,"client");d(this,"side");d(this,"buildId");this.client=t,this.side=i,this.buildId=r,this.scopeClass=s.Scope,this.breadcrumbs=n,t.addIntegration(s.linkedErrorsIntegration({limit:4}))}setState(t){this.state=h(t)}capture(t,i={},r){var s;try{if(L(t))return;if(typeof t=="object"&&t!==null){if(this.seen.has(t))return;this.seen.add(t)}const n=S(t),a=h({...this.state,...i}),c=C(a),m=c?JSON.stringify(c):`${n.name}:${n.message}:${((s=n.stack)==null?void 0:s.split(`
|
|
8
|
-
`)[1])??""}:${i.stage??""}`,o=this.budget.take(m);if(!o)return;const l=new this.scopeClass;l.setClient(this.client),l.setTags({side:this.side,buildId:this.buildId}),a.level==="warning"&&l.setLevel("warning"),c&&l.setFingerprint(c),l.setContext("diagnostic",{...a,repeats:o.repeats});for(const g of this.breadcrumbs.snapshot())l.addBreadcrumb(g,100);return l.captureException(n,r?{event_id:r}:void 0)}catch{return}}ignore(t){this.seen.add(t)}}function ne(e,t){return e({...t,bufferSize:20},async({body:i})=>{const r=await fetch(t.url,{method:"POST",body:i,signal:AbortSignal.timeout(3e3),credentials:"omit",referrerPolicy:"no-referrer",redirect:"error",headers:{"Content-Type":"application/x-sentry-envelope"}});return{statusCode:r.status,headers:{"x-sentry-rate-limits":r.headers.get("x-sentry-rate-limits"),"retry-after":r.headers.get("retry-after")}}})}let w;function M(){if(w!==void 0)return w;const e=location.hash.slice(1);try{w=e||sessionStorage.getItem("pi-web-token"),e&&sessionStorage.setItem("pi-web-token",e)}catch{w=e||null}return e&&history.replaceState(null,"",location.pathname),w}const H="pi-webapp@0.1.
|
|
8
|
+
`)[1])??""}:${i.stage??""}`,o=this.budget.take(m);if(!o)return;const l=new this.scopeClass;l.setClient(this.client),l.setTags({side:this.side,buildId:this.buildId}),a.level==="warning"&&l.setLevel("warning"),c&&l.setFingerprint(c),l.setContext("diagnostic",{...a,repeats:o.repeats});for(const g of this.breadcrumbs.snapshot())l.addBreadcrumb(g,100);return l.captureException(n,r?{event_id:r}:void 0)}catch{return}}ignore(t){this.seen.add(t)}}function ne(e,t){return e({...t,bufferSize:20},async({body:i})=>{const r=await fetch(t.url,{method:"POST",body:i,signal:AbortSignal.timeout(3e3),credentials:"omit",referrerPolicy:"no-referrer",redirect:"error",headers:{"Content-Type":"application/x-sentry-envelope"}});return{statusCode:r.status,headers:{"x-sentry-rate-limits":r.headers.get("x-sentry-rate-limits"),"retry-after":r.headers.get("retry-after")}}})}let w;function M(){if(w!==void 0)return w;const e=location.hash.slice(1);try{w=e||sessionStorage.getItem("pi-web-token"),e&&sessionStorage.setItem("pi-web-token",e)}catch{w=e||null}return e&&history.replaceState(null,"",location.pathname),w}const H="pi-webapp@0.1.21+c6b0921cd1db2811f3fc",J="c6b0921cd1db2811f3fc";function Q(){if(typeof crypto.randomUUID=="function")return crypto.randomUUID();const e=crypto.getRandomValues(new Uint8Array(16));e[6]=e[6]&15|64,e[8]=e[8]&63|128;const t=Array.from(e,i=>i.toString(16).padStart(2,"0")).join("");return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20)}`}let f,z=!0,$=!1,P=!1,_=[];const E=new WeakSet,b=new Map;let y={};function k(e,t={}){try{if(L(e))return;if(typeof e=="object"&&e!==null){if(E.has(e))return;E.add(e)}if(f)return f.capture(e,t);z&&_.length<20&&_.push({error:S(e),context:h(t)})}catch{}}function oe(e){E.add(e)}function ae(e,t={}){f==null||f.breadcrumbs.add(e,t)}function ce(e){e.sessionId&&(b.has(e.sessionId)||(b.size>=32&&b.delete(b.keys().next().value),b.set(e.sessionId,Q())),e={...e,session:b.get(e.sessionId)}),y=h({...y,...e}),f==null||f.setState(y)}function G(){$||($=!0,P=new URL(location.href).searchParams.get("sentry_release_probe")==="1",window.addEventListener("error",e=>{e instanceof ErrorEvent?k(e.error??new Error(e.message),{stage:"global"}):(e.target instanceof HTMLScriptElement||e.target instanceof HTMLLinkElement)&&k(new Error("Application resource failed to load"),{stage:"resource"})},!0),window.addEventListener("unhandledrejection",e=>k(e.reason,{stage:"unhandled_rejection"})),X())}async function X(){var e;try{const t=M();if(!t)return;const i=await fetch("/api/telemetry/config",{headers:{Authorization:`Bearer ${t}`},signal:AbortSignal.timeout(1e3)});if(!i.ok)return;const r=await i.json();if(!r.enabled||!r.dsn)return;const{createBrowserReporter:s}=await A(async()=>{const{createBrowserReporter:a}=await import("./telemetry-client-CBQBug9X.js");return{createBrowserReporter:a}},[]);f=s({...r,buildId:J,release:H});const n=((e=navigator.userAgent.match(/(?:Firefox|Edg|Chrome|Version)\/[\d.]+/))==null?void 0:e[0])??"unknown";f.setState({...y,browser:n,platform:navigator.platform}),y={...y,browser:n,platform:navigator.platform};for(const a of _)f.capture(a.error,a.context);r.environment==="sentry-verification"&&P&&f.capture(new Error("Sentry browser release verification"),{stage:"release_verification",code:"sentry_release_probe"})}catch{}finally{_=[],z=!1}}G();A(()=>import("./app-4px1DWHV.js").then(e=>e.d),[]).catch(e=>k(e,{stage:"startup"}));export{se as E,A as _,Q as a,te as b,ae as c,M as d,ie as e,ne as f,oe as i,re as o,ee as p,k as r,ce as s};
|