pi-webapp 0.1.12 → 0.1.13
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/bin/pi-webapp.mjs +29 -8
- package/dist/extension.js +2 -2
- package/docs/sentry.md +4 -0
- package/package.json +2 -2
- package/web/dist/assets/app.js +3 -3
package/bin/pi-webapp.mjs
CHANGED
|
@@ -131,26 +131,43 @@ async function serve(pi, args) {
|
|
|
131
131
|
let runningUrl = null;
|
|
132
132
|
let buffer = "";
|
|
133
133
|
let killTimer;
|
|
134
|
+
let stopReason;
|
|
135
|
+
let forceStopRequested = false;
|
|
136
|
+
const instanceId = randomUUID();
|
|
137
|
+
const startedAt = performance.now();
|
|
138
|
+
const lifecycle = (event, fields = {}) => {
|
|
139
|
+
try {
|
|
140
|
+
console.error(JSON.stringify({ timestamp: new Date().toISOString(), event,
|
|
141
|
+
level: event === "pi_process_exit" && (!stopping || failed) ? "error" : "info",
|
|
142
|
+
instanceId, pid: process.pid, piPid: child.pid, uptimeMs: Math.round(performance.now() - startedAt), ...fields }));
|
|
143
|
+
} catch { /* Diagnostics must not interrupt process supervision. */ }
|
|
144
|
+
};
|
|
134
145
|
const devWatchers = [];
|
|
135
146
|
let devReloadTimer;
|
|
136
147
|
let devReloadCount = 0;
|
|
137
148
|
let devReloadCommand;
|
|
138
|
-
const shutdown = () => {
|
|
149
|
+
const shutdown = (reason) => {
|
|
139
150
|
if (stopping) return;
|
|
140
151
|
stopping = true;
|
|
152
|
+
stopReason = reason;
|
|
153
|
+
lifecycle("launcher_stop_requested", { reason });
|
|
141
154
|
child.stdin?.end();
|
|
142
|
-
killTimer = setTimeout(() =>
|
|
155
|
+
killTimer = setTimeout(() => {
|
|
156
|
+
forceStopRequested = true;
|
|
157
|
+
lifecycle("pi_force_stop", { reason, signal: "SIGTERM" });
|
|
158
|
+
child.kill("SIGTERM");
|
|
159
|
+
}, 5000);
|
|
143
160
|
killTimer.unref();
|
|
144
161
|
};
|
|
145
162
|
const fail = (message) => {
|
|
146
163
|
if (failed || ready) return;
|
|
147
164
|
failed = true;
|
|
148
165
|
notifyParent({ type: "error", message });
|
|
149
|
-
shutdown();
|
|
166
|
+
shutdown("startup_failure");
|
|
150
167
|
};
|
|
151
168
|
const startupTimer = setTimeout(() => fail(`Pi 启动超时。日志:${logPath}`), 60000);
|
|
152
169
|
const stopTimer = setInterval(async () => {
|
|
153
|
-
try { if ((await readFile(stopPath, "utf8")).trim() === nonce) shutdown(); }
|
|
170
|
+
try { if ((await readFile(stopPath, "utf8")).trim() === nonce) shutdown("stop_request"); }
|
|
154
171
|
catch { /* No stop request. */ }
|
|
155
172
|
if (stopping) return;
|
|
156
173
|
try {
|
|
@@ -158,12 +175,12 @@ async function serve(pi, args) {
|
|
|
158
175
|
const prepared = JSON.parse(await readFile(updatePath, "utf8"));
|
|
159
176
|
if (request.nonce === nonce && request.launcher === prepared.launcher && existsSync(request.launcher)) {
|
|
160
177
|
restartRequest = request;
|
|
161
|
-
shutdown();
|
|
178
|
+
shutdown("restart_request");
|
|
162
179
|
}
|
|
163
180
|
} catch { /* No valid restart request. */ }
|
|
164
181
|
}, 400);
|
|
165
|
-
process.on("SIGTERM", shutdown);
|
|
166
|
-
process.on("SIGINT", shutdown);
|
|
182
|
+
process.on("SIGTERM", () => shutdown("signal_sigterm"));
|
|
183
|
+
process.on("SIGINT", () => shutdown("signal_sigint"));
|
|
167
184
|
child.stdout?.on("data", (chunk) => {
|
|
168
185
|
if (failed) return;
|
|
169
186
|
buffer += chunk.toString("utf8");
|
|
@@ -210,6 +227,7 @@ async function serve(pi, args) {
|
|
|
210
227
|
if (closed || failed) return;
|
|
211
228
|
ready = true;
|
|
212
229
|
clearTimeout(startupTimer);
|
|
230
|
+
lifecycle("launcher_ready", { port: Number(url.port) });
|
|
213
231
|
notifyParent({ type: "ready", pid: process.pid, url: url.href });
|
|
214
232
|
for (const root of pluginRoots) {
|
|
215
233
|
try {
|
|
@@ -233,8 +251,11 @@ async function serve(pi, args) {
|
|
|
233
251
|
child.stdin?.write(JSON.stringify({ id: "list-commands", type: "get_commands" }) + "\n");
|
|
234
252
|
await new Promise((resolveExit) => {
|
|
235
253
|
child.once("error", (error) => { fail(`无法启动 Pi:${error.message}`); resolveExit(); });
|
|
236
|
-
child.once("close", (code) => {
|
|
254
|
+
child.once("close", (code, signal) => {
|
|
237
255
|
closed = true;
|
|
256
|
+
lifecycle("pi_process_exit", { ready, exitCode: code, signal,
|
|
257
|
+
reason: stopReason ?? (ready ? "unexpected_exit" : "startup_failure"), forceStopRequested,
|
|
258
|
+
port: runningUrl ? Number(new URL(runningUrl).port) : null });
|
|
238
259
|
if (!ready) fail(`Pi 提前退出(代码 ${code ?? "未知"})。日志:${logPath}`);
|
|
239
260
|
resolveExit();
|
|
240
261
|
});
|
package/dist/extension.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
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]="
|
|
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]="04e37c1f-8757-4953-a834-c0cc5f374c80",r._sentryDebugIdIdentifier="sentry-dbid-04e37c1f-8757-4953-a834-c0cc5f374c80")}catch{}})();import{delimiter as Ri,dirname as Ni,join as xe,resolve as Je}from"node:path";import{realpathSync as Wi,watch as Di}from"node:fs";import{fileURLToPath as ji}from"node:url";import{DefaultPackageManager as er,getAgentDir as q,ModelRuntime as Oi,SessionManager as tr,SettingsManager as $i,VERSION as Ie}from"@earendil-works/pi-coding-agent";import{getSupportedThinkingLevels as Bi}from"@earendil-works/pi-ai";import{randomBytes as pn,randomUUID as Re,timingSafeEqual as un}from"node:crypto";import{readFile as fn,readdir as gn}from"node:fs/promises";import{createServer as mn}from"node:http";import{join as xt}from"node:path";import{mkdir as or,opendir as ar,stat as lr}from"node:fs/promises";import{homedir as cr}from"node:os";import{basename as dr,dirname as Ye,join as Xe,posix as pr,resolve as Ze,win32 as ur}from"node:path";function Qe(r){return process.platform==="win32"?ur.isAbsolute(r)&&/^(?:[A-Za-z]:[\\/]|[\\/]{2}[^\\/]+[\\/]+[^\\/]+)/.test(r):pr.isAbsolute(r)}function fr(r,e,t){if(r.length===t&&e.name.localeCompare(r[r.length-1].name)>=0)return!0;let n=0,s=r.length;for(;n<s;){let o=n+s>>>1;e.name.localeCompare(r[o].name)<0?s=o:n=o+1}return r.splice(n,0,e),r.length<=t?!1:(r.pop(),!0)}async function et(r){if(r!==void 0&&!Qe(r))throw new Error("\u76EE\u5F55\u8DEF\u5F84\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84");let e=cr(),t=Ze(r??e),n=[];for(let d=t;;d=Ye(d)){let y=Ye(d);if(n.unshift({name:y===d?d:dr(d),path:d,hidden:!1}),y===d)break}let s=[],o=!1,a=await ar(t);for await(let d of a)!d.isDirectory()&&!d.isSymbolicLink()||fr(s,{name:d.name,isDirectory:d.isDirectory(),isSymbolicLink:d.isSymbolicLink()},1001)&&(o=!0);let u=[];for(let d of s){let y=Xe(t,d.name);if(!d.isDirectory&&d.isSymbolicLink)try{if(!(await lr(y)).isDirectory())continue}catch{continue}if(u.length===1e3){o=!0;break}u.push({name:d.name,path:y,hidden:d.name.startsWith(".")})}return{path:t,home:e,crumbs:n,entries:u,truncated:o}}async function tt(r,e){if(!Qe(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=Xe(Ze(r),e);return await or(t),t}import{execFile as gr}from"node:child_process";import{accessSync as mr,constants as hr}from"node:fs";import{delimiter as wr,join as yr}from"node:path";var br=(r,e,t)=>new Promise((n,s)=>{gr(r,[...e],{encoding:"utf8",signal:t,windowsHide:!0},(o,a,u)=>{o?s(Object.assign(new Error(o.message,{cause:o}),{code:o.code,stdout:a,stderr:u})):n({stdout:a,stderr:u})})});function vr(r){for(let e of(r??"").split(wr))if(e)for(let t of["zenity","kdialog"])try{return mr(yr(e,t),hr.X_OK),!0}catch{}return!1}function rt(r=process.platform,e=process.env){return e.SSH_CONNECTION||e.SSH_TTY?"browse":r==="darwin"||r==="linux"&&(e.DISPLAY||e.WAYLAND_DISPLAY)&&vr(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 kr(r){return typeof r=="object"&&r!==null&&"stderr"in r&&typeof r.stderr=="string"?r.stderr:""}function _e(r){return r.replace(/[\r\n]+$/,"")||null}async function nt(r,e=process.platform,t=br){if(e==="darwin")try{let n=await t("osascript",["-e",'set selectedFolder to choose folder with prompt "Select Workspace Directory"',"-e","POSIX path of selectedFolder"],r);return _e(n.stdout)}catch(n){if(!r.aborted&&ce(n)===1&&/(?:User canceled|-128)/i.test(kr(n)))return null;throw n}if(e==="linux"){try{return _e((await t("zenity",["--file-selection","--directory","--title=Select Workspace Directory"],r)).stdout)}catch(n){if(r.aborted)throw n;if(ce(n)===1)return null;if(ce(n)!=="ENOENT")throw n}try{return _e((await t("kdialog",["--getexistingdirectory",".","--title","Select Workspace Directory"],r)).stdout)}catch(n){if(r.aborted)throw n;if(ce(n)===1)return null;throw n}}throw new Error(`\u5F53\u524D\u7CFB\u7EDF\u4E0D\u652F\u6301\u672C\u5730\u76EE\u5F55\u9009\u62E9\u5668\uFF1A${e}`)}import{createHash as Er,randomUUID as Pr}from"node:crypto";import{mkdir as xr,readFile as Ir,writeFile as Sr}from"node:fs/promises";import{join as it}from"node:path";import{getAgentDir as Cr}from"@earendil-works/pi-coding-agent";var de=20*1024*1024,st=20,_r=/^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])$/iu;function Tr(r){let e=r.indexOf("."),t=(e<0?r:r.slice(0,e)).replace(/[. ]+$/u,"");return _r.test(t)}function Ar(r,e){let t=0,n="";for(let s of Buffer.from(r).toString("utf8")){let o=Buffer.byteLength(s);if(t+o>e)break;n+=s,t+=o}return n}function Mr(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 Tr(t)&&(t=`_${t}`),t=Ar(t,255).replace(/[. ]+$/u,""),t===""||t==="."||t===".."?"file":t}function Rr(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 ot(r,e,t,n){if(n.byteLength===0||n.byteLength>de)throw new Error("\u6587\u4EF6\u4E3A\u7A7A\u6216\u8D85\u8FC7 20 MB");let s=Mr(e),o=Er("sha256").update(n).digest("hex"),a=it(Cr(),"pi-web","attachments",o);await xr(a,{recursive:!0});let u=it(a,s);try{await Sr(u,n,{flag:"wx",mode:384})}catch(d){if(!(d instanceof Error&&"code"in d&&d.code==="EEXIST"))throw d}return{id:Pr(),name:s,bytes:n.byteLength,path:u,mediaType:Rr(n)??t.replace(/^image\//,"application/"),sessionId:r}}async function at(r){return{type:"image",data:(await Ir(r.path)).toString("base64"),mimeType:r.mediaType}}import{randomBytes as Nr}from"node:crypto";function lt(r,e,t){return r!=="openai-codex"||e!=="oauth"?t:{...t,prompt:n=>n.type==="select"&&n.options.some(s=>s.id==="browser")&&n.options.some(s=>s.id==="device_code")?Promise.resolve("browser"):t.prompt(n)}}var pe=class{flows=new Map;reportError;constructor(e=()=>{}){this.reportError=e}start(e,t,n,s,o){let a=this.getActive();if(a){if(a.providerId===e&&a.method===t&&s===void 0)return a;throw new Error("\u5176\u4ED6\u63D0\u4F9B\u65B9\u7684\u767B\u5F55\u6B63\u5728\u8FDB\u884C\uFF0C\u8BF7\u5148\u5B8C\u6210\u6216\u53D6\u6D88\u5F53\u524D\u767B\u5F55")}this.flows.clear();let u=Nr(18).toString("base64url"),d={view:{id:u,providerId:e,method:t,status:"running"},controller:new AbortController};return this.flows.set(u,d),n(e,t,{signal:d.controller.signal,notify:y=>{d.view={...d.view,event:y,...y.type==="auth_url"||y.type==="device_code"?{authorization:y}:{}}},prompt:y=>{if(y.type==="secret"&&s!==void 0){let h=s;return s=void 0,Promise.resolve(h)}return new Promise((h,c)=>{let{signal:p,...g}=y;d.answer=h,d.reject=c,d.view={...d.view,status:"waiting",prompt:g},p?.aborted?c(new Error("\u767B\u5F55\u8F93\u5165\u5DF2\u53D6\u6D88")):p?.addEventListener("abort",()=>c(new Error("\u767B\u5F55\u8F93\u5165\u5DF2\u53D6\u6D88")),{once:!0})})}}).then(()=>{d.view.status!=="cancelled"&&(d.view={id:u,providerId:e,method:t,status:"done"})}).catch(y=>{if(d.view.status!=="cancelled"){let h=new Error("Provider login failed");y instanceof Error&&y.stack&&(h.stack=`${h.message}
|
|
2
2
|
${y.stack.split(`
|
|
3
3
|
`).slice(1).join(`
|
|
4
4
|
`)}`);let c=this.reportError(h,{...o,stage:"provider_login"});d.view={id:u,providerId:e,method:t,status:"error",error:"\u767B\u5F55\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u63D0\u4F9B\u65B9\u63D0\u793A\u5E76\u91CD\u8BD5\u3002",errorId:c}}}),{...d.view}}get(e){let t=this.flows.get(e)?.view;return t?{...t}:void 0}getActive(){let e=[...this.flows.values()].find(({view:t})=>t.status==="running"||t.status==="waiting")?.view;return e?{...e}:void 0}respond(e,t){let n=this.flows.get(e);if(!n?.answer||n.view.status!=="waiting"||n.view.prompt?.type==="select"&&!n.view.prompt.options.some(o=>o.id===t))return!1;let s=n.answer;return n.answer=void 0,n.reject=void 0,n.view={...n.view,status:"running",prompt:void 0},s(t),!0}cancel(e){let t=this.flows.get(e);return!t||t.view.status==="done"||t.view.status==="error"?!1:(t.view={...t.view,status:"cancelled",prompt:void 0},t.controller.abort(),t.reject?.(new Error("\u767B\u5F55\u5DF2\u53D6\u6D88")),t.answer=void 0,t.reject=void 0,!0)}close(){for(let e of this.flows.keys())this.cancel(e);this.flows.clear()}};import{randomBytes as Wr}from"node:crypto";import{readFile as Dr,rename as jr,rm as Or,stat as $r,writeFile as Br,mkdir as Fr}from"node:fs/promises";import{dirname as Lr}from"node:path";var Vr=["openai-completions","openai-responses","anthropic-messages"];function Te(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||!Vr.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 ct(r,e){if(!Te(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 Dr(r,"utf8")}catch(u){if(u.code!=="ENOENT")throw u}let n;if(t===void 0)n={providers:{}};else{try{n=JSON.parse(t)}catch{throw new Error("models.json \u542B\u6CE8\u91CA\u6216\u683C\u5F0F\u9519\u8BEF\uFF0C\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u624B\u52A8\u6DFB\u52A0\u63D0\u4F9B\u65B9")}if(!n||typeof n!="object"||!n.providers||typeof n.providers!="object"||Array.isArray(n.providers))throw new Error("models.json \u7ED3\u6784\u65E0\u6548")}if(Object.hasOwn(n.providers,e.id))throw new Error("\u63D0\u4F9B\u65B9\u5DF2\u5B58\u5728");let s={...n,providers:{...n.providers,[e.id]:{name:e.name.trim(),baseUrl:e.baseUrl,api:e.api,models:[{id:e.modelId.trim()}]}}};await Fr(Lr(r),{recursive:!0});let o=t===void 0?384:(await $r(r)).mode&511,a=`${r}.pi-web-${Wr(6).toString("hex")}.tmp`;try{await Br(a,`${JSON.stringify(s,null,2)}
|
|
5
5
|
`,{mode:o,flag:"wx"}),await jr(a,r)}finally{await Or(a,{force:!0})}}import{randomBytes as Ur}from"node:crypto";import{mkdir as zr,readFile as Hr,rename as Kr,rm as Gr,stat as Jr,writeFile as qr}from"node:fs/promises";import{dirname as Yr}from"node:path";function dt(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 pt(r){if(!r||typeof r!="object")return!1;let e=r;return e.action==="save"?(e.originalId===void 0||typeof e.originalId=="string")&&ut(e.model):e.action==="base_url"?e.baseUrl===null||typeof e.baseUrl=="string"&&dt(e.baseUrl):e.action==="remove"&&typeof e.id=="string"&&e.id.length>0&&e.id.length<=200}function ut(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 ft(r){let e;try{e=await Hr(r,"utf8")}catch(n){if(n.code!=="ENOENT")throw n}if(e===void 0)return{config:{providers:{}}};let t;try{t=JSON.parse(e)}catch{throw new Error("models.json \u542B\u6CE8\u91CA\u6216\u683C\u5F0F\u9519\u8BEF\uFF0C\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u624B\u52A8\u4FEE\u6539")}if(!t||typeof t!="object"||!t.providers||typeof t.providers!="object"||Array.isArray(t.providers))throw new Error("models.json \u7ED3\u6784\u65E0\u6548");return{config:t,existing:e}}async function Xr(r,e,t){await zr(Yr(r),{recursive:!0});let n=t===void 0?384:(await Jr(r)).mode&511,s=`${r}.pi-web-${Ur(6).toString("hex")}.tmp`;try{await qr(s,`${JSON.stringify(e,null,2)}
|
|
6
|
-
`,{mode:n,flag:"wx"}),await Kr(s,r)}finally{await Gr(s,{force:!0})}}async function gt(r,e,t){if(!t.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:n}=await ft(r),s=n.providers[e],o=new Set(s?.models?.map(a=>a.id)??[]);return{providerId:e,baseUrl:s?.baseUrl,models:t.getModels(e).map(a=>({id:a.id,name:a.name,contextWindow:a.contextWindow,maxTokens:a.maxTokens,input:[...a.input],source:o.has(a.id)?"custom":"builtin",overridden:!!s?.modelOverrides?.[a.id]}))}}async function mt(r,e,t,n){if(!n.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:s,existing:o}=await ft(r),a={...s.providers[e]??{}},u=[...a.models??[]],d={...a.modelOverrides??{}};if(t.action==="base_url"){if(t.baseUrl!==null&&!dt(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(!ut(t.model))throw new Error("\u6A21\u578B\u53C2\u6570\u65E0\u6548");let y={id:t.model.id.trim(),...t.model.name===void 0?{}:{name:t.model.name},...t.model.contextWindow===void 0?{}:{contextWindow:t.model.contextWindow},...t.model.maxTokens===void 0?{}:{maxTokens:t.model.maxTokens},...t.model.input===void 0?{}:{input:t.model.input}},h=t.originalId,c=h===void 0?-1:u.findIndex(p=>p.id===h);if(h===void 0&&(u.some(p=>p.id===y.id)||n.getModel(e,y.id)))throw new Error("\u6A21\u578B ID \u5DF2\u5B58\u5728");if(c>=0){if(y.id!==h&&(u.some(g=>g.id===y.id)||n.getModel(e,y.id)))throw new Error("\u6A21\u578B ID \u5DF2\u5B58\u5728");let p={...u[c],...y};for(let g of["name","contextWindow","maxTokens","input"])y[g]===void 0&&delete p[g];u[c]=p}else if(h!==void 0&&n.getModel(e,h)){if(y.id!==h)throw new Error("\u5185\u7F6E\u6A21\u578B ID \u4E0D\u53EF\u4FEE\u6539");let{id:p,...g}=y;d[h]={...d[h],...g};for(let m of["name","contextWindow","maxTokens","input"])y[m]===void 0&&delete d[h][m]}else{if(h!==void 0)throw new Error("\u6A21\u578B\u4E0D\u5B58\u5728");u.push(y)}}else{let y=u.findIndex(h=>h.id===t.id);if(y>=0)u.splice(y,1);else if(Object.hasOwn(d,t.id))delete d[t.id];else throw new Error("\u53EA\u80FD\u79FB\u9664\u81EA\u5B9A\u4E49\u6A21\u578B\u6216\u6062\u590D\u5DF2\u4FEE\u6539\u7684\u5185\u7F6E\u6A21\u578B")}u.length?a.models=u:delete a.models,Object.keys(d).length?a.modelOverrides=d:delete a.modelOverrides,Object.keys(a).length?s.providers[e]=a:delete s.providers[e],await Xr(r,s,o)}function ht(r){return/^(?:npm:|git:|https?:\/\/|ssh:\/\/|git@)/i.test(r.trim())}import{randomBytes as Et,createHash as sn}from"node:crypto";import{fileURLToPath as on}from"node:url";var ue="pi-webapp@0.1.
|
|
6
|
+
`,{mode:n,flag:"wx"}),await Kr(s,r)}finally{await Gr(s,{force:!0})}}async function gt(r,e,t){if(!t.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:n}=await ft(r),s=n.providers[e],o=new Set(s?.models?.map(a=>a.id)??[]);return{providerId:e,baseUrl:s?.baseUrl,models:t.getModels(e).map(a=>({id:a.id,name:a.name,contextWindow:a.contextWindow,maxTokens:a.maxTokens,input:[...a.input],source:o.has(a.id)?"custom":"builtin",overridden:!!s?.modelOverrides?.[a.id]}))}}async function mt(r,e,t,n){if(!n.getProvider(e))throw new Error("\u63D0\u4F9B\u65B9\u4E0D\u5B58\u5728");let{config:s,existing:o}=await ft(r),a={...s.providers[e]??{}},u=[...a.models??[]],d={...a.modelOverrides??{}};if(t.action==="base_url"){if(t.baseUrl!==null&&!dt(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(!ut(t.model))throw new Error("\u6A21\u578B\u53C2\u6570\u65E0\u6548");let y={id:t.model.id.trim(),...t.model.name===void 0?{}:{name:t.model.name},...t.model.contextWindow===void 0?{}:{contextWindow:t.model.contextWindow},...t.model.maxTokens===void 0?{}:{maxTokens:t.model.maxTokens},...t.model.input===void 0?{}:{input:t.model.input}},h=t.originalId,c=h===void 0?-1:u.findIndex(p=>p.id===h);if(h===void 0&&(u.some(p=>p.id===y.id)||n.getModel(e,y.id)))throw new Error("\u6A21\u578B ID \u5DF2\u5B58\u5728");if(c>=0){if(y.id!==h&&(u.some(g=>g.id===y.id)||n.getModel(e,y.id)))throw new Error("\u6A21\u578B ID \u5DF2\u5B58\u5728");let p={...u[c],...y};for(let g of["name","contextWindow","maxTokens","input"])y[g]===void 0&&delete p[g];u[c]=p}else if(h!==void 0&&n.getModel(e,h)){if(y.id!==h)throw new Error("\u5185\u7F6E\u6A21\u578B ID \u4E0D\u53EF\u4FEE\u6539");let{id:p,...g}=y;d[h]={...d[h],...g};for(let m of["name","contextWindow","maxTokens","input"])y[m]===void 0&&delete d[h][m]}else{if(h!==void 0)throw new Error("\u6A21\u578B\u4E0D\u5B58\u5728");u.push(y)}}else{let y=u.findIndex(h=>h.id===t.id);if(y>=0)u.splice(y,1);else if(Object.hasOwn(d,t.id))delete d[t.id];else throw new Error("\u53EA\u80FD\u79FB\u9664\u81EA\u5B9A\u4E49\u6A21\u578B\u6216\u6062\u590D\u5DF2\u4FEE\u6539\u7684\u5185\u7F6E\u6A21\u578B")}u.length?a.models=u:delete a.models,Object.keys(d).length?a.modelOverrides=d:delete a.modelOverrides,Object.keys(a).length?s.providers[e]=a:delete s.providers[e],await Xr(r,s,o)}function ht(r){return/^(?:npm:|git:|https?:\/\/|ssh:\/\/|git@)/i.test(r.trim())}import{randomBytes as Et,createHash as sn}from"node:crypto";import{fileURLToPath as on}from"node:url";var ue="pi-webapp@0.1.13+47b0cab9b46d97bbc98c",B="47b0cab9b46d97bbc98c";var ge=new Set(["bash","powershell","read","write","edit","grep","find","ls"]),Zr=new Set(["cancelled","blocked","validation","not_found","permission","timeout","process_exit","unknown"]),wt={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},Qr=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"]),en=new Set(["/api/plugins","/api/plugin-action","/api/plugin-interaction","/api/resume","/api/update","/api/update/version","/api/provider/models","/api/provider/logout","/api/provider/login/active","/api/telemetry/config","/api/image","/api/attachment","/api/attachment/remove","/api/session","/api/providers","/api/models","/api/config","/api/workspaces","/api/commands","/api/events","/api/message","/api/abort","/api/compact","/api/new-session","/api/model","/api/thinking-level","/api/provider/login","/api/provider/login/respond","/api/provider/login/cancel","/api/provider/custom","/api/workspace/add","/api/workspace/select","/api/workspace/new-session","/api/workspace/remove","/api/session/select","/api/directory/capability","/api/directory/list","/api/directory/create","/api/directory/pick"]);function yt(r){return r==="/api/message"||r.startsWith("/api/provider/")||["/api/plugin-action","/api/plugin-interaction","/api/resume","/api/compact"].includes(r)}function W(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 $(r){let e={};for(let t of Qr){let n=r[t];t==="toolName"?typeof n=="string"&&(ge.has(n)||n==="custom")&&(e[t]=n):t==="failureKind"?Zr.has(n)&&(e[t]=n):t==="level"?(n==="warning"||n==="error")&&(e[t]=n):t==="diagnosticSource"?(n==="tool_execution_end"||n==="message_end")&&(e[t]=n):t==="errorCode"?typeof n=="string"&&/^(?:E[A-Z0-9]{1,20}|nonzero_exit|timeout|cancelled|blocked|invalid_arguments|tool_not_found|unknown)$/.test(n)&&(e[t]=n):t==="toolId"?typeof n=="string"&&/^[a-f0-9]{16}$/.test(n)&&(e[t]=n):t==="route"&&typeof n=="string"?e[t]=en.has(n.split("?")[0])?n.split("?")[0]:"[route]":t==="model"&&typeof n=="string"&&/^[\w.-]+\/[\w.-]+$/.test(n)?e[t]=n.split("/").map(W).join("/"):typeof n=="string"?e[t]=["requestId","operationId","errorId","session","buildId","toolId","toolCallId"].includes(t)&&/^[\w-]{1,80}$/.test(n)?n:W(n).slice(0,t==="errorSummary"?512:1024):(typeof n=="boolean"||typeof n=="number"&&Number.isFinite(n)||n===null)&&(e[t]=n)}return e}function Ae(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 Y(r,e=0){let t=r instanceof Error?r:new Error(typeof r=="string"?r:"Non-Error rejection"),n=new Error(W(t.message));if(n.name=W(t.name).slice(0,100),t.stack){let s=t.stack.split(`
|
|
7
7
|
`).slice(1,31).map(o=>{let a=o.match(/((?:file:\/\/|https?:\/\/|\/|[A-Za-z]:\\)[^\s()]+):(\d+):(\d+)(\)?)$/);return a?`${W(o.slice(0,a.index))}${a[1]}:${a[2]}:${a[3]}${a[4]}`:W(o)});n.stack=`${n.name}: ${n.message}
|
|
8
8
|
${s.join(`
|
|
9
9
|
`)}`}else n.stack=void 0;return e<3&&t.cause!==void 0&&(n.cause=Y(t.cause,e+1)),n}function te(r,e){let t=new Error(e);return r instanceof Error&&(t.name=r.name,r.stack&&(t.stack=`${t.name}: ${e}
|
package/docs/sentry.md
CHANGED
|
@@ -55,6 +55,10 @@ Filter Sentry by `side:node`, `toolName`, `failureKind` and `errorCode`, then in
|
|
|
55
55
|
|
|
56
56
|
## Performance and reliability
|
|
57
57
|
|
|
58
|
+
The background launcher's local `launcher.log` records JSON lifecycle events: `launcher_ready`, `launcher_stop_requested`, `pi_force_stop`, and `pi_process_exit`. The default location is `~/.pi/agent/pi-web/launcher.log` (`%USERPROFILE%\.pi\agent\pi-web\launcher.log` on Windows); `PI_CODING_AGENT_DIR` overrides the agent directory. These records are local diagnostics, not Sentry events.
|
|
59
|
+
|
|
60
|
+
Each run has a separate random `instanceId`, UTC `timestamp`, process IDs, and monotonic `uptimeMs`. Readiness and exit include the listening port without the URL or access token. Exit records include `ready`, `exitCode`, `signal`, `forceStopRequested`, and a reason: `unexpected_exit`, `stop_request`, `restart_request`, `signal_sigterm`, `signal_sigint`, or `startup_failure`. Use the instance ID and timestamps to distinguish an unexpected Pi exit from a requested stop or upgrade; a stop request does not prove which cause ultimately terminated the process, so inspect the exit code and signal as well. The correlation ID is independent of the launcher control nonce. These lifecycle records omit arguments, paths, credentials, and arbitrary child output. If the launcher itself is forcibly terminated, it may not be able to record the child's exit.
|
|
61
|
+
|
|
58
62
|
After an accepted update, browser version polling retains temporary network failures as `request_failed` breadcrumbs while waiting for the restarted service. If the target version is still unavailable after 60 seconds, it stops polling and reports one `stage=update_restart`, `code=update_restart_timeout` error, even if a request is still pending. Closing settings cancels the pending request and deadline. HTTP and response parsing failures, and network failures from other requests, retain normal reporting.
|
|
59
63
|
|
|
60
64
|
Each side sends at most 20 events/minute and one event per fingerprint/minute. Repetition counts appear on the next retained event. Startup and transport queues are bounded to 20 events. Transport requests time out after 3 seconds, do not persist offline, and do not retry indefinitely. Rate-limited/dropped events are intentionally lossy. Browser configuration has a 1-second timeout and never gates rendering; SDKs load only when reporting is enabled. No tracing, profiling, automatic console/DOM instrumentation or token-by-token logging is enabled.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-webapp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
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.13/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 B=(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)=>B(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 B=(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)=>B(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]="e8ca6826-5cde-4082-9c73-e69cc3ddc9d9",e._sentryDebugIdIdentifier="sentry-dbid-e8ca6826-5cde-4082-9c73-e69cc3ddc9d9")}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 x="modulepreload",j=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=j(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 f=document.createElement("link");if(f.rel=l?"stylesheet":x,l||(f.as="script"),f.crossOrigin="",f.href=o,m&&f.setAttribute("nonce",m),document.head.appendChild(f),l)return new Promise((T,N)=>{f.addEventListener("load",T),f.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)})},D=new Set(["bash","powershell","read","write","edit","grep","find","ls"]),q=new Set(["cancelled","blocked","validation","not_found","permission","timeout","process_exit","unknown"]),Y={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},F=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"]),R=new Set(["/api/plugins","/api/plugin-action","/api/plugin-interaction","/api/resume","/api/update","/api/update/version","/api/provider/models","/api/provider/logout","/api/provider/login/active","/api/telemetry/config","/api/image","/api/attachment","/api/attachment/remove","/api/session","/api/providers","/api/models","/api/config","/api/workspaces","/api/commands","/api/events","/api/message","/api/abort","/api/compact","/api/new-session","/api/model","/api/thinking-level","/api/provider/login","/api/provider/login/respond","/api/provider/login/cancel","/api/provider/custom","/api/workspace/add","/api/workspace/select","/api/workspace/new-session","/api/workspace/remove","/api/session/select","/api/directory/capability","/api/directory/list","/api/directory/create","/api/directory/pick"]);function ee(e){return e==="/api/message"||e.startsWith("/api/provider/")||["/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 F){const r=e[i];i==="toolName"?typeof r=="string"&&(D.has(r)||r==="custom")&&(t[i]=r):i==="failureKind"?q.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]=R.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 E(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 te(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
|
-
`)}`)),i}function K(e){return{...e.filename?{filename:E(e.filename)}:{},...e.abs_path?{abs_path:E(e.abs_path)}:{},...e.function?{function:p(e.function)}:{},lineno:e.lineno,colno:e.colno,in_app:e.in_app}}function Z(e){var r,s,n,a,
|
|
8
|
-
`)[1])??""}:${i.stage??""}`,o=this.budget.take(m);if(!o)return;const
|
|
7
|
+
`)}`)),i}function K(e){return{...e.filename?{filename:E(e.filename)}:{},...e.abs_path?{abs_path:E(e.abs_path)}:{},...e.function?{function:p(e.function)}:{},lineno:e.lineno,colno:e.colno,in_app:e.in_app}}function Z(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(K)}}:{},...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:E(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 re(e,t){return t.attachments=[],Z(e)}class M{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 U{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 V=new Set(["目录路径必须是绝对路径","父目录路径必须是绝对路径","文件夹名称无效","工作区目录不可用,请恢复目录或从列表移除后重新添加","会话已切换","Pi 正在运行,请等待当前回复结束","请等待当前回复结束","请等待当前回复结束再切换工作区","请等待当前回复结束再切换会话","请先切换到其他工作区","新会话已取消","已有登录正在进行","模型不可用","模型提供方未配置认证","当前模型不支持此推理强度","其他提供方的登录正在进行,请先完成或取消当前登录","当前会话没有暂停的任务","请先完成当前交互或审批","请先选择模型","请先连接当前模型","插件未启用","会话运行实例已切换","提供方已存在","文件超过 20 MB","请求内容过大","会话不属于该工作区","推理强度无效"]);function L(e){return e instanceof Error&&(e.name==="AbortError"||V.has(e.message))}class ie{constructor(t,i,r,s,n=new M){d(this,"budget",new U);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 se(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 W(){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.13+47b0cab9b46d97bbc98c",J="47b0cab9b46d97bbc98c";let u,z=!0,$=!1,P=!1,v=[];const k=new WeakSet,b=new Map;let y={};function _(e,t={}){try{if(L(e))return;if(typeof e=="object"&&e!==null){if(k.has(e))return;k.add(e)}if(u)return u.capture(e,t);z&&v.length<20&&v.push({error:S(e),context:h(t)})}catch{}}function ne(e){k.add(e)}function oe(e,t={}){u==null||u.breadcrumbs.add(e,t)}function ae(e){e.sessionId&&(b.has(e.sessionId)||(b.size>=32&&b.delete(b.keys().next().value),b.set(e.sessionId,crypto.randomUUID())),e={...e,session:b.get(e.sessionId)}),y=h({...y,...e}),u==null||u.setState(y)}function Q(){$||($=!0,P=new URL(location.href).searchParams.get("sentry_release_probe")==="1",window.addEventListener("error",e=>{e instanceof ErrorEvent?_(e.error??new Error(e.message),{stage:"global"}):(e.target instanceof HTMLScriptElement||e.target instanceof HTMLLinkElement)&&_(new Error("Application resource failed to load"),{stage:"resource"})},!0),window.addEventListener("unhandledrejection",e=>_(e.reason,{stage:"unhandled_rejection"})),G())}async function G(){var e;try{const t=W();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-BUyFe34_.js");return{createBrowserReporter:a}},[]);u=s({...r,buildId:J,release:H});const n=((e=navigator.userAgent.match(/(?:Firefox|Edg|Chrome|Version)\/[\d.]+/))==null?void 0:e[0])??"unknown";u.setState({...y,browser:n,platform:navigator.platform}),y={...y,browser:n,platform:navigator.platform};for(const a of v)u.capture(a.error,a.context);r.environment==="sentry-verification"&&P&&u.capture(new Error("Sentry browser release verification"),{stage:"release_verification",code:"sentry_release_probe"})}catch{}finally{v=[],z=!1}}Q();A(()=>import("./app-Boh5DRzv.js").then(e=>e.a),[]).catch(e=>_(e,{stage:"startup"}));export{ie as E,A as _,ee as a,oe as b,W as c,re as d,se as e,ne as i,te as o,Y as p,_ as r,ae as s};
|