@jetcrab/pi-desk 1.1.1 → 1.1.5-dev
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/docs/pi-desk/README.md +47 -0
- package/docs/pi-desk/commands.md +76 -0
- package/docs/pi-desk/examples/local-application/browser/application.js +106 -0
- package/docs/pi-desk/examples/local-application/browser/entry.js +9 -0
- package/docs/pi-desk/examples/local-application/package.json +9 -0
- package/docs/pi-desk/examples/local-application/pi-desk.ts +11 -0
- package/docs/pi-desk/plugins.md +119 -0
- package/package.json +3 -2
- package/src/client/l2_biz/pi-settings/hooks/l2-use-pi-settings.ts +37 -21
- package/src/client/l2_biz/pi-settings/l2-pi-settings.tsx +37 -43
- package/src/client/l2_biz/pi-settings/views/l2-mcp-settings-editor.tsx +3 -1
- package/src/client/l2_biz/pi-settings/views/l2-mcp-settings-list.tsx +1 -1
- package/src/client/l2_biz/plugin-host/hooks/l2-use-plugin-catalog.ts +3 -1
- package/src/client/l2_biz/plugin-host/hooks/l2-use-plugin-download-source.ts +5 -1
- package/src/client/l2_biz/plugin-host/l2-plugin-capability-details.tsx +57 -41
- package/src/client/l2_biz/plugin-host/l2-plugin-management-controls.tsx +89 -116
- package/src/client/l2_biz/plugin-host/l2-plugin-management.tsx +492 -338
- package/src/client/l2_biz/plugin-host/l2-use-plugin-management.ts +72 -22
- package/src/client/l2_biz/plugin-host/views/l2-plugin-catalog-detail.tsx +104 -76
- package/src/client/l2_biz/plugin-host/views/l2-plugin-catalog-search.tsx +101 -56
- package/src/client/l2_biz/plugin-host/views/l2-plugin-direct-install.tsx +91 -59
- package/src/client/l2_biz/plugin-host/views/l2-plugin-download-source.tsx +36 -27
- package/src/client/l2_biz/plugin-host/views/l2-plugin-installed-list.tsx +218 -208
- package/src/client/l2_biz/plugin-host/views/l2-plugin-management-channel.tsx +12 -5
- package/src/client/l2_biz/plugin-host/views/l2-plugin-management-dialog.tsx +84 -106
- package/src/client/l2_biz/plugin-host/views/l2-plugin-readme.tsx +29 -15
- package/src/client/l2_biz/settings/hooks/l2-use-project-model-default-settings.ts +22 -11
- package/src/client/l2_biz/settings/l2-settings.tsx +6 -11
- package/src/client/l2_biz/settings/views/l2-project-model-default-settings.tsx +20 -14
- package/src/client/l2_biz/terminal/l2-terminal-workspace.tsx +35 -1
- package/src/client/l2_biz/workbench/file-workspace/l2-work-session-file-preview.tsx +6 -2
- package/src/client/l2_biz/workbench/hooks/l2-workbench-chat-viewport.ts +14 -1
- package/src/client/l2_biz/workbench/l2-workbench-branch-picker.tsx +33 -5
- package/src/client/l2_biz/workbench/l2-workbench-sidebar-layout.tsx +3 -1
- package/src/client/l2_biz/workbench/l2-workbench.tsx +20 -3
- package/src/client/l3_modules/conversation/l3-conversation-call-summary.tsx +0 -3
- package/src/client/l3_modules/project-files/l3-file-context-menu-content.tsx +1 -0
- package/src/client/l4_foundation/ui/l4-app-dialog.tsx +3 -1
- package/src/client/l4_foundation/ui/l4-image-viewer.tsx +21 -0
- package/src/client/l4_foundation/ui/shadcn/checkbox.tsx +27 -0
- package/src/client/l4_foundation/ui/shadcn/context-menu.tsx +8 -1
- package/src/client/l4_foundation/ui/shadcn/dropdown-menu.tsx +5 -0
- package/src/client/l4_foundation/ui/shadcn/popover.tsx +2 -0
- package/src/client/l4_foundation/ui/shadcn/select.tsx +2 -0
- package/src/client/l4_foundation/ui/shadcn/switch.tsx +31 -0
- package/src/client/l4_foundation/ui/shadcn/tabs.tsx +74 -0
- package/src/common/l2_biz/plugin/l2-plugin-management-messages.ts +52 -22
- package/src/common/l3_modules/conversation/l3-conversation-locale-messages.ts +2 -2
- package/src/common/l3_modules/conversation/l3-conversation-pidesk.ts +1 -1
- package/src/common/l4_foundation/plugin/l4-plugin-package.ts +1 -0
- package/src/server/l2_biz/plugin-management/l2-plugin-catalog.ts +16 -5
- package/src/server/l2_biz/plugin-management/l2-plugin-commands.ts +21 -1
- package/src/server/l2_biz/plugin-management/l2-plugin-management.ts +21 -2
- package/src/server/l2_biz/plugin-management/l2-plugin-updates.ts +17 -3
- package/src/server/l4_foundation/pi/l4-pi-basic-session-services.ts +3 -3
- package/src/server/l4_foundation/pi/l4-pi-package-maintenance-runner.mts +4 -11
- package/src/server/l4_foundation/pi/l4-pi-plugin-registry-config.ts +52 -34
- package/src/server/l4_foundation/pi/l4-pi-plugin-registry-network.ts +5 -3
- package/src/server/l4_foundation/pi/l4-pi-plugin-registry.ts +23 -8
- package/src/server/l4_foundation/pi/l4-pi-session-initialization.ts +2 -5
- package/src/server/l4_foundation/pidesk/l4-pidesk-command.ts +8 -1
- package/src/server/l4_foundation/pidesk/l4-pidesk-runtime.ts +24 -38
- package/src/server/l4_foundation/pidesk/l4-pidesk-system-prompt.ts +11 -0
- package/temp/build/pi-desk/release/.next/BUILD_ID +1 -1
- package/temp/build/pi-desk/release/.next/build-manifest.json +3 -3
- package/temp/build/pi-desk/release/.next/prerender-manifest.json +3 -3
- package/temp/build/pi-desk/release/.next/react-loadable-manifest.json +1 -1
- package/temp/build/pi-desk/release/.next/required-server-files.js +3 -3
- package/temp/build/pi-desk/release/.next/required-server-files.json +3 -3
- package/temp/build/pi-desk/release/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.html +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.rsc +3 -3
- package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_full.segment.rsc +3 -3
- package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +3 -3
- package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/health/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/login/page.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/page.js +79 -79
- package/temp/build/pi-desk/release/.next/server/app/page_client-reference-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/25406.js +8 -77
- package/temp/build/pi-desk/release/.next/server/chunks/{81107.js → 35348.js} +2 -2
- package/temp/build/pi-desk/release/.next/server/chunks/35985.js +4 -4
- package/temp/build/pi-desk/release/.next/server/chunks/36361.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/47757.js +6 -75
- package/temp/build/pi-desk/release/.next/server/chunks/50520.js +4 -4
- package/temp/build/pi-desk/release/.next/server/chunks/58330.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/84231.js +2 -2
- package/temp/build/pi-desk/release/.next/server/chunks/89236.js +2 -2
- package/temp/build/pi-desk/release/.next/server/chunks/92386.js +5 -5
- package/temp/build/pi-desk/release/.next/server/chunks/94518.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/9874.js +1 -1
- package/temp/build/pi-desk/release/.next/server/middleware-build-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/temp/build/pi-desk/release/.next/server/pages/500.html +1 -1
- package/temp/build/pi-desk/release/.next/server/server-reference-manifest.json +1 -1
- package/temp/build/pi-desk/release/.next/static/chunks/14197-3d3ddd426ac06c9c.js +3 -0
- package/temp/build/pi-desk/release/.next/static/chunks/34903-e4205c0becabea76.js +318 -0
- package/temp/build/pi-desk/release/.next/static/chunks/{54206.7c0792096df8a5cf.js → 54206.82a63ab971911eda.js} +3 -3
- package/temp/build/pi-desk/release/.next/static/chunks/74132-876f256c7a6101af.js +13 -0
- package/temp/build/pi-desk/release/.next/static/chunks/78923-17a9c337b29dcecd.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/96995-8f8313ea2ac3abd7.js +62 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/{layout-7c5409cced9c2501.js → layout-4faf3a52d219296d.js} +2 -2
- package/temp/build/pi-desk/release/.next/static/chunks/app/login/{page-8c87fb9e6c918848.js → page-bf893718bb151f3c.js} +1 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/page-28e1d77d6b884657.js +158 -0
- package/temp/build/pi-desk/release/.next/static/chunks/{webpack-45424d28099bbefa.js → webpack-7bfbf627379fb4c1.js} +1 -1
- package/temp/build/pi-desk/release/.next/static/css/3213ee28336bddc2.css +1 -0
- package/temp/build/pi-desk/release/.next/trace-build +1 -1
- package/src/server/l4_foundation/pidesk/l4-pidesk-skill-template.ts +0 -87
- package/temp/build/pi-desk/release/.next/static/chunks/27491-8b2d3e345b9142ea.js +0 -318
- package/temp/build/pi-desk/release/.next/static/chunks/7089-600a8f5593b7846c.js +0 -3
- package/temp/build/pi-desk/release/.next/static/chunks/74132-0884df6a6f11861a.js +0 -13
- package/temp/build/pi-desk/release/.next/static/chunks/78923-539a8b5f7af3c54a.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/96995-ae32167974365050.js +0 -62
- package/temp/build/pi-desk/release/.next/static/chunks/app/page-39b146293b6eb488.js +0 -158
- package/temp/build/pi-desk/release/.next/static/css/56486914a8ba0a1b.css +0 -1
- /package/temp/build/pi-desk/release/.next/static/{STVrBHA3z9KPtvBE4WcE2 → IgHJ40fniC07-ioYUKobL}/_buildManifest.js +0 -0
- /package/temp/build/pi-desk/release/.next/static/{STVrBHA3z9KPtvBE4WcE2 → IgHJ40fniC07-ioYUKobL}/_ssgManifest.js +0 -0
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";exports.id=36361,exports.ids=[36361],exports.modules={4287:(a,b,c)=>{c.d(b,{LD:()=>k,SZ:()=>f,_C:()=>j,mR:()=>e,ug:()=>l,w3:()=>g,zj:()=>m});var d=c(36153);let e=d.Yj().trim().min(1).max(128).regex(/^[a-zA-Z][a-zA-Z0-9._-]*$/),f=d.Yj().trim().url().max(2048).refine(a=>{let b=new URL(a);return["https:","http:"].includes(b.protocol)&&!b.username&&!b.password&&!b.search&&!b.hash},"插件源必须是 HTTP 或 HTTPS 仓库地址"),g=d.gM("mode",[d.Ik({mode:d.eu("auto")}).strict(),d.Ik({mode:d.eu("official")}).strict(),d.Ik({mode:d.eu("domestic")}).strict(),d.Ik({mode:d.eu("custom"),registry:f}).strict()]),h=d.Ik({description:d.Yj().trim().min(1).max(4e3).optional(),readme:d.Yj().trim().min(1).max(1024).optional()}),i=d.Ik({description:d.Yj().optional(),piDesk:d.Ik({i18n:d.g1(d.Yj().min(1).max(35),h).optional()}).passthrough().optional()}).passthrough();function j(a){let b=i.safeParse(a);if(!b.success)return null;let c=b.data.description?.trim();if(!c)return null;let d=Object.fromEntries(Object.entries(b.data.piDesk?.i18n??{}).slice(0,16).flatMap(([a,b])=>b.description?[[a,b.description]]:[]));return Object.keys(d).length?{default:c,translations:d}:c}function k(a){let b=/^npm:((?:@[^/]+\/)?[^@]+)(?:@.+)?$/.exec(a);return b?`npm:${b[1]}`:a.replaceAll("\\","/")}function l(a){return/^npm:((?:@[^/]+\/)?[^@]+)(?:@.+)?$/.exec(a)?.[1]??null}function m(a,b){let c=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/,d=c.exec(a),e=c.exec(b);if(!d||!e)return!1;for(let a=1;a<=3;a++){let b=Number(d[a])-Number(e[a]);if(b)return b>0}if(!d[4]||!e[4])return!d[4]&&!!e[4];let f=d[4].split("."),g=e[4].split(".");for(let a=0;a<Math.max(f.length,g.length);a++){let b=f[a],c=g[a];if(b===c)continue;if(void 0===b||void 0===c)return void 0===c;let d=/^\d+$/.test(b),e=/^\d+$/.test(c);if(d&&e)return Number(b)>Number(c);if(d!==e)return e;return b>c}return!1}},5235:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{El:()=>n,Nx:()=>q,ey:()=>o,ks:()=>p,sv:()=>r,to:()=>l});var e=c(73024),f=c(76760),g=c(77598),h=c(75430),i=c(36153),j=c(4287),k=a([h]);h=(k.then?(await k)():k)[0];let q="https://registry.npmjs.org",r="https://mirrors.cloud.tencent.com/npm",s=i.Ik({downloadSource:j.w3.default({mode:"auto"}),disabled:i.YO(i.Yj()).max(2e3).default([]),registries:i.g1(i.Yj(),j.SZ).default({}),updateTags:i.g1(i.Yj(),j.mR).default({})}).strict();function l(a=(0,h.getAgentDir)()){let b=(0,f.join)(a,"pi-desk-plugins.json");return(0,e.existsSync)(b)?s.parse(JSON.parse((0,e.readFileSync)(b,"utf8"))):s.parse({})}function m(a,b){let c=(0,f.join)(a,"pi-desk-plugins.json"),d=s.parse(b(l(a)));(0,e.mkdirSync)((0,f.dirname)(c),{recursive:!0});let h=`${c}.${(0,g.randomUUID)()}.tmp`;try{(0,e.writeFileSync)(h,`${JSON.stringify(d,null,2)}
|
|
1
|
+
"use strict";exports.id=36361,exports.ids=[36361],exports.modules={4287:(a,b,c)=>{c.d(b,{LD:()=>k,SZ:()=>f,_C:()=>j,mR:()=>e,ug:()=>l,w3:()=>g,zj:()=>m});var d=c(36153);let e=d.Yj().trim().min(1).max(128).regex(/^[a-zA-Z][a-zA-Z0-9._-]*$/),f=d.Yj().trim().url().max(2048).refine(a=>{let b=new URL(a);return["https:","http:"].includes(b.protocol)&&!b.username&&!b.password&&!b.search&&!b.hash},"插件源必须是 HTTP 或 HTTPS 仓库地址"),g=d.gM("mode",[d.Ik({mode:d.eu("auto")}).strict(),d.Ik({mode:d.eu("local")}).strict(),d.Ik({mode:d.eu("official")}).strict(),d.Ik({mode:d.eu("domestic")}).strict(),d.Ik({mode:d.eu("custom"),registry:f}).strict()]),h=d.Ik({description:d.Yj().trim().min(1).max(4e3).optional(),readme:d.Yj().trim().min(1).max(1024).optional()}),i=d.Ik({description:d.Yj().optional(),piDesk:d.Ik({i18n:d.g1(d.Yj().min(1).max(35),h).optional()}).passthrough().optional()}).passthrough();function j(a){let b=i.safeParse(a);if(!b.success)return null;let c=b.data.description?.trim();if(!c)return null;let d=Object.fromEntries(Object.entries(b.data.piDesk?.i18n??{}).slice(0,16).flatMap(([a,b])=>b.description?[[a,b.description]]:[]));return Object.keys(d).length?{default:c,translations:d}:c}function k(a){let b=/^npm:((?:@[^/]+\/)?[^@]+)(?:@.+)?$/.exec(a);return b?`npm:${b[1]}`:a.replaceAll("\\","/")}function l(a){return/^npm:((?:@[^/]+\/)?[^@]+)(?:@.+)?$/.exec(a)?.[1]??null}function m(a,b){let c=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/,d=c.exec(a),e=c.exec(b);if(!d||!e)return!1;for(let a=1;a<=3;a++){let b=Number(d[a])-Number(e[a]);if(b)return b>0}if(!d[4]||!e[4])return!d[4]&&!!e[4];let f=d[4].split("."),g=e[4].split(".");for(let a=0;a<Math.max(f.length,g.length);a++){let b=f[a],c=g[a];if(b===c)continue;if(void 0===b||void 0===c)return void 0===c;let d=/^\d+$/.test(b),e=/^\d+$/.test(c);if(d&&e)return Number(b)>Number(c);if(d!==e)return e;return b>c}return!1}},5235:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{El:()=>n,Nx:()=>q,ey:()=>o,ks:()=>p,sv:()=>r,to:()=>l});var e=c(73024),f=c(76760),g=c(77598),h=c(75430),i=c(36153),j=c(4287),k=a([h]);h=(k.then?(await k)():k)[0];let q="https://registry.npmjs.org",r="https://mirrors.cloud.tencent.com/npm",s=i.Ik({downloadSource:j.w3.default({mode:"auto"}),disabled:i.YO(i.Yj()).max(2e3).default([]),registries:i.g1(i.Yj(),j.SZ).default({}),updateTags:i.g1(i.Yj(),j.mR).default({})}).strict();function l(a=(0,h.getAgentDir)()){let b=(0,f.join)(a,"pi-desk-plugins.json");return(0,e.existsSync)(b)?s.parse(JSON.parse((0,e.readFileSync)(b,"utf8"))):s.parse({})}function m(a,b){let c=(0,f.join)(a,"pi-desk-plugins.json"),d=s.parse(b(l(a)));(0,e.mkdirSync)((0,f.dirname)(c),{recursive:!0});let h=`${c}.${(0,g.randomUUID)()}.tmp`;try{(0,e.writeFileSync)(h,`${JSON.stringify(d,null,2)}
|
|
2
2
|
`,"utf8"),(0,e.renameSync)(h,c)}finally{(0,e.rmSync)(h,{force:!0})}}function n(a,b,c=(0,h.getAgentDir)()){let d=(0,j.LD)(a);m(c,a=>({...a,disabled:[...a.disabled.filter(a=>a!==d),...b?[]:[d]]}))}function o(a,b=(0,h.getAgentDir)()){let c=l(b).updateTags[(0,j.LD)(a)];if(c)return c;let d=/^npm:(?:@[^/]+\/)?[^@]+@([^@]+)$/.exec(a)?.[1];return d&&!/^v?\d+\./.test(d)&&j.mR.safeParse(d).success?d:"latest"}function p(a,b,c=(0,h.getAgentDir)()){let d=(0,j.LD)(a);m(c,a=>({...a,updateTags:{...a.updateTags,[d]:b}}))}d()}catch(a){d(a)}})},16056:(a,b,c)=>{c.d(b,{P:()=>e});let d=process.argv.includes("--safe-mode")||"1"===process.env.PI_DESK_SAFE_MODE;function e(){return d}},30987:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{n:()=>n});var e=c(51455),f=c(48161),g=c(76760),h=c(4287),i=c(5235),j=a([i]);async function k(a){let b=await (0,e.realpath)(a).catch(()=>(0,g.resolve)(a));return"win32"===process.platform?b.toLowerCase():b}function l(a,b){return/^(npm:|git:|https?:|ssh:|git@)/.test(a)?null:a.startsWith("~/")?(0,g.join)((0,f.homedir)(),a.slice(2)):(0,g.resolve)(b,a)}function m(a,b){let c=(0,g.relative)(a,b);return""===c||!c.startsWith("..")&&!(0,g.isAbsolute)(c)}async function n(a,b,c){let d=new Set((0,i.to)(a).disabled.map(h.LD)),f=new Set;for(let b of d){let c=l(b,a);c&&f.add(await k(c))}for(let c of b.listConfiguredPackages()){if("user"!==c.scope||!c.installedPath)continue;let b=l(c.source,a),e=b&&f.has(await k(b));(d.has((0,h.LD)(c.source))||e)&&f.add(await k(c.installedPath))}if(f.size>0){let d=(0,g.join)(a,"extensions"),h=await (0,e.readdir)(d,{withFileTypes:!0}).catch(a=>{if(a&&"object"==typeof a&&"code"in a&&"ENOENT"===a.code)return[];throw a}),i=[...b.listConfiguredPackages().filter(a=>"user"===a.scope).flatMap(a=>a.installedPath??[]),...h.filter(a=>!a.name.startsWith(".")&&"node_modules"!==a.name&&(a.isDirectory()||a.isSymbolicLink())).map(a=>(0,g.join)(d,a.name)),...(c.getGlobalSettings().extensions??[]).filter(a=>!/^[!+-]|[?*{}]/.test(a)).flatMap(b=>l(b,a)??[])],j=[];for(let a of i)await (0,e.stat)(a).then(a=>a.isDirectory(),()=>!1)&&j.push(await k(a));for(let a of(j.sort((a,b)=>b.length-a.length),[...f])){if(!await (0,e.stat)(a).then(a=>a.isFile(),()=>!1))continue;let b=j.find(b=>m(b,a));b&&f.add(b)}}let j=new Map;return async(a,b,c)=>{if(c&&d.has((0,h.LD)(a)))return!0;if(!b||b.startsWith("builtin:")||0===f.size)return!1;let e=j.get(b);e||(e=k(b),j.set(b,e));let g=await e;return[...f].some(a=>m(a,g))}}i=(j.then?(await j)():j)[0],d()}catch(a){d(a)}})},36361:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.r(b),c.d(b,{L4PiGlobalPluginRuntime:()=>o,L4PiPluginOwnerRuntime:()=>g.K,L4PiPluginRuntimeBusyError:()=>g.y,disposeL4PiGlobalPluginRuntime:()=>n,getL4PiGlobalPluginRuntime:()=>m});var e=c(67841),f=c(75430),g=c(99667),h=c(16056),i=c(60719),j=c(66024),k=c(44493),l=a([e,f,g,i,k]);[e,f,g,i,k]=l.then?(await l)():l;class o extends g.K{constructor(a=process.cwd(),b=(0,f.getAgentDir)()){const c=new j.N,d=async()=>(0,h.P)()?{sources:[],errors:[]}:(0,i.o)(a,b,{DefaultPackageManager:f.DefaultPackageManager,SettingsManager:f.SettingsManager});super(async()=>{let a=await d();for(let b of a.errors)console.warn("[Pi Desk][GlobalPluginRuntime] 插件来源发现诊断",{message:b});return await c.initialize(a),a.sources.flatMap(a=>a.enabled&&!a.error&&a.piDeskRoot?[{source:a.source,installedPath:a.piDeskRoot}]:[])},(0,e.J)()),this.sourceChanges=c,this.discover=d}async scanSourceChanges(a){return await this.initialize(),this.sourceChanges.scan(await this.discover(),a)}async applySourceChange(a){let[b]=await this.scanSourceChanges([a.source]);if(!b||b.fingerprint!==a.fingerprint||b.current?.enabled&&b.current.error)throw Error(b?.current?.error??"插件源码在预检后发生变化,请重新加载");a.previous?.piDeskRoot||a.current?.piDeskRoot?await this.replaceSource(a.source,a.current?.enabled?a.current.piDeskRoot:null):(0,k.N)(),this.sourceChanges.commit(a)}}function m(){return globalThis.__piDeskGlobalPluginRuntime||(globalThis.__piDeskGlobalPluginRuntime=new o),globalThis.__piDeskGlobalPluginRuntime}async function n(){let a=globalThis.__piDeskGlobalPluginRuntime;globalThis.__piDeskGlobalPluginRuntime=void 0,await a?.dispose()}d()}catch(a){d(a)}})},44493:(a,b,c)=>{c.a(a,async(a,d)=>{try{let n;c.d(b,{G:()=>m,N:()=>k});var e=c(93736),f=c(73024),g=c(76760),h=a([e]);e=(h.then?(await h)():h)[0];let o=(0,g.join)(process.cwd(),"package.json"),{createRequire:p}=process.getBuiltinModule("module"),q=(0,e.createJiti)((0,g.join)(process.env.PI_DESK_PI_PACKAGE_DIR??process.cwd(),"package.json")),r=new Map,s=0;function i(a){let b=r.get(a);return b&&(r.delete(a),r.set(a,b)),b}function j(a,b){let c=r.get(a);if(c&&(r.delete(a),s-=c.bytes),!(b.bytes>0x2000000)){for(;r.size>=512||s+b.bytes>0x2000000;){let a=r.entries().next().value;r.delete(a[0]),s-=a[1].bytes}r.set(a,b),s+=b.bytes}}function k(){r.size>0&&console.info("[Pi Desk][PluginResources] 已清除插件代码缓存",{fileCount:r.size,bytes:s}),r.clear(),s=0}async function l(){let[a,b,c,d,f,h,k,l,m]=await Promise.all([q.import("@earendil-works/pi-coding-agent"),q.import("@earendil-works/pi-agent-core"),q.import("@earendil-works/pi-tui"),q.import("@earendil-works/pi-ai/compat"),q.import("@earendil-works/pi-ai/oauth"),q.import("@earendil-works/pi-ai/providers/all"),q.import("typebox"),q.import("typebox/compile"),q.import("typebox/value")]),n=(0,e.createJiti)(o,{moduleCache:!1,fsCache:!1,tryNative:!1,virtualModules:{"@earendil-works/pi-coding-agent":a,"@earendil-works/pi-agent-core":b,"@earendil-works/pi-tui":c,"@earendil-works/pi-ai/providers/all":h,"@earendil-works/pi-ai/compat":d,"@earendil-works/pi-ai/oauth":f,"@earendil-works/pi-ai":d,"@mariozechner/pi-coding-agent":a,"@mariozechner/pi-agent-core":b,"@mariozechner/pi-tui":c,"@mariozechner/pi-ai/providers/all":h,"@mariozechner/pi-ai/compat":d,"@mariozechner/pi-ai/oauth":f,"@mariozechner/pi-ai":d,typebox:k,"typebox/compile":l,"typebox/value":m,"@sinclair/typebox":k,"@sinclair/typebox/compile":l,"@sinclair/typebox/value":m}}),p=n.options.transform;return n.options.transform=a=>(function(a,b){if(!a.filename)return b(a);let c=(0,g.resolve)(a.filename),d=i(c),e=d?.source===a.source?d:void 0,f=!0===a.async,h=e?.transforms.get(f);if(h)return h;let k=a.source,l=b(a);return l.error||l.code.includes("__JITI_ERROR__")||j(c,{source:k,transforms:new Map(e?.transforms).set(f,l),bytes:(e?.bytes??Buffer.byteLength(k))+Buffer.byteLength(l.code)}),l})(a,p),n}async function m(a,b=(0,g.dirname)(a)){let c=await (n??=l()),d=p(o).cache,e=(0,g.resolve)(b);for(let a of Object.keys(d)){let b=(0,g.relative)(e,a);b.startsWith("..")||(0,g.isAbsolute)(b)||b.split(/[\\/]/).includes("node_modules")||delete d[a]}try{let b,d=(0,g.resolve)(a),e=c.evalModule((b=(0,f.readFileSync)(d,"utf8"),i(d)?.source!==b&&j(d,{source:b,transforms:new Map,bytes:Buffer.byteLength(b)}),b),{filename:d,async:!1});return{default:e?.default??e}}catch(a){if(k(),a instanceof Error&&/await is only valid|top.level await|ERR_REQUIRE_ASYNC_MODULE/i.test(a.message))throw Error("Pi Desk Node Entry 不支持模块顶层 await,请将异步初始化放入 async setup()",{cause:a});throw a}}d()}catch(a){d(a)}})},59214:(a,b,c)=>{c.d(b,{J:()=>f,a:()=>e});var d=c(36153);let e=d.Ik({locale:d.k5(["zh-CN","en"]),timeZone:d.Yj().trim().min(1).max(100).refine(a=>{try{return new Intl.DateTimeFormat("en",{timeZone:a}),!0}catch{return!1}},"无效的 IANA 时区")}).strict().readonly(),f=d.Ik({region:e}).strict().readonly()},60719:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{W:()=>p,o:()=>o});var e=c(51455),f=c(48161),g=c(76760),h=c(4287),i=c(30987),j=a([i]);function k(a,b){let c=(0,g.relative)(a,b);return""===c||!c.startsWith("..")&&!(0,g.isAbsolute)(c)}async function l(a){try{return await (0,e.realpath)(a)}catch{return(0,g.resolve)(a)}}function m(a){return"win32"===process.platform?a.toLowerCase():a}async function n(a){try{if((await (0,e.stat)(a)).isFile())return{version:null,description:null,hasNodeEntry:!1,error:null};let b=JSON.parse(await (0,e.readFile)((0,g.join)(a,"package.json"),"utf8"));if(!b||"object"!=typeof b||Array.isArray(b))throw Error("package.json 必须是对象");return{version:"string"==typeof b.version?b.version:null,description:(0,h._C)(b),hasNodeEntry:b.piDesk?.entry!==void 0||b.piDesk?.global!==void 0,hasNativeEntries:Array.isArray(b.pi?.extensions)&&b.pi.extensions.length>0,error:null}}catch(a){if(a&&"object"==typeof a&&"code"in a&&"ENOENT"===a.code)return{version:null,description:null,hasNodeEntry:!1,error:null};return{version:null,description:null,hasNodeEntry:!1,error:a instanceof Error?a.message:String(a)}}}async function o(a,b,c){let d=c.SettingsManager.create(a,b,{projectTrusted:!1}),h=new c.DefaultPackageManager({cwd:a,agentDir:b,settingsManager:d}),j=d.drainErrors().map(({error:a})=>a.message),o=new Map,p=new Map;for(let a of h.listConfiguredPackages()){if("user"!==a.scope)continue;let b=a.installedPath?await l(a.installedPath):null,c=b?await n(b):null,d=b?p.get(m(b)):void 0;b&&!d&&p.set(m(b),a.source),o.set(a.source,{source:a.source,kind:"package",path:b,nativePaths:[],hasPiResources:!0,piDeskRoot:b&&c?.hasNodeEntry&&!d?b:null,version:c?.version??null,description:c?.description??null,enabled:!0,error:d?`此目录已由 ${d} 声明,不能重复加载`:b?c?.error??null:"插件包未安装或安装目录不存在"})}let q=(0,g.join)(b,"extensions"),r=new Set;try{for(let a of(await (0,e.readdir)(q,{withFileTypes:!0})))if(!a.name.startsWith(".")&&"node_modules"!==a.name&&(a.isDirectory()||a.isSymbolicLink()))try{let b=await l((0,g.join)(q,a.name));(await (0,e.stat)(b)).isDirectory()&&r.add(b)}catch(b){j.push(`${a.name}: ${b instanceof Error?b.message:String(b)}`)}}catch(a){a&&"object"==typeof a&&"code"in a&&"ENOENT"===a.code||j.push(a instanceof Error?a.message:String(a))}for(let a of d.getGlobalSettings().extensions??[]){if(/^[!+-]|[?*{}]/.test(a))continue;let c=await l(a.startsWith("~/")?(0,g.join)((0,f.homedir)(),a.slice(2)):(0,g.resolve)(b,a));try{(await (0,e.stat)(c)).isDirectory()&&r.add(c)}catch{}}let s=[...r].sort((a,b)=>b.length-a.length);try{let a=await h.resolve(async()=>"skip");for(let a of o.values())a.hasPiResources=!1;for(let b of[...a.extensions,...a.skills,...a.prompts,...a.themes])if(b.enabled&&"user"===b.metadata.scope&&"package"===b.metadata.origin){let a=o.get(b.metadata.source);a&&(a.hasPiResources=!0)}for(let b of a.extensions){if("user"!==b.metadata.scope)continue;let a=await l(b.path);if("package"===b.metadata.origin){let c=o.get(b.metadata.source);c&&b.enabled&&!c.nativePaths.includes(a)&&c.nativePaths.push(a);continue}let c=s.find(b=>k(b,a))??a,d=[...p].find(([b])=>k(b,m(a)));if(d){let c=o.get(d[1]);b.enabled&&c&&!c.nativePaths.includes(a)&&c.nativePaths.push(a),j.push(`扩展入口 ${a} 与已配置包 ${d[1]} 重复,保留包来源`);continue}let e=o.get(c);e||(e={source:c,kind:"extension",path:c,nativePaths:[],piDeskRoot:null,version:null,description:null,enabled:!1,error:null},o.set(c,e)),b.enabled&&(e.enabled=!0,e.nativePaths.includes(a)||e.nativePaths.push(a))}}catch(a){j.push(a instanceof Error?a.message:String(a))}for(let a of s){if([...p.keys()].some(b=>k(b,m(a))))continue;let b=await n(a),c=o.get(a);if(!c&&!b.hasNodeEntry&&!b.error)continue;let d=(await Promise.all(["index.ts","index.js"].map(b=>(0,e.stat)((0,g.join)(a,b)).then(a=>a.isFile(),()=>!1)))).some(Boolean),f=c??{source:a,kind:"extension",path:a,nativePaths:[],piDeskRoot:null,version:null,description:null,enabled:!b.hasNativeEntries&&!d,error:null};f.version=b.version,f.description=b.description,f.error=b.error,b.hasNodeEntry&&f.enabled&&(f.piDeskRoot=a),o.set(a,f)}let t=await (0,i.n)(b,h,d);for(let a of o.values())await t(a.source,a.path,"package"===a.kind)&&(a.enabled=!1);return{sources:[...o.values()].sort((a,b)=>a.source.localeCompare(b.source)),errors:j}}async function p(a){if(!a.path)return null;try{return(await (0,e.stat)(a.path)).isFile()?(0,g.dirname)(a.path):a.path}catch{return null}}i=(j.then?(await j)():j)[0],d()}catch(a){d(a)}})},63603:(a,b,c)=>{c.d(b,{Qg:()=>m,RC:()=>p,a4:()=>k,dO:()=>j,j0:()=>n});var d=c(36153);let e=d.Yj().min(1).max(64).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),f=d.Yj().trim().min(1).max(256),g=d.Ik({allow:d.YO(f).max(5e3).optional(),deny:d.YO(f).max(5e3).optional()}).strict(),h=d.Ik({value:d.Yj().trim().min(1).max(256),label:d.Yj().trim().min(1).max(120).optional(),description:d.Yj().trim().max(1e3).optional()}).strict(),i=d.Ik({label:d.Yj().trim().min(1).max(120),options:d.YO(h).max(5e3)}).strict(),j=d.g1(e,i),k=d.Yj().min(1).max(64),l=d.Ik({name:d.Yj().trim().min(1).max(64),tools:g.optional(),skills:g.optional(),plugins:d.g1(e,d.g1(e,g)).optional()}).strict(),m=d.g1(k,l).refine(a=>Object.keys(a).length<=100,"最多保存 100 个能力模式").refine(a=>new Set(Object.values(a).map(a=>a.name)).size===Object.keys(a).length,"模式名称不能重复"),n=d.g1(k,l.shape.name);function o(a,b){let c=0,d=0,e=-1,f=0;for(;d<b.length;)if("*"===a[c])e=c++,f=d;else if(a[c]===b[d])c+=1,d+=1;else{if(!(e>=0))return!1;c=e+1,d=++f}for(;"*"===a[c];)c+=1;return c===a.length}function p(a,b){return(a?.allow===void 0||a.allow.some(a=>o(a,b)))&&!a?.deny?.some(a=>o(a,b))}d.Ik({tools:d.YO(h),skills:d.YO(h),plugins:d.g1(e,j)}).strict(),d.Ik({tools:g,skills:g,capabilities:d.g1(e,g)}).strict()},66024:(a,b,c)=>{c.d(b,{N:()=>l});var d=c(77598),e=c(51455),f=c(76760);let g=new Set([".ts",".tsx",".mts",".cts",".js",".jsx",".mjs",".cjs",".json",".md",".css",".yaml",".yml",".toml",".wasm",".node"]),h=new Set(["node_modules","temp","logs","coverage"]);class i extends Error{constructor(a){super(`插件来源不存在:${a}`),this.source=a,this.name="L4PiPluginSourceNotFoundError"}}async function j(a){let b=(0,d.createHash)("sha256").update(JSON.stringify({path:a.path,enabled:a.enabled,nativePaths:[...a.nativePaths].sort(),piDeskRoot:a.piDeskRoot,hasPiResources:a.hasPiResources}));if(!a.path||a.error||!a.enabled)return b.update(a.error??"").digest("hex");let c=await (0,e.realpath)(a.path),i=0,j=0,k=async(a,d,l)=>{if(++j>8192)throw Error("源码目录条目超过8192项,请使用独立插件目录");let m=await (0,e.realpath)(a),n=(0,f.relative)(c,m);if(n.startsWith("..")||(0,f.isAbsolute)(n))return;let o=await (0,e.stat)(m);if(o.isDirectory()){if(l.has(m))throw Error("源码目录存在符号链接循环");let a=new Set(l).add(m);for(let b of(await (0,e.readdir)(m,{withFileTypes:!0})).sort((a,b)=>a.name.localeCompare(b.name)))b.name.startsWith(".")||h.has(b.name)||await k((0,f.join)(m,b.name),`${d}/${b.name}`,a)}else if(o.isFile()&&(""===d||g.has((0,f.extname)(d)))){if(o.size>0x1000000||i+o.size>0x4000000)throw Error("源码指纹内容超过容量上限");let a=await (0,e.readFile)(m),c=await (0,e.stat)(m);if(c.size!==o.size||c.mtimeMs!==o.mtimeMs||a.length!==o.size)throw Error("插件源码正在变化,请保存或构建完成后重新加载");i+=a.length,b.update(d).update("\0").update(a).update("\0")}};return await k(c,"",new Set),b.digest("hex")}async function k(a){try{return{source:a,fingerprint:await j(a)}}catch(c){let b={...a,error:c instanceof Error?c.message:String(c)};return{source:b,fingerprint:`failed:${b.error}`}}}class l{async initialize(a){for(let b of(this.applied.clear(),a.sources))this.applied.set(b.source,await k(b))}async scan(a,b){let c=new Map(a.sources.map(a=>[a.source,a])),d=b?[...new Set(b)]:[...new Set([...this.applied.keys(),...c.keys()])],e=[];for(let f of d){let d=this.applied.get(f),g=c.get(f);if(!d&&!g)throw new i(f);if(!g&&a.errors.length>0){if(b)throw Error(`来源发现不完整,不能确认已删除:${f}`);continue}let h=g?await k(g):null;(b||d?.fingerprint!==h?.fingerprint)&&e.push({source:f,previous:d?.source??null,current:h?.source??null,fingerprint:h?.fingerprint??null})}return e}commit(a){a.current&&null!==a.fingerprint?this.applied.set(a.source,{source:a.current,fingerprint:a.fingerprint}):this.applied.delete(a.source)}constructor(){this.applied=new Map}}},67841:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{J:()=>l});var e=c(77598),f=c(73024),g=c(76760),h=c(75430),i=c(59214),j=a([h]);function k(){let a=Intl.DateTimeFormat().resolvedOptions();return i.J.parse({region:{locale:a.locale.toLowerCase().startsWith("zh")?"zh-CN":"en",timeZone:a.timeZone||"UTC"}})}h=(j.then?(await j)():j)[0];class m{constructor(a=(0,g.join)((0,h.getAgentDir)(),"pi-desk-settings.json"),b=k){this.path=a,this.defaults=b,this.snapshot=null,this.listeners=new Set,this.tail=Promise.resolve()}getSnapshot(){if(!this.snapshot)if((0,f.existsSync)(this.path))this.snapshot=i.J.parse(JSON.parse((0,f.readFileSync)(this.path,"utf8")));else{let a=i.J.parse(this.defaults());this.save(a),this.snapshot=a}return this.snapshot}subscribe(a){return this.listeners.add(a),()=>this.listeners.delete(a)}update(a){let b=this.tail.then(()=>{let b=this.getSnapshot(),c=i.J.parse({region:{...b.region,...a}});if(JSON.stringify(b)!==JSON.stringify(c))for(let a of(this.save(c),this.snapshot=c,console.info("[Pi Desk][Settings] 共享地区设置已保存",c.region),this.listeners))try{a()}catch(a){console.error("[Pi Desk][Settings] 设置订阅回调失败",{message:a instanceof Error?a.message:String(a)})}});return this.tail=b.catch(()=>void 0),b}save(a){(0,f.mkdirSync)((0,g.dirname)(this.path),{recursive:!0});let b=`${this.path}.${process.pid}.${(0,e.randomUUID)()}.tmp`;try{(0,f.writeFileSync)(b,`${JSON.stringify(a,null,2)}
|
|
3
3
|
`,"utf8"),(0,f.renameSync)(b,this.path)}finally{(0,f.existsSync)(b)&&(0,f.unlinkSync)(b)}}}function l(){return globalThis.__piDeskHostSettingsStore??=new m}d()}catch(a){d(a)}})},73630:(a,b,c)=>{c.d(b,{f:()=>h});var d=c(77598),e=c(51455),f=c(76760);function g(a,b){let c=(0,f.relative)(a,b);return""===c||!c.startsWith("..")&&!(0,f.isAbsolute)(c)}async function h(a){if("entry.js"!==(0,f.basename)(a))throw Error("Browser Entry 必须命名为 entry.js");let b=await (0,e.realpath)((0,f.dirname)(a)),c=new Map,h=0,i=0,j=[],k=async(a,l,m)=>{let n=await (0,e.realpath)(a);if(!g(b,n))return;if(m.has(n))throw Error("Browser 模块目录存在符号链接循环");let o=new Set(m).add(n);for(let a of(await (0,e.readdir)(n,{withFileTypes:!0})).sort((a,b)=>a.name.localeCompare(b.name))){if(++i>4096)throw Error("Browser 模块目录条目超过上限");if(a.name.startsWith(".")||"node_modules"===a.name)continue;let m=(0,f.join)(n,a.name),p=await (0,e.realpath)(m);if(!g(b,p))continue;let q=await (0,e.stat)(p),r=l?`${l}/${a.name}`:a.name;if(q.isDirectory()){await k(p,r,o);continue}if(!q.isFile()||!a.name.endsWith(".js"))continue;if("entry.js"===r&&"entry.js"!==(0,f.basename)(p))throw Error("Browser Entry 符号链接必须指向 entry.js");if(c.size>=2048||q.size>0x1000000||h+q.size>0x2000000)throw Error("Browser 模块快照超过数量或容量上限");let s=await (0,e.readFile)(p),t=await (0,e.stat)(p);if(s.length!==q.size||t.size!==q.size||t.mtimeMs!==q.mtimeMs)throw Error("Browser 模块在读取时发生变化,请构建完成后重新加载");h+=s.length,j.push({path:p,size:t.size,mtimeMs:t.mtimeMs,ino:t.ino}),c.set(r,{content:s,etag:`"${(0,d.createHash)("sha256").update(s).digest("hex")}"`})}};for(let a of(await k(b,"",new Set),j)){let b=await (0,e.stat)(a.path);if(b.size!==a.size||b.mtimeMs!==a.mtimeMs||b.ino!==a.ino)throw Error("Browser 模块组在读取时发生变化,请构建完成后重新加载")}if(!c.has("entry.js"))throw Error("Browser Entry 模块缺失或越出专用目录");return{size:h,modules:c}}},90733:(a,b,c)=>{c.d(b,{$m:()=>g,FX:()=>h,Pu:()=>m,QK:()=>i,Tk:()=>k,nJ:()=>j,qs:()=>l});var d=c(36153);let e=d.Yj().trim().min(1).max(64).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),f=d.g1(d.Yj(),d.Pq());function g(a,b){return`${a}\u0000${b}`}function h(a){return e.parse(a)}function i(a){return e.parse(a)}function j(a,b){let c=f.parse(a);if(Buffer.byteLength(JSON.stringify(c),"utf8")>2097152)throw new m(b);return c}class k extends Error{constructor(a,b){super(`Plugin method was not found: ${a}/${b}`),this.name="L4PiPluginMethodNotFoundError"}}class l extends Error{constructor(a,b){super(`Plugin method is already registered: ${a}/${b}`),this.name="L4PiPluginMethodConflictError"}}class m extends Error{constructor(a){super(`Plugin method ${a} exceeds 2MB`),this.direction=a,this.name="L4PiPluginMethodPayloadTooLargeError"}}},99667:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{K:()=>y,y:()=>w});var e=c(77598),f=c(58500),g=c(51455),h=c(76760),i=c(36153),j=c(63603),k=c(44493),l=c(73630),m=c(90733),n=a([k]);k=(n.then?(await n)():n)[0];let r=i.g1(i.Yj(),i.Pq()),s=i.Ik({workId:i.Yj().trim().min(1),sessionId:i.Yj().trim().min(1),branchId:i.Yj().trim().min(1)}).strict(),t=i.Ik({source:s,cwd:i.Yj().trim().min(1),status:i.k5(["main_running","background_running","completed","idle"])}).strict(),u=i.Yj().trim().min(1).max(64).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),v=i.ai().int().safe();class w extends Error{constructor(){super("插件运行时仍有调用正在执行"),this.name="L4PiPluginRuntimeBusyError"}}class x extends Error{constructor(a,b){super(b instanceof Error?b.message:String(b),{cause:b}),this.phase=a,this.name="L4PiPluginPhaseError"}}function o(a,b,c){if("string"!=typeof b||!b.trim())throw Error(`package.json.${c} must be a non-empty string`);let d=(0,h.resolve)(a,b),e=(0,h.relative)(a,d);if(e.startsWith("..")||(0,h.isAbsolute)(e))throw Error(`package.json.${c} must stay inside the package root`);return d}function p(a){return a instanceof Error&&a.message?a.message:String(a)}async function q(a){let b=null;try{if(await Promise.race([Promise.resolve().then(a.execute).then(()=>!0),new Promise(a=>{b=setTimeout(()=>a(!1),1500)})]))return;throw a.onTimeout?.(),Error(`插件 ${a.phase} 超时,关闭结果未确认`)}catch(b){console.warn("[Pi Desk][GlobalPluginRuntime] Pi Desk Plugin 生命周期执行失败",{source:a.owner.source,packageName:a.owner.packageName,phase:a.phase,timeoutMs:1500,message:p(b)})}finally{b&&clearTimeout(b)}}class y{constructor(a,b){this.packageProvider=a,this.hostSettings=b,this.methods=new Map,this.pluginOwners=new Map,this.browserEntries=new Map,this.declarations=new Map,this.capabilityLoaders=new Map,this.owners=[],this.loadingOwners=new Set,this.changeListeners=new Set,this.changingSources=new Set,this.maintainingSources=new Set,this.lifetime=new AbortController,this.packageDiagnostics=new Map,this.initializePromise=null,this.initialized=!1,this.disposed=!1,this.acceptingCalls=!0,this.loadError=null,this.workSessionProvider=null,this.pushSender=null,this.appRuntimeSink=null}initialize(){return this.disposed?Promise.reject(Error("Global plugin runtime has been disposed")):this.initialized?Promise.resolve():(this.initializePromise||(this.initializePromise=this.loadConfiguredPackages().catch(a=>{this.loadError=p(a),console.error("[Pi Desk][GlobalPluginRuntime] 读取插件配置失败,核心应用继续启动",{errorName:a instanceof Error?a.name:"UnknownError",message:this.loadError})}).finally(()=>{this.initializePromise=null,this.initialized=!0,this.publishChanges()})),this.initializePromise)}subscribeChanges(a){return this.changeListeners.add(a),()=>this.changeListeners.delete(a)}publishChanges(){if(!this.disposed)for(let a of this.changeListeners)try{a()}catch(a){console.warn("[Pi Desk][GlobalPluginRuntime] 状态监听失败",{message:p(a)})}}async withSourceIdle(a,b,c,d){let e,g=AbortSignal.any([c,this.lifetime.signal]);g.throwIfAborted();let h=new Promise((a,b)=>{e=()=>b(g.reason),g.addEventListener("abort",e,{once:!0})});try{await Promise.race([this.initialize(),h])}finally{g.removeEventListener("abort",e)}if(g.throwIfAborted(),!this.acceptingCalls||this.changingSources.has(a)||this.maintainingSources.has(a))throw new w;this.maintainingSources.add(a);try{for(;this.owners.some(b=>b.source===a&&b.activeCalls.size>0);)d(`插件 ${a} 仍有调用正在执行`),await (0,f.setTimeout)(250,void 0,{signal:g});return g.throwIfAborted(),await b()}finally{this.maintainingSources.delete(a)}}async replaceSource(a,b){if(await this.initialize(),this.disposed||!this.acceptingCalls||this.changingSources.has(a))throw new w;let c=this.owners.find(b=>b.source===a);this.changingSources.add(a);try{if(c&&this.releaseOwner(c),this.disposed)throw Error("Global plugin runtime has been disposed");if((0,k.N)(),this.packageDiagnostics.delete(a),null!==b){if(await this.loadPackage(a,b),this.disposed)throw Error("Global plugin runtime has been disposed");let c=this.packageDiagnostics.get(a);if(c?.status==="failed")throw Error(c.error?.message??"插件加载失败")}}finally{this.changingSources.delete(a),this.publishChanges()}}ownerPublished(a){return a.active&&!a.draining&&!this.changingSources.has(a.source)&&this.owners.includes(a)}readDiagnostics(){return{packages:[...this.packageDiagnostics.values()].sort((a,b)=>a.source.localeCompare(b.source)).map(a=>structuredClone(a)),loadError:this.loadError}}readCapabilityRegistrations(){return[...this.owners].filter(a=>this.ownerPublished(a)).sort((a,b)=>a.source.localeCompare(b.source)).map(a=>({source:a.source,methods:[...this.methods.values()].filter(b=>b.owner===a).sort((a,b)=>{let c=a.pluginName.localeCompare(b.pluginName);return 0===c?a.method.localeCompare(b.method):c}).map(({pluginName:a,method:b})=>({pluginName:a,method:b})),browserEntries:[...this.browserEntries.values()].filter(b=>b.owner===a).sort((a,b)=>a.pluginName.localeCompare(b.pluginName)).map(({pluginName:a})=>({pluginName:a})),messageDeclarations:[...this.declarations.values()].filter(b=>b.owner===a).sort((a,b)=>{let c=a.pluginName.localeCompare(b.pluginName);return 0===c?a.declarationName.localeCompare(b.declarationName):c}).map(({pluginName:a,declarationName:b,declaration:c})=>({pluginName:a,declarationName:b,priority:c.priority}))}))}async prepareReload(){if(await this.initialize(),this.disposed)throw Error("Global plugin runtime has been disposed");if(!this.acceptingCalls||this.changingSources.size>0||this.maintainingSources.size>0||this.owners.some(a=>a.activeCalls.size>0))throw new w;for(let a of(this.acceptingCalls=!1,this.owners))a.draining=!0;await Promise.all([...this.owners].reverse().map(async a=>{let b=a.beforeReload;if(!b)return;a.beforeReload=null;let c=new AbortController;await q({owner:a,phase:"beforeReload",execute:()=>b({signal:c.signal}),onTimeout:()=>c.abort()})}))}bindWorkSessionProvider(a){if(this.disposed)throw Error("Global plugin runtime has been disposed");return this.workSessionProvider=a,()=>{this.workSessionProvider===a&&(this.workSessionProvider=null)}}bindPushSender(a){if(this.disposed)throw Error("Global plugin runtime has been disposed");return this.pushSender=a,()=>{this.pushSender===a&&(this.pushSender=null)}}bindAppRuntimeSink(a){if(this.disposed)throw Error("Global plugin runtime has been disposed");return this.appRuntimeSink=a,()=>{this.appRuntimeSink===a&&(this.appRuntimeSink=null)}}async runOwnedCall(a,b){let c;if(this.ensureOwnerActive(a),this.maintainingSources.has(a.source))throw new w;let d=new AbortController,e=new Promise((a,b)=>{c=b}),f=()=>{c(Error("Pi Desk Plugin owner is no longer active"))};d.signal.addEventListener("abort",f,{once:!0}),a.activeCalls.add(d);try{let c=await Promise.race([Promise.resolve().then(()=>(this.ensureOwnerActive(a),b(d.signal))),e]);return this.ensureOwnerActive(a),c}finally{a.activeCalls.delete(d),d.signal.removeEventListener("abort",f)}}async invoke(a,b,c){if(await this.initialize(),this.disposed)throw Error("Global plugin runtime has been disposed");if(!this.acceptingCalls)throw new w;let d=(0,m.FX)(a),e=(0,m.QK)(b),f=this.methods.get((0,m.$m)(d,e));if(!f)throw new m.Tk(d,e);if(!this.ownerPublished(f.owner)||this.changingSources.has(f.owner.source))throw new w;let g=(0,m.nJ)(c,"input");return this.runOwnedCall(f.owner,async a=>{let b=await f.execute(g,{signal:a});return(0,m.nJ)(b,"output")})}async listCapabilityDeclarations(){if(await this.initialize(),this.disposed||!this.acceptingCalls)throw new w;let a=await Promise.all([...this.capabilityLoaders].filter(([,a])=>this.ownerPublished(a.owner)&&!this.changingSources.has(a.owner.source)).map(async([a,b])=>{try{return await this.runOwnedCall(b.owner,async c=>{let d=await b.load({signal:c});if(this.capabilityLoaders.get(a)!==b)throw Error(`能力声明已被替换:${a}`);return[a,j.dO.parse(d)]})}catch(b){throw Error(`读取 ${a} 能力选项失败:${p(b)}`,{cause:b})}}));return Object.fromEntries(a)}async listBrowserEntries(){return await this.initialize(),[...this.browserEntries.values()].filter(a=>this.ownerPublished(a.owner)).sort((a,b)=>a.pluginName.localeCompare(b.pluginName)).flatMap(({pluginName:a,entryPath:b,resourceKey:c,snapshot:d})=>d?[{pluginName:a,entryPath:b,resourceKey:c,snapshot:d}]:[])}async listMessageDeclarations(){return await this.initialize(),this.readMessageDeclarations()}readMessageDeclarations(){return[...this.declarations.values()].filter(a=>this.ownerPublished(a.owner)).sort((a,b)=>{let c=a.pluginName.localeCompare(b.pluginName);return 0===c?a.declarationName.localeCompare(b.declarationName):c}).map(({pluginName:a,declarationName:b,declaration:c})=>({pluginName:a,declarationName:b,declaration:c}))}async dispose(){if(this.disposed)return;this.disposed=!0,this.lifetime.abort(),this.acceptingCalls=!1,this.changeListeners.clear(),this.workSessionProvider=null,this.pushSender=null;let a=[...new Set([...this.owners,...this.loadingOwners])].reverse();this.owners.length=0,this.loadingOwners.clear(),await Promise.all(a.map(a=>this.releaseOwner(a))),this.methods.clear(),this.pluginOwners.clear(),this.browserEntries.clear(),this.declarations.clear(),this.capabilityLoaders.clear(),this.appRuntimeSink=null}async loadConfiguredPackages(){for(let a of(this.loadError=null,this.packageDiagnostics.clear(),await this.packageProvider())){if(this.disposed)return;await this.loadPackage(a.source,a.installedPath)}}async loadOwnerWithinDeadline(a,b,c){let d,e=(async()=>{void 0!==b?await this.loadEntryOwner(a,b):await this.loadLegacyOwner(a,c);try{await this.validateOwnerResources(a)}catch(a){throw new x("resources",a)}this.ensureOwnerActive(a)})();try{await Promise.race([e,new Promise((a,b)=>{d=setTimeout(()=>{b(new x("setup",Error("插件初始化超时,已放弃加载")))},15e3)})])}finally{d&&clearTimeout(d)}}async loadPackage(a,b){let c,d=performance.now(),e=(0,h.resolve)(b);try{let a=(0,h.join)(e,"package.json");c=JSON.parse(await (0,g.readFile)(a,"utf8"))}catch(b){this.packageDiagnostics.set(a,{source:a,packageName:null,version:null,pluginName:null,status:"failed",error:{phase:"package",message:p(b)}});return}let f=c.piDesk?.entry,i=c.piDesk?.global;if(void 0===f&&void 0===i||this.disposed)return;let j={source:a,packageName:"string"==typeof c.name?c.name:null,version:"string"==typeof c.version?c.version:null,packageRoot:e,active:!0,draining:!1,pluginNames:new Set,activeCalls:new Set,subscriptions:new Set,beforeReload:null,disposer:null};console.info("[Pi Desk][GlobalPluginRuntime] 开始加载 Pi Desk Plugin",{source:a,packageName:j.packageName}),this.loadingOwners.add(j);try{await this.loadOwnerWithinDeadline(j,f,i),this.owners.push(j),this.recordOwnerDiagnostic(j),console.info("[Pi Desk][GlobalPluginRuntime] Pi Desk Plugin 已加载",{source:a,packageName:j.packageName,pluginNames:[...j.pluginNames],methodCount:[...this.methods.values()].filter(a=>a.owner===j).length,browserEntryCount:[...this.browserEntries.values()].filter(a=>a.owner===j).length,declarationCount:[...this.declarations.values()].filter(a=>a.owner===j).length,durationMs:Math.round(performance.now()-d)})}catch(f){let b=f instanceof x?f.phase:"entry",c=[...j.pluginNames][0]??null;await this.releaseOwner(j);let e=p(f);this.packageDiagnostics.set(a,{source:a,packageName:j.packageName,version:j.version,pluginName:c,status:"failed",error:{phase:b,message:e}}),console.warn("[Pi Desk][GlobalPluginRuntime] Pi Desk Plugin 加载失败",{source:a,packageName:j.packageName,phase:b,errorName:f instanceof Error?f.name:"UnknownError",message:e,durationMs:Math.round(performance.now()-d)})}finally{this.loadingOwners.delete(j)}}async loadEntryOwner(a,b){let c=o(a.packageRoot,b,"piDesk.entry");if(!(await (0,g.stat)(c)).isFile())throw Error("Pi Desk Plugin entry is not a file");let d=(await (0,k.G)(c,a.packageRoot)).default;if(!d||"object"!=typeof d||"string"!=typeof d.name||"function"!=typeof d.setup)throw Error("Pi Desk Plugin entry must default-export definePiDeskPlugin(...)");let e=(0,m.FX)(d.name);this.claimPluginName(a,e);try{let b=function(a){if(void 0===a)return{beforeReload:null,disposer:null};if("function"==typeof a)return{beforeReload:null,disposer:a};if(!a||"object"!=typeof a)throw Error("Pi Desk Plugin setup must return void, a disposer, or a lifecycle object");if(void 0!==a.beforeReload&&"function"!=typeof a.beforeReload)throw Error("Pi Desk Plugin lifecycle.beforeReload must be a function");if(void 0!==a.dispose&&"function"!=typeof a.dispose)throw Error("Pi Desk Plugin lifecycle.dispose must be a function");return{beforeReload:a.beforeReload??null,disposer:a.dispose??null}}(await d.setup(this.createPiDeskFacade(a,e,a.packageRoot)));if(a.beforeReload=b.beforeReload,a.disposer=b.disposer,!a.active||this.disposed)throw await this.releaseOwner(a),Error("插件初始化完成时 Owner 已失效")}catch(a){throw new x("setup",a)}}async loadLegacyOwner(a,b){let c=o(a.packageRoot,b,"piDesk.global");if(!(await (0,g.stat)(c)).isFile())throw Error("Global Plugin entry is not a file");let d=await (0,k.G)(c,a.packageRoot);if("function"!=typeof d.default)throw Error("Global Plugin entry must default-export a factory function");let e=d.default;try{let b=await e(this.createLegacyApi(a));if(void 0!==b&&"function"!=typeof b)throw Error("Global Plugin factory must return void or a disposer function");if(a.disposer=b??null,!a.active||this.disposed)throw await this.releaseOwner(a),Error("插件初始化完成时 Owner 已失效")}catch(a){throw new x("setup",a)}}claimPluginName(a,b){this.ensureOwnerActive(a);let c=this.pluginOwners.get(b);if(c&&c!==a)throw Error(`Pi Desk pluginName is already registered: ${b}`);this.pluginOwners.set(b,a),a.pluginNames.add(b)}createLegacyApi(a){return{bindPlugin:b=>{let c=(0,m.FX)(b);return this.claimPluginName(a,c),{name:c,registerMethod:(b,d)=>this.registerMethod(a,c,b,d)}}}}createPiDeskFacade(a,b,c){return{name:b,host:{settings:{getSnapshot:()=>{if(this.ensureOwnerActive(a),!this.hostSettings)throw Error("宿主共享设置尚未就绪");return this.hostSettings.getSnapshot()},subscribe:b=>{if(this.ensureOwnerActive(a),!this.hostSettings)throw Error("宿主共享设置尚未就绪");let c=this.hostSettings.subscribe(()=>{a.active&&!a.draining&&b()});return a.subscriptions.add(c),()=>{if(a.subscriptions.delete(c))return c()}}},workSessions:{listWorkSessions:async()=>{this.ensureOwnerActive(a);let b=await this.readWorkSessions();return this.ensureOwnerActive(a),b}}},notifications:{publish:c=>(this.ensureOwnerActive(a),this.requireAppRuntimeSink().publishNotification(b,c)),update:(c,d)=>{this.ensureOwnerActive(a),this.requireAppRuntimeSink().updateNotification(b,c,d)},delete:c=>{this.ensureOwnerActive(a),this.requireAppRuntimeSink().deleteNotification(b,c)}},setState:c=>{this.ensureOwnerActive(a),this.requireAppRuntimeSink().setState(b,c)},registerMethod:(c,d)=>this.registerMethod(a,b,c,d),registerBrowserEntry:d=>{if(this.ensureOwnerActive(a),this.browserEntries.has(b))throw Error(`Browser Entry is already registered: ${b}`);let f=o(c,d,"browserEntry"),g={pluginName:b,entryPath:f,resourceKey:(0,e.randomUUID)(),snapshot:null,owner:a};return this.browserEntries.set(b,g),this.registrationDisposer(a,()=>{this.browserEntries.get(b)===g&&this.browserEntries.delete(b)})},declareCapabilities:c=>{if(this.ensureOwnerActive(a),"function"!=typeof c)throw Error("能力声明必须是按需查询函数");if(this.capabilityLoaders.has(b))throw Error(`能力声明已注册:${b}`);let d={load:c,owner:a};return this.capabilityLoaders.set(b,d),this.registrationDisposer(a,()=>{this.capabilityLoaders.get(b)===d&&this.capabilityLoaders.delete(b)})},declareMessage:(c,d)=>this.registerDeclaration(a,b,c,d),pushGlobal:(c,d)=>{a.active&&!a.draining&&this.sendPush(b,{scope:"global"},c,d)},pushSession:(c,d,e)=>{a.active&&!a.draining&&this.sendPush(b,{scope:"session",source:s.parse(c)},d,e)}}}registerMethod(a,b,c,d){this.ensureOwnerActive(a);let e=(0,m.QK)(c),f=(0,m.$m)(b,e);if(this.methods.has(f))throw new m.qs(b,e);let g={pluginName:b,method:e,execute:d,owner:a};return this.methods.set(f,g),this.registrationDisposer(a,()=>{this.methods.get(f)===g&&this.methods.delete(f)})}registerDeclaration(a,b,c,d){var e;this.ensureOwnerActive(a);let f=u.parse(c);if(!d||"object"!=typeof d||"function"!=typeof d.match||"function"!=typeof d.project)throw Error("Message Declaration must provide match and project functions");let g={priority:(e=d.priority,v.parse(e)),match:d.match,project:d.project},h=`${b}\u0000${f}`;if(this.declarations.has(h))throw Error(`Message Declaration is already registered: ${b}/${f}`);let i={pluginName:b,declarationName:f,declaration:g,owner:a};return this.declarations.set(h,i),this.registrationDisposer(a,()=>{this.declarations.get(h)===i&&this.declarations.delete(h)})}registrationDisposer(a,b){let c=!0;return()=>{c&&(c=!1,a.active&&b())}}requireAppRuntimeSink(){if(!this.appRuntimeSink)throw Error("App Runtime sink has not been bound");return this.appRuntimeSink}sendPush(a,b,c,d){if(this.disposed)return;let e=(0,m.QK)(c),f=function(a){let b=r.parse(a);if(Buffer.byteLength(JSON.stringify(b),"utf8")>65536)throw Error("Plugin Push data exceeds 64KB");return b}(d);this.pushSender?.({pluginName:a,target:b,event:e,data:structuredClone(f)})}async readWorkSessions(){if(!this.workSessionProvider||this.disposed)return[];let a=await this.workSessionProvider();return i.YO(t).parse(a).map(a=>structuredClone(a))}async validateOwnerResources(a){for(let b of[...this.browserEntries.values()].filter(b=>b.owner===a)){if(!(await (0,g.stat)(b.entryPath)).isFile())throw Error("Browser Entry resource is not a file");if("entry.js"!==(0,h.basename)(b.entryPath))throw Error("Browser Entry resource file must be named entry.js");let c=await (0,l.f)(b.entryPath);if(this.ensureOwnerActive(a),[...this.browserEntries.values()].reduce((a,b)=>a+(b.snapshot?.size??0),0)+c.size>0x8000000)throw Error("Browser 模块快照总量超过128MB,拒绝加载此插件");b.snapshot=c}}recordOwnerDiagnostic(a){this.packageDiagnostics.set(a.source,{source:a.source,packageName:a.packageName,version:a.version,pluginName:[...a.pluginNames][0]??null,status:"ready",error:null})}ensureOwnerActive(a){if(!a.active||a.draining||this.disposed)throw Error("Pi Desk Plugin owner is no longer active")}async releaseOwner(a){let b=[...a.subscriptions];if(a.subscriptions.clear(),a.active){for(let b of(a.active=!1,a.activeCalls))b.abort();a.activeCalls.clear();let b=this.owners.indexOf(a);for(let[c,d]of(b>=0&&this.owners.splice(b,1),this.methods))d.owner===a&&this.methods.delete(c);for(let[b,c]of this.browserEntries)c.owner===a&&this.browserEntries.delete(b);for(let[b,c]of this.declarations)c.owner===a&&this.declarations.delete(b);for(let[b,c]of this.capabilityLoaders)c.owner===a&&this.capabilityLoaders.delete(b);for(let b of a.pluginNames)if(this.pluginOwners.get(b)===a){this.pluginOwners.delete(b);try{this.appRuntimeSink?.releasePlugin(b)}catch(a){console.warn("[Pi Desk][GlobalPluginRuntime] 清理插件 App Runtime 失败",{pluginName:b,errorName:a instanceof Error?a.name:"UnknownError",message:p(a)})}}a.pluginNames.clear()}let c=a.beforeReload,d=a.disposer;a.beforeReload=null,a.disposer=null;let e=new AbortController;await Promise.all([...b.map(b=>q({owner:a,phase:"dispose",execute:b})),c?q({owner:a,phase:"beforeReload",execute:()=>c({signal:e.signal}),onTimeout:()=>e.abort()}):Promise.resolve(),d?q({owner:a,phase:"dispose",execute:d}):Promise.resolve()])}}d()}catch(a){d(a)}})}};
|
|
@@ -1,78 +1,9 @@
|
|
|
1
|
-
"use strict";exports.id=47757,exports.ids=[47757],exports.modules={16056:(a,b,c)=>{c.d(b,{P:()=>e});let d=process.argv.includes("--safe-mode")||"1"===process.env.PI_DESK_SAFE_MODE;function e(){return d}},17691:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{M:()=>j});var e=c(77598),f=c(73024),g=c(76760),h=c(75430),i=a([h]);function j(){let a=(0,h.getAgentDir)(),b=(0,g.join)(a,"pi-desk"),c=(0,g.join)(a,"pi-super");if((0,f.existsSync)(b)||!(0,f.existsSync)(c))return b;let d=(0,g.join)(a,`.pi-desk-migration-${(0,e.randomUUID)()}`);try{(0,f.cpSync)(c,d,{recursive:!0,errorOnExist:!0,force:!1}),(0,f.renameSync)(d,b),console.info("[Pi Desk] 已复制旧版应用数据到新目录")}finally{(0,f.rmSync)(d,{recursive:!0,force:!0})}return b}h=(i.then?(await i)():i)[0],d()}catch(a){d(a)}})},47757:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.r(b),c.d(b,{createL4PiDeskTool:()=>s,disposeL4PiDeskCommands:()=>p,executeL4PiDeskCommand:()=>r,initializeL4PiDeskCommands:()=>o
|
|
2
|
-
…结果过长,已截断。`:d.message};return{content:[{type:"text",text:JSON.stringify(f)}],details:f}}}):null}d()}catch(a){d(a)}})},55574:(a,b,c)=>{c.d(b,{h:()=>g});let d=[{path:["--version"],description:"查看 Pi Desk 版本"},{path:["info"],description:"查看当前宿主环境与目录"},{path:["session","reload"],description:"等待当前会话空闲后重载 Pi 配置与已安装插件;完成后通知并唤醒本会话"},{path:["plugins","list"],description:"查看全局插件及维护状态;可按跟随渠道筛选并检查更新,不改变渠道",scope:"optional",tag:!0,checkUpdates:!0},{path:["plugins","show"],description:"查看插件详情",name:"single",scope:"required"},{path:["plugins","install"],description:"安装、更新或重新安装一个或多个插件;版本可省略,完成后向本会话汇总结果",name:"multiple",scope:"required",version:!0,tag:!0},{path:["plugins","remove"],description:"卸载一个或多个包来源;完成后向本会话汇总结果",name:"multiple",scope:"required"}];function e(a){return["pidesk",...a.path,...a.name?["multiple"===a.name?"<name...>":"<name>"]:[],..."required"===a.scope?["--scope global"]:a.scope?["[--scope global]"]:[],...a.checkUpdates?["[--check-updates]"]:[],...a.version?["[--tag <tag> | --version <exact>]"]:a.tag?["[--tag <tag>]"]:[]].join(" ")}function f(a){let b=d.filter(b=>a.every((a,c)=>b.path[c]===a));if(0===b.length)throw Error("未知命令,请使用 pidesk --help");return[...b.map(a=>`${e(a)}
|
|
1
|
+
"use strict";exports.id=47757,exports.ids=[47757],exports.modules={16056:(a,b,c)=>{c.d(b,{P:()=>e});let d=process.argv.includes("--safe-mode")||"1"===process.env.PI_DESK_SAFE_MODE;function e(){return d}},17691:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{M:()=>j});var e=c(77598),f=c(73024),g=c(76760),h=c(75430),i=a([h]);function j(){let a=(0,h.getAgentDir)(),b=(0,g.join)(a,"pi-desk"),c=(0,g.join)(a,"pi-super");if((0,f.existsSync)(b)||!(0,f.existsSync)(c))return b;let d=(0,g.join)(a,`.pi-desk-migration-${(0,e.randomUUID)()}`);try{(0,f.cpSync)(c,d,{recursive:!0,errorOnExist:!0,force:!1}),(0,f.renameSync)(d,b),console.info("[Pi Desk] 已复制旧版应用数据到新目录")}finally{(0,f.rmSync)(d,{recursive:!0,force:!0})}return b}h=(i.then?(await i)():i)[0],d()}catch(a){d(a)}})},47757:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.r(b),c.d(b,{appendL4PiDeskSystemPrompt:()=>q,createL4PiDeskTool:()=>s,disposeL4PiDeskCommands:()=>p,executeL4PiDeskCommand:()=>r,initializeL4PiDeskCommands:()=>o});var e=c(51455),f=c(76760),g=c(75430),h=c(60815),i=c(17691),j=c(16056),k=c(55574),l=c(77167),m=a([g,h,i]);function n(a){return a.replaceAll("\\","/")}async function o(a,b=!1){let c=(0,g.getAgentDir)(),d=process.cwd(),h=JSON.parse(await (0,e.readFile)((0,f.join)(d,"package.json"),"utf8"));if(!h||"object"!=typeof h||!("version"in h)||"string"!=typeof h.version)throw Error("Pi Desk package.json 缺少版本号");let{createRequire:j}=process.getBuiltinModule("module"),k=(0,f.dirname)((0,f.dirname)(j((0,f.join)(d,"package.json")).resolve("@jetcrab/pi-desk-sdk"))),m=(0,f.join)(d,"docs","pi-desk");await Promise.all(["README.md","commands.md","plugins.md"].map(a=>(0,e.access)((0,f.join)(m,a)))),await (0,e.rm)((0,f.join)((0,i.M)(),b?"dev-skills":"skills","pi-desk"),{recursive:!0,force:!0});let p={handler:a,docsDirectory:m,systemPrompt:(0,l.O)({docsDirectory:n(m),sdkRoot:n(k)}),version:h.version,development:b,agentDir:c};globalThis.__piDeskCommandRuntime=p,console.info("[Pi Desk][Commands] 命令入口与系统资料导航已准备完成",{docsDirectory:m})}function p(){globalThis.__piDeskCommandRuntime=void 0}function q(a=[]){let b=globalThis.__piDeskCommandRuntime?.systemPrompt;return b?[...a,b]:[...a]}async function r(a,b){let c=globalThis.__piDeskCommandRuntime;if(!c)throw Error("Pi Desk 命令入口尚未准备完成");b.signal.throwIfAborted();let d=(0,k.h)(a);if("help"===d.kind)return{mode:"sync",message:d.message};if("version"===d.kind)return{mode:"sync",message:c.version};if("info"===d.kind)return{mode:"sync",message:JSON.stringify({version:c.version,environment:c.development?"development":"production",mode:(0,j.P)()?"basic":"normal",cwd:b.cwd,agentDir:c.agentDir,docsDirectory:c.docsDirectory})};if("session"===d.kind)return b.reload();if("plugins"!==d.kind)throw Error("Pi Desk 命令无效");return c.handler(d,b)}[g,h,i]=m.then?(await m)():m;let t=h.Type.Object({args:h.Type.Array(h.Type.String({minLength:1,maxLength:2048}),{maxItems:32})},{additionalProperties:!1});function s(a){return globalThis.__piDeskCommandRuntime?(0,g.defineTool)({name:"pidesk",exposure:"model-only",label:"Pi Desk",description:"Pi Desk 命令入口。",parameters:t,async execute(b,c){let d=await a(c.args,b),e=(0,g.truncateHead)(d.message),f={mode:d.mode,message:e.truncated?`${e.content}
|
|
2
|
+
…结果过长,已截断。`:d.message};return{content:[{type:"text",text:JSON.stringify(f)}],details:f}}}):null}d()}catch(a){d(a)}})},55574:(a,b,c)=>{c.d(b,{h:()=>g});let d=[{path:["--version"],description:"查看 Pi Desk 版本"},{path:["info"],description:"查看当前宿主环境与目录"},{path:["session","reload"],description:"等待当前会话空闲后重载 Pi 配置与已安装插件;完成后通知并唤醒本会话"},{path:["plugins","list"],description:"查看全局插件及维护状态;可按跟随渠道筛选并检查更新,不改变渠道",scope:"optional",tag:!0,checkUpdates:!0},{path:["plugins","show"],description:"查看插件详情",name:"single",scope:"required"},{path:["plugins","install"],description:"安装、更新或重新安装一个或多个插件;版本可省略,完成后向本会话汇总结果",name:"multiple",scope:"required",version:!0,tag:!0},{path:["plugins","reload"],description:"重新加载一个或多个已安装插件;不下载、不重启宿主,不重载已有 Pi 会话;完成后向本会话汇总结果",name:"multiple",scope:"required"},{path:["plugins","remove"],description:"卸载一个或多个包来源;完成后向本会话汇总结果",name:"multiple",scope:"required"}];function e(a){return["pidesk",...a.path,...a.name?["multiple"===a.name?"<name...>":"<name>"]:[],..."required"===a.scope?["--scope global"]:a.scope?["[--scope global]"]:[],...a.checkUpdates?["[--check-updates]"]:[],...a.version?["[--tag <tag> | --version <exact>]"]:a.tag?["[--tag <tag>]"]:[]].join(" ")}function f(a){let b=d.filter(b=>a.every((a,c)=>b.path[c]===a));if(0===b.length)throw Error("未知命令,请使用 pidesk --help");return[...b.map(a=>`${e(a)}
|
|
3
3
|
${a.description}`),"各级命令均支持 --help。当前插件管理只支持 global 范围。",..."plugins"===a[0]&&(1===a.length||"install"===a[1])?["install = install + update + reinstall。版本和渠道均可省略:新 npm 插件默认 latest,已有插件沿保存的渠道;--tag 选择跟随渠道,--version 固定完整版本号,两者互斥。","多个插件可共用同一渠道或具体版本;同版本仍重新安装。","本地扩展使用 Pi 全局 extensions 目录中的名字,加载当前代码;不接受版本、渠道或自定义路径。","异步接纳不代表生效;结果会插入本会话并唤醒模型,无需持续查询。"]:[]].join("\n\n")}function g(a){let b,c,g,h;if(a.length>32)throw Error("命令参数最多 32 项");if(0===a.length)return{kind:"help",message:f([])};let i=d.find(b=>b.path.every((b,c)=>a[c]===b));if(a.includes("--help")||a.includes("-h")||1===a.length&&["plugins","session"].includes(a[0])){let b=["plugins","session"].includes(a[0])?a[0]:null,c=i?.path??(b?[b]:[]);if(!i&&!b&&!["--help","-h"].includes(a[0]))throw Error("未知命令,请使用 pidesk --help");if(!i&&b&&a[1]&&!["--help","-h"].includes(a[1]))throw Error(`未知子命令,请使用 pidesk ${b} --help`);return{kind:"help",message:f(c)}}if(!i)throw Error("未知命令,请使用 pidesk --help");let j=[];for(let d=i.path.length;d<a.length;d+=1){let f=a[d];if("--scope"===f&&i.scope){if(void 0!==b)throw Error("--scope 不允许重复");if(!(b=a[++d])||b.startsWith("--"))throw Error("--scope 缺少范围")}else if("--version"===f&&i.version){if(void 0!==c)throw Error("--version 不允许重复");if(!(c=a[++d])||c.startsWith("--"))throw Error("--version 缺少版本号")}else if("--tag"===f&&i.tag){if(void 0!==g)throw Error("--tag 不允许重复");if(!(g=a[++d])||g.startsWith("--"))throw Error("--tag 缺少渠道标签")}else if("--check-updates"===f&&i.checkUpdates){if(void 0!==h)throw Error("--check-updates 不允许重复");h=!0}else if(i.name&&("multiple"===i.name||0===j.length)&&!f.startsWith("-"))j.push(f);else throw Error(`不支持的参数:${f}
|
|
4
4
|
${e(i)}`)}if("required"===i.scope&&void 0===b)throw Error(`必须指定 --scope global
|
|
5
5
|
${e(i)}`);if(void 0!==b&&"global"!==b)throw Error("当前插件管理只支持 global 范围,不支持项目级操作");if(i.name){if(0===j.length)throw Error(`缺少插件名字
|
|
6
|
-
${e(i)}`);for(let a of j)if(!/^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/.test(a)||"node_modules"===a)throw Error(`插件名字必须是扩展名字或完整 npm 包名,不接受路径或内嵌版本号:${a}`)}if(void 0!==c&&!/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/.test(c))throw Error("--version 必须是完整版本号,例如 1.2.3;版本可省略");if(void 0!==g&&(g.length>128||!/^[a-zA-Z][a-zA-Z0-9._-]*$/.test(g)))throw Error("--tag 必须是有效的渠道标签,例如 latest 或 dev");if(void 0!==g&&void 0!==c)throw Error("--tag 与 --version 互斥,不能同时指定");return"--version"===i.path[0]?{kind:"version"}:"info"===i.path[0]?{kind:"info"}:"session"===i.path[0]?{kind:"session",action:"reload"}:{kind:"plugins",action:i.path[1],...1===j.length?{name:j[0]}:j.length>1?{names:j}:{},...void 0===c?{}:{version:c},...void 0===g?{}:{tag:g},...void 0===h?{}:{checkUpdates:h}}}},
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
# Pi Desk
|
|
12
|
-
|
|
13
|
-
通过 \`pidesk\` 工具执行宿主命令,参数为 \`{ "args": ["命令", "子命令", "参数"] }\`。当前命令以 \`["--help"]\` 为准,具体命令也支持 \`--help\`。
|
|
14
|
-
|
|
15
|
-
- 插件开发、安装、更新或卸载:先阅读 [插件管理](references/plugins.md)。
|
|
16
|
-
- 开发 Pi Desk 插件:阅读 ${a.sdkRoot}/README.md 和当前版本的公开类型声明;涉及界面时,先向用户取得对应版本的 UI 标准及分册,并完整阅读。
|
|
17
|
-
- 原生 Pi 扩展:阅读 ${a.piDocs}/extensions.md。
|
|
18
|
-
|
|
19
|
-
## 执行结果
|
|
20
|
-
|
|
21
|
-
- \`mode: sync\`:本次执行已经结束,直接使用返回结果。
|
|
22
|
-
- \`mode: async\`:本次操作已接纳,尚未完成。宿主会向本会话插入最终结果并唤醒模型;无独立工作时结束当前轮,不持续查询或重复提交。
|
|
23
|
-
- 工具报错表示请求失败;不能把已接纳、等待加载或等待重启说成已生效。
|
|
24
|
-
|
|
25
|
-
## 重载当前会话
|
|
26
|
-
|
|
27
|
-
调用 \`{ "args": ["session", "reload"] }\`,等同输入框“更多 → 重载 Pi 配置”。保留聊天历史与当前分支,重新加载 Pi 配置、Skills 和本机已安装插件的当前代码;不会自动下载插件新版本,需要更新时先使用插件安装命令。
|
|
28
|
-
|
|
29
|
-
接纳后结束本轮对话,等待宿主在当前会话完全空闲后执行;最终结果会通知并唤醒本会话。重载可能重建插件内存状态、使缓存失效;配置或工具定义变化也可能影响模型的提示词缓存命中。
|
|
30
|
-
|
|
31
|
-
## 当前目录
|
|
32
|
-
|
|
33
|
-
Pi AgentDir:${a.agentDir}
|
|
34
|
-
全局本地扩展:${a.agentDir}/extensions
|
|
35
|
-
|
|
36
|
-
这些文件由当前宿主启动时生成;修改指引应修改宿主源码中的模板。
|
|
37
|
-
`}function e(a){return`# 插件管理
|
|
38
|
-
|
|
39
|
-
通过 \`pidesk\` 的 \`plugins\` 子命令复用设置中的插件管理。当前只支持全局范围;项目级管理与裸扩展卸载不在当前能力中。
|
|
40
|
-
|
|
41
|
-
| 任务 | args |
|
|
42
|
-
| --- | --- |
|
|
43
|
-
| 查询清单与状态 | \`["plugins", "list"]\` |
|
|
44
|
-
| 批量检查更新 | \`["plugins", "list", "--check-updates"]\` |
|
|
45
|
-
| 只检查跟随 dev 的插件 | \`["plugins", "list", "--check-updates", "--tag", "dev"]\` |
|
|
46
|
-
| 查询插件详情 | \`["plugins", "show", "<name>", "--scope", "global"]\` |
|
|
47
|
-
| 安装、更新或重装 | \`["plugins", "install", "<name>", "--scope", "global"]\` |
|
|
48
|
-
| 批量安装或更新 | \`["plugins", "install", "<name-1>", "<name-2>", "--scope", "global"]\` |
|
|
49
|
-
| 安装并跟随 dev 渠道 | \`["plugins", "install", "<name>", "--scope", "global", "--tag", "dev"]\` |
|
|
50
|
-
| 安装指定 npm 版本 | \`["plugins", "install", "<name>", "--scope", "global", "--version", "1.2.3"]\` |
|
|
51
|
-
| 批量卸载包来源 | \`["plugins", "remove", "<name-1>", "<name-2>", "--scope", "global"]\` |
|
|
52
|
-
|
|
53
|
-
\`install/remove\` 可传一个或多个名字;批量安装共用所选标签或版本。不指定版本或标签也可以安装。
|
|
54
|
-
|
|
55
|
-
## 本地开发
|
|
56
|
-
|
|
57
|
-
源码放在 ${a}/extensions/<name>/,使用插件清单或固定目录中的名字,不传自定义路径。单文件扩展也可使用清单中的名字。
|
|
58
|
-
|
|
59
|
-
开发完成后验证代码并调用 \`install\`,修改后仍调用 \`install\` 重新加载当前代码。原生 TypeScript 可直接加载;存在浏览器构建入口时先完成必要编译,不要求发布 npm 或生成安装包。本地来源不接受 \`--version\` 或 \`--tag\`。
|
|
60
|
-
|
|
61
|
-
## npm 插件
|
|
62
|
-
|
|
63
|
-
使用完整 npm 包名,例如 \`@example/plugin\`。\`install\` 统一表示首次安装、更新和重新安装;已是目标版本也执行重装。
|
|
64
|
-
|
|
65
|
-
版本和标签均可省略:新插件默认 \`latest\`,已有插件沿保存的更新渠道。\`--tag dev\` 安装该标签指向的版本并保存后续跟随渠道;\`--version\` 只指定本次完整版本,不改变已有渠道。两者不能同时使用,不从版本后缀猜测更新渠道。
|
|
66
|
-
|
|
67
|
-
\`list --check-updates\` 按各插件自己的渠道检查;附加 \`--tag dev\` 只检查跟随 dev 的插件,不修改渠道、不执行安装。缺少标签或查询失败仅报告对应项错误,不回退 latest。需要只调整渠道、不安装时,在插件管理界面多选后使用“设置渠道”。
|
|
68
|
-
|
|
69
|
-
插件文件与 \`settings.json\` 由 Pi 官方包管理器维护。不要直接覆盖配置或自行修改安装目录。存在同名来源冲突时,先确认目标,不猜测。
|
|
70
|
-
|
|
71
|
-
## 生效与卸载
|
|
72
|
-
|
|
73
|
-
安装与卸载接纳后由宿主串行处理,只等待目标插件必要的在途调用,不冻结常规聊天、不自动重载已有 Pi 会话。完成表示插件包及宿主能力已应用;新建会话采用最新工具配置,需要让已有会话采用新版工具时,再按用户需要重载该会话。
|
|
74
|
-
|
|
75
|
-
每批只发送一条结果汇总,逐项区分成功、未接纳、失败和等待重启;部分失败不代表其他项失败。最终结果以会话通知为准,需要重启时沿用插件管理界面的维护流程,不能提前报告成功。
|
|
76
|
-
|
|
77
|
-
\`remove\` 只作用于现有插件管理支持的包来源,不附带业务数据清理,不用删除源码或新增禁用规则代替卸载。
|
|
78
|
-
`}c.d(b,{_:()=>e,i:()=>d})}};
|
|
6
|
+
${e(i)}`);for(let a of j)if(!/^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/.test(a)||"node_modules"===a)throw Error(`插件名字必须是扩展名字或完整 npm 包名,不接受路径或内嵌版本号:${a}`)}if(void 0!==c&&!/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/.test(c))throw Error("--version 必须是完整版本号,例如 1.2.3;版本可省略");if(void 0!==g&&(g.length>128||!/^[a-zA-Z][a-zA-Z0-9._-]*$/.test(g)))throw Error("--tag 必须是有效的渠道标签,例如 latest 或 dev");if(void 0!==g&&void 0!==c)throw Error("--tag 与 --version 互斥,不能同时指定");return"--version"===i.path[0]?{kind:"version"}:"info"===i.path[0]?{kind:"info"}:"session"===i.path[0]?{kind:"session",action:"reload"}:{kind:"plugins",action:i.path[1],...1===j.length?{name:j[0]}:j.length>1?{names:j}:{},...void 0===c?{}:{version:c},...void 0===g?{}:{tag:g},...void 0===h?{}:{checkUpdates:h}}}},77167:(a,b,c)=>{c.d(b,{O:()=>d});function d(a){return`Pi Desk 资料(仅在使用、管理 Pi Desk 或开发其插件时读取):
|
|
7
|
+
- 文档入口:${a.docsDirectory}/README.md
|
|
8
|
+
- SDK 公开类型声明:${a.sdkRoot}/dist/
|
|
9
|
+
从入口选择并完整阅读对应文档及引用示例;原生 Pi 能力按入口引用查阅官方资料。相对路径从文档所在目录解析。`}}};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"use strict";exports.id=50520,exports.ids=[37681,50520],exports.modules={621:(a,b,c)=>{c.d(b,{JM:()=>
|
|
1
|
+
"use strict";exports.id=50520,exports.ids=[37681,50520],exports.modules={621:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{JM:()=>k,w$:()=>m});var e=c(51455),f=c(76760),g=c(38522),h=c(57975);c(77598);var i=c(73159),j=a([i]);function k(a){return a&&"object"==typeof a&&!Array.isArray(a)?a:{}}async function l(a,b){let c;if(!(c=b.replaceAll("\\","/").replace(/^\.\//,""))||(0,f.isAbsolute)(b)||f.win32.isAbsolute(b)||c.includes("\0")||c.split("/").some(a=>".."===a)||!c)return null;try{let c=await (0,e.realpath)((0,f.resolve)(a,b)),d=(0,f.relative)(a,c);if((0,f.isAbsolute)(d)||".."===d||d.startsWith(`..${"win32"===process.platform?"\\":"/"}`))return null;let g=await (0,e.open)(c,"r");try{let a=await g.stat();if(!a.isFile()||a.size>65536)return null;let b=Buffer.alloc(65537),c=0;for(;c<b.length;){let{bytesRead:a}=await g.read(b,c,b.length-c,c);if(!a)break;c+=a}return c<=65536?b.subarray(0,c).toString("utf8"):null}finally{await g.close()}}catch(a){if(["ENOENT","ENOTDIR"].includes(a.code??""))return null;throw a}}async function m(a){let b,c=await (0,e.realpath)(a),d=await l(c,"package.json"),f=d?k(JSON.parse(d)):{},g={};for(let[a,d]of(b=k(k(f.piDesk).i18n),Object.entries(b).slice(0,16).flatMap(([a,b])=>{let c=k(b).readme;return a.length>0&&a.length<=35&&"string"==typeof c&&c.length<=1024?[[a,c]]:[]}))){let b=await l(c,d);null!==b&&(g[a]=b)}var h=await l(c,"README.md");if(null===h&&!Object.keys(g).length)return null;let i=h??Object.values(g)[0];return Object.keys(g).length?{default:i,translations:g}:i}i=(j.then?(await j)():j)[0],(0,h.promisify)(g.gunzip),d()}catch(a){d(a)}})},2472:(a,b,c)=>{c.d(b,{i:()=>i});var d=c(31421),e=c(76760),f=c(73136);let{createRequire:g}=process.getBuiltinModule("module"),h=g((0,e.join)(process.cwd(),"package.json"))("./src/server/l4_foundation/process/l4-process-tree.js");function i(a){return new Promise((b,c)=>{let g=(0,f.pathToFileURL)((0,e.join)(process.cwd(),"src/server/l4_foundation/pi/l4-pi-runtime-register.mjs")).href,i=(0,d.spawn)(process.execPath,["--import",g,...a.args],{cwd:process.cwd(),env:{...process.env,PI_CODING_AGENT_DIR:a.agentDir,PI_CODING_AGENT_SESSION_DIR:(0,e.join)(a.agentDir,"sessions"),TSX_TSCONFIG_PATH:(0,e.join)(process.cwd(),"tsconfig.json"),...a.env},stdio:["ignore","pipe","pipe"],windowsHide:!0,detached:"win32"!==process.platform}),j="",k="",l=!1,m=null,n=b=>{!l&&(l=!0,m&&clearTimeout(m),h.terminateManagedTree(i).then(b,b=>{let d=b instanceof Error?b:Error(String(b)),e="code"in d?String(d.code):d.name,f="killed"in d&&!0===d.killed,g="stderr"in d&&"string"==typeof d.stderr?d.stderr.trim().slice(-2e3):"";console.error("[Pi Desk][Runner] 子进程清理未完成",{pid:i.pid,exitCode:i.exitCode,code:e,killed:f,detail:g});let h=Error(`子进程 ${i.pid} 清理${f?"超时":"失败"}(${e})${g?`:${g}`:""}`,{cause:d});c(a.cleanupError(k.trim(),h))}))},o=(b,c)=>`${b}${c.toString("utf8")}`.slice(-a.maxOutputBytes);i.stdout.on("data",a=>{j=o(j,a)}),i.stderr.on("data",a=>{k=o(k,a)}),i.once("error",a=>n(()=>c(a))),i.once("close",a=>n(()=>b({stdout:j,stderr:k,code:a}))),(m=setTimeout(()=>{let b=a.timeoutError(),d=`${k}
|
|
2
2
|
${j}`.trim().slice(-4e3);d&&(b.message+=`
|
|
3
|
-
${d}`),n(()=>c(b))},a.timeoutMs)).unref()})}},17691:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{M:()=>j});var e=c(77598),f=c(73024),g=c(76760),h=c(75430),i=a([h]);function j(){let a=(0,h.getAgentDir)(),b=(0,g.join)(a,"pi-desk"),c=(0,g.join)(a,"pi-super");if((0,f.existsSync)(b)||!(0,f.existsSync)(c))return b;let d=(0,g.join)(a,`.pi-desk-migration-${(0,e.randomUUID)()}`);try{(0,f.cpSync)(c,d,{recursive:!0,errorOnExist:!0,force:!1}),(0,f.renameSync)(d,b),console.info("[Pi Desk] 已复制旧版应用数据到新目录")}finally{(0,f.rmSync)(d,{recursive:!0,force:!0})}return b}h=(i.then?(await i)():i)[0],d()}catch(a){d(a)}})},20700:(a,b,c)=>{function d(){return globalThis.__piDeskRestartHandler??null}function e(){return null!==d()}function f(a,b){let c=d();if(!c)throw Error("当前启动方式不支持自动重启 Pi Desk");setTimeout(()=>c(a,b),150).unref()}c.d(b,{Z:()=>f,k:()=>e})},33290:(a,b,c)=>{function d(){return globalThis.__piDeskNativePluginDiagnostics||(globalThis.__piDeskNativePluginDiagnostics=[]),globalThis.__piDeskNativePluginDiagnostics}function e(a,b){let c=d();!c.some(c=>c.cwd===a&&c.message===b)&&(c.push({cwd:a,message:b}),c.length>100&&c.splice(0,c.length-100))}function f(a){let b=a=>{let b=a.replaceAll("\\","/");return"win32"===process.platform?b.toLowerCase():b},c=b(a).replace(/\/$/,""),e=d();for(let a=e.length-1;a>=0;a-=1){let d=b(e[a].message);(d.includes(`${c}:`)||d.includes(`${c}/`))&&e.splice(a,1)}}function g(){return d().map(a=>({...a}))}c.d(b,{pL:()=>e,tt:()=>f,u7:()=>g})},34458:(a,b,c)=>{c.a(a,async(a,d)=>{try{let r;c.d(b,{dz:()=>o,qX:()=>n,w$:()=>i.w$});var e=c(4287),f=c(5235),g=c(64253),h=c(73159),i=c(621),j=a([f]);function k(a){return new URL(e.SZ.parse(a)).href.replace(/\/+$/,"")}function l(a,b,c){return new URL(`${k(a)}/${encodeURIComponent(b)}${c?`/${encodeURIComponent(c)}`:""}`)}function m(a,b){let c=(0,i.JM)(a.versions),d=(0,i.JM)(a["dist-tags"]),e="string"==typeof d[b]?d[b]:b.replace(/^v(?=\d+\.)/,"");if("string"!=typeof e||!Object.hasOwn(c,e))throw new h.XH("插件源不存在指定版本或标签",404,"missing");if(!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(e))throw new h.XH("插件源返回的版本无效");return e}async function n(a,b){if(b.registry){let a=k(b.registry);if(![f.Nx,f.sv].includes(a))return{registry:a,fallback:!1}}let
|
|
3
|
+
${d}`),n(()=>c(b))},a.timeoutMs)).unref()})}},17691:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{M:()=>j});var e=c(77598),f=c(73024),g=c(76760),h=c(75430),i=a([h]);function j(){let a=(0,h.getAgentDir)(),b=(0,g.join)(a,"pi-desk"),c=(0,g.join)(a,"pi-super");if((0,f.existsSync)(b)||!(0,f.existsSync)(c))return b;let d=(0,g.join)(a,`.pi-desk-migration-${(0,e.randomUUID)()}`);try{(0,f.cpSync)(c,d,{recursive:!0,errorOnExist:!0,force:!1}),(0,f.renameSync)(d,b),console.info("[Pi Desk] 已复制旧版应用数据到新目录")}finally{(0,f.rmSync)(d,{recursive:!0,force:!0})}return b}h=(i.then?(await i)():i)[0],d()}catch(a){d(a)}})},20700:(a,b,c)=>{function d(){return globalThis.__piDeskRestartHandler??null}function e(){return null!==d()}function f(a,b){let c=d();if(!c)throw Error("当前启动方式不支持自动重启 Pi Desk");setTimeout(()=>c(a,b),150).unref()}c.d(b,{Z:()=>f,k:()=>e})},33290:(a,b,c)=>{function d(){return globalThis.__piDeskNativePluginDiagnostics||(globalThis.__piDeskNativePluginDiagnostics=[]),globalThis.__piDeskNativePluginDiagnostics}function e(a,b){let c=d();!c.some(c=>c.cwd===a&&c.message===b)&&(c.push({cwd:a,message:b}),c.length>100&&c.splice(0,c.length-100))}function f(a){let b=a=>{let b=a.replaceAll("\\","/");return"win32"===process.platform?b.toLowerCase():b},c=b(a).replace(/\/$/,""),e=d();for(let a=e.length-1;a>=0;a-=1){let d=b(e[a].message);(d.includes(`${c}:`)||d.includes(`${c}/`))&&e.splice(a,1)}}function g(){return d().map(a=>({...a}))}c.d(b,{pL:()=>e,tt:()=>f,u7:()=>g})},34458:(a,b,c)=>{c.a(a,async(a,d)=>{try{let r;c.d(b,{dz:()=>o,qX:()=>n,w$:()=>i.w$});var e=c(4287),f=c(5235),g=c(64253),h=c(73159),i=c(621),j=a([f,g,h,i]);function k(a){return new URL(e.SZ.parse(a)).href.replace(/\/+$/,"")}function l(a,b,c){return new URL(`${k(a)}/${encodeURIComponent(b)}${c?`/${encodeURIComponent(c)}`:""}`)}function m(a,b){let c=(0,i.JM)(a.versions),d=(0,i.JM)(a["dist-tags"]),e="string"==typeof d[b]?d[b]:b.replace(/^v(?=\d+\.)/,"");if("string"!=typeof e||!Object.hasOwn(c,e))throw new h.XH("插件源不存在指定版本或标签",404,"missing");if(!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(e))throw new h.XH("插件源返回的版本无效");return e}async function n(a,b){let c=(0,f.to)(b.agentDir),d=b.downloadSource??c.downloadSource;if("local"===d.mode){let c=await (0,g.B)(b.agentDir),d=a.startsWith("@")?c[`${a.split("/")[0]}:registry`]:void 0;return{registry:k(d||c.registry||f.Nx),fallback:!1}}if(b.registry){let a=k(b.registry);if(![f.Nx,f.sv].includes(a))return{registry:a,fallback:!1}}let e=c.registries[`npm:${a}`];if(e)return{registry:k(e),fallback:!1};if(a.startsWith("@")){let c=(await (0,g.B)(b.agentDir))[`${a.split("/")[0]}:registry`];if(c){let a=k(c);if(![f.Nx,f.sv].includes(a))return{registry:a,fallback:!1}}}return"custom"===d.mode?{registry:k(d.registry),fallback:!1}:"official"===d.mode?{registry:f.Nx,fallback:!1}:"domestic"===d.mode?{registry:f.sv,fallback:!1}:{registry:await function(){if(!r||r.expires<=Date.now()){let a=(async()=>{try{let a=await (0,h.NL)(new URL("https://ipwho.is/?fields=success,country_code"),{limit:1024,timeout:3e3,cache:!1,auth:!1}),b=(0,i.JM)(JSON.parse(a.toString("utf8")));if(!0!==b.success)throw Error("出口地区检测失败");return"CN"===b.country_code?f.sv:f.Nx}catch{return r&&(r.expires=Date.now()+6e4),f.Nx}})();r={expires:Date.now()+18e5,value:a}}return r.value}(),fallback:!0}}async function o(a,b={}){let c;if(!a.startsWith("npm:"))return{source:a};let d=/^npm:((?:@[^/]+\/)?[^@]+)(?:@([^@]+))?$/.exec(a);if(!d)throw new h.XH("npm 插件来源无效",400);let e=d[1];if(e.length>214||!/^(?:@[a-z0-9_.-]+\/)?[a-z0-9][a-z0-9_.-]*$/i.test(e))throw new h.XH("npm 插件包名无效",400);let g=d[2]??"latest";if(g.length>128||!/^[a-zA-Z0-9._+-]+$/.test(g))throw new h.XH("npm 插件版本或标签无效",400);let j=b.downloadSource??(0,f.to)(b.agentDir).downloadSource,k=await n(e,{...b,downloadSource:j}),r=k.registry,s=g;try{let a=await p(l(r,e),b),d=(0,i.JM)(a["dist-tags"])[g];"string"==typeof d&&(s=d),c=m(a,s),q((0,i.JM)(a.versions)[c],e,c)}catch(d){if(!k.fallback||r===f.Nx||!(d instanceof h.XH)||!["network","missing"].includes(d.reason))throw d;console.warn("[Pi Desk][PluginRegistry] 自动下载源不可用,回退 npm 官方源",{name:e,reason:d.reason}),r=f.Nx;let a=await p(l(r,e),b);c=m(a,s),q((0,i.JM)(a.versions)[c],e,c)}return{source:`npm:${e}@${c}`,..."local"===j.mode?{}:{registry:r}}}async function p(a,b){if(!1!==b.cache)return(0,h.Yq)(a,b.signal,b.agentDir);let c=await (0,h.NL)(a,{limit:8388608,signal:b.signal,cache:!1,agentDir:b.agentDir});try{let a=JSON.parse(c.toString("utf8"));if(!a||"object"!=typeof a||Array.isArray(a))throw Error("invalid");return a}catch{throw new h.XH("插件源返回的元数据格式无效")}}function q(a,b,c){let d=(0,i.JM)(a);if(d.name!==b||"string"!=typeof d.version||c&&d.version!==c)throw new h.XH("插件源返回的包名或版本不匹配");return d}[f,g,h,i]=j.then?(await j)():j,d()}catch(a){d(a)}})},47154:(a,b,c)=>{c.d(b,{V:()=>d});function d(a){let b=(globalThis.__piDeskPackageRootTail??Promise.resolve()).then(a,a);return globalThis.__piDeskPackageRootTail=b.then(()=>void 0,()=>void 0),b}},50520:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.r(b),c.d(b,{L2PluginManagement:()=>P,L2PluginManagementInvalidPackageError:()=>L,L2PluginManagementNotFoundError:()=>J,L2PluginManagementOperationConflictError:()=>K,L2PluginManagementPackageRootError:()=>M,L2PluginManagementRestartPendingError:()=>N,L2PluginManagementRestartUnavailableError:()=>O,disposeL2PluginManagement:()=>G,getL2PluginManagement:()=>I,initializeL2PluginManagement:()=>H});var e=c(16056),f=c(17691),g=c(76019),h=c(77598),i=c(51455),j=c(76760),k=c(75430),l=c(93951),m=c(4287),n=c(34458),o=c(5235),p=c(36361),q=c(69371),r=c(75157),s=c(47154),t=c(60719),u=c(33290),v=c(53584),w=c(96783),x=c(20700),y=c(78597),z=a([f,k,n,o,p,t,y]);[f,k,n,o,p,t,y]=z.then?(await z)():z;class J extends Error{constructor(a){super(`插件不存在:${a}`),this.source=a,this.name="L2PluginManagementNotFoundError"}}class K extends Error{constructor(a){super(a),this.name="L2PluginManagementOperationConflictError"}}class L extends Error{constructor(a){super(a),this.name="L2PluginManagementInvalidPackageError"}}class M extends Error{constructor(a){super(a.message),this.rootError=a,this.name="L2PluginManagementPackageRootError"}}class N extends Error{constructor(){super("已有插件操作需要重启完成"),this.name="L2PluginManagementRestartPendingError"}}class O extends Error{constructor(){super("当前启动方式不支持自动重启 Pi Desk"),this.name="L2PluginManagementRestartUnavailableError"}}function A(a,b,c){let d=(0,j.resolve)(a,b),e=(0,j.relative)(a,d);if(e.startsWith("..")||(0,j.isAbsolute)(e))throw Error(`${c} 必须位于插件包目录内`);return d}async function B(a){try{return(await (0,i.stat)(a)).isFile()}catch{return!1}}function C(a){return a instanceof Error&&a.message?a.message:String(a)}async function D(a){let b;if((await (0,i.stat)(a)).isFile())return{version:null,error:null};try{b=JSON.parse(await (0,i.readFile)((0,j.join)(a,"package.json"),"utf8"))}catch(a){if(a&&"object"==typeof a&&"code"in a&&"ENOENT"===a.code)return{version:null,error:null};return{version:null,error:{phase:"package",message:C(a)}}}let c="string"==typeof b.version&&b.version.trim()?b.version.trim():null;try{let d=b.piDesk?.entry??b.piDesk?.global;if(void 0!==d){if("string"!=typeof d||!d.trim())throw Error("piDesk.entry 必须是非空字符串");let b=A(a,d,"piDesk.entry");if(!await B(b))throw Error("Pi Desk Entry 文件不存在")}let e=b.pi?.extensions;if(void 0!==e&&!Array.isArray(e))throw Error("pi.extensions 必须是数组");for(let b of e??[]){if("string"!=typeof b||!b.trim())throw Error("pi.extensions 只允许非空字符串");if(/[*?[\]{}]/.test(b))continue;let c=A(a,b,"pi.extensions");if(!await B(c))throw Error(`Native Extension 文件不存在:${b}`)}return{version:c,error:null}}catch(a){return{version:c,error:{phase:"entry",message:C(a)}}}}async function E(a,b){let[c,d]=await Promise.all([(0,i.realpath)(a),(0,i.realpath)(b)]),e=(0,j.relative)(c,d);if(e.startsWith("..")||(0,j.isAbsolute)(e))throw Error("插件能力资源必须位于 Package 目录内");let f=await (0,i.open)(d,"r");try{let a=Buffer.alloc(65537),{bytesRead:b}=await f.read(a,0,a.length,0);return{content:a.subarray(0,Math.min(b,65536)).toString("utf8"),truncated:b>65536}}finally{await f.close()}}function F(a,b,c){return{error:function(a){if(!a)return null;if(a.length<=32768)return a;let b=a.slice(0,32752);return(0,g.J8)(`${b}
|
|
4
4
|
…(已截断)`,`${b}
|
|
5
|
-
… (truncated)`)}(a?.error??c),extensions:a?.extensions??[],tools:a?.tools.map(a=>({name:a.name,label:a.label,state:a.state,description:a.description,promptSnippet:a.promptSnippet,promptGuidelineCount:a.promptGuidelineCount,promptGuidelinePreview:a.promptGuidelinePreview}))??[],skills:a?.skills.map(a=>({name:a.name,description:a.description,path:a.path,modelVisible:a.modelVisible}))??[],prompts:a?.prompts.map(a=>({name:a.name,description:a.description,path:a.path}))??[],themes:a?.themes??[],providers:a?.providers??[],piDesk:{methods:b?[...b.methods]:[],browserEntries:b?[...b.browserEntries]:[],messageDeclarations:b?[...b.messageDeclarations]:[]}}}class P{get restartRequired(){return this.deferredMaintenance.size>0}constructor(a,b=process.cwd(),c=(0,k.getAgentDir)()){this.workSessions=a,this.cwd=b,this.agentDir=c,this.operationTail=Promise.resolve(),this.operations=new Map,this.listeners=new Set,this.lifetime=new AbortController,this.disposed=!1,this.activeSource=null,this.sourceCache=null,this.capabilityCache=null,this.deferredMaintenance=new Map;const d=(0,h.createHash)("sha256").update(this.agentDir).digest("hex").slice(0,16);this.stagingRoot=(0,j.join)(this.cwd,"temp","pi",`plugin-management-${d}`),this.packageManagerCwd=(0,j.join)((0,f.M)(),"plugin-package-manager"),this.updates=new y.E(this.agentDir,this.packageManagerCwd,this.lifetime.signal),this.maintenanceError=process.env.PI_DESK_PLUGIN_MAINTENANCE_ERROR?.trim()||null,this.unsubscribeRuntime=(0,p.getL4PiGlobalPluginRuntime)().subscribeChanges(()=>this.publish()),this.staleStagingCleanup=(0,i.rm)(this.stagingRoot,{recursive:!0,force:!0}).catch(a=>{console.warn("[Pi Desk][PluginManagement] 清理上次中断的候选目录失败",{path:this.stagingRoot,errorName:a instanceof Error?a.name:"UnknownError"})})}list(a=!1){return this.assertOpen(),this.readSnapshot(a)}async batch(a){this.assertOpen();let b=[],c=new Set;for(let d of"add"===a.action?a.items:a.sources.map(a=>({source:a})))try{let e="add"===a.action?this.normalizeAddedSource(d.source):d.source,f=(0,m.LD)(e);if(c.has(f))throw new K("批量请求中包含重复来源");if(c.add(f),"add"===a.action){let{source:a,...b}=d;await this.reinstall(e,void 0,b)}else"update"===a.action?await this.update(e):"del"===a.action?await this.del(e):await this.setUpdateTag(e,a.tag);b.push({source:d.source,error:null})}catch(a){b.push({source:d.source,error:C(a).slice(0,4e3)})}return{snapshot:await this.readSnapshot(!1),results:b}}subscribe(a){return this.assertOpen(),this.listeners.add(a),()=>this.listeners.delete(a)}get(a){return this.assertOpen(),this.readDetail(a)}add(a,b={}){return this.mutate("add",this.normalizeAddedSource(a),!1,void 0,b)}setEnabled(a,b){return this.mutate(b?"enable":"disable",a)}async update(a){if(this.assertOpen(),(0,e.P)())throw new K("基础模式不执行插件维护");this.assertSourceIdle(a);let b=(await this.readSources()).sources.find(b=>(0,m.LD)(b.source)===(0,m.LD)(a));if(!b)throw new J(a);if((0,m.ug)(b.source)){let a=await this.readSnapshot({checkUpdates:!0,sources:[b.source]}),c=a.plugins.find(a=>a.source===b.source);if(c.updateError)throw new L(c.updateError);if(!0!==c.updateAvailable)return a}return this.mutate("update",b.source)}reinstall(a,b,c={}){return this.mutate("add",this.normalizeAddedSource(a),!0,b,c)}async setUpdateTag(a,b){if(this.assertOpen(),(0,e.P)())throw new K("基础模式不执行插件维护");let c=(await this.readSources()).sources.find(b=>(0,m.LD)(b.source)===(0,m.LD)(a));if(!c)throw new J(a);if("package"!==c.kind||!(0,m.ug)(c.source))throw new L("只有 npm 插件包支持更新渠道");this.assertSourceIdle(c.source),(0,o.ks)(c.source,m.mR.parse(b),this.agentDir),this.updates.clear(c.source),this.publish()}assertSourceIdle(a){let b=(0,m.LD)(a);if(this.activeSource&&(0,m.LD)(this.activeSource)===b||[...this.operations].some(([a,c])=>(0,m.LD)(a)===b&&"failed"!==c.phase))throw new K("该来源已有未完成的维护操作")}waitForOperations(a,b){return b=AbortSignal.any([b,this.lifetime.signal]),new Promise((c,d)=>{let e=()=>void 0,f=a=>{e(),b.removeEventListener("abort",g),a?d(a):c()},g=()=>f(Error(this.disposed?"插件管理已关闭":"发起命令的会话已关闭")),h=()=>{if(this.disposed)return f(Error("插件管理已关闭"));for(let b of a){let a=this.operations.get(b);if(a?.phase==="failed")return f(Error(a.message??"插件操作失败"));if(a?.phase==="waiting"&&this.activeSource!==b&&this.restartRequired)return f(Error(`插件尚未生效,需要在设置的插件管理中重启 Pi Desk。${a.message??""}`))}a.some(a=>this.operations.has(a)||this.activeSource===a)||f()};if(b.aborted)return g();e=this.subscribe(h),b.addEventListener("abort",g,{once:!0}),h()})}del(a){return this.mutate("del",a)}async apply(a){if(this.assertOpen(),(0,e.P)())throw new K("基础模式不加载外部插件");if(a?.some(a=>this.deferredMaintenance.has(a)))throw new N;let b=await (0,p.getL4PiGlobalPluginRuntime)().scanSourceChanges(a);this.assertOpen();let c=b.filter(b=>{if(this.deferredMaintenance.has(b.source))return!1;let c=this.operations.get(b.source);if(!c||"failed"===c.phase)return!0;if(a)throw new K("该来源已有未完成操作");return!1}),d=new Set([...this.operations].filter(([,a])=>"failed"!==a.phase).map(([a])=>a));for(let a of c)d.add(a.source);if(d.size>32)throw new K("加载变更超过队列上限,请选择部分来源");for(let a of c){if(!this.operations.has(a.source)&&this.operations.size>=64){let a=[...this.operations].find(([,a])=>"failed"===a.phase);a&&this.operations.delete(a[0])}this.operations.set(a.source,{action:"apply",phase:"queued",message:null}),this.enqueueApply(a)}return this.publish(),this.readSnapshot(!1)}enqueueApply(a){this.runExclusive(async()=>{this.activeSource=a.source;try{this.setOperation(a.source,"checking",null),await this.probeSourceChange(a),this.assertOpen(),this.setOperation(a.source,"applying",null),await (0,p.getL4PiGlobalPluginRuntime)().applySourceChange(a),a.current?.path&&(0,u.tt)(a.current.path),a.previous?.path&&(0,u.tt)(a.previous.path),this.capabilityCache=null,this.workSessions.refreshPluginMessages(),this.operations.delete(a.source)}catch(b){this.setOperation(a.source,"failed",C(b))}finally{this.activeSource=null,this.sourceCache=null,this.publish()}}).catch(b=>{this.disposed||this.setOperation(a.source,"failed",C(b))})}async probeSourceChange(a){let b=a.current;if(!b||!b.enabled)return;if(b.error)throw new L(b.error);if(!b.path)throw new L("插件来源目录不存在");let c=performance.now();console.info("[Pi Desk][PluginManagement] 源码候选预检开始",{source:a.source});let d=(0,j.join)(this.stagingRoot,(0,h.randomUUID)()),e=(0,j.join)(d,"agent"),f=(0,j.join)(d,"workspace");await (0,i.mkdir)(e,{recursive:!0}),await (0,i.mkdir)(f,{recursive:!0});try{if(await (0,i.writeFile)((0,j.join)(e,"settings.json"),JSON.stringify({extensions:[b.path]}),"utf8"),b.piDeskRoot||b.nativePaths.length>0){let c=await (0,w.Y)(f,e,b.nativePaths.length>0),d=c.loadError??c.packages.find(a=>"failed"===a.status)?.error?.message;if(d)throw new L(d);if(b.piDeskRoot&&!c.packages.some(a=>"ready"===a.status))throw new L("预检未加载到候选 Node Entry,放弃本次变更");for(let b of c.packages)if(b.pluginName&&(0,p.getL4PiGlobalPluginRuntime)().readDiagnostics().packages.some(c=>c.source!==a.source&&"ready"===c.status&&c.pluginName===b.pluginName))throw new L(`插件名冲突:${b.pluginName}`)}this.assertOpen()}finally{await (0,i.rm)(d,{recursive:!0,force:!0}),console.info("[Pi Desk][PluginManagement] 源码候选预检结束",{source:a.source,durationMs:Math.round(performance.now()-c)})}}reload(a){return this.activeSource?Promise.reject(new K("维护仍在执行或等待,请先完成当前操作")):this.runExclusive(async()=>(this.assertRestartAvailable(),this.restartWhenQuiet(a)))}async mutate(a,b,c=!1,d,f={}){if(this.assertOpen(),(0,e.P)())throw new K("基础模式不执行插件维护,请通过基础聊天修复或正常启动后维护");let g=await this.readSources();this.assertOpen();let h=g.sources.find(a=>(0,m.LD)(a.source)===(0,m.LD)(b));if("add"!==a){if(!h)throw new J(b);if("package"!==h.kind&&"enable"!==a&&"disable"!==a)throw new L("裸扩展不是已安装包,请编辑源码后加载变更;此操作不会删除源码")}let i=(d??=h?.source)??b;if(f.tag&&!(0,m.ug)(b))throw new L("只有 npm 插件包支持更新渠道");for(let a of[b,i])this.assertSourceIdle(a);if([...this.operations.values()].filter(a=>"failed"!==a.phase).length>=32)throw new K("插件维护队列已满,请等待当前操作完成");if(this.operations.size>=64){let a=[...this.operations].find(([,a])=>"failed"===a.phase);a&&this.operations.delete(a[0])}return d&&d!==b&&this.operations.get(d)?.phase==="failed"&&this.operations.delete(d),this.operations.set(i,{action:a,phase:"queued",message:null}),this.updates.clear(i),this.updates.clear(b),this.publish(),this.runExclusive(async()=>{this.activeSource=i;try{await this.executeMutation(a,b,i,c,f),this.deferredMaintenance.has(i)||this.operations.delete(i)}catch(a){this.setOperation(i,"failed",C(a))}finally{this.updates.clear(i),this.updates.clear(b),this.sourceCache=null,this.activeSource=null,this.publish()}}).catch(a=>{this.disposed||this.setOperation(i,"failed",C(a))}),this.readSnapshot(!1)}async executeMutation(a,b,c,d,e){let f=(0,p.getL4PiGlobalPluginRuntime)(),g=a=>this.setOperation(c,"waiting",a),h=this.createPackageManager();this.throwSettingsErrors(h.settingsManager);let i=h.packageManager.listConfiguredPackages().filter(a=>"user"===a.scope),j=i.find(a=>a.source===c),k=null,l=null;if("enable"!==a&&"disable"!==a){var n;let f=await (0,r.c)({agentDir:this.agentDir,configured:i});if(f)throw new M(f);if("add"!==a&&!j)throw new J(b);this.setOperation(c,"checking","正在确认插件版本和下载源");let h=this.candidateSource(b,j?.installedPath),p=(0,m.ug)(h),q="del"===a?{source:h,updateTag:null}:await this.updates.resolveInstall(h,c,e,"update"===a);if(l=q.updateTag,"update"===a&&p&&j?.installedPath){let a=await D(j.installedPath),b=q.source.slice(q.source.lastIndexOf("@")+1);if(!a.version)throw new L("无法读取插件已安装版本");if(!(0,m.zj)(b,a.version))return}if(k={...p&&"del"!==a&&(d||j||"update"===a)?{action:"reinstall",source:q.source}:(n=q.source,{action:"add"===a?"install":"update"===a?"update":"remove",source:n}),..."registry"in q&&q.registry?{registry:q.registry}:{}},"del"!==a&&await this.probeCandidate(q.source,c,k.registry),l&&((0,o.ks)(c,l,this.agentDir),this.updates.clear(c)),this.deferredMaintenance.size>0){this.deferredMaintenance.set(c,k),g("等待重启后完成安装维护");return}}this.assertOpen(),await f.withSourceIdle(c,async()=>{if(this.setOperation(c,"applying",k?.registry?`下载源:${k.registry}`:null),"enable"===a||"disable"===a){let c=(0,o.to)(this.agentDir).disabled.includes((0,m.LD)(b));(0,o.El)(b,"enable"===a,this.agentDir),this.sourceCache=null;try{if(await this.applyMutationSources([b],!0),"enable"===a&&!(await this.readSources()).sources.find(a=>a.source===b)?.enabled)throw new L("此插件仍被 Pi 配置排除,请先调整原有资源配置")}catch(a){throw(0,o.El)(b,!c,this.agentDir),this.sourceCache=null,a}}else if(k)try{await f.replaceSource(c,null),await (0,s.V)(async()=>{await (0,q.wC)({maintenance:k,agentDir:this.agentDir,cwd:this.packageManagerCwd}),"del"!==a&&await this.verifyInstalledPackage(k.source)}),this.sourceCache=null,await this.applyMutationSources([c,k.source],!1)}catch(a){if(a instanceof q.rZ&&"locked"===a.kind&&(0,x.k)())this.deferredMaintenance.set(c,k),g("文件正在被使用,需要重启后完成操作");else throw a}this.updates.clear(c),this.updates.clear(b),this.capabilityCache=null,this.workSessions.refreshPluginMessages()},this.lifetime.signal,g)}async verifyInstalledPackage(a){let b=this.createPackageManager();this.throwSettingsErrors(b.settingsManager);let c=(0,m.LD)(a),d=b.packageManager.listConfiguredPackages().find(a=>"user"===a.scope&&(0,m.LD)(a.source)===c);if(!d?.installedPath)throw new L("插件安装后没有有效目录");await this.verifyPackageVersion(a,d.installedPath)}async verifyPackageVersion(a,b){let c=await D(b);if(c.error)throw new L("string"==typeof c.error.message?c.error.message:c.error.message.default);if((0,m.ug)(a)){let b=a.slice(a.lastIndexOf("@")+1);if(c.version!==b)throw new L(`插件实际安装版本与目标不一致:${c.version??"未知"},目标 ${b}`)}}async applyMutationSources(a,b){let c=new Set(a.map(m.LD)),d=(0,p.getL4PiGlobalPluginRuntime)(),e=await d.scanSourceChanges(),f=await this.readSources(),g=[...new Set([...e.filter(a=>c.has((0,m.LD)(a.source))).map(a=>a.source),...f.sources.filter(a=>c.has((0,m.LD)(a.source))).map(a=>a.source)])];for(let a of g.length?await d.scanSourceChanges(g):[])b&&await this.probeSourceChange(a),await d.applySourceChange(a),a.current?.path&&(0,u.tt)(a.current.path),a.previous?.path&&(0,u.tt)(a.previous.path)}dispose(){this.disposed||(this.disposed=!0,this.lifetime.abort(),this.unsubscribeRuntime(),this.listeners.clear())}assertOpen(){if(this.disposed)throw new K("插件管理已关闭")}setOperation(a,b,c){let d=this.operations.get(a);if(!d)return;let e=c?.slice(0,4e3)??null;(d.phase!==b||d.message!==e)&&(this.operations.set(a,{...d,phase:b,message:e}),"failed"===b&&console.warn("[Pi Desk][PluginManagement] 插件操作失败",{source:a,action:d.action,message:e}),this.publish())}publish(){if(!this.disposed)for(let a of this.listeners)try{a()}catch(a){console.warn("[Pi Desk][PluginManagement] 状态监听失败",{message:C(a)})}}async readSources(){let a=()=>null!==this.activeSource&&this.operations.get(this.activeSource)?.phase==="applying";if(a()&&this.sourceCache)return this.sourceCache;let b=await (0,t.o)(this.packageManagerCwd,this.agentDir,{DefaultPackageManager:k.DefaultPackageManager,SettingsManager:k.SettingsManager});return a()&&this.sourceCache||(this.sourceCache=b),a()&&this.sourceCache?this.sourceCache:b}async probeCandidate(a,b,c){let d=(0,j.join)(this.stagingRoot,(0,h.randomUUID)()),e=(0,j.join)(d,"agent"),f=(0,j.join)(d,"workspace");await (0,i.mkdir)(f,{recursive:!0}),console.info("[Pi Desk][PluginManagement] 开始在隔离 AgentDir 预检候选插件",{source:a});try{await (0,q.wC)({maintenance:{action:"install",source:a,...c?{registry:c}:{}},agentDir:e,cwd:f}),this.assertOpen();let d=this.createPackageManager(e,f);this.throwSettingsErrors(d.settingsManager);let g=d.packageManager.listConfiguredPackages().filter(a=>"user"===a.scope)[0];if(!g?.installedPath)throw new L("候选插件安装后没有有效目录");await this.verifyPackageVersion(a,g.installedPath);let h=await (0,w.Y)(f,e,!0);if(h.loadError)throw new L(h.loadError);let i=h.packages.find(a=>"failed"===a.status);if(i?.error)throw new L(i.error.message);let j=h.packages[0]?.pluginName;if(j&&(0,p.getL4PiGlobalPluginRuntime)().readDiagnostics().packages.find(a=>a.source!==b&&a.pluginName===j))throw new L(`pluginName 已由其他 Package 注册:${j}`);this.assertOpen(),console.info("[Pi Desk][PluginManagement] 候选插件隔离预检通过",{source:a})}catch(a){if(a instanceof L)throw a;throw new L(C(a))}finally{await (0,i.rm)(d,{recursive:!0,force:!0}).catch(a=>{console.warn("[Pi Desk][PluginManagement] 清理候选插件目录失败",{path:d,errorName:a instanceof Error?a.name:"UnknownError"})})}}restartWhenQuiet(a){return this.workSessions.runPluginRestart(async()=>{let b=(0,p.getL4PiGlobalPluginRuntime)(),c=await this.readSnapshot(!1);return await b.prepareReload(),console.info("[Pi Desk][PluginManagement] 插件 Runtime 已通过静默检查,准备重启",{deferredCount:this.deferredMaintenance.size}),(0,x.Z)("basic"===a||0===this.deferredMaintenance.size?void 0:[...this.deferredMaintenance.values()],a),c})}async readDetail(a){if((0,e.P)())throw new K("基础模式不执行插件能力盘点");let b=(await this.readSources()).sources.find(b=>b.source===a),c=b?await (0,t.W)(b):null;if(!c)throw new J(a);let d=await this.readCapabilities(!1),f=d.packages.find(b=>b.source===a);if(!f)throw Error(d.loadError??`插件能力详情不可用:${a}`);let[g,h]=await Promise.all([Promise.all(f.skills.map(async a=>({name:a.name,description:a.description,path:a.path,modelVisible:a.modelVisible,...await E(c,a.filePath)}))),Promise.all(f.prompts.map(async a=>({name:a.name,description:a.description,path:a.path,...await E(c,a.filePath)})))]);return l.tA.parse({source:a,readme:await (0,n.w$)(c),tools:f.tools.map(a=>({name:a.name,label:a.label,state:a.state,description:a.description,parameters:a.parameters,promptSnippet:a.promptSnippetDetail,promptGuidelines:a.promptGuidelines})),skills:g,prompts:h})}async readSnapshot(a){if((0,e.P)())return{plugins:[],restartRequired:!1,loadError:this.maintenanceError};let b=this.createPackageManager(),c=b.settingsManager.drainErrors().map(a=>a.error.message),d=b.packageManager.listConfiguredPackages().filter(a=>"user"===a.scope),f=await (0,r.c)({agentDir:this.agentDir,configured:d}),h=await this.readSources(),i=await this.updates.read(h.sources,"boolean"==typeof a?{checkUpdates:a}:a),j=(0,p.getL4PiGlobalPluginRuntime)(),k=j.readDiagnostics(),n=new Map(k.packages.map(a=>[a.source,a])),q=(0,u.u7)(),s=this.capabilityCache??{packages:[],loadError:null},t=new Map(s.packages.map(a=>[a.source,a])),v=new Map(j.readCapabilityRegistrations().map(a=>[a.source,a])),w=await Promise.all(h.sources.map(async a=>{let b=n.get(a.source),c=a.path?this.findNativeDiagnostic(a.path,q):null,d=(a.error?{phase:"package"===a.kind?"package":"entry",message:a.error}:null)??(b?.status==="failed"?b.error:null)??(c?{phase:"native",message:c}:null);return{source:a.source,kind:a.kind,operation:this.operationFor(a.source),pluginName:b?.pluginName??null,description:a.description,version:a.version??b?.version??null,updateAvailable:i.get(a.source)?.updateAvailable??null,updateTag:i.get(a.source)?.updateTag??null,availableVersion:i.get(a.source)?.availableVersion??null,updateError:i.get(a.source)?.updateError??null,status:a.enabled?d?"failed":b?.status==="ready"?"ready":"available":"disabled",error:d,capabilities:F(t.get(a.source),v.get(a.source),s.loadError)}}));for(let[a,b]of this.operations)w.some(b=>(0,m.LD)(b.source)===(0,m.LD)(a))||w.push({source:a,kind:"package",operation:b,pluginName:null,description:null,version:null,updateAvailable:null,updateTag:(0,m.ug)(a)?(0,o.ey)(a,this.agentDir):null,availableVersion:null,updateError:null,status:"failed"===b.phase?"failed":"available",error:null,capabilities:F(void 0,void 0,null)});return l.oP.parse({plugins:w.sort((a,b)=>a.source.localeCompare(b.source)),restartRequired:this.restartRequired,loadError:function(a){let b=[...new Map(a.flatMap(a=>{let b=("string"==typeof a?a:a.message).trim();return b?[[b,{defaultText:b,englishText:"string"==typeof a?b:a.englishMessage.trim()}]]:[]})).values()];if(0===b.length)return null;let c=b.map(a=>a.defaultText).join("; ");return b.every(a=>a.defaultText===a.englishText)?c:(0,g.J8)(c,b.map(a=>a.englishText).join("; "))}([...c,...h.errors,...k.loadError?[k.loadError]:[],...this.maintenanceError?[this.maintenanceError]:[],...f?[f]:[]])})}async readCapabilities(a){if(!a&&this.capabilityCache)return this.capabilityCache;try{return this.capabilityCache=await (0,s.V)(()=>(this.assertOpen(),!a&&this.capabilityCache)?Promise.resolve(this.capabilityCache):(0,v.a)(this.cwd,this.agentDir)),this.publish(),console.info("[Pi Desk][PluginManagement] 插件能力盘点完成",{packageCount:this.capabilityCache.packages.length,hasLoadError:null!==this.capabilityCache.loadError}),this.capabilityCache}catch(b){let a=C(b);return console.warn("[Pi Desk][PluginManagement] 插件能力盘点失败",{errorName:b instanceof Error?b.name:"UnknownError",message:a}),this.capabilityCache={packages:[],loadError:a},this.publish(),this.capabilityCache}}findNativeDiagnostic(a,b){let c,d=(c=(0,j.resolve)(a).replaceAll("\\","/"),"win32"===process.platform?c.toLowerCase():c),e=b.find(a=>("win32"===process.platform?a.message.replaceAll("\\","/").toLowerCase():a.message.replaceAll("\\","/")).includes(d));return e?.message??null}createPackageManager(a=this.agentDir,b=this.packageManagerCwd){let c=k.SettingsManager.create(b,a,{projectTrusted:!1});return{settingsManager:c,packageManager:new k.DefaultPackageManager({cwd:b,agentDir:a,settingsManager:c})}}candidateSource(a,b){return(0,j.isAbsolute)(a)||/^(?:[a-z][a-z0-9+.-]*:|git@)/i.test(a)?a:b?(0,j.resolve)(b):(0,j.resolve)(this.agentDir,a)}operationFor(a){let b=(0,m.LD)(a);return[...this.operations].find(([a])=>(0,m.LD)(a)===b)?.[1]??null}normalizeAddedSource(a){return/^(?:@[a-z0-9_.-]+\/)?[a-z0-9][a-z0-9_.-]*(?:@[^\s/]+)?$/i.test(a)?`npm:${a}`:(0,j.isAbsolute)(a)||/^(?:[a-z][a-z0-9+.-]*:|git@)/i.test(a)?a:(0,j.resolve)(this.cwd,a)}throwSettingsErrors(a){let b=a.drainErrors();if(0!==b.length)throw Error(b.map(a=>a.error.message).join("; "))}assertRestartAvailable(){if(!(0,x.k)())throw new O}runExclusive(a){let b=()=>this.staleStagingCleanup.then(()=>(this.assertOpen(),a())),c=this.operationTail.then(b,b);return this.operationTail=c.then(()=>void 0,()=>void 0),c}}function G(){globalThis.__piDeskPluginManagement?.dispose()}function H(a){globalThis.__piDeskPluginManagement||(globalThis.__piDeskPluginManagement=new P(a))}function I(){if(!globalThis.__piDeskPluginManagement)throw Error("插件管理尚未完成进程级装配");return globalThis.__piDeskPluginManagement}d()}catch(a){d(a)}})},53584:(a,b,c)=>{c.d(b,{a:()=>l});var d=c(76760),e=c(36153),f=c(86148),g=c(2472);let h="__PI_DESK_PLUGIN_CAPABILITIES__",i=e.Yj(),j=e.Ik({name:e.Yj(),description:e.Yj().nullable()}).strict(),k=e.Ik({packages:e.YO(e.Ik({source:e.Yj(),error:e.Yj().nullable(),extensions:e.YO(e.Ik({path:e.Yj(),events:e.YO(e.Ik({name:e.Yj(),count:e.ai().int().positive()}).strict()),commands:e.YO(j),shortcuts:e.YO(e.Ik({shortcut:e.Yj(),description:e.Yj().nullable()}).strict()),flags:e.YO(e.Ik({name:e.Yj(),type:e.k5(["boolean","string"]),description:e.Yj().nullable(),default:e.KC([e.zM(),e.Yj(),e.ch()])}).strict()),messageRenderers:e.YO(e.Yj()),entryRenderers:e.YO(e.Yj())}).strict()),tools:e.YO(e.Ik({name:e.Yj(),label:i,state:e.k5(["active","inactive","shadowed"]),description:i,parameters:e.g1(e.Yj(),e.Pq()),promptSnippet:i.nullable(),promptSnippetDetail:i.nullable(),promptGuidelines:e.YO(i),promptGuidelineCount:e.ai().int().nonnegative(),promptGuidelinePreview:i.nullable()}).strict()),skills:e.YO(e.Ik({name:e.Yj(),description:e.Yj(),path:e.Yj(),filePath:e.Yj(),modelVisible:e.zM()}).strict()),prompts:e.YO(e.Ik({name:e.Yj(),description:e.Yj(),path:e.Yj(),filePath:e.Yj()}).strict()),themes:e.YO(e.Ik({name:e.Yj(),path:e.Yj()}).strict()),providers:e.YO(e.Ik({name:e.Yj(),kind:e.k5(["config","native"])}).strict())}).strict()),loadError:e.Yj().nullable()}).strict();async function l(a,b){let c=(0,f.I)(),e=(0,d.join)(process.cwd(),"src","server","l4_foundation","pi","l4-pi-plugin-capability-probe-runner.mts"),{stdout:i,stderr:j,code:l}=await (0,g.i)({args:["--conditions=react-server","--import",c,e],agentDir:b,env:{PI_DESK_PLUGIN_CAPABILITY_AGENT_DIR:b,PI_DESK_PLUGIN_CAPABILITY_CWD:a},maxOutputBytes:4194304,timeoutMs:3e4,timeoutError:()=>Error("插件能力盘点超时"),cleanupError:(a,b)=>Error(`${a}
|
|
6
|
-
能力盘点进程树清理失败`,{cause:b})});if(0!==l)throw Error(j.trim()||`插件能力盘点进程退出码 ${l??"null"}`);let m=i.lastIndexOf(h);if(m<0)throw Error("插件能力盘点没有返回有效结果");let n=i.slice(m+h.length).split(/\r?\n/,1)[0];return k.parse(JSON.parse(n))}},64253:(a,b,c)=>{let d;c.d(b,{B:()=>n,I:()=>o});var e=c(31421),f=c(73024),g=c(51455),h=c(76760),i=c(48161);let j=(0,c(57975).promisify)(e.execFile);function k(a){return a.replace(/\$\{([^}]+)\}/g,(a,b)=>process.env[b]??a)}async function l(a,b){let c;try{let b=await (0,g.readFile)(a);if(b.length>262144)throw Error("npm 配置文件过大");c=b.toString("utf8")}catch(a){if("ENOENT"===a.code)return;throw a}for(let a of c.split(/\r?\n/)){let c=/^\s*([^;#][^=]*?)\s*=\s*(.*?)\s*$/.exec(a);if(!c)continue;let d=c[2].replace(/\s+[;#].*$/,"").replace(/^(['"])(.*)\1$/,"$2");b[c[1].trim()]=k(d)}}async function m(){let a=function(){for(let a of[(0,h.dirname)(process.execPath),...(process.env.PATH??"").split("win32"===process.platform?";":":")])for(let b of[(0,h.join)(a,"node_modules/npm/bin/npm-cli.js"),(0,h.resolve)(a,"../lib/node_modules/npm/bin/npm-cli.js")])if((0,f.existsSync)(b))return b}(),b={};if(a)try{let c=await j(process.execPath,[a,"config","list","--json"],{cwd:process.cwd(),timeout:4e3,maxBuffer:524288,windowsHide:!0});b=JSON.parse(c.stdout)}catch{console.warn("[Pi Desk][PluginRegistry] npm 有效配置读取失败,改用 npmrc 和环境配置")}let c={};a&&await l((0,h.resolve)((0,h.dirname)(a),"../npmrc"),c);let d="string"==typeof b.prefix?b.prefix:(0,h.dirname)(process.execPath),e="string"==typeof b.globalconfig?b.globalconfig:(0,h.join)(d,"etc/npmrc"),g=process.env.NPM_CONFIG_USERCONFIG??process.env.npm_config_userconfig??("string"==typeof b.userconfig?b.userconfig:(0,h.join)((0,i.homedir)(),".npmrc"));await l(e,c),await l(g,c);let m="string"==typeof b["local-prefix"]?b["local-prefix"]:process.cwd();for(let[a,d]of(await l((0,h.join)(m,".npmrc"),c),Object.entries(b)))"string"!=typeof d||"(protected)"===d||/auth|password|username/i.test(a)||(c[a]=d);for(let[a,b]of Object.entries(process.env))if(void 0!==b&&/^npm_config_/i.test(a)){let d=a.slice(11);c[d.startsWith("//")?d:d.replace(/(?!^)_/g,"-").toLowerCase()]=k(b)}return c}function n(){let a=process.cwd();if(!d||d.cwd!==a||d.expires<=Date.now()){let b=m();d={cwd:a,expires:Date.now()+3e4,value:b},b.catch(()=>{d?.value===b&&(d=void 0)})}return d.value}function o(a,b){let c=`//${a.host}${a.pathname}`;for(let a of Object.keys(b).flatMap(a=>{let b=/^(\/\/.*\/):(?:_authToken|_auth|username|_password)$/i.exec(a);return b&&c.startsWith(b[1])?[b[1]]:[]}).sort((a,b)=>b.length-a.length)){let c=b[`${a}:_authToken`]??b[`${a}:_authtoken`];if(c&&!c.includes("${"))return`Bearer ${c}`;let d=b[`${a}:_auth`];if(d&&!d.includes("${"))return`Basic ${d}`;let e=b[`${a}:username`],f=b[`${a}:_password`];if(e&&f&&!f.includes("${"))return`Basic ${Buffer.from(`${e}:${Buffer.from(f,"base64").toString("utf8")}`).toString("base64")}`}let d=b.registry;if(d){let c=new URL(d);if(a.origin===c.origin&&a.pathname.startsWith(`${c.pathname.replace(/\/+$/,"")}/`)){let a=b._authToken??b._authtoken;if(a&&!a.includes("${"))return`Bearer ${a}`;if(b._auth&&!b._auth.includes("${"))return`Basic ${b._auth}`}}}},69371:(a,b,c)=>{c.d(b,{rZ:()=>g,wC:()=>h});var d=c(76760),e=c(86148),f=c(2472);class g extends Error{constructor(a,b,c){super(b.slice(-4e3)||`Pi Package 命令退出码 ${c??"null"}`),this.kind=a,this.output=b,this.exitCode=c,this.name="L4PiPackageMaintenanceError"}}async function h(a){let b=(0,e.I)(),c=(0,d.join)(process.cwd(),"src","server","l4_foundation","pi","l4-pi-package-maintenance-runner.mts"),{stdout:h,stderr:i,code:j}=await (0,f.i)({args:["--import",b,c,a.maintenance.action,a.maintenance.source,...a.maintenance.registry?[a.maintenance.registry]:[]],agentDir:a.agentDir,env:{PI_DESK_PACKAGE_MAINTENANCE_CWD:a.cwd},maxOutputBytes:1048576,timeoutMs:12e4,timeoutError:()=>new g("failed","包维护超过120秒,已停止;结果未确认,请检查配置后手动处理",null),cleanupError:(a,b)=>new g("failed",`维护进程树未确认释放:${b instanceof Error?b.message:String(b)}`,null)});if(0===j)return;let k=(i||h).trim();throw new g(function(a){let b=a.toLowerCase();if(b.includes("ebusy")||b.includes("etxtbsy")||b.includes("resource busy")||b.includes("being used by another process")||b.includes("used by another process")||b.includes("process cannot access the file because it is being used"))return"locked";let c=b.includes("eperm")||b.includes("eacces")||b.includes("operation not permitted"),d=/\b(unlink|rename|rmdir|rimraf|remove|cleanup)\b/.test(b);return c&&d?"locked":"failed"}(k),k,j)}},69375:(a,b,c)=>{c.d(b,{Od:()=>r,tU:()=>n,hE:()=>q,P9:()=>f,_G:()=>j,Vc:()=>i});var d=c(36153);d.Yj().uuid();let e=d.Ik({key:d.Yj().min(1).max(160),params:d.g1(d.Yj().min(1).max(80),d.KC([d.Yj().max(1e3),d.ai().finite()])).optional()}).strict(),f=4001,g=d.Yj().trim().min(1),h=d.Yj().uuid();function i(a){return Object.freeze({op:"req",path:g.parse(a.path),inputSchema:a.inputSchema,outputSchema:a.outputSchema,...void 0===a.timeoutMs?{}:{timeoutMs:d.ai().int().positive().parse(a.timeoutMs)}})}function j(a){return Object.freeze({op:"push",path:g.parse(a.path),bodySchema:a.bodySchema})}let k=d.Ik({op:d.eu("req"),path:g,requestId:h}).strict(),l=d.Ik({op:d.eu("resp"),path:g,requestId:h}).strict(),m=d.Ik({op:d.eu("push"),path:g}).strict(),n=d.Ik({head:k,body:d.Pq()}).strict(),o=d.Ik({head:l,body:d.Ik({code:d.eu(0),msg:d.eu(""),data:d.Pq()}).strict()}).strict(),p=d.Ik({head:l,body:d.Ik({code:d.ai().int().positive(),msg:d.Yj().min(1),data:d.ch(),i18n:e.optional()}).strict()}).strict(),q=d.KC([o,p]),r=d.Ik({head:m,body:d.Pq()}).strict()},72497:(a,b,c)=>{c.d(b,{Dz:()=>h,f7:()=>g,tv:()=>f});var d=c(36153);let e=d.Yj().trim().min(1).max(64).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),f=e,g=e,h=d.g1(d.Yj(),d.Pq());d.Yj().trim().min(3).max(129).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*\/[a-z0-9]+(?:-[a-z0-9]+)*$/);let i=d.k5(["plugin","server","rocket","settings","panel","message","terminal","file","folder","bot","wrench","database","globe"]);d.gM("type",[d.Ik({type:d.eu("builtin"),name:i}).strict(),d.Ik({type:d.eu("svg"),content:d.Yj().trim().min(1).max(16384)}).strict()])},73159:(a,b,c)=>{c.d(b,{NL:()=>i,XH:()=>f,Yq:()=>j});var d=c(77598),e=c(64253);class f extends Error{constructor(a,b=502,c="invalid"){super(a),this.status=b,this.reason=c,this.name="L4PluginRegistryError"}}let g=new Map,h=0;async function i(a,b){b.signal?.throwIfAborted();let c=!1===b.auth?{}:await (0,e.B)(),i=(0,e.I)(a,c),j=`${a.href}:${b.limit}:${(0,d.createHash)("sha256").update(i??"").digest("hex")}`,k=g.get(j);if(!1!==b.cache&&k&&k.expires>Date.now())return k.body;let l=AbortSignal.any([AbortSignal.timeout(b.timeout??1e4),...b.signal?[b.signal]:[]]),m=a;try{for(let a=0;a<=3;a++){let d=(0,e.I)(m,c),i=await fetch(m,{signal:l,redirect:"manual",headers:d?{Authorization:d}:{}});if([301,302,303,307,308].includes(i.status)){await i.body?.cancel();let b=i.headers.get("location");if(!b||3===a)throw new f("插件源重定向无效");let c=new URL(b,m);if(!["http:","https:"].includes(c.protocol)||c.username||c.password||"https:"===m.protocol&&"https:"!==c.protocol)throw new f("插件源重定向不安全");m=c;continue}if(!i.ok){await i.body?.cancel();let a=404===i.status?"missing":[401,403].includes(i.status)?"denied":i.status>=500?"network":"invalid";throw new f(`插件源请求失败(HTTP ${i.status})`,i.status,a)}if(Number(i.headers.get("content-length")??0)>b.limit)throw await i.body?.cancel(),new f("插件源响应超过大小限制");let k=i.body?.getReader(),n=[],o=0;if(k)try{for(;;){let a=await k.read();if(a.done)break;if((o+=a.value.byteLength)>b.limit)throw new f("插件源响应超过大小限制");n.push(a.value)}}finally{await k.cancel().catch(()=>void 0),k.releaseLock()}let p=Buffer.concat(n);if(!1!==b.cache){for(let[a,b]of g)(b.expires<=Date.now()||a===j)&&(g.delete(a),h-=b.body.length);for(;g.size>=96||h+p.length>0x1800000;){let a=g.entries().next().value;if(!a)break;g.delete(a[0]),h-=a[1].body.length}p.length<=0x1800000&&(g.set(j,{body:p,expires:Date.now()+12e4}),h+=p.length)}return p}throw new f("插件源重定向过多")}catch(a){if(b.signal?.aborted)throw b.signal.reason;if(a instanceof f)throw a;throw new f("插件源网络连接失败或超时",502,"network")}}async function j(a,b){let c=await i(a,{limit:8388608,signal:b});try{let a=JSON.parse(c.toString("utf8"));if(!a||"object"!=typeof a||Array.isArray(a))throw Error("invalid");return a}catch{throw new f("插件源返回的元数据格式无效")}}},75157:(a,b,c)=>{c.d(b,{c:()=>g});var d=c(51455),e=c(76760);async function f(a){try{return(await (0,d.stat)(a)).isDirectory()}catch{return!1}}async function g(a){let b=a.configured.flatMap(a=>{let b=function(a){if(!a.startsWith("npm:"))return null;let b=a.slice(4).trim(),c=b.match(/^(@?[^@]+(?:\/[^@]+)?)(?:@(.+))?$/);return c?.[1]??(b||null)}(a.source);return b?[{name:b,item:a}]:[]}),c=(0,e.join)(a.agentDir,"npm","package.json"),g={};try{let a=JSON.parse(await (0,d.readFile)(c,"utf8"));a.dependencies&&"object"==typeof a.dependencies&&(g=a.dependencies)}catch(c){if(0===b.length)return null;let a=c instanceof Error&&c.message?c.message:String(c);return{message:`Pi Package npm 根不可用:${a}`,englishMessage:`Pi Package npm root is unavailable: ${a}`,i18n:{key:"errors:pluginNpmRootUnavailable",params:{detail:a.slice(0,1e3)}}}}let h=new Set(b.map(a=>a.name)),i=new Set(Object.keys(g)),j=[...h].filter(a=>!i.has(a)),k=[];for(let{name:a,item:c}of b)c.installedPath&&await f(c.installedPath)||k.push(a);if(0===j.length&&0===k.length)return null;let l=[j.length>0?`缺少声明:${j.join("、")}`:null,k.length>0?`缺少目录:${k.join("、")}`:null].filter(a=>null!==a),m=[j.length>0?`missing declarations: ${j.join(", ")}`:null,k.length>0?`missing folders: ${k.join(", ")}`:null].filter(a=>null!==a),n=j.length>0?k.length>0?"errors:pluginNpmRootMissingBoth":"errors:pluginNpmRootMissingDeclarations":"errors:pluginNpmRootMissingFolders";return{message:`Pi Package 配置与 npm 根不一致(${l.join(";")})`,englishMessage:`Pi Package configuration does not match the npm root (${m.join("; ")})`,i18n:{key:n,params:{declarations:j.join(", ").slice(0,1e3),folders:k.join(", ").slice(0,1e3)}}}}},76019:(a,b,c)=>{c.d(b,{J8:()=>f,fD:()=>g,qf:()=>e});var d=c(36153);let e=d.KC([d.Yj(),d.Ik({default:d.Yj(),translations:d.g1(d.Yj().min(1).max(35),d.Yj()).refine(a=>Object.keys(a).length<=16,"too many translations")}).strict()]);function f(a,b){return{default:a,translations:{en:b}}}function g(a,b){return"string"==typeof a?a:a.translations[b]??a.translations[b.split("-")[0]]??a.default}},78597:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{E:()=>k});var e=c(75430),f=c(4287),g=c(5235),h=c(34458),i=c(47154),j=a([e,g,h]);[e,g,h]=j.then?(await j)():j;class k{constructor(a,b,c){this.agentDir=a,this.cwd=b,this.signal=c,this.cache=new Map}async resolveInstall(a,b,c,d){let e=(0,f.ug)(a),i=e?/^npm:(?:@[^/]+\/)?[^@]+@([^@]+)$/.exec(a)?.[1]:void 0,j=i&&!/^v?\d+\./.test(i)&&f.mR.safeParse(i).success?i:null,k=e?d?(0,g.ey)(b,this.agentDir):c.tag??j??(0,g.ey)(b,this.agentDir):null,l=e&&k&&(d||!i)?`npm:${e}@${k}`:a;return{...await (0,h.dz)(l,{...c,agentDir:this.agentDir,signal:this.signal,cache:!d&&void 0}),updateTag:k}}clear(a){let b=(0,f.LD)(a);for(let[a,c]of this.cache)c.identity===b&&this.cache.delete(a)}async read(a,b){for(let[a,b]of this.cache)b.expiresAt<=Date.now()&&this.cache.delete(a);let c=b.sources?new Set(b.sources.map(f.LD)):null,d=new Map;for(let j of a){if("package"!==j.kind)continue;let a=(0,f.LD)(j.source),k=(0,f.ug)(j.source),l=k?(0,g.ey)(j.source,this.agentDir):null,m={updateTag:l,updateAvailable:null,availableVersion:null,updateError:null};d.set(j.source,m);let n=!0===b.checkUpdates&&(!c||c.has(a))&&(!b.tag||b.tag===l);if(k){if(!n&&![...this.cache.values()].some(b=>b.identity===a))continue;let b=null;try{let c=await (0,h.qX)(k,{agentDir:this.agentDir});b=JSON.stringify([a,l,c.registry,c.fallback]);let e=this.cache.get(b)?.value;if(n){if(!j.path||!j.version)throw Error("无法读取插件已安装版本");let c=await (0,h.dz)(`npm:${k}@${l}`,{agentDir:this.agentDir,signal:this.signal,cache:!1}),d=c.source.slice(c.source.lastIndexOf("@")+1);e={...m,availableVersion:d},this.store(b,a,e)}e&&d.set(j.source,{...e,updateAvailable:!e.updateError&&j.version&&e.availableVersion?(0,f.zj)(e.availableVersion,j.version):null})}catch(e){let c={...m,updateError:this.message(j.source,e)};d.set(j.source,c),b&&this.store(b,a,c)}}else if(/^(?:git:|https?:|git@)/.test(j.source)){let b=JSON.stringify([a,"git"]),c=this.cache.get(b)?.value;if(c&&d.set(j.source,c),!n)continue;try{let c=e.SettingsManager.inMemory({packages:[j.source]}),f=new e.DefaultPackageManager({agentDir:this.agentDir,cwd:this.cwd,settingsManager:c}),g=await (0,i.V)(()=>f.checkForAvailableUpdates()),h={...m,updateAvailable:g.some(a=>"user"===a.scope)};d.set(j.source,h),this.store(b,a,h)}catch(e){let c={...m,updateError:this.message(j.source,e)};d.set(j.source,c),this.store(b,a,c)}}}return d}store(a,b,c){for(this.cache.delete(a);this.cache.size>=128;){let a=this.cache.keys().next().value;if(void 0===a)break;this.cache.delete(a)}this.cache.set(a,{identity:b,expiresAt:Date.now()+3e5,value:c})}message(a,b){let c=(b instanceof Error?b.message:String(b)).slice(0,4e3);return console.warn("[Pi Desk][PluginManagement] 检查插件更新失败",{source:a,message:c}),this.clear(a),c}}d()}catch(a){d(a)}})},86148:(a,b,c)=>{function d(a){let b=a.replaceAll("\\","/");return"tsx"===b||/(?:^|\/)tsx(?:\/|$)/.test(b)}function e(a=process.execArgv){for(let b=0;b<a.length;b+=1){let c=a[b];if("--import"===c){let c=a[b+1];if(c&&d(c))return c;b+=1;continue}if(c.startsWith("--import=")){let a=c.slice(9);if(d(a))return a}}throw Error("Pi Desk 服务缺少 tsx loader,无法启动插件维护子进程")}c.d(b,{I:()=>e})},93951:(a,b,c)=>{c.d(b,{LC:()=>E,tA:()=>G,oP:()=>H});var d=c(36153),e=c(72497),f=c(76019),g=c(4287),h=c(69375);let i=g.SZ,j=g.w3;d.Ik({downloadSource:j,recommendedRegistry:i}).strict(),d.Ik({downloadSource:j}).strict(),d.Ik({query:d.Yj().trim().max(200).default(""),page:d.ai().int().min(1).max(100).default(1),kind:d.k5(["all","desk","pi"]).default("all"),registry:i.optional()}).strict(),d.Ik({name:d.Yj().trim().min(1).max(214).regex(/^(?:@[a-z0-9_.-]+\/)?[a-z0-9][a-z0-9_.-]*$/i),version:d.Yj().trim().min(1).max(128).optional(),registry:i.optional()}).strict();let k=d.Ik({name:d.Yj(),description:f.qf.nullable(),version:d.Yj(),publisher:d.Yj().nullable(),kind:d.k5(["desk","pi","unknown"]),official:d.zM(),registry:i}).strict();d.Ik({items:d.YO(k),hasMore:d.zM()}).strict(),k.extend({versions:d.YO(d.Yj()),readme:f.qf.nullable(),homepage:d.Yj().nullable(),repository:d.Yj().nullable(),compatible:d.zM().nullable(),compatibilityNote:d.Yj().nullable()}).strict();let l=d.Yj().trim().min(1).max(2048),m=g.mR,n=d.YO(l).min(1).max(32),o=d.Ik({phase:d.k5(["package","entry","setup","resources","resolve","native"]),message:f.qf.refine(a=>"string"==typeof a?a.length>0:a.default.length>0)}).strict(),p=d.Yj().trim().min(1).max(4096),q=d.Yj().trim().min(1).max(256),r=d.Yj().max(32768),s=d.Ik({name:q,label:r,state:d.k5(["active","inactive","shadowed"]),description:r,promptSnippet:r.nullable(),promptGuidelineCount:d.ai().int().nonnegative(),promptGuidelinePreview:r.nullable()}).strict(),t=d.Ik({name:q,label:r,state:d.k5(["active","inactive","shadowed"]),description:r,parameters:e.Dz,promptSnippet:r.nullable(),promptGuidelines:d.YO(r)}).strict(),u=d.Ik({path:p,events:d.YO(d.Ik({name:q,count:d.ai().int().positive()}).strict()),commands:d.YO(d.Ik({name:q,description:r.nullable()}).strict()),shortcuts:d.YO(d.Ik({shortcut:q,description:r.nullable()}).strict()),flags:d.YO(d.Ik({name:q,type:d.k5(["boolean","string"]),description:r.nullable(),default:d.KC([d.zM(),d.Yj(),d.ch()])}).strict()),messageRenderers:d.YO(q),entryRenderers:d.YO(q)}).strict(),v=d.Ik({name:q,description:r,path:p}).strict(),w=v.extend({modelVisible:d.zM()}).strict(),x=v.extend({content:d.Yj().max(65536),truncated:d.zM()}).strict(),y=x.extend({modelVisible:d.zM()}).strict(),z=d.Ik({name:q,path:p}).strict(),A=d.Ik({name:q,kind:d.k5(["config","native"])}).strict(),B=d.Ik({methods:d.YO(d.Ik({pluginName:q,method:q}).strict()),browserEntries:d.YO(d.Ik({pluginName:q}).strict()),messageDeclarations:d.YO(d.Ik({pluginName:q,declarationName:q,priority:d.ai().int().safe()}).strict())}).strict(),C=d.Ik({error:f.qf.refine(a=>"string"==typeof a?a.length<=32768:[a.default,...Object.values(a.translations)].every(a=>a.length<=32768)).nullable(),extensions:d.YO(u),tools:d.YO(s),skills:d.YO(w),prompts:d.YO(v),themes:d.YO(z),providers:d.YO(A),piDesk:B}).strict(),D=d.Ik({action:d.k5(["add","update","del","apply","enable","disable"]),phase:d.k5(["queued","checking","applying","waiting","failed"]),message:d.Yj().max(4e3).nullable()}).strict(),E=(0,h._G)({path:"plugins/management-update",bodySchema:d.Ik({}).strict()}),F=d.Ik({source:l,kind:d.k5(["package","extension"]).default("package"),operation:D.nullable().default(null),pluginName:d.Yj().trim().min(1).nullable(),description:f.qf.nullable().default(null),version:d.Yj().trim().min(1).nullable(),updateAvailable:d.zM().nullable(),updateTag:m.nullable().optional(),availableVersion:d.Yj().min(1).nullable().optional(),updateError:d.Yj().max(4e3).nullable().optional(),status:d.k5(["ready","available","disabled","failed"]),error:o.nullable(),capabilities:C}).strict(),G=d.Ik({source:l,readme:f.qf.nullable().default(null),tools:d.YO(t),skills:d.YO(y),prompts:d.YO(x)}).strict(),H=d.Ik({plugins:d.YO(F),restartRequired:d.zM(),loadError:f.qf.refine(a=>"string"==typeof a?a.length>0:a.default.length>0).nullable()}).strict();d.Ik({sources:d.YO(l).min(1).max(32).optional()}).strict(),d.Ik({}).strict().extend({mode:d.k5(["normal","basic"]).optional()}).strict(),d.Ik({checkUpdates:d.zM().optional(),sources:n.optional(),tag:m.optional()}).strict();let I=d.Ik({source:l}).strict(),J=I.extend({downloadSource:j.optional(),registry:i.optional(),tag:m.optional()}).strict();d.gM("action",[d.Ik({action:d.eu("add"),items:d.YO(J).min(1).max(32)}).strict(),d.Ik({action:d.eu("update"),sources:n}).strict(),d.Ik({action:d.eu("del"),sources:n}).strict(),d.Ik({action:d.eu("tag"),sources:n,tag:m}).strict()]),d.Ik({snapshot:H,results:d.YO(d.Ik({source:l,error:d.Yj().max(4e3).nullable()}).strict()).max(32)}).strict(),I.extend({enabled:d.zM()}).strict()},96783:(a,b,c)=>{c.d(b,{Y:()=>j});var d=c(76760),e=c(36153),f=c(86148),g=c(2472);let h="__PI_DESK_PLUGIN_PROBE__",i=e.Ik({packages:e.YO(e.Ik({source:e.Yj(),packageName:e.Yj().nullable(),version:e.Yj().nullable(),pluginName:e.Yj().nullable(),status:e.k5(["ready","failed"]),error:e.Ik({phase:e.k5(["package","entry","setup","resources","resolve"]),message:e.Yj()}).strict().nullable()}).strict()),loadError:e.Yj().nullable()}).strict();async function j(a,b,c=!1){let e=(0,f.I)(),k=(0,d.join)(process.cwd(),"src","server","l4_foundation","pi","l4-pi-plugin-probe-runner.mts"),{stdout:l,stderr:m,code:n}=await (0,g.i)({args:["--conditions=react-server","--import",e,k],agentDir:b,env:{PI_DESK_PLUGIN_PROBE_AGENT_DIR:b,PI_DESK_PLUGIN_PROBE_CWD:a,PI_DESK_PLUGIN_PROBE_NATIVE:c?"1":void 0},maxOutputBytes:1048576,timeoutMs:3e4,timeoutError:()=>Error("插件预检超时"),cleanupError:(a,b)=>Error(`${a}
|
|
5
|
+
… (truncated)`)}(a?.error??c),extensions:a?.extensions??[],tools:a?.tools.map(a=>({name:a.name,label:a.label,state:a.state,description:a.description,promptSnippet:a.promptSnippet,promptGuidelineCount:a.promptGuidelineCount,promptGuidelinePreview:a.promptGuidelinePreview}))??[],skills:a?.skills.map(a=>({name:a.name,description:a.description,path:a.path,modelVisible:a.modelVisible}))??[],prompts:a?.prompts.map(a=>({name:a.name,description:a.description,path:a.path}))??[],themes:a?.themes??[],providers:a?.providers??[],piDesk:{methods:b?[...b.methods]:[],browserEntries:b?[...b.browserEntries]:[],messageDeclarations:b?[...b.messageDeclarations]:[]}}}class P{get restartRequired(){return this.deferredMaintenance.size>0}constructor(a,b=process.cwd(),c=(0,k.getAgentDir)()){this.workSessions=a,this.cwd=b,this.agentDir=c,this.operationTail=Promise.resolve(),this.operations=new Map,this.listeners=new Set,this.lifetime=new AbortController,this.disposed=!1,this.activeSource=null,this.sourceCache=null,this.capabilityCache=null,this.deferredMaintenance=new Map;const d=(0,h.createHash)("sha256").update(this.agentDir).digest("hex").slice(0,16);this.stagingRoot=(0,j.join)(this.cwd,"temp","pi",`plugin-management-${d}`),this.packageManagerCwd=(0,j.join)((0,f.M)(),"plugin-package-manager"),this.updates=new y.E(this.agentDir,this.packageManagerCwd,this.lifetime.signal),this.maintenanceError=process.env.PI_DESK_PLUGIN_MAINTENANCE_ERROR?.trim()||null,this.unsubscribeRuntime=(0,p.getL4PiGlobalPluginRuntime)().subscribeChanges(()=>this.publish()),this.staleStagingCleanup=(0,i.rm)(this.stagingRoot,{recursive:!0,force:!0}).catch(a=>{console.warn("[Pi Desk][PluginManagement] 清理上次中断的候选目录失败",{path:this.stagingRoot,errorName:a instanceof Error?a.name:"UnknownError"})})}list(a=!1){return this.assertOpen(),this.readSnapshot(a)}async batch(a){this.assertOpen();let b=[],c=new Set;for(let d of"add"===a.action?a.items:a.sources.map(a=>({source:a})))try{let e="add"===a.action?this.normalizeAddedSource(d.source):d.source,f=(0,m.LD)(e);if(c.has(f))throw new K("批量请求中包含重复来源");if(c.add(f),"add"===a.action){let{source:a,...b}=d;await this.reinstall(e,void 0,b)}else"update"===a.action?await this.update(e):"del"===a.action?await this.del(e):await this.setUpdateTag(e,a.tag);b.push({source:d.source,error:null})}catch(a){b.push({source:d.source,error:C(a).slice(0,4e3)})}return{snapshot:await this.readSnapshot(!1),results:b}}subscribe(a){return this.assertOpen(),this.listeners.add(a),()=>this.listeners.delete(a)}get(a){return this.assertOpen(),this.readDetail(a)}add(a,b={}){return this.mutate("add",this.normalizeAddedSource(a),!1,void 0,b)}setEnabled(a,b){return this.mutate(b?"enable":"disable",a)}async update(a){if(this.assertOpen(),(0,e.P)())throw new K("基础模式不执行插件维护");this.assertSourceIdle(a);let b=(await this.readSources()).sources.find(b=>(0,m.LD)(b.source)===(0,m.LD)(a));if(!b)throw new J(a);if((0,m.ug)(b.source)){let a=await this.readSnapshot({checkUpdates:!0,sources:[b.source]}),c=a.plugins.find(a=>a.source===b.source);if(c.updateError)throw new L(c.updateError);if(!0!==c.updateAvailable)return a}return this.mutate("update",b.source)}reinstall(a,b,c={}){return this.mutate("add",this.normalizeAddedSource(a),!0,b,c)}async setUpdateTag(a,b){if(this.assertOpen(),(0,e.P)())throw new K("基础模式不执行插件维护");let c=(await this.readSources()).sources.find(b=>(0,m.LD)(b.source)===(0,m.LD)(a));if(!c)throw new J(a);if("package"!==c.kind||!(0,m.ug)(c.source))throw new L("只有 npm 插件包支持更新渠道");this.assertSourceIdle(c.source),(0,o.ks)(c.source,m.mR.parse(b),this.agentDir),this.updates.clear(c.source),this.publish()}assertSourceIdle(a){let b=(0,m.LD)(a);if(this.activeSource&&(0,m.LD)(this.activeSource)===b||[...this.operations].some(([a,c])=>(0,m.LD)(a)===b&&"failed"!==c.phase))throw new K("该来源已有未完成的维护操作")}waitForOperations(a,b){return b=AbortSignal.any([b,this.lifetime.signal]),new Promise((c,d)=>{let e=()=>void 0,f=a=>{e(),b.removeEventListener("abort",g),a?d(a):c()},g=()=>f(Error(this.disposed?"插件管理已关闭":"发起命令的会话已关闭")),h=()=>{if(this.disposed)return f(Error("插件管理已关闭"));for(let b of a){let a=this.operations.get(b);if(a?.phase==="failed")return f(Error(a.message??"插件操作失败"));if(a?.phase==="waiting"&&this.activeSource!==b&&this.restartRequired)return f(Error(`插件尚未生效,需要在设置的插件管理中重启 Pi Desk。${a.message??""}`))}a.some(a=>this.operations.has(a)||this.activeSource===a)||f()};if(b.aborted)return g();e=this.subscribe(h),b.addEventListener("abort",g,{once:!0}),h()})}del(a){return this.mutate("del",a)}async apply(a){if(this.assertOpen(),(0,e.P)())throw new K("基础模式不加载外部插件");if(a?.some(a=>this.deferredMaintenance.has(a)))throw new N;let b=await (0,p.getL4PiGlobalPluginRuntime)().scanSourceChanges(a);this.assertOpen();let c=b.filter(b=>{if(this.deferredMaintenance.has(b.source))return!1;let c=this.operations.get(b.source);if(!c||"failed"===c.phase)return!0;if(a)throw new K("该来源已有未完成操作");return!1}),d=new Set([...this.operations].filter(([,a])=>"failed"!==a.phase).map(([a])=>a));for(let a of c)d.add(a.source);if(d.size>32)throw new K("加载变更超过队列上限,请选择部分来源");for(let a of c){if(!this.operations.has(a.source)&&this.operations.size>=64){let a=[...this.operations].find(([,a])=>"failed"===a.phase);a&&this.operations.delete(a[0])}this.operations.set(a.source,{action:"apply",phase:"queued",message:null}),this.enqueueApply(a)}return this.publish(),this.readSnapshot(!1)}enqueueApply(a){this.runExclusive(async()=>{this.activeSource=a.source;try{this.setOperation(a.source,"checking",null),await this.probeSourceChange(a),this.assertOpen(),this.setOperation(a.source,"applying",null),await (0,p.getL4PiGlobalPluginRuntime)().applySourceChange(a),a.current?.path&&(0,u.tt)(a.current.path),a.previous?.path&&(0,u.tt)(a.previous.path),this.capabilityCache=null,this.workSessions.refreshPluginMessages(),this.operations.delete(a.source)}catch(b){this.setOperation(a.source,"failed",C(b))}finally{this.activeSource=null,this.sourceCache=null,this.publish()}}).catch(b=>{this.disposed||this.setOperation(a.source,"failed",C(b))})}async probeSourceChange(a){let b=a.current;if(!b||!b.enabled)return;if(b.error)throw new L(b.error);if(!b.path)throw new L("插件来源目录不存在");let c=performance.now();console.info("[Pi Desk][PluginManagement] 源码候选预检开始",{source:a.source});let d=(0,j.join)(this.stagingRoot,(0,h.randomUUID)()),e=(0,j.join)(d,"agent"),f=(0,j.join)(d,"workspace");await (0,i.mkdir)(e,{recursive:!0}),await (0,i.mkdir)(f,{recursive:!0});try{if(await (0,i.writeFile)((0,j.join)(e,"settings.json"),JSON.stringify({extensions:[b.path]}),"utf8"),b.piDeskRoot||b.nativePaths.length>0){let c=await (0,w.Y)(f,e,b.nativePaths.length>0),d=c.loadError??c.packages.find(a=>"failed"===a.status)?.error?.message;if(d)throw new L(d);if(b.piDeskRoot&&!c.packages.some(a=>"ready"===a.status))throw new L("预检未加载到候选 Node Entry,放弃本次变更");for(let b of c.packages)if(b.pluginName&&(0,p.getL4PiGlobalPluginRuntime)().readDiagnostics().packages.some(c=>c.source!==a.source&&"ready"===c.status&&c.pluginName===b.pluginName))throw new L(`插件名冲突:${b.pluginName}`)}this.assertOpen()}finally{await (0,i.rm)(d,{recursive:!0,force:!0}),console.info("[Pi Desk][PluginManagement] 源码候选预检结束",{source:a.source,durationMs:Math.round(performance.now()-c)})}}reload(a){return this.activeSource?Promise.reject(new K("维护仍在执行或等待,请先完成当前操作")):this.runExclusive(async()=>(this.assertRestartAvailable(),this.restartWhenQuiet(a)))}async mutate(a,b,c=!1,d,f={}){if(this.assertOpen(),(0,e.P)())throw new K("基础模式不执行插件维护,请通过基础聊天修复或正常启动后维护");let g=await this.readSources();this.assertOpen();let h=g.sources.find(a=>(0,m.LD)(a.source)===(0,m.LD)(b));if("add"!==a){if(!h)throw new J(b);if("package"!==h.kind&&"enable"!==a&&"disable"!==a)throw new L("裸扩展不是已安装包,请编辑源码后加载变更;此操作不会删除源码")}let i=(d??=h?.source)??b;if(f.tag&&!(0,m.ug)(b))throw new L("只有 npm 插件包支持更新渠道");for(let a of[b,i])this.assertSourceIdle(a);if([...this.operations.values()].filter(a=>"failed"!==a.phase).length>=32)throw new K("插件维护队列已满,请等待当前操作完成");if(this.operations.size>=64){let a=[...this.operations].find(([,a])=>"failed"===a.phase);a&&this.operations.delete(a[0])}return d&&d!==b&&this.operations.get(d)?.phase==="failed"&&this.operations.delete(d),this.operations.set(i,{action:a,phase:"queued",message:null}),this.updates.clear(i),this.updates.clear(b),this.publish(),this.runExclusive(async()=>{this.activeSource=i;try{await this.executeMutation(a,b,i,c,f),this.deferredMaintenance.has(i)||this.operations.delete(i)}catch(a){this.setOperation(i,"failed",C(a))}finally{this.updates.clear(i),this.updates.clear(b),this.sourceCache=null,this.activeSource=null,this.publish()}}).catch(a=>{this.disposed||this.setOperation(i,"failed",C(a))}),this.readSnapshot(!1)}async executeMutation(a,b,c,d,e){let f=(0,p.getL4PiGlobalPluginRuntime)(),g=a=>this.setOperation(c,"waiting",a),h=this.createPackageManager();this.throwSettingsErrors(h.settingsManager);let i=h.packageManager.listConfiguredPackages().filter(a=>"user"===a.scope),j=i.find(a=>a.source===c),k=null,l=null;if("enable"!==a&&"disable"!==a){var n;let f=await (0,r.c)({agentDir:this.agentDir,configured:i});if(f)throw new M(f);if("add"!==a&&!j)throw new J(b);this.setOperation(c,"checking","正在确认插件版本和下载源");let h=this.candidateSource(b,j?.installedPath),p=(0,m.ug)(h),q="del"===a?{source:h,updateTag:null}:await this.updates.resolveInstall(h,c,e,"update"===a);if(l=q.updateTag,"update"===a&&p&&j?.installedPath){let a=await D(j.installedPath),b=q.source.slice(q.source.lastIndexOf("@")+1);if(!a.version)throw new L("无法读取插件已安装版本");if(!(0,m.zj)(b,a.version))return}if(k={...p&&"del"!==a&&(d||j||"update"===a)?{action:"reinstall",source:q.source}:(n=q.source,{action:"add"===a?"install":"update"===a?"update":"remove",source:n}),..."registry"in q&&q.registry?{registry:q.registry}:{}},"del"!==a&&await this.probeCandidate(q.source,c,k.registry),l&&((0,o.ks)(c,l,this.agentDir),this.updates.clear(c)),this.deferredMaintenance.size>0){this.deferredMaintenance.set(c,k),g("等待重启后完成安装维护");return}}this.assertOpen(),await f.withSourceIdle(c,async()=>{if(this.setOperation(c,"applying",k?.registry?`下载源:${k.registry}`:null),"enable"===a||"disable"===a){let c=(0,o.to)(this.agentDir).disabled.includes((0,m.LD)(b));(0,o.El)(b,"enable"===a,this.agentDir),this.sourceCache=null;try{if(await this.applyMutationSources([b],!0),"enable"===a&&!(await this.readSources()).sources.find(a=>a.source===b)?.enabled)throw new L("此插件仍被 Pi 配置排除,请先调整原有资源配置")}catch(a){throw(0,o.El)(b,!c,this.agentDir),this.sourceCache=null,a}}else if(k)try{await f.replaceSource(c,null),await (0,s.V)(async()=>{await (0,q.wC)({maintenance:k,agentDir:this.agentDir,cwd:this.packageManagerCwd}),"del"!==a&&await this.verifyInstalledPackage(k.source)}),this.sourceCache=null,await this.applyMutationSources([c,k.source],!1)}catch(a){if(a instanceof q.rZ&&"locked"===a.kind&&(0,x.k)())this.deferredMaintenance.set(c,k),g("文件正在被使用,需要重启后完成操作");else throw a}this.updates.clear(c),this.updates.clear(b),this.capabilityCache=null,this.workSessions.refreshPluginMessages()},this.lifetime.signal,g)}async verifyInstalledPackage(a){let b=this.createPackageManager();this.throwSettingsErrors(b.settingsManager);let c=(0,m.LD)(a),d=b.packageManager.listConfiguredPackages().find(a=>"user"===a.scope&&(0,m.LD)(a.source)===c);if(!d?.installedPath)throw new L("插件安装后没有有效目录");await this.verifyPackageVersion(a,d.installedPath)}async verifyPackageVersion(a,b){let c=await D(b);if(c.error)throw new L("string"==typeof c.error.message?c.error.message:c.error.message.default);if((0,m.ug)(a)){let b=a.slice(a.lastIndexOf("@")+1);if(c.version!==b)throw new L(`插件实际安装版本与目标不一致:${c.version??"未知"},目标 ${b}`)}}async applyMutationSources(a,b){let c=new Set(a.map(m.LD)),d=(0,p.getL4PiGlobalPluginRuntime)(),e=await d.scanSourceChanges(),f=await this.readSources(),g=[...new Set([...e.filter(a=>c.has((0,m.LD)(a.source))).map(a=>a.source),...f.sources.filter(a=>c.has((0,m.LD)(a.source))).map(a=>a.source)])];for(let a of g.length?await d.scanSourceChanges(g):[])b&&await this.probeSourceChange(a),await d.applySourceChange(a),a.current?.path&&(0,u.tt)(a.current.path),a.previous?.path&&(0,u.tt)(a.previous.path)}dispose(){this.disposed||(this.disposed=!0,this.lifetime.abort(),this.unsubscribeRuntime(),this.listeners.clear())}assertOpen(){if(this.disposed)throw new K("插件管理已关闭")}setOperation(a,b,c){let d=this.operations.get(a);if(!d)return;let e=c?.slice(0,4e3)??null;(d.phase!==b||d.message!==e)&&(this.operations.set(a,{...d,phase:b,message:e}),"failed"===b&&console.warn("[Pi Desk][PluginManagement] 插件操作失败",{source:a,action:d.action,message:e}),this.publish())}publish(){if(!this.disposed)for(let a of this.listeners)try{a()}catch(a){console.warn("[Pi Desk][PluginManagement] 状态监听失败",{message:C(a)})}}async readSources(){let a=()=>null!==this.activeSource&&this.operations.get(this.activeSource)?.phase==="applying";if(a()&&this.sourceCache)return this.sourceCache;let b=await (0,t.o)(this.packageManagerCwd,this.agentDir,{DefaultPackageManager:k.DefaultPackageManager,SettingsManager:k.SettingsManager});return a()&&this.sourceCache||(this.sourceCache=b),a()&&this.sourceCache?this.sourceCache:b}async probeCandidate(a,b,c){let d=(0,j.join)(this.stagingRoot,(0,h.randomUUID)()),e=(0,j.join)(d,"agent"),f=(0,j.join)(d,"workspace");await (0,i.mkdir)(f,{recursive:!0}),console.info("[Pi Desk][PluginManagement] 开始在隔离 AgentDir 预检候选插件",{source:a});try{if(!c&&(0,m.ug)(a))for(let b of[".npmrc",(0,j.join)("etc","npmrc")]){let c=(0,j.join)(e,"npm",b);await (0,i.mkdir)((0,j.dirname)(c),{recursive:!0});try{await (0,i.copyFile)((0,j.join)(this.agentDir,"npm",b),c),console.info("[Pi Desk][PluginManagement] 已为隔离预检继承本机 npm 配置",{source:a,configPath:b})}catch(a){if("ENOENT"!==a.code)throw new L(`无法继承本机 npm 配置(${b}):${C(a)}`)}}await (0,q.wC)({maintenance:{action:"install",source:a,...c?{registry:c}:{}},agentDir:e,cwd:f}),this.assertOpen();let d=this.createPackageManager(e,f);this.throwSettingsErrors(d.settingsManager);let g=d.packageManager.listConfiguredPackages().filter(a=>"user"===a.scope)[0];if(!g?.installedPath)throw new L("候选插件安装后没有有效目录");await this.verifyPackageVersion(a,g.installedPath);let h=await (0,w.Y)(f,e,!0);if(h.loadError)throw new L(h.loadError);let k=h.packages.find(a=>"failed"===a.status);if(k?.error)throw new L(k.error.message);let l=h.packages[0]?.pluginName;if(l&&(0,p.getL4PiGlobalPluginRuntime)().readDiagnostics().packages.find(a=>a.source!==b&&a.pluginName===l))throw new L(`pluginName 已由其他 Package 注册:${l}`);this.assertOpen(),console.info("[Pi Desk][PluginManagement] 候选插件隔离预检通过",{source:a})}catch(a){if(a instanceof L)throw a;throw new L(C(a))}finally{await (0,i.rm)(d,{recursive:!0,force:!0}).catch(a=>{console.warn("[Pi Desk][PluginManagement] 清理候选插件目录失败",{path:d,errorName:a instanceof Error?a.name:"UnknownError"})})}}restartWhenQuiet(a){return this.workSessions.runPluginRestart(async()=>{let b=(0,p.getL4PiGlobalPluginRuntime)(),c=await this.readSnapshot(!1);return await b.prepareReload(),console.info("[Pi Desk][PluginManagement] 插件 Runtime 已通过静默检查,准备重启",{deferredCount:this.deferredMaintenance.size}),(0,x.Z)("basic"===a||0===this.deferredMaintenance.size?void 0:[...this.deferredMaintenance.values()],a),c})}async readDetail(a){if((0,e.P)())throw new K("基础模式不执行插件能力盘点");let b=(await this.readSources()).sources.find(b=>b.source===a),c=b?await (0,t.W)(b):null;if(!c)throw new J(a);let d=await this.readCapabilities(!1),f=d.packages.find(b=>b.source===a);if(!f)throw Error(d.loadError??`插件能力详情不可用:${a}`);let[g,h]=await Promise.all([Promise.all(f.skills.map(async a=>({name:a.name,description:a.description,path:a.path,modelVisible:a.modelVisible,...await E(c,a.filePath)}))),Promise.all(f.prompts.map(async a=>({name:a.name,description:a.description,path:a.path,...await E(c,a.filePath)})))]);return l.tA.parse({source:a,readme:await (0,n.w$)(c),tools:f.tools.map(a=>({name:a.name,label:a.label,state:a.state,description:a.description,parameters:a.parameters,promptSnippet:a.promptSnippetDetail,promptGuidelines:a.promptGuidelines})),skills:g,prompts:h})}async readSnapshot(a){if((0,e.P)())return{plugins:[],restartRequired:!1,loadError:this.maintenanceError};let b=this.createPackageManager(),c=b.settingsManager.drainErrors().map(a=>a.error.message),d=b.packageManager.listConfiguredPackages().filter(a=>"user"===a.scope),f=await (0,r.c)({agentDir:this.agentDir,configured:d}),h=await this.readSources(),i=await this.updates.read(h.sources,"boolean"==typeof a?{checkUpdates:a}:a),j=(0,p.getL4PiGlobalPluginRuntime)(),k=j.readDiagnostics(),n=new Map(k.packages.map(a=>[a.source,a])),q=(0,u.u7)(),s=this.capabilityCache??{packages:[],loadError:null},t=new Map(s.packages.map(a=>[a.source,a])),v=new Map(j.readCapabilityRegistrations().map(a=>[a.source,a])),w=await Promise.all(h.sources.map(async a=>{let b=n.get(a.source),c=a.path?this.findNativeDiagnostic(a.path,q):null,d=(a.error?{phase:"package"===a.kind?"package":"entry",message:a.error}:null)??(b?.status==="failed"?b.error:null)??(c?{phase:"native",message:c}:null);return{source:a.source,kind:a.kind,operation:this.operationFor(a.source),pluginName:b?.pluginName??null,description:a.description,version:a.version??b?.version??null,updateAvailable:i.get(a.source)?.updateAvailable??null,updateTag:i.get(a.source)?.updateTag??null,availableVersion:i.get(a.source)?.availableVersion??null,updateError:i.get(a.source)?.updateError??null,status:a.enabled?d?"failed":b?.status==="ready"?"ready":"available":"disabled",error:d,capabilities:F(t.get(a.source),v.get(a.source),s.loadError)}}));for(let[a,b]of this.operations)w.some(b=>(0,m.LD)(b.source)===(0,m.LD)(a))||w.push({source:a,kind:"package",operation:b,pluginName:null,description:null,version:null,updateAvailable:null,updateTag:(0,m.ug)(a)?(0,o.ey)(a,this.agentDir):null,availableVersion:null,updateError:null,status:"failed"===b.phase?"failed":"available",error:null,capabilities:F(void 0,void 0,null)});return l.oP.parse({plugins:w.sort((a,b)=>a.source.localeCompare(b.source)),restartRequired:this.restartRequired,loadError:function(a){let b=[...new Map(a.flatMap(a=>{let b=("string"==typeof a?a:a.message).trim();return b?[[b,{defaultText:b,englishText:"string"==typeof a?b:a.englishMessage.trim()}]]:[]})).values()];if(0===b.length)return null;let c=b.map(a=>a.defaultText).join("; ");return b.every(a=>a.defaultText===a.englishText)?c:(0,g.J8)(c,b.map(a=>a.englishText).join("; "))}([...c,...h.errors,...k.loadError?[k.loadError]:[],...this.maintenanceError?[this.maintenanceError]:[],...f?[f]:[]])})}async readCapabilities(a){if(!a&&this.capabilityCache)return this.capabilityCache;try{return this.capabilityCache=await (0,s.V)(()=>(this.assertOpen(),!a&&this.capabilityCache)?Promise.resolve(this.capabilityCache):(0,v.a)(this.cwd,this.agentDir)),this.publish(),console.info("[Pi Desk][PluginManagement] 插件能力盘点完成",{packageCount:this.capabilityCache.packages.length,hasLoadError:null!==this.capabilityCache.loadError}),this.capabilityCache}catch(b){let a=C(b);return console.warn("[Pi Desk][PluginManagement] 插件能力盘点失败",{errorName:b instanceof Error?b.name:"UnknownError",message:a}),this.capabilityCache={packages:[],loadError:a},this.publish(),this.capabilityCache}}findNativeDiagnostic(a,b){let c,d=(c=(0,j.resolve)(a).replaceAll("\\","/"),"win32"===process.platform?c.toLowerCase():c),e=b.find(a=>("win32"===process.platform?a.message.replaceAll("\\","/").toLowerCase():a.message.replaceAll("\\","/")).includes(d));return e?.message??null}createPackageManager(a=this.agentDir,b=this.packageManagerCwd){let c=k.SettingsManager.create(b,a,{projectTrusted:!1});return{settingsManager:c,packageManager:new k.DefaultPackageManager({cwd:b,agentDir:a,settingsManager:c})}}candidateSource(a,b){return(0,j.isAbsolute)(a)||/^(?:[a-z][a-z0-9+.-]*:|git@)/i.test(a)?a:b?(0,j.resolve)(b):(0,j.resolve)(this.agentDir,a)}operationFor(a){let b=(0,m.LD)(a);return[...this.operations].find(([a])=>(0,m.LD)(a)===b)?.[1]??null}normalizeAddedSource(a){return/^(?:@[a-z0-9_.-]+\/)?[a-z0-9][a-z0-9_.-]*(?:@[^\s/]+)?$/i.test(a)?`npm:${a}`:(0,j.isAbsolute)(a)||/^(?:[a-z][a-z0-9+.-]*:|git@)/i.test(a)?a:(0,j.resolve)(this.cwd,a)}throwSettingsErrors(a){let b=a.drainErrors();if(0!==b.length)throw Error(b.map(a=>a.error.message).join("; "))}assertRestartAvailable(){if(!(0,x.k)())throw new O}runExclusive(a){let b=()=>this.staleStagingCleanup.then(()=>(this.assertOpen(),a())),c=this.operationTail.then(b,b);return this.operationTail=c.then(()=>void 0,()=>void 0),c}}function G(){globalThis.__piDeskPluginManagement?.dispose()}function H(a){globalThis.__piDeskPluginManagement||(globalThis.__piDeskPluginManagement=new P(a))}function I(){if(!globalThis.__piDeskPluginManagement)throw Error("插件管理尚未完成进程级装配");return globalThis.__piDeskPluginManagement}d()}catch(a){d(a)}})},53584:(a,b,c)=>{c.d(b,{a:()=>l});var d=c(76760),e=c(36153),f=c(86148),g=c(2472);let h="__PI_DESK_PLUGIN_CAPABILITIES__",i=e.Yj(),j=e.Ik({name:e.Yj(),description:e.Yj().nullable()}).strict(),k=e.Ik({packages:e.YO(e.Ik({source:e.Yj(),error:e.Yj().nullable(),extensions:e.YO(e.Ik({path:e.Yj(),events:e.YO(e.Ik({name:e.Yj(),count:e.ai().int().positive()}).strict()),commands:e.YO(j),shortcuts:e.YO(e.Ik({shortcut:e.Yj(),description:e.Yj().nullable()}).strict()),flags:e.YO(e.Ik({name:e.Yj(),type:e.k5(["boolean","string"]),description:e.Yj().nullable(),default:e.KC([e.zM(),e.Yj(),e.ch()])}).strict()),messageRenderers:e.YO(e.Yj()),entryRenderers:e.YO(e.Yj())}).strict()),tools:e.YO(e.Ik({name:e.Yj(),label:i,state:e.k5(["active","inactive","shadowed"]),description:i,parameters:e.g1(e.Yj(),e.Pq()),promptSnippet:i.nullable(),promptSnippetDetail:i.nullable(),promptGuidelines:e.YO(i),promptGuidelineCount:e.ai().int().nonnegative(),promptGuidelinePreview:i.nullable()}).strict()),skills:e.YO(e.Ik({name:e.Yj(),description:e.Yj(),path:e.Yj(),filePath:e.Yj(),modelVisible:e.zM()}).strict()),prompts:e.YO(e.Ik({name:e.Yj(),description:e.Yj(),path:e.Yj(),filePath:e.Yj()}).strict()),themes:e.YO(e.Ik({name:e.Yj(),path:e.Yj()}).strict()),providers:e.YO(e.Ik({name:e.Yj(),kind:e.k5(["config","native"])}).strict())}).strict()),loadError:e.Yj().nullable()}).strict();async function l(a,b){let c=(0,f.I)(),e=(0,d.join)(process.cwd(),"src","server","l4_foundation","pi","l4-pi-plugin-capability-probe-runner.mts"),{stdout:i,stderr:j,code:l}=await (0,g.i)({args:["--conditions=react-server","--import",c,e],agentDir:b,env:{PI_DESK_PLUGIN_CAPABILITY_AGENT_DIR:b,PI_DESK_PLUGIN_CAPABILITY_CWD:a},maxOutputBytes:4194304,timeoutMs:3e4,timeoutError:()=>Error("插件能力盘点超时"),cleanupError:(a,b)=>Error(`${a}
|
|
6
|
+
能力盘点进程树清理失败`,{cause:b})});if(0!==l)throw Error(j.trim()||`插件能力盘点进程退出码 ${l??"null"}`);let m=i.lastIndexOf(h);if(m<0)throw Error("插件能力盘点没有返回有效结果");let n=i.slice(m+h.length).split(/\r?\n/,1)[0];return k.parse(JSON.parse(n))}},64253:(a,b,c)=>{c.a(a,async(a,d)=>{try{let s;c.d(b,{B:()=>q,I:()=>r});var e=c(31421),f=c(73024),g=c(51455),h=c(76760),i=c(48161),j=c(57975),k=c(75430),l=a([k]);k=(l.then?(await l)():l)[0];let t=(0,j.promisify)(e.execFile);function m(a){return a.replace(/\$\{([^}]+)\}/g,(a,b)=>process.env[b]??a)}async function n(a,b){let c;try{let b=await (0,g.readFile)(a);if(b.length>262144)throw Error("npm 配置文件过大");c=b.toString("utf8")}catch(a){if("ENOENT"===a.code)return;throw a}for(let a of c.split(/\r?\n/)){let c=/^\s*([^;#][^=]*?)\s*=\s*(.*?)\s*$/.exec(a);if(!c)continue;let d=c[2].replace(/\s+[;#].*$/,"").replace(/^(['"])(.*)\1$/,"$2");b[c[1].trim()]=m(d)}}function o(a,b){return("win32"===process.platform?/^~[\\/]/:/^~\//).test(a)?(0,h.resolve)((0,i.homedir)(),a.slice(2)):(0,h.resolve)(b,a)}async function p(a,b){let c={};for(let[a,b]of Object.entries(process.env))if(void 0!==b&&""!==b&&/^npm_config_/i.test(a)){let d=a.slice(11);c[d.startsWith("//")?d:d.replace(/(?!^)_/g,"-").toLowerCase()]=m(b)}let d=function(){for(let a of[(0,h.dirname)(process.execPath),...(process.env.PATH??"").split("win32"===process.platform?";":":")])for(let b of[(0,h.join)(a,"node_modules/npm/bin/npm-cli.js"),(0,h.resolve)(a,"../lib/node_modules/npm/bin/npm-cli.js")])if((0,f.existsSync)(b))return b}(),e={};if(d)try{await (0,g.mkdir)(a,{recursive:!0});let c=await t(process.execPath,[d,"config","list","--json","--prefix",b],{cwd:a,timeout:4e3,maxBuffer:524288,windowsHide:!0});e=JSON.parse(c.stdout)}catch{console.warn("[Pi Desk][PluginRegistry] npm 有效配置读取失败,改用 npmrc 和环境配置")}let j={};d&&await n((0,h.resolve)((0,h.dirname)(d),"../npmrc"),j);let k="string"==typeof e.globalconfig?e.globalconfig:c.globalconfig??(0,h.join)(b,"etc/npmrc"),l="string"==typeof e.userconfig?e.userconfig:c.userconfig??(0,h.join)((0,i.homedir)(),".npmrc");for(let[d,f]of(await n(o(k,a),j),await n(o(l,a),j),!0!==e.global&&"true"!==c.global&&"global"!==e.location&&"global"!==c.location&&await n((0,h.join)(b,".npmrc"),j),Object.entries(e)))"string"!=typeof f||"(protected)"===f||/auth|password|username/i.test(d)||(j[d]=f);return{...j,...c}}function q(a=(0,k.getAgentDir)()){let b=process.env.PI_DESK_PACKAGE_MAINTENANCE_CWD??(0,h.join)(a,"pi-desk","plugin-package-manager"),c=(0,h.join)(a,"npm");if(!s||s.cwd!==b||s.prefix!==c||s.expires<=Date.now()){let a=p(b,c);s={cwd:b,prefix:c,expires:Date.now()+3e4,value:a},a.catch(()=>{s?.value===a&&(s=void 0)})}return s.value}function r(a,b){let c=`//${a.host}${a.pathname}`;for(let a of Object.keys(b).flatMap(a=>{let b=/^(\/\/.*\/):(?:_authToken|_auth|username|_password)$/i.exec(a);return b&&c.startsWith(b[1])?[b[1]]:[]}).sort((a,b)=>b.length-a.length)){let c=b[`${a}:_authToken`]??b[`${a}:_authtoken`];if(c&&!c.includes("${"))return`Bearer ${c}`;let d=b[`${a}:_auth`];if(d&&!d.includes("${"))return`Basic ${d}`;let e=b[`${a}:username`],f=b[`${a}:_password`];if(e&&f&&!f.includes("${"))return`Basic ${Buffer.from(`${e}:${Buffer.from(f,"base64").toString("utf8")}`).toString("base64")}`}let d=b.registry;if(d){let c=new URL(d);if(a.origin===c.origin&&a.pathname.startsWith(`${c.pathname.replace(/\/+$/,"")}/`)){let a=b._authToken??b._authtoken;if(a&&!a.includes("${"))return`Bearer ${a}`;if(b._auth&&!b._auth.includes("${"))return`Basic ${b._auth}`}}}d()}catch(a){d(a)}})},69371:(a,b,c)=>{c.d(b,{rZ:()=>g,wC:()=>h});var d=c(76760),e=c(86148),f=c(2472);class g extends Error{constructor(a,b,c){super(b.slice(-4e3)||`Pi Package 命令退出码 ${c??"null"}`),this.kind=a,this.output=b,this.exitCode=c,this.name="L4PiPackageMaintenanceError"}}async function h(a){let b=(0,e.I)(),c=(0,d.join)(process.cwd(),"src","server","l4_foundation","pi","l4-pi-package-maintenance-runner.mts"),{stdout:h,stderr:i,code:j}=await (0,f.i)({args:["--import",b,c,a.maintenance.action,a.maintenance.source,...a.maintenance.registry?[a.maintenance.registry]:[]],agentDir:a.agentDir,env:{PI_DESK_PACKAGE_MAINTENANCE_CWD:a.cwd},maxOutputBytes:1048576,timeoutMs:12e4,timeoutError:()=>new g("failed","包维护超过120秒,已停止;结果未确认,请检查配置后手动处理",null),cleanupError:(a,b)=>new g("failed",`维护进程树未确认释放:${b instanceof Error?b.message:String(b)}`,null)});if(0===j)return;let k=(i||h).trim();throw new g(function(a){let b=a.toLowerCase();if(b.includes("ebusy")||b.includes("etxtbsy")||b.includes("resource busy")||b.includes("being used by another process")||b.includes("used by another process")||b.includes("process cannot access the file because it is being used"))return"locked";let c=b.includes("eperm")||b.includes("eacces")||b.includes("operation not permitted"),d=/\b(unlink|rename|rmdir|rimraf|remove|cleanup)\b/.test(b);return c&&d?"locked":"failed"}(k),k,j)}},69375:(a,b,c)=>{c.d(b,{Od:()=>r,tU:()=>n,hE:()=>q,P9:()=>f,_G:()=>j,Vc:()=>i});var d=c(36153);d.Yj().uuid();let e=d.Ik({key:d.Yj().min(1).max(160),params:d.g1(d.Yj().min(1).max(80),d.KC([d.Yj().max(1e3),d.ai().finite()])).optional()}).strict(),f=4001,g=d.Yj().trim().min(1),h=d.Yj().uuid();function i(a){return Object.freeze({op:"req",path:g.parse(a.path),inputSchema:a.inputSchema,outputSchema:a.outputSchema,...void 0===a.timeoutMs?{}:{timeoutMs:d.ai().int().positive().parse(a.timeoutMs)}})}function j(a){return Object.freeze({op:"push",path:g.parse(a.path),bodySchema:a.bodySchema})}let k=d.Ik({op:d.eu("req"),path:g,requestId:h}).strict(),l=d.Ik({op:d.eu("resp"),path:g,requestId:h}).strict(),m=d.Ik({op:d.eu("push"),path:g}).strict(),n=d.Ik({head:k,body:d.Pq()}).strict(),o=d.Ik({head:l,body:d.Ik({code:d.eu(0),msg:d.eu(""),data:d.Pq()}).strict()}).strict(),p=d.Ik({head:l,body:d.Ik({code:d.ai().int().positive(),msg:d.Yj().min(1),data:d.ch(),i18n:e.optional()}).strict()}).strict(),q=d.KC([o,p]),r=d.Ik({head:m,body:d.Pq()}).strict()},72497:(a,b,c)=>{c.d(b,{Dz:()=>h,f7:()=>g,tv:()=>f});var d=c(36153);let e=d.Yj().trim().min(1).max(64).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),f=e,g=e,h=d.g1(d.Yj(),d.Pq());d.Yj().trim().min(3).max(129).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*\/[a-z0-9]+(?:-[a-z0-9]+)*$/);let i=d.k5(["plugin","server","rocket","settings","panel","message","terminal","file","folder","bot","wrench","database","globe"]);d.gM("type",[d.Ik({type:d.eu("builtin"),name:i}).strict(),d.Ik({type:d.eu("svg"),content:d.Yj().trim().min(1).max(16384)}).strict()])},73159:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{NL:()=>h,XH:()=>j,Yq:()=>i});var e=c(77598),f=c(64253),g=a([f]);f=(g.then?(await g)():g)[0];class j extends Error{constructor(a,b=502,c="invalid"){super(a),this.status=b,this.reason=c,this.name="L4PluginRegistryError"}}let k=new Map,l=0;async function h(a,b){b.signal?.throwIfAborted();let c=!1===b.auth?{}:await (0,f.B)(b.agentDir),d=(0,f.I)(a,c),g=`${a.href}:${b.limit}:${(0,e.createHash)("sha256").update(d??"").digest("hex")}`,h=k.get(g);if(!1!==b.cache&&h&&h.expires>Date.now())return h.body;let i=AbortSignal.any([AbortSignal.timeout(b.timeout??1e4),...b.signal?[b.signal]:[]]),m=a;try{for(let a=0;a<=3;a++){let d=(0,f.I)(m,c),e=await fetch(m,{signal:i,redirect:"manual",headers:d?{Authorization:d}:{}});if([301,302,303,307,308].includes(e.status)){await e.body?.cancel();let b=e.headers.get("location");if(!b||3===a)throw new j("插件源重定向无效");let c=new URL(b,m);if(!["http:","https:"].includes(c.protocol)||c.username||c.password||"https:"===m.protocol&&"https:"!==c.protocol)throw new j("插件源重定向不安全");m=c;continue}if(!e.ok){await e.body?.cancel();let a=404===e.status?"missing":[401,403].includes(e.status)?"denied":e.status>=500?"network":"invalid";throw new j(`插件源请求失败(HTTP ${e.status})`,e.status,a)}if(Number(e.headers.get("content-length")??0)>b.limit)throw await e.body?.cancel(),new j("插件源响应超过大小限制");let h=e.body?.getReader(),n=[],o=0;if(h)try{for(;;){let a=await h.read();if(a.done)break;if((o+=a.value.byteLength)>b.limit)throw new j("插件源响应超过大小限制");n.push(a.value)}}finally{await h.cancel().catch(()=>void 0),h.releaseLock()}let p=Buffer.concat(n);if(!1!==b.cache){for(let[a,b]of k)(b.expires<=Date.now()||a===g)&&(k.delete(a),l-=b.body.length);for(;k.size>=96||l+p.length>0x1800000;){let a=k.entries().next().value;if(!a)break;k.delete(a[0]),l-=a[1].body.length}p.length<=0x1800000&&(k.set(g,{body:p,expires:Date.now()+12e4}),l+=p.length)}return p}throw new j("插件源重定向过多")}catch(a){if(b.signal?.aborted)throw b.signal.reason;if(a instanceof j)throw a;throw new j("插件源网络连接失败或超时",502,"network")}}async function i(a,b,c){let d=await h(a,{limit:8388608,signal:b,agentDir:c});try{let a=JSON.parse(d.toString("utf8"));if(!a||"object"!=typeof a||Array.isArray(a))throw Error("invalid");return a}catch{throw new j("插件源返回的元数据格式无效")}}d()}catch(a){d(a)}})},75157:(a,b,c)=>{c.d(b,{c:()=>g});var d=c(51455),e=c(76760);async function f(a){try{return(await (0,d.stat)(a)).isDirectory()}catch{return!1}}async function g(a){let b=a.configured.flatMap(a=>{let b=function(a){if(!a.startsWith("npm:"))return null;let b=a.slice(4).trim(),c=b.match(/^(@?[^@]+(?:\/[^@]+)?)(?:@(.+))?$/);return c?.[1]??(b||null)}(a.source);return b?[{name:b,item:a}]:[]}),c=(0,e.join)(a.agentDir,"npm","package.json"),g={};try{let a=JSON.parse(await (0,d.readFile)(c,"utf8"));a.dependencies&&"object"==typeof a.dependencies&&(g=a.dependencies)}catch(c){if(0===b.length)return null;let a=c instanceof Error&&c.message?c.message:String(c);return{message:`Pi Package npm 根不可用:${a}`,englishMessage:`Pi Package npm root is unavailable: ${a}`,i18n:{key:"errors:pluginNpmRootUnavailable",params:{detail:a.slice(0,1e3)}}}}let h=new Set(b.map(a=>a.name)),i=new Set(Object.keys(g)),j=[...h].filter(a=>!i.has(a)),k=[];for(let{name:a,item:c}of b)c.installedPath&&await f(c.installedPath)||k.push(a);if(0===j.length&&0===k.length)return null;let l=[j.length>0?`缺少声明:${j.join("、")}`:null,k.length>0?`缺少目录:${k.join("、")}`:null].filter(a=>null!==a),m=[j.length>0?`missing declarations: ${j.join(", ")}`:null,k.length>0?`missing folders: ${k.join(", ")}`:null].filter(a=>null!==a),n=j.length>0?k.length>0?"errors:pluginNpmRootMissingBoth":"errors:pluginNpmRootMissingDeclarations":"errors:pluginNpmRootMissingFolders";return{message:`Pi Package 配置与 npm 根不一致(${l.join(";")})`,englishMessage:`Pi Package configuration does not match the npm root (${m.join("; ")})`,i18n:{key:n,params:{declarations:j.join(", ").slice(0,1e3),folders:k.join(", ").slice(0,1e3)}}}}},76019:(a,b,c)=>{c.d(b,{J8:()=>f,fD:()=>g,qf:()=>e});var d=c(36153);let e=d.KC([d.Yj(),d.Ik({default:d.Yj(),translations:d.g1(d.Yj().min(1).max(35),d.Yj()).refine(a=>Object.keys(a).length<=16,"too many translations")}).strict()]);function f(a,b){return{default:a,translations:{en:b}}}function g(a,b){return"string"==typeof a?a:a.translations[b]??a.translations[b.split("-")[0]]??a.default}},78597:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{E:()=>k});var e=c(75430),f=c(4287),g=c(5235),h=c(34458),i=c(47154),j=a([e,g,h]);[e,g,h]=j.then?(await j)():j;class k{constructor(a,b,c){this.agentDir=a,this.cwd=b,this.signal=c,this.cache=new Map}async resolveInstall(a,b,c,d){let e=(0,f.ug)(a),i=e?/^npm:(?:@[^/]+\/)?[^@]+@([^@]+)$/.exec(a)?.[1]:void 0,j=i&&!/^v?\d+\./.test(i)&&f.mR.safeParse(i).success?i:null,k=e?d?(0,g.ey)(b,this.agentDir):c.tag??j??(0,g.ey)(b,this.agentDir):null,l=e&&k&&(d||!i)?`npm:${e}@${k}`:a;return{...await (0,h.dz)(l,{...c,agentDir:this.agentDir,signal:this.signal,cache:!d&&void 0}),updateTag:k}}clear(a){let b=(0,f.LD)(a);for(let[a,c]of this.cache)c.identity===b&&this.cache.delete(a)}async read(a,b){for(let[a,b]of this.cache)b.expiresAt<=Date.now()&&this.cache.delete(a);let c=b.sources?new Set(b.sources.map(f.LD)):null,d=new Map;for(let j of a){if("package"!==j.kind)continue;let a=(0,f.LD)(j.source),k=(0,f.ug)(j.source),l=k?(0,g.ey)(j.source,this.agentDir):null,m={updateTag:l,updateAvailable:null,availableVersion:null,updateError:null};d.set(j.source,m);let n=!0===b.checkUpdates&&(!c||c.has(a))&&(!b.tag||b.tag===l);if(k){if(!n&&![...this.cache.values()].some(b=>b.identity===a))continue;let b=null;try{let c=(0,g.to)(this.agentDir).downloadSource,e=await (0,h.qX)(k,{agentDir:this.agentDir,downloadSource:c});b=JSON.stringify([a,l,c.mode,e.registry,e.fallback]);let i=this.cache.get(b)?.value;if(n){if(!j.path||!j.version)throw Error("无法读取插件已安装版本");let d=await (0,h.dz)(`npm:${k}@${l}`,{downloadSource:c,agentDir:this.agentDir,signal:this.signal,cache:!1}),e=d.source.slice(d.source.lastIndexOf("@")+1);i={...m,availableVersion:e},this.store(b,a,i)}i&&d.set(j.source,{...i,updateAvailable:!i.updateError&&j.version&&i.availableVersion?(0,f.zj)(i.availableVersion,j.version):null})}catch(e){let c={...m,updateError:this.message(j.source,e)};d.set(j.source,c),b&&this.store(b,a,c)}}else if(/^(?:git:|https?:|git@)/.test(j.source)){let b=JSON.stringify([a,"git"]),c=this.cache.get(b)?.value;if(c&&d.set(j.source,c),!n)continue;try{let c=e.SettingsManager.inMemory({packages:[j.source]}),f=new e.DefaultPackageManager({agentDir:this.agentDir,cwd:this.cwd,settingsManager:c}),g=await (0,i.V)(()=>f.checkForAvailableUpdates()),h={...m,updateAvailable:g.some(a=>"user"===a.scope)};d.set(j.source,h),this.store(b,a,h)}catch(e){let c={...m,updateError:this.message(j.source,e)};d.set(j.source,c),this.store(b,a,c)}}}return d}store(a,b,c){for(this.cache.delete(a);this.cache.size>=128;){let a=this.cache.keys().next().value;if(void 0===a)break;this.cache.delete(a)}this.cache.set(a,{identity:b,expiresAt:Date.now()+3e5,value:c})}message(a,b){let c=(b instanceof Error?b.message:String(b)).slice(0,4e3);return console.warn("[Pi Desk][PluginManagement] 检查插件更新失败",{source:a,message:c}),this.clear(a),c}}d()}catch(a){d(a)}})},86148:(a,b,c)=>{function d(a){let b=a.replaceAll("\\","/");return"tsx"===b||/(?:^|\/)tsx(?:\/|$)/.test(b)}function e(a=process.execArgv){for(let b=0;b<a.length;b+=1){let c=a[b];if("--import"===c){let c=a[b+1];if(c&&d(c))return c;b+=1;continue}if(c.startsWith("--import=")){let a=c.slice(9);if(d(a))return a}}throw Error("Pi Desk 服务缺少 tsx loader,无法启动插件维护子进程")}c.d(b,{I:()=>e})},93951:(a,b,c)=>{c.d(b,{LC:()=>E,tA:()=>G,oP:()=>H});var d=c(36153),e=c(72497),f=c(76019),g=c(4287),h=c(69375);let i=g.SZ,j=g.w3;d.Ik({downloadSource:j,recommendedRegistry:i}).strict(),d.Ik({downloadSource:j}).strict(),d.Ik({query:d.Yj().trim().max(200).default(""),page:d.ai().int().min(1).max(100).default(1),kind:d.k5(["all","desk","pi"]).default("all"),registry:i.optional()}).strict(),d.Ik({name:d.Yj().trim().min(1).max(214).regex(/^(?:@[a-z0-9_.-]+\/)?[a-z0-9][a-z0-9_.-]*$/i),version:d.Yj().trim().min(1).max(128).optional(),registry:i.optional()}).strict();let k=d.Ik({name:d.Yj(),description:f.qf.nullable(),version:d.Yj(),publisher:d.Yj().nullable(),kind:d.k5(["desk","pi","unknown"]),official:d.zM(),registry:i}).strict();d.Ik({items:d.YO(k),hasMore:d.zM()}).strict(),k.extend({versions:d.YO(d.Yj()),readme:f.qf.nullable(),homepage:d.Yj().nullable(),repository:d.Yj().nullable(),compatible:d.zM().nullable(),compatibilityNote:d.Yj().nullable()}).strict();let l=d.Yj().trim().min(1).max(2048),m=g.mR,n=d.YO(l).min(1).max(32),o=d.Ik({phase:d.k5(["package","entry","setup","resources","resolve","native"]),message:f.qf.refine(a=>"string"==typeof a?a.length>0:a.default.length>0)}).strict(),p=d.Yj().trim().min(1).max(4096),q=d.Yj().trim().min(1).max(256),r=d.Yj().max(32768),s=d.Ik({name:q,label:r,state:d.k5(["active","inactive","shadowed"]),description:r,promptSnippet:r.nullable(),promptGuidelineCount:d.ai().int().nonnegative(),promptGuidelinePreview:r.nullable()}).strict(),t=d.Ik({name:q,label:r,state:d.k5(["active","inactive","shadowed"]),description:r,parameters:e.Dz,promptSnippet:r.nullable(),promptGuidelines:d.YO(r)}).strict(),u=d.Ik({path:p,events:d.YO(d.Ik({name:q,count:d.ai().int().positive()}).strict()),commands:d.YO(d.Ik({name:q,description:r.nullable()}).strict()),shortcuts:d.YO(d.Ik({shortcut:q,description:r.nullable()}).strict()),flags:d.YO(d.Ik({name:q,type:d.k5(["boolean","string"]),description:r.nullable(),default:d.KC([d.zM(),d.Yj(),d.ch()])}).strict()),messageRenderers:d.YO(q),entryRenderers:d.YO(q)}).strict(),v=d.Ik({name:q,description:r,path:p}).strict(),w=v.extend({modelVisible:d.zM()}).strict(),x=v.extend({content:d.Yj().max(65536),truncated:d.zM()}).strict(),y=x.extend({modelVisible:d.zM()}).strict(),z=d.Ik({name:q,path:p}).strict(),A=d.Ik({name:q,kind:d.k5(["config","native"])}).strict(),B=d.Ik({methods:d.YO(d.Ik({pluginName:q,method:q}).strict()),browserEntries:d.YO(d.Ik({pluginName:q}).strict()),messageDeclarations:d.YO(d.Ik({pluginName:q,declarationName:q,priority:d.ai().int().safe()}).strict())}).strict(),C=d.Ik({error:f.qf.refine(a=>"string"==typeof a?a.length<=32768:[a.default,...Object.values(a.translations)].every(a=>a.length<=32768)).nullable(),extensions:d.YO(u),tools:d.YO(s),skills:d.YO(w),prompts:d.YO(v),themes:d.YO(z),providers:d.YO(A),piDesk:B}).strict(),D=d.Ik({action:d.k5(["add","update","del","apply","enable","disable"]),phase:d.k5(["queued","checking","applying","waiting","failed"]),message:d.Yj().max(4e3).nullable()}).strict(),E=(0,h._G)({path:"plugins/management-update",bodySchema:d.Ik({}).strict()}),F=d.Ik({source:l,kind:d.k5(["package","extension"]).default("package"),operation:D.nullable().default(null),pluginName:d.Yj().trim().min(1).nullable(),description:f.qf.nullable().default(null),version:d.Yj().trim().min(1).nullable(),updateAvailable:d.zM().nullable(),updateTag:m.nullable().optional(),availableVersion:d.Yj().min(1).nullable().optional(),updateError:d.Yj().max(4e3).nullable().optional(),status:d.k5(["ready","available","disabled","failed"]),error:o.nullable(),capabilities:C}).strict(),G=d.Ik({source:l,readme:f.qf.nullable().default(null),tools:d.YO(t),skills:d.YO(y),prompts:d.YO(x)}).strict(),H=d.Ik({plugins:d.YO(F),restartRequired:d.zM(),loadError:f.qf.refine(a=>"string"==typeof a?a.length>0:a.default.length>0).nullable()}).strict();d.Ik({sources:d.YO(l).min(1).max(32).optional()}).strict(),d.Ik({}).strict().extend({mode:d.k5(["normal","basic"]).optional()}).strict(),d.Ik({checkUpdates:d.zM().optional(),sources:n.optional(),tag:m.optional()}).strict();let I=d.Ik({source:l}).strict(),J=I.extend({downloadSource:j.optional(),registry:i.optional(),tag:m.optional()}).strict();d.gM("action",[d.Ik({action:d.eu("add"),items:d.YO(J).min(1).max(32)}).strict(),d.Ik({action:d.eu("update"),sources:n}).strict(),d.Ik({action:d.eu("del"),sources:n}).strict(),d.Ik({action:d.eu("tag"),sources:n,tag:m}).strict()]),d.Ik({snapshot:H,results:d.YO(d.Ik({source:l,error:d.Yj().max(4e3).nullable()}).strict()).max(32)}).strict(),I.extend({enabled:d.zM()}).strict()},96783:(a,b,c)=>{c.d(b,{Y:()=>j});var d=c(76760),e=c(36153),f=c(86148),g=c(2472);let h="__PI_DESK_PLUGIN_PROBE__",i=e.Ik({packages:e.YO(e.Ik({source:e.Yj(),packageName:e.Yj().nullable(),version:e.Yj().nullable(),pluginName:e.Yj().nullable(),status:e.k5(["ready","failed"]),error:e.Ik({phase:e.k5(["package","entry","setup","resources","resolve"]),message:e.Yj()}).strict().nullable()}).strict()),loadError:e.Yj().nullable()}).strict();async function j(a,b,c=!1){let e=(0,f.I)(),k=(0,d.join)(process.cwd(),"src","server","l4_foundation","pi","l4-pi-plugin-probe-runner.mts"),{stdout:l,stderr:m,code:n}=await (0,g.i)({args:["--conditions=react-server","--import",e,k],agentDir:b,env:{PI_DESK_PLUGIN_PROBE_AGENT_DIR:b,PI_DESK_PLUGIN_PROBE_CWD:a,PI_DESK_PLUGIN_PROBE_NATIVE:c?"1":void 0},maxOutputBytes:1048576,timeoutMs:3e4,timeoutError:()=>Error("插件预检超时"),cleanupError:(a,b)=>Error(`${a}
|
|
7
7
|
插件预检进程树清理失败`,{cause:b})});if(0!==n)throw Error(m.trim()||`插件预检进程退出码 ${n??"null"}`);let o=l.lastIndexOf(h);if(o<0)throw Error("插件预检没有返回有效结果");let p=l.slice(o+h.length).split(/\r?\n/,1)[0];return i.parse(JSON.parse(p))}}};
|