@jetcrab/pi-desk 1.1.8-dev → 1.1.10
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/plugins.md +15 -1
- package/package.json +7 -7
- package/src/client/l2_biz/auth/l2-login-biz.ts +4 -1
- package/src/client/l2_biz/settings/hooks/l2-use-auth-settings.ts +18 -1
- package/src/client/l2_biz/settings/l2-auth-settings-biz.ts +18 -1
- package/src/client/l2_biz/settings/l2-auth-settings.tsx +19 -5
- package/src/client/l2_biz/workbench/file-workspace/l2-file-workspace-runtime.ts +144 -23
- package/src/client/l2_biz/workbench/file-workspace/l2-file-workspace-view.tsx +9 -5
- package/src/client/l2_biz/workbench/file-workspace/l2-project-file-browser.tsx +94 -5
- package/src/client/l2_biz/workbench/file-workspace/l2-project-preview-biz.ts +48 -0
- package/src/client/l2_biz/workbench/git-workspace/l2-git-workspace-runtime.ts +26 -8
- package/src/client/l2_biz/workbench/hooks/l2-workbench-chat-viewport.ts +70 -47
- package/src/client/l2_biz/workbench/l2-work-session-columns.tsx +1 -0
- package/src/client/l2_biz/workbench/l2-workbench-chat-view.tsx +18 -14
- package/src/client/l2_biz/workbench/l2-workbench.tsx +37 -6
- package/src/client/l3_modules/conversation/l3-conversation-messages.tsx +28 -9
- package/src/client/l3_modules/project-files/l3-project-file-browser.tsx +27 -15
- package/src/client/l3_modules/project-files/l3-project-file-runtime.ts +7 -0
- package/src/client/l4_foundation/ui/code/l4-code-preferences.ts +1 -1
- package/src/common/l2_biz/auth/l2-auth-contract.ts +14 -1
- package/src/common/l2_biz/auth/l2-auth-messages.ts +27 -10
- package/src/common/l3_modules/app-runtime/l3-app-runtime-contract.ts +4 -1
- package/src/common/l3_modules/conversation/l3-conversation-locale-messages.ts +4 -0
- package/src/common/l3_modules/project-files/l3-project-files-locale-messages.ts +8 -0
- package/src/common/l4_foundation/file/l4-project-preview-contract.ts +25 -0
- package/src/server/l1_entry/api/l1-auth-login-route.ts +20 -6
- package/src/server/l1_entry/api/l1-auth-settings-routes.ts +1 -1
- package/src/server/l1_entry/api/l1-project-route.ts +14 -5
- package/src/server/l1_entry/node/l1-server.ts +4 -7
- package/src/server/l2_biz/app-runtime/l2-app-runtime.ts +6 -1
- package/src/server/l2_biz/auth/l2-auth.ts +52 -2
- package/src/server/l2_biz/work-session/l2-work-session-chat-runtime.ts +28 -0
- package/src/server/l2_biz/work-session/l2-work-session-manage.ts +8 -0
- package/src/server/l3_modules/app-runtime/l3-app-notification-runtime.ts +48 -14
- package/src/server/l4_foundation/auth/l4-auth-config.ts +19 -3
- package/src/server/l4_foundation/pi/l4-pi-chat-worker.ts +2 -1
- package/src/server/l4_foundation/pi/l4-pi-global-runtime.js +3 -13
- package/src/server/l4_foundation/pi/l4-pi-session-plugin-runtime.ts +60 -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 +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- 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/auth/login/route.js +2 -4
- package/temp/build/pi-desk/release/.next/server/app/api/auth/logout/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/auth-settings/get/route.js +1 -1
- package/temp/build/pi-desk/release/.next/server/app/api/auth-settings/replace/route.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/api/project-files/reveal/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 +64 -64
- 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/23054.js +2 -2
- package/temp/build/pi-desk/release/.next/server/chunks/25406.js +7 -7
- package/temp/build/pi-desk/release/.next/server/chunks/35985.js +3 -3
- package/temp/build/pi-desk/release/.next/server/chunks/49900.js +4 -0
- package/temp/build/pi-desk/release/.next/server/chunks/5034.js +1 -0
- package/temp/build/pi-desk/release/.next/server/chunks/50520.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/61211.js +2 -0
- package/temp/build/pi-desk/release/.next/server/chunks/6917.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/77953.js +1 -0
- package/temp/build/pi-desk/release/.next/server/chunks/8584.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/92386.js +4 -4
- package/temp/build/pi-desk/release/.next/server/chunks/93049.js +1 -0
- package/temp/build/pi-desk/release/.next/server/chunks/94296.js +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/98227.js +3 -0
- package/temp/build/pi-desk/release/.next/server/instrumentation.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/45992-304a49aaaebd853e.js +13 -0
- package/temp/build/pi-desk/release/.next/static/chunks/{34903-e4205c0becabea76.js → 47340-c1c09c77c1a88514.js} +1 -1
- package/temp/build/pi-desk/release/.next/static/chunks/70669.07f3670bfb7d6dd2.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/{layout-586f6f88483051a7.js → layout-839162b6cfae8347.js} +1 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/login/page-4532a3bbee48e219.js +1 -0
- package/temp/build/pi-desk/release/.next/static/chunks/app/page-9f478658c50efdbe.js +158 -0
- package/temp/build/pi-desk/release/.next/static/chunks/{webpack-26261285e181235a.js → webpack-735430d61da52e9d.js} +1 -1
- package/temp/build/pi-desk/release/.next/static/css/8a41765636e09e52.css +1 -0
- package/temp/build/pi-desk/release/.next/trace-build +1 -1
- package/temp/build/pi-desk/release/.next/server/chunks/31442.js +0 -3
- package/temp/build/pi-desk/release/.next/server/chunks/37681.js +0 -1
- package/temp/build/pi-desk/release/.next/server/chunks/65589.js +0 -4
- package/temp/build/pi-desk/release/.next/server/chunks/99672.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/45992-a39a014497ec4dd1.js +0 -13
- package/temp/build/pi-desk/release/.next/static/chunks/70669.8b4231a8675499e0.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/login/page-bf893718bb151f3c.js +0 -1
- package/temp/build/pi-desk/release/.next/static/chunks/app/page-0f2cf68a4666420b.js +0 -158
- package/temp/build/pi-desk/release/.next/static/css/3213ee28336bddc2.css +0 -1
- /package/temp/build/pi-desk/release/.next/static/{-pemk30NXpiExEU5tjb1t → ZYtCj4W63FjXCrTLTDbvO}/_buildManifest.js +0 -0
- /package/temp/build/pi-desk/release/.next/static/{-pemk30NXpiExEU5tjb1t → ZYtCj4W63FjXCrTLTDbvO}/_ssgManifest.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
exports.id=77953,exports.ids=[77953],exports.modules={494:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{UM:()=>g}),c(24187);var e=c(30010),f=a([e]);function g(){let a=globalThis.__piDeskAppPluginStateRuntime;globalThis.__piDeskAppPluginStateRuntime=void 0,a?.dispose()}e=(f.then?(await f)():f)[0],d()}catch(a){d(a)}})},2214:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{I:()=>o,Q:()=>m});var e=c(51455),f=c(76760),g=c(75430),h=a([g]);g=(h.then?(await h)():h)[0];class m extends Error{constructor(a,b){super(b),this.code=a,this.name="L4ModelAuthError"}}let n=["baseUrl","apiKey","headers","api","oauth","authHeader","compat"];async function i(a,b){let c;if(!b)return a;let d=new Promise((a,d)=>{c=()=>d(new DOMException("账号操作已取消","AbortError")),b.aborted?c():b.addEventListener("abort",c,{once:!0})});try{return await Promise.race([a,d])}finally{b.removeEventListener("abort",c)}}function j(a){return"object"==typeof a&&null!==a&&!Array.isArray(a)}function k(a){return n.some(b=>void 0!==a[b])}async function l(a){let b,c;try{b=await (0,e.readFile)(a,"utf8")}catch(a){if(j(a)&&"ENOENT"===a.code)return new Set;throw new m(500,"无法读取模型配置,暂时不能进行账号操作")}try{let a=(65279===b.charCodeAt(0)?b.slice(1):b).replace(/"(?:\\.|[^"\\])*"|\/\/[^\n]*/g,a=>'"'===a[0]?a:"").replace(/"(?:\\.|[^"\\])*"|,(\s*[}\]])/g,(a,b)=>b??a);c=JSON.parse(a)}catch{throw new m(409,"模型配置格式无效,请先修正 models.json")}if(!j(c)||void 0!==c.providers&&!j(c.providers))throw new m(409,"模型配置格式无效,请先修正 models.json");let d=new Set;for(let[a,b]of Object.entries(c.providers??{})){if(!j(b))throw new m(409,"模型服务配置格式无效");(k(b)||Array.isArray(b.models)&&b.models.some(a=>j(a)&&k(a)))&&d.add(a)}return d}class o{constructor(a,b,c){this.runtime=a,this.conflicts=b,this.agentDir=c}static async create(a){let b=(0,g.getAgentDir)(),c=(0,f.join)(b,"models.json"),d=await i(l(c),a);a?.throwIfAborted();let e=await i(g.ModelRuntime.create({authPath:(0,f.join)(b,"auth.json"),modelsPath:c,refreshOnCreate:!1,allowModelNetwork:!1,signal:a}),a);return a?.throwIfAborted(),new o(e,d,b)}async list(a){let b=await i(this.runtime.listCredentials({signal:a}),a),c=new Set(b.filter(a=>"oauth"===a.type).map(a=>a.providerId));return this.runtime.getProviders().filter(a=>a.auth.oauth).map(a=>({provider:a.id,name:a.name,loggedIn:c.has(a.id),conflict:this.conflicts.has(a.id)?"同名服务已有自定义连接,会改变账号凭据的使用方式。请先将自定义连接改为独立服务 ID,再登录账号。":null}))}async login(a,b){try{return await i(this.runtime.login(a,"oauth",b,{getDeviceId:()=>g.SettingsManager.create(process.cwd(),this.agentDir).getOrCreateDeviceId()}),b.signal),!0}catch(a){if(a instanceof g.CredentialSynchronizationError&&"login"===a.operation)return!1;throw a}}async refreshCatalog(a,b){b.throwIfAborted();let c=await i(this.runtime.refresh({allowNetwork:!0,providers:[a],signal:b}),b);if(b.throwIfAborted(),c.aborted)throw Error("CatalogRefreshAborted");let d=c.errors.get(a);if(d)throw d}async logout(a,b){try{await i(this.runtime.logout(a,{signal:b}),b)}catch(a){if(a instanceof g.CredentialSynchronizationError&&"logout"===a.operation)throw new m(500,"账号已退出,但本地模型目录同步失败,请重新获取模型列表");throw a}}}d()}catch(a){d(a)}})},9050:(a,b,c)=>{"use strict";c.d(b,{CR:()=>k,ED:()=>l,I1:()=>i,Oi:()=>h,XV:()=>j,XZ:()=>g,tu:()=>f,xb:()=>e});var d=c(59473);let e=400,f=200,g=2e3,h=16384,i=8388608,j={cols:d.ai().int().min(2).max(e),rows:d.ai().int().min(2).max(f)},k=d.Ik({...j,data:d.Yj().max(i)}).strict(),l=d.gM("type",[d.Ik({type:d.eu("snapshot"),snapshot:k}).strict(),d.Ik({type:d.eu("output"),data:d.Yj().min(1).max(65536)}).strict(),d.Ik({type:d.eu("resize"),...j}).strict(),d.Ik({type:d.eu("exit"),exitCode:d.ai().int()}).strict()])},13578:(a,b,c)=>{"use strict";c.d(b,{IC:()=>h,J:()=>i,eL:()=>f});var d=c(77598),e=c(57075);class f extends Error{constructor(a,b){super(`Plugin Browser resource was not found: ${a}/${b}`),this.name="L4PiPluginBrowserResourceNotFoundError"}}class g{replace(a){let b=new Set(a.map(a=>a.pluginName));if(b.size!==a.length)throw Error("Browser Entry 清单包含重复插件");if(a.reduce((a,b)=>a+b.snapshot.size,0)>0x8000000)throw Error("Browser 活动资源超过容量上限");for(let[a,c]of this.recordsByPlugin)b.has(a)||(this.recordsByPlugin.delete(a),this.retire(c));let c=a.map(a=>{let b=this.recordsByPlugin.get(a.pluginName),c=b?.resourceKey===a.resourceKey&&b.entryPath===a.entryPath?b:{pluginName:a.pluginName,resourceGroup:(0,d.randomBytes)(24).toString("base64url"),resourceKey:a.resourceKey,entryPath:a.entryPath,snapshot:a.snapshot,retiredAt:null};return b!==c&&(b&&this.retire(b),this.recordsByPlugin.set(a.pluginName,c),this.recordsByGroup.set(c.resourceGroup,c)),{resourceGroup:c.resourceGroup,url:`/api/plugins/browser-resources/${c.resourceGroup}/entry.js`,entry:a}});return this.prune(),c}async read(a,b){this.prune();let c=this.recordsByGroup.get(a),d=!(!b||b.length>4096||b.startsWith("/")||b.includes("\\")||b.includes("\0"))&&b.endsWith(".js")&&b.split("/").every(a=>""!==a&&"."!==a&&".."!==a)?c?.snapshot.modules.get(b):void 0;if(!d)throw new f(a,b);return{stream:e.Readable.toWeb(e.Readable.from([d.content])),size:d.content.length,etag:d.etag}}dispose(){this.pruneTimer&&clearTimeout(this.pruneTimer),this.pruneTimer=null,this.recordsByPlugin.clear(),this.recordsByGroup.clear()}retire(a){a.retiredAt??=Date.now()}prune(){this.pruneTimer&&clearTimeout(this.pruneTimer),this.pruneTimer=null;let a=Date.now(),b=[...this.recordsByGroup.values()].filter(a=>null!==a.retiredAt).sort((a,b)=>a.retiredAt-b.retiredAt),c=b.reduce((a,b)=>a+b.snapshot.size,0),d=b.length;for(let e of b)(a-e.retiredAt>=6e4||d>32||c>0x4000000)&&(this.recordsByGroup.delete(e.resourceGroup),c-=e.snapshot.size,d-=1);let e=b.find(a=>this.recordsByGroup.has(a.resourceGroup));e&&(this.pruneTimer=setTimeout(()=>this.prune(),Math.max(1,e.retiredAt+6e4-a)),this.pruneTimer.unref())}constructor(){this.recordsByPlugin=new Map,this.recordsByGroup=new Map,this.pruneTimer=null}}function h(){return globalThis.__piDeskPluginBrowserResourceRegistry||(globalThis.__piDeskPluginBrowserResourceRegistry=new g),globalThis.__piDeskPluginBrowserResourceRegistry}function i(){globalThis.__piDeskPluginBrowserResourceRegistry?.dispose(),globalThis.__piDeskPluginBrowserResourceRegistry=void 0}},15801:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{Y:()=>h});var e=c(54133),f=c(31656),g=a([f]);f=(g.then?(await g)():g)[0];class h{constructor(a){this.connection=a,this.disposed=!1,this.auth=new f.c(a=>{!this.disposed&&this.connection.isCurrent()&&this.connection.sendPush(e.c.state,a)}),this.routes=Object.freeze([this.route(e.c.list,async()=>({providers:await this.auth.list()})),this.route(e.c.start,async a=>(await this.auth.start(a.provider,a.loginId),{})),this.route(e.c.respond,a=>(this.auth.respond(a.loginId,a.promptId,a.value),{})),this.route(e.c.cancel,a=>(this.auth.cancel(a.loginId),{})),this.route(e.c.logout,async a=>(await this.auth.logout(a.provider),{}))])}dispose(){this.disposed||(this.disposed=!0,this.auth.dispose())}route(a,b){return{path:a.path,access:"ready",handle:async c=>{let d=a.inputSchema.safeParse(c.body);if(!d.success)return void this.connection.sendError(a.path,c.head.requestId,400,"账号操作参数无效");if(!this.disposed&&this.connection.isCurrent())try{let e=await b(d.data);!this.disposed&&this.connection.isCurrent()&&this.connection.sendSuccess(a,c.head.requestId,e)}catch(b){if(this.disposed||!this.connection.isCurrent())return;if(b instanceof f.m)return void this.connection.sendError(a.path,c.head.requestId,b.code,b.message);console.warn("[Pi Desk][ModelAuthSocket] 账号请求失败",{stage:a.path,errorName:b instanceof Error?b.name:"UnknownError"}),this.connection.sendError(a.path,c.head.requestId,500,"账号操作失败,请重试")}}}}}d()}catch(a){d(a)}})},22307:(a,b,c)=>{"use strict";c.d(b,{P6:()=>K});var d=c(59473),e=c(43037),f=c(610),g=c(2002);let h=d.Ik({source:e.Pi,cursor:e.UR}).strict(),i=d.Ik({subscriptions:d.YO(h).min(1)}).strict().superRefine((a,b)=>{let c=new Set;for(let[d,e]of a.subscriptions.entries())c.has(e.source.workId)&&b.addIssue({code:"custom",message:"subscriptions cannot contain duplicate workId values",path:["subscriptions",d,"source","workId"]}),c.add(e.source.workId)}),j=d.Ik({}).strict(),k=d.YO(e.wR).superRefine((a,b)=>{let c=new Set;for(let[d,e]of a.entries())d>0&&e.location.index!==a[d-1].location.index+1&&b.addIssue({code:"custom",message:"chat sync message indexes must be continuous",path:[d,"location","index"]}),c.has(e.location.entryId)&&b.addIssue({code:"custom",message:"chat sync entryId values must be unique",path:[d,"location","entryId"]}),c.add(e.location.entryId)}),l=d.Ik({type:d.eu("session_sync"),mode:d.eu("full"),baseCursor:d.ch(),messages:k,temporaryMessages:d.YO(e.yI),runtime:e.wf}).strict().superRefine((a,b)=>{a.messages[0]&&0!==a.messages[0].location.index&&b.addIssue({code:"custom",message:"full sync must start at index 0",path:["messages",0,"location","index"]})}),m=d.Ik({type:d.eu("session_sync"),mode:d.eu("incremental"),baseCursor:e.DK,messages:k,temporaryMessages:d.YO(e.yI),runtime:e.wf}).strict().superRefine((a,b)=>{let c=a.messages[0];c&&c.location.index!==a.baseCursor.index+1&&b.addIssue({code:"custom",message:"incremental sync must start after baseCursor",path:["messages",0,"location","index"]})}),n=d.KC([l,m]),o=f.hS,p=f.ef,q=f.gK,r=f.PS,s=d.Ik({type:d.eu("runtime_update"),runtime:e.wf}).strict(),t=d.KC([n,o,p,q,r,s]),u=d.Ik({source:e.Pi,event:t}).strict(),v=d.k5(["auto","follow_up"]),w=d.Ik({source:e.Pi,mode:v,text:d.Yj(),images:d.YO(e.xh).max(10)}).strict().refine(a=>a.text.trim().length>0||a.images.length>0,{message:"chat input requires text or images"}),x=d.Ik({tempId:e.R3.shape.tempId}).strict(),y=d.Ik({source:e.Pi}).strict(),z=d.Ik({}).strict(),A=y.extend({mode:e.TV.optional()}).strict(),B=y.extend({mode:e.TV}).strict(),C=d.Ik({}).strict(),D=d.Ik({}).strict(),E=d.Ik({text:d.Yj(),images:d.YO(e.xh)}).strict(),F=d.Ik({source:e.Pi,model:e.w$}).strict(),G=d.Ik({}).strict(),H=d.Ik({source:e.Pi,capabilityMode:e.wf.shape.capabilityMode}).strict(),I=d.Ik({}).strict();d.k5(["chat/subscribe","chat/send","chat/interrupt","chat/reload","chat/presentation-set","chat/compact","chat/queue-restore","chat/model-set","chat/capability-mode-set"]);let J=d.eu("chat/source-event"),K=Object.freeze({subscribe:(0,g.Vc)({path:"chat/subscribe",inputSchema:i,outputSchema:j,timeoutMs:125e3}),send:(0,g.Vc)({path:"chat/send",inputSchema:w,outputSchema:x,timeoutMs:12e4}),interrupt:(0,g.Vc)({path:"chat/interrupt",inputSchema:y,outputSchema:z}),reload:(0,g.Vc)({path:"chat/reload",inputSchema:A,outputSchema:C,timeoutMs:125e3}),presentationSet:(0,g.Vc)({path:"chat/presentation-set",inputSchema:B,outputSchema:C}),compact:(0,g.Vc)({path:"chat/compact",inputSchema:y,outputSchema:D,timeoutMs:6e5}),queueRestore:(0,g.Vc)({path:"chat/queue-restore",inputSchema:y,outputSchema:E}),modelSet:(0,g.Vc)({path:"chat/model-set",inputSchema:F,outputSchema:G}),capabilityModeSet:(0,g.Vc)({path:"chat/capability-mode-set",inputSchema:H,outputSchema:I}),sourceEvent:(0,g._G)({path:J.value,bodySchema:u})})},23179:(a,b,c)=>{"use strict";c.d(b,{OY:()=>l});var d=c(59473),e=c(96089),f=c(2002);let g=d.Yj().trim().min(1).max(64).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),h=d.g1(d.Yj(),d.Pq()),i=d.Ik({pluginName:g,method:g,scope:d.eu("global"),input:h}).strict(),j=d.Ik({pluginName:g,method:g,scope:d.eu("session"),source:e.R,input:h}).strict(),k=d.gM("scope",[i,j]),l=Object.freeze({invoke:(0,f.Vc)({path:"plugins/invoke",inputSchema:k,outputSchema:h})})},25588:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{c:()=>r});var e=c(26519),f=c(16438),g=c(23179),h=c(59587),i=c(25084),j=c(9753),k=c(47574),l=c(32980),m=c(13578),n=c(96459),o=c(40333),p=c(44095),q=a([f,k,l,n,p]);[f,k,l,n,p]=q.then?(await q)():q;class r{constructor(a,b,c){this.connection=a,this.manage=b,this.disposed=!1,this.unsubscribeManagement=(0,f.ZY)().subscribe(()=>{!this.disposed&&c()&&this.connection.isCurrent()&&this.connection.sendPush(e.LC,{})}),this.routes=Object.freeze([{path:g.OY.invoke.path,access:"ready",handle:a=>this.invoke(a)},{path:h.bm.list.path,access:"ready",handle:a=>this.listBrowserEntries(a)},{path:i.QV.commandsList.path,access:"ready",handle:a=>this.listCommands(a)},{path:i.QV.commandExecute.path,access:"ready",handle:a=>this.executeCommand(a)},{path:i.QV.toolsList.path,access:"ready",handle:a=>this.listTools(a)},{path:i.QV.bashExecute.path,access:"ready",handle:a=>this.executeBash(a)},{path:i.QV.bashAbort.path,access:"ready",handle:a=>this.abortBash(a)}])}dispose(){this.disposed||(this.disposed=!0,this.unsubscribeManagement())}async invoke(a){let b=g.OY.invoke,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"插件调用参数无效");try{let d="global"===c.data.scope?await (0,n.WE)().invoke(c.data.pluginName,c.data.method,c.data.input):await this.manage.invokeSessionPluginMethod(c.data);this.connection.sendSuccess(b,a.head.requestId,d)}catch(d){this.sendInvokeError(b.path,a.head.requestId,d,c.data.pluginName,c.data.method)}}async listBrowserEntries(a){let b=h.bm.list;if(!b.inputSchema.safeParse(a.body).success)return void this.connection.sendError(b.path,a.head.requestId,400,"插件入口参数无效");try{let c=await (0,n.WE)().listBrowserEntries(),d=(0,m.IC)().replace(c);this.connection.sendSuccess(b,a.head.requestId,{entries:d.map(a=>({pluginName:a.entry.pluginName,url:a.url}))})}catch(c){console.error("[Pi Desk][PluginSocket] 查询 Browser Entry 失败",{errorName:c instanceof Error?c.name:"UnknownError",message:c instanceof Error?c.message:String(c)}),this.connection.sendError(b.path,a.head.requestId,500,"查询插件入口失败")}}async listCommands(a){let b=i.QV.commandsList,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"Pi 命令参数无效");try{this.connection.sendSuccess(b,a.head.requestId,await this.manage.listNativeCommands(c.data))}catch(c){this.sendNativeError(b.path,a.head.requestId,c,"查询 Pi 命令失败")}}async executeCommand(a){let b=i.QV.commandExecute,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"Pi 命令参数无效");try{await this.manage.executeNativeCommand(c.data),this.connection.sendSuccess(b,a.head.requestId,{})}catch(c){this.sendNativeError(b.path,a.head.requestId,c,"执行 Pi 命令失败")}}async listTools(a){let b=i.QV.toolsList,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"Pi Tool 参数无效");try{this.connection.sendSuccess(b,a.head.requestId,await this.manage.listNativeTools(c.data))}catch(c){this.sendNativeError(b.path,a.head.requestId,c,"查询 Pi Tool 失败")}}async executeBash(a){let b=i.QV.bashExecute,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"Pi Bash 参数无效");try{this.connection.sendSuccess(b,a.head.requestId,await this.manage.executeDirectBash(c.data))}catch(c){this.sendNativeError(b.path,a.head.requestId,c,"执行 Pi Bash 失败")}}async abortBash(a){let b=i.QV.bashAbort,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"Pi Bash 参数无效");try{await this.manage.abortDirectBash(c.data),this.connection.sendSuccess(b,a.head.requestId,{})}catch(c){this.sendNativeError(b.path,a.head.requestId,c,"中止 Pi Bash 失败")}}sendNativeError(a,b,c,d){c instanceof k.dM?this.connection.sendError(a,b,409,"工作会话来源已变化"):c instanceof k.nJ?this.connection.sendError(a,b,409,"工作会话正在变更"):c instanceof l.X9?this.connection.sendError(a,b,404,"Pi 命令不存在"):c instanceof l.yT?this.connection.sendError(a,b,409,"当前工作会话已有 Bash 正在执行"):(console.warn("[Pi Desk][PluginSocket] Native Pi 调用失败",{path:a,errorName:c instanceof Error?c.name:"UnknownError",message:c instanceof Error?c.message:String(c)}),this.connection.sendError(a,b,500,c instanceof Error&&c.message?c.message:d))}sendInvokeError(a,b,c,d,e){c instanceof k.dM?this.connection.sendError(a,b,409,"工作会话来源已变化"):c instanceof k.nJ?this.connection.sendError(a,b,409,"工作会话正在变更"):c instanceof p.y||c instanceof Error&&"L4PiPluginRuntimeBusyError"===c.name?this.connection.sendError(a,b,409,"插件正在重载"):c instanceof o.Tk||c instanceof Error&&"L4PiPluginMethodNotFoundError"===c.name?this.connection.sendError(a,b,404,"插件方法不存在"):c instanceof o.Pu?"input"===c.direction?this.connection.sendError(a,b,413,"插件调用数据超过 2MB"):(console.warn("[Pi Desk][PluginSocket] 插件方法输出超过限制",{pluginName:d,method:e,path:a,errorName:c.name}),this.connection.sendError(a,b,500,`插件方法执行失败:${d}/${e} 返回数据超过 2MB,请缩小查询范围或减少返回内容`)):(0,j.LO)(c)?this.connection.sendError(a,b,c.code,c.message):(console.warn("[Pi Desk][PluginSocket] 插件方法执行失败",{pluginName:d,method:e,path:a,errorName:c instanceof Error?c.name:"UnknownError",message:c instanceof Error?c.message:"Unknown plugin method error"}),this.connection.sendError(a,b,500,"插件方法执行失败"))}}d()}catch(a){d(a)}})},27235:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{U:()=>h});var e=c(35997),f=c(87016),g=a([f]);f=(g.then?(await g)():g)[0];class h{constructor(a,b){this.connection=a,this.runtime=b,this.routes=Object.freeze([{path:e.R.apply.path,access:"ready",handle:a=>this.apply(a)}])}dispose(){}async apply(a){let b=e.R.apply,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"App Runtime 更新参数无效");try{await this.runtime.applyClient(c.data),this.connection.sendSuccess(b,a.head.requestId,{})}catch(d){let c=d instanceof f.uF;this.connection.sendError(b.path,a.head.requestId,c?404:500,c?"App Runtime 目标不存在":"App Runtime 更新失败")}}}d()}catch(a){d(a)}})},27998:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{C:()=>h,I:()=>i});var e=c(69779),f=c(41468),g=a([f]);function h(a,b){let c=null===b.body?null:"text"===b.body.kind?b.body:{kind:"conversation",messages:b.body.entries.map((b,c)=>(0,f.NA)((0,f.Cz)(c,b.entryId,b.timestampMs,b.message,a))),temporaryMessages:b.body.temporaryMessages.map(({tempId:b,message:c})=>(0,f.QS)(b,c,a)),truncated:b.body.truncated};return e.ui.parse({taskId:b.taskId,canInterrupt:b.canInterrupt,body:c})}function i(a,b,c){return"snapshot"===c.type?e.gm.parse({type:"snapshot",snapshot:h(a,c.snapshot)}):"text_append"===c.type||"unavailable"===c.type?e.gm.parse(c):function(a,b,c){if(b.body?.kind!=="conversation")throw Error("Task conversation event requires a conversation snapshot");let d=b.body;if("durable_append"===c.type)return e.gm.parse({type:"conversation_event",event:{type:"durable_append",messages:c.entries.map((b,c)=>(0,f.NA)((0,f.Cz)(d.messages.length+c,b.entryId,b.timestampMs,b.message,a)))}});if("message_start"===c.type)return e.gm.parse({type:"conversation_event",event:{type:"message_start",snapshot:(0,f.QS)(c.tempId,c.message,a)}});if("message_update"===c.type){let b=d.temporaryMessages.find(a=>a.location.tempId===c.tempId);if(!b)throw Error(`Task Temporary message was not found: ${c.tempId}`);let g=(0,f.Ht)(b,(0,f.QS)(c.tempId,c.message,a,!1,"update"));return g?e.gm.parse({type:"conversation_event",event:g}):null}return"message_commit"===c.type?e.gm.parse({type:"conversation_event",event:{type:"message_commit",location:{tempId:c.tempId},durable:{index:d.messages.length,entryId:c.entryId},fixed:{timestampMs:c.timestampMs}}}):e.gm.parse({type:"conversation_event",event:{type:"message_discard",location:{tempId:c.tempId}}})}(a,b,c.event)}f=(g.then?(await g)():g)[0],d()}catch(a){d(a)}})},31656:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{c:()=>k,m:()=>f.Q});var e=c(77598),f=c(2214),g=a([f]);f=(g.then?(await g)():g)[0];let j=new Set;function h(a){if(j.has(a))throw new f.Q(409,"该服务正在登录或退出,请等待当前操作结束");if(j.size>=32)throw new f.Q(429,"正在处理的账号操作过多,请稍后重试");j.add(a)}function i(a,b,c){console.warn("[Pi Desk][ModelAuth] 账号操作未完成",{provider:a.state.provider,loginId:a.state.loginId,stage:b,errorName:c instanceof Error?c.name:"UnknownError"})}class k{constructor(a){this.onState=a,this.active=null,this.disposed=!1,this.logoutControllers=new Set}async list(){return this.assertOpen(),(await f.I.create()).list()}async start(a,b){if(this.assertOpen(),this.active)throw new f.Q(409,"当前连接已有登录流程,请先完成或取消");h(a);let c={state:{loginId:b,provider:a,status:"running",notice:null,prompt:null,message:null},abort:new AbortController,timer:null,scheduled:null,pending:null};this.active=c,c.timer=setTimeout(()=>this.stop(c,!0),9e5);try{let b=await f.I.create(c.abort.signal),d=(await b.list(c.abort.signal)).find(b=>b.provider===a);if(!d)throw new f.Q(400,"该服务不支持账号登录");if(d.conflict)throw new f.Q(409,d.conflict);c.abort.signal.throwIfAborted(),this.assertOpen(),c.scheduled=setImmediate(()=>{c.scheduled=null,this.login(c,b)})}catch(b){if(this.release(c),j.delete(a),c.abort.signal.aborted)throw new f.Q(409,"登录流程已取消或超时");throw b}}respond(a,b,c){let d=this.getRun(a),e=d.pending;if(!e||e.id!==b)throw new f.Q(409,"该登录问题已结束,请使用当前问题");let g=d.state.prompt;if(g?.type==="select"&&!g.options?.some(a=>a.id===c))throw new f.Q(400,"请选择当前问题提供的选项");this.clearPrompt(d),e.resolve(c),this.push(d)}cancel(a){this.stop(this.getRun(a),!1)}async logout(a){this.assertOpen(),h(a);let b=new AbortController;this.logoutControllers.add(b);let c=setTimeout(()=>b.abort(),15e3);try{let c=await f.I.create(b.signal),d=(await c.list(b.signal)).find(b=>b.provider===a);if(!d)throw new f.Q(400,"该服务不支持账号登录");if(!d.loggedIn)throw new f.Q(409,"该服务没有已保存的账号登录");b.signal.throwIfAborted(),await c.logout(a,b.signal)}catch(c){if(console.warn("[Pi Desk][ModelAuth] 退出账号未完成",{provider:a,stage:"logout",errorName:c instanceof Error?c.name:"UnknownError"}),c instanceof f.Q)throw c;throw new f.Q(500,b.signal.aborted?"退出账号已取消或超时,请重新获取账号状态":"退出账号失败,请重试")}finally{clearTimeout(c),this.logoutControllers.delete(b),j.delete(a)}}dispose(){if(!this.disposed){for(let a of(this.disposed=!0,this.active&&this.stop(this.active,!1),this.logoutControllers))a.abort();this.logoutControllers.clear()}}assertOpen(){if(this.disposed)throw new f.Q(409,"账号连接已关闭")}getRun(a){this.assertOpen();let b=this.active;if(!b||b.state.loginId!==a||"running"!==b.state.status)throw new f.Q(409,"登录流程已结束或不属于当前连接");return b}push(a){this.disposed||this.onState({...a.state})}notify(a,b){"running"!==a.state.status||a.abort.signal.aborted||("progress"===b.type?(a.state.message=b.message,a.state.notice?.type!=="auth_url"&&a.state.notice?.type!=="device_code"&&(a.state.notice={type:"progress",message:b.message})):"info"===b.type?(a.state.notice={type:"info",message:b.message,...b.links?{links:b.links.map(a=>({...a}))}:{}},a.state.message=b.message):(a.state.notice="device_code"===b.type?{type:"device_code",userCode:b.userCode,verificationUri:b.verificationUri}:{...b},a.state.message=null),this.push(a))}prompt(a,b){if(a.abort.signal.aborted||"running"!==a.state.status||b.signal?.aborted)return Promise.reject(new DOMException("登录问题已取消","AbortError"));if(a.pending){let b=a.pending;this.clearPrompt(a),b.reject(new DOMException("登录问题已替换","AbortError"))}return new Promise((c,d)=>{let f=(0,e.randomUUID)(),g=()=>{a.pending?.id===f&&(this.clearPrompt(a),d(new DOMException("登录问题已取消","AbortError")),"running"===a.state.status&&this.push(a))};a.pending={id:f,resolve:c,reject:d,cleanup:()=>{a.abort.signal.removeEventListener("abort",g),b.signal?.removeEventListener("abort",g)}},a.state.prompt={id:f,type:b.type,message:b.message,..."select"===b.type?{options:b.options.map(a=>({...a}))}:{placeholder:b.placeholder}},a.abort.signal.addEventListener("abort",g,{once:!0}),b.signal?.addEventListener("abort",g,{once:!0}),this.push(a)})}clearPrompt(a){a.pending?.cleanup(),a.pending=null,a.state.prompt=null}stop(a,b){"running"===a.state.status&&(a.state.status=b?"error":"cancelled",a.state.message=b?"登录已超时,请重新开始":"登录已取消",i(a,b?"timeout":"cancel",new DOMException("登录已结束","AbortError")),this.release(a),a.abort.abort(),this.push(a),a.scheduled&&(clearImmediate(a.scheduled),a.scheduled=null,j.delete(a.state.provider)))}release(a){a.timer&&clearTimeout(a.timer),a.timer=null;let b=a.pending;this.clearPrompt(a),b?.reject(new DOMException("登录已结束","AbortError")),this.active===a&&(this.active=null)}async login(a,b){let c="login";try{this.push(a);let d=await b.login(a.state.provider,{signal:a.abort.signal,prompt:b=>this.prompt(a,b),notify:b=>this.notify(a,b)});if("running"!==a.state.status)return;d||i(a,"credential-sync",new DOMException("本地同步失败","CredentialSynchronizationError")),c="catalog",a.state.message="登录成功,正在更新模型目录",this.push(a);let e=d?"登录成功":"登录成功,但本地模型状态同步失败,请重新获取模型列表",f=new AbortController,g=AbortSignal.any([a.abort.signal,f.signal]),h=setTimeout(()=>f.abort(),15e3);try{await b.refreshCatalog(a.state.provider,g)}catch(b){i(a,c,b),e="登录成功,但模型目录刷新失败,请稍后重新获取模型列表"}finally{clearTimeout(h)}if("running"!==a.state.status)return;a.state.status="completed",a.state.message=e,this.release(a),this.push(a)}catch(b){if("running"!==a.state.status)return;i(a,c,b),a.state.status=a.abort.signal.aborted?"cancelled":"error",a.state.message=a.abort.signal.aborted?"登录已取消":"登录未完成,请重试",this.release(a),this.push(a)}finally{this.release(a),a.abort.abort(),j.delete(a.state.provider)}}}d()}catch(a){d(a)}})},35997:(a,b,c)=>{"use strict";c.d(b,{R:()=>f});var d=c(58311),e=c(2002);let f=Object.freeze({apply:(0,e.Vc)({path:"app-runtime/apply",inputSchema:d.$C,outputSchema:d.Pq}),update:(0,e._G)({path:"app-runtime/update",bodySchema:d.YT})})},36262:(a,b,c)=>{"use strict";c.d(b,{m:()=>r});var d=c(76760),e=c(59473),f=c(2002),g=c(24187);let h=e.Yj().trim().min(1).max(32768),i=e.Ik({text:e.Yj(),truncated:e.zM()}).strict(),j=e.KC([e.Ik({type:e.eu("text_append"),text:e.Yj().min(1)}).strict(),e.Ik({type:e.eu("snapshot"),snapshot:i}).strict(),e.Ik({type:e.eu("unavailable")}).strict()]),k=e.Ik({pluginName:g.tv,path:h}).strict(),l=e.Ik({snapshot:i}).strict(),m=e.Ik({}).strict(),n=e.Ik({pluginName:g.tv,path:h,event:j}).strict(),o=Object.freeze({watch:(0,f.Vc)({path:"plugins/logs/watch",inputSchema:k,outputSchema:l}),unwatch:(0,f.Vc)({path:"plugins/logs/unwatch",inputSchema:k,outputSchema:m}),event:(0,f._G)({path:"plugins/logs/event",bodySchema:n})});var p=c(75613);function q(a,b){return JSON.stringify([a,b])}class r{constructor(a){this.connection=a,this.watches=new Map,this.operationTail=Promise.resolve(),this.disposed=!1,this.routes=Object.freeze([{path:o.watch.path,access:"ready",handle:a=>this.enqueue(()=>this.watch(a))},{path:o.unwatch.path,access:"ready",handle:a=>this.enqueue(()=>this.unwatch(a))}])}dispose(){if(!this.disposed){for(let a of(this.disposed=!0,this.watches.values()))a.observation.release();this.watches.clear()}}enqueue(a){let b=this.operationTail.then(a,a);return this.operationTail=b.then(()=>void 0,()=>void 0),b}async watch(a){let b=o.watch,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"日志观察参数无效");if(!(0,d.isAbsolute)(c.data.path))return void this.connection.sendError(b.path,a.head.requestId,400,"日志路径必须是服务端绝对路径");let e=q(c.data.pluginName,c.data.path),f=this.watches.get(e);if(f)return void this.connection.sendSuccess(b,a.head.requestId,{snapshot:f.observation.readSnapshot()});if(this.watches.size>=16)return void this.connection.sendError(b.path,a.head.requestId,409,"当前页面观察的日志过多");try{let d=await this.createStableWatch(e,c.data.pluginName,c.data.path);if(this.disposed||!this.connection.isCurrent())return void d.observation.release();this.watches.set(e,d),this.connection.sendSuccess(b,a.head.requestId,{snapshot:d.observation.snapshot}),d.status="ready",this.flushQueuedEvents(d),console.info("[Pi Desk][PluginLogSocket] 日志观察完成",{clientId:this.connection.clientId,pluginName:d.pluginName,path:d.path})}catch(d){console.warn("[Pi Desk][PluginLogSocket] 初始化日志观察失败",{pluginName:c.data.pluginName,path:c.data.path,errorName:d instanceof Error?d.name:"UnknownError",message:d instanceof Error?d.message:String(d)}),this.connection.sendError(b.path,a.head.requestId,500,"读取日志失败")}}async createStableWatch(a,b,c){for(;;){let d=[],e={state:null},f=await (0,p.i)().observe(c,b=>{let c=e.state;if(!c||this.watches.get(a)!==c||this.disposed){d.length<128&&d.push(b);return}this.handleEvent(c,b)}),g={key:a,pluginName:b,path:c,observation:f,status:"syncing",queuedEvents:d,overflowed:d.length>=128};if(e.state=g,!g.overflowed)return g;f.release()}}async unwatch(a){let b=o.unwatch,c=b.inputSchema.safeParse(a.body);c.success?(0,d.isAbsolute)(c.data.path)?(this.releaseWatch(q(c.data.pluginName,c.data.path)),this.connection.sendSuccess(b,a.head.requestId,{})):this.connection.sendError(b.path,a.head.requestId,400,"日志路径必须是服务端绝对路径"):this.connection.sendError(b.path,a.head.requestId,400,"日志解除观察参数无效")}handleEvent(a,b){if(this.watches.get(a.key)===a&&!this.disposed&&this.connection.isCurrent()){if("syncing"===a.status){if(a.queuedEvents.length>=128){a.queuedEvents.length=0,a.overflowed=!0;return}a.queuedEvents.push(b);return}this.connection.sendPush(o.event,{pluginName:a.pluginName,path:a.path,event:b}),"unavailable"===b.type&&this.releaseWatch(a.key)}}flushQueuedEvents(a){if(this.watches.get(a.key)===a){if(a.overflowed){this.connection.sendPush(o.event,{pluginName:a.pluginName,path:a.path,event:{type:"snapshot",snapshot:a.observation.readSnapshot()}}),a.queuedEvents.length=0,a.overflowed=!1;return}for(let b of a.queuedEvents.splice(0))if(this.connection.sendPush(o.event,{pluginName:a.pluginName,path:a.path,event:b}),"unavailable"===b.type)return void this.releaseWatch(a.key)}}releaseWatch(a){let b=this.watches.get(a);b&&(this.watches.delete(a),b.observation.release())}}},36559:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{Y3:()=>q,ni:()=>s,o3:()=>p,q2:()=>t,qc:()=>r,rt:()=>n,x4:()=>o});var e=c(69779),f=c(97824),g=c(41468),h=c(99327),i=c(73383),j=c(27998),k=a([g,h,i,j]);[g,h,i,j]=k.then?(await k)():k;class n{constructor(a){this.resolveRuntime=a,this.commandTails=new Map}async watchDetail(a,b,c){let d=await this.resolveRuntime(a),e=[],g=null,h=null,i=!1,k=!1,l=d=>{if(!k){if(!i||!g||!h)return void e.push(d);try{let b=(0,j.I)(a,g,d);if(!b)return;let e=(0,f.dZ)(g,b);e&&(g=e),c(b)}catch(f){console.warn("[Pi Desk][TaskCenterRuntime] 任务详情增量无效,重建 Snapshot",{workId:a.workId,taskId:b,eventType:d.type,errorName:f instanceof Error?f.name:"UnknownError"});let e=(0,j.C)(a,h.readSnapshot());g=e,c({type:"snapshot",snapshot:e})}}};try{for(let c of(h=await d.watchTaskDetail(b,l),await this.resolveRuntime(a),g=(0,j.C)(a,h.snapshot),i=!0,e.splice(0)))l(c);return{snapshot:g,release:()=>{k||(k=!0,e.length=0,h?.release(),h=null,g=null)}}}catch(a){throw k=!0,h?.release(),m(a)}}async getMessageDetail(a,b,c){try{let d=await this.resolveRuntime(a),{index:f,entry:h}=await d.readTaskMessage(b,c),i=(0,g.Cz)(f,h.entryId,h.timestampMs,h.message,a);if(!i.fixed.hasDetail||void 0===i.detail)throw new t(c);return e.NN.parse({index:f,entryId:c,detail:i.detail})}catch(a){throw l(a)}}async getImage(a,b,c,d){try{let f=await this.resolveRuntime(a);return e.Ld.parse(await f.readTaskImage(b,c,d))}catch(a){throw l(a)}}interrupt(a,b){let c=JSON.stringify([a.workId,a.sessionId,a.branchId,b]),d=this.commandTails.get(c)??Promise.resolve(),e=async()=>{let c=await this.resolveRuntime(a);await c.interruptTask(b)},f=d.then(e,e),g=f.then(()=>void 0,()=>void 0);return this.commandTails.set(c,g),g.finally(()=>{this.commandTails.get(c)===g&&this.commandTails.delete(c)}),f.catch(a=>Promise.reject(m(a)))}}function l(a){let b=m(a);return b===a?new s(a instanceof Error?a.message:"Task detail source is unavailable"):b}function m(a){return a instanceof i.cI||a instanceof h.L9?new o(a.message):a instanceof i.JF?new p(a.message):a instanceof h.dw?new q(a.message):a instanceof h.HJ?new r(a.message):a}class o extends Error{constructor(a){super(a),this.name="L2TaskNotFoundError"}}class p extends Error{constructor(a){super(a),this.name="L2TaskNotInterruptibleError"}}class q extends Error{constructor(a){super(a),this.name="L2TaskDetailUnsupportedError"}}class r extends Error{constructor(a){super(a),this.name="L2TaskMessageNotFoundError"}}class s extends Error{constructor(a){super(a),this.name="L2TaskDetailUnavailableError"}}class t extends Error{constructor(a){super(`Task message does not provide canonical detail: ${a}`),this.name="L2TaskMessageDetailUnavailableError"}}d()}catch(a){d(a)}})},36925:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{T:()=>j});var e=c(22307),f=c(47574),g=c(77844),h=a([f,g]);function i(a,b){return a.workId===b.workId&&a.sessionId===b.sessionId&&a.branchId===b.branchId}[f,g]=h.then?(await h)():h;class j{constructor(a,b){this.connection=a,this.manage=b,this.subscriptionsByWorkId=new Map,this.operationTail=Promise.resolve(),this.disposed=!1,this.routes=Object.freeze([{path:e.P6.subscribe.path,access:"ready",handle:a=>this.enqueueSubscribe(a)},{path:e.P6.send.path,access:"ready",handle:a=>this.send(a)},{path:e.P6.interrupt.path,access:"ready",handle:a=>this.interrupt(a)},{path:e.P6.compact.path,access:"ready",handle:a=>this.compact(a)},{path:e.P6.reload.path,access:"ready",handle:a=>this.reload(a)},{path:e.P6.presentationSet.path,access:"ready",handle:a=>this.setPresentation(a)},{path:e.P6.queueRestore.path,access:"ready",handle:a=>this.restoreQueue(a)},{path:e.P6.modelSet.path,access:"ready",handle:a=>this.setModel(a)},{path:e.P6.capabilityModeSet.path,access:"ready",handle:a=>this.setCapabilityMode(a)}]),this.unsubscribeMessages=this.manage.subscribeMessageEvents(a=>this.handleRuntimeEvent(a))}dispose(){this.disposed||(this.disposed=!0,this.unsubscribeMessages(),this.subscriptionsByWorkId.clear())}enqueueSubscribe(a){let b=()=>this.subscribe(a),c=this.operationTail.then(b,b);return this.operationTail=c.then(()=>void 0,()=>void 0),c}async subscribe(a){let b,c=e.P6.subscribe,d=c.inputSchema.safeParse(a.body);if(!d.success)return void this.connection.sendError(c.path,a.head.requestId,400,"聊天订阅参数无效",{key:"errors:chatSubscribeInvalid"});let g=new Map;for(let a of d.data.subscriptions)g.set(a.source.workId,this.subscriptionsByWorkId.get(a.source.workId)),this.subscriptionsByWorkId.set(a.source.workId,{source:a.source,status:"syncing",queuedEvents:[],overflowed:!1});try{b=await this.manage.prepareChatSourceSyncs(d.data.subscriptions)}catch(h){this.restoreSubscriptions(g);let b=h instanceof f.dM;b||console.error("[Pi Desk][ChatSocket] 聊天 Source 订阅初始化失败",{clientId:this.connection.clientId,connectionId:this.connection.connectionId,requestId:a.head.requestId,sources:d.data.subscriptions.map(a=>a.source),errorName:h instanceof Error?h.name:"UnknownError",errorMessage:h instanceof Error?h.message:String(h),errorStack:h instanceof Error?h.stack:void 0});let e=h instanceof Error?h.message.slice(0,32e3):null;this.connection.sendError(c.path,a.head.requestId,b?409:500,b?"聊天订阅绑定已过期":e||"聊天订阅初始化失败",b?{key:"errors:chatSubscribeExpired"}:e?void 0:{key:"errors:chatSubscribeFailed"});return}if(!this.disposed&&this.connection.isCurrent()){this.connection.sendSuccess(c,a.head.requestId,{});try{for(let a of b)await this.finishSync(a.source,a.event,a.watermark);console.info("[Pi Desk][ChatSocket] 聊天 Source 订阅完成",{clientId:this.connection.clientId,connectionId:this.connection.connectionId,sourceCount:b.length})}catch(a){console.error("[Pi Desk][ChatSocket] 聊天 Source 同步失败",{clientId:this.connection.clientId,connectionId:this.connection.connectionId,errorName:a instanceof Error?a.name:"UnknownError"}),this.connection.close(1011,"聊天消息同步失败")}}}async send(a){let b=e.P6.send,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"聊天发送参数无效",{key:"errors:chatSendInvalid"});if(Buffer.byteLength(JSON.stringify({head:a.head,body:c.data}),"utf8")>g.lr)return void this.connection.sendError(b.path,a.head.requestId,413,"聊天发送内容超过 31MB",{key:"errors:chatSendTooLarge"});try{console.info("[Pi Desk][ChatSocket] 聊天发送开始",{clientId:this.connection.clientId,requestId:a.head.requestId,workId:c.data.source.workId,sessionId:c.data.source.sessionId,branchId:c.data.source.branchId,mode:c.data.mode});let d=await this.manage.sendChat(c.data);console.info("[Pi Desk][ChatSocket] 聊天发送已接纳",{clientId:this.connection.clientId,requestId:a.head.requestId,workId:c.data.source.workId,tempId:d.tempId}),this.connection.sendSuccess(b,a.head.requestId,d)}catch(c){this.sendCommandError(b.path,a.head.requestId,c,"发送聊天消息失败")}}async interrupt(a){let b=e.P6.interrupt,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"聊天打断参数无效",{key:"errors:chatInterruptInvalid"});try{await this.manage.interruptChat(c.data.source),this.connection.sendSuccess(b,a.head.requestId,{})}catch(c){this.sendCommandError(b.path,a.head.requestId,c,"打断当前响应失败")}}async compact(a){let b=e.P6.compact,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"上下文压缩参数无效",{key:"errors:chatCompactInvalid"});try{console.info("[Pi Desk][ChatSocket] 手动上下文压缩开始",{clientId:this.connection.clientId,requestId:a.head.requestId,workId:c.data.source.workId,sessionId:c.data.source.sessionId,branchId:c.data.source.branchId}),await this.manage.compactChat(c.data.source),console.info("[Pi Desk][ChatSocket] 手动上下文压缩完成",{clientId:this.connection.clientId,requestId:a.head.requestId,workId:c.data.source.workId}),this.connection.sendSuccess(b,a.head.requestId,{})}catch(c){this.sendCommandError(b.path,a.head.requestId,c,"压缩上下文失败")}}async reload(a){let b=e.P6.reload,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"Pi 配置重载参数无效",{key:"errors:chatReloadInvalid"});try{console.info("[Pi Desk][ChatSocket] Pi 配置重载开始",{clientId:this.connection.clientId,requestId:a.head.requestId,workId:c.data.source.workId,sessionId:c.data.source.sessionId,branchId:c.data.source.branchId}),await this.manage.reloadChat(c.data.source,c.data.mode),console.info("[Pi Desk][ChatSocket] Pi 配置重载完成",{clientId:this.connection.clientId,requestId:a.head.requestId,workId:c.data.source.workId}),this.connection.sendSuccess(b,a.head.requestId,{})}catch(c){this.sendCommandError(b.path,a.head.requestId,c,"重载 Pi 配置失败")}}async setPresentation(a){let b=e.P6.presentationSet,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"消息展示模式参数无效");try{await this.manage.setChatPresentation(c.data.source,c.data.mode),this.connection.sendSuccess(b,a.head.requestId,{})}catch(c){this.sendCommandError(b.path,a.head.requestId,c,"切换消息展示失败")}}async restoreQueue(a){let b=e.P6.queueRestore,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"恢复队列参数无效",{key:"errors:chatRestoreInvalid"});try{let d=await this.manage.restoreChatQueue(c.data.source),e=Buffer.byteLength(JSON.stringify({head:{op:"resp",path:b.path,requestId:a.head.requestId},body:{code:0,msg:"",data:d}}),"utf8");if(e>g.lr){console.error("[Pi Desk][ChatSocket] 队列恢复响应突破应用上限",{workId:c.data.source.workId,responseBytes:e}),this.connection.sendError(b.path,a.head.requestId,500,"恢复内容超过传输上限",{key:"errors:chatRestoreTooLarge"});return}this.connection.sendSuccess(b,a.head.requestId,d)}catch(c){this.sendCommandError(b.path,a.head.requestId,c,"恢复全部排队消息失败")}}async setModel(a){let b=e.P6.modelSet,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"模型设置参数无效",{key:"errors:chatModelInvalid"});try{await this.manage.setChatModel(c.data),this.connection.sendSuccess(b,a.head.requestId,{})}catch(c){this.sendCommandError(b.path,a.head.requestId,c,"设置模型失败")}}async setCapabilityMode(a){let b=e.P6.capabilityModeSet,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"能力模式参数无效",{key:"errors:chatModeInvalid"});try{await this.manage.setChatCapabilityMode(c.data),this.connection.sendSuccess(b,a.head.requestId,{})}catch(c){this.sendCommandError(b.path,a.head.requestId,c,"切换能力模式失败")}}sendCommandError(a,b,c,d){if(c instanceof f.dM||c instanceof Error&&"L2ChatSourceBindingError"===c.name)return void this.connection.sendError(a,b,409,"聊天 Source 已过期",{key:"errors:sourceExpired"});if(c instanceof f.nJ||c instanceof Error&&"L2ChatLifecycleBlockedError"===c.name)return void this.connection.sendError(a,b,409,"工作会话正在替换或切换分支",{key:"errors:chatSourceBusy"});let e=c instanceof Error&&c.message?c.message:d;console.warn("[Pi Desk][ChatSocket] 聊天命令执行失败",{path:a,errorName:c instanceof Error?c.name:"UnknownError",message:e}),this.connection.sendError(a,b,400,e)}async finishSync(a,b,c){let d=b,f=c;for(;;){let b=this.subscriptionsByWorkId.get(a.workId);if(!b||!i(b.source,a))return;if(b.overflowed){b.overflowed=!1,b.queuedEvents=[];let[c]=await this.manage.prepareChatSourceSyncs([{source:a,cursor:null}]);if(!c)return;d=c.event,f=c.watermark;continue}for(this.connection.sendPush(e.P6.sourceEvent,{source:a,event:d});;){let c=b.queuedEvents.filter(a=>a.version>f);for(let d of(b.queuedEvents=[],c))this.connection.sendPush(e.P6.sourceEvent,{source:a,event:d.event}),f=d.version;if(b.overflowed)break;if(!(b.queuedEvents.length>0)){b.status="ready";return}}}}handleRuntimeEvent(a){if(this.disposed||!this.connection.isCurrent())return;let b=this.subscriptionsByWorkId.get(a.source.workId);if(b&&i(b.source,a.source)){if("source_invalidated"===a.type)return void this.subscriptionsByWorkId.delete(a.source.workId);if("syncing"===b.status){if(b.overflowed)return;if(b.queuedEvents.length>=128){b.queuedEvents=[],b.overflowed=!0;return}b.queuedEvents.push({version:a.version,event:a.event});return}this.connection.sendPush(e.P6.sourceEvent,{source:a.source,event:a.event})}}restoreSubscriptions(a){for(let[b,c]of a)c?this.subscriptionsByWorkId.set(b,c):this.subscriptionsByWorkId.delete(b)}}d()}catch(a){d(a)}})},41935:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{G:()=>i});var e=c(18477),f=c(35997),g=c(23054),h=a([g]);g=(h.then?(await h)():h)[0];class i{constructor(a,b,c){this.connection=a,this.manage=b,this.appRuntime=c,this.status="new",this.dirty=!1,this.disposed=!1,this.unsubscribeWorkSessions=null,this.unsubscribeAppRuntime=null,this.routes=Object.freeze([{path:e.kM.list.path,access:"bootstrap",handle:a=>this.initialize(a)},{path:e.kM.acknowledgeCompleted.path,access:"ready",handle:a=>this.acknowledgeCompleted(a)}])}isReady(){return"ready"===this.status&&!this.disposed}dispose(){this.disposed||(this.disposed=!0,this.status="new",this.unsubscribeWorkSessions?.(),this.unsubscribeWorkSessions=null,this.unsubscribeAppRuntime?.(),this.unsubscribeAppRuntime=null)}async initialize(a){let b=e.kM.list;if("initializing"===this.status)return void this.connection.sendError(b.path,a.head.requestId,409,"工作会话正在初始化",{key:"errors:sessionsInitializing"});if(!b.inputSchema.safeParse(a.body).success)return void this.connection.sendError(b.path,a.head.requestId,400,"工作会话初始化参数无效",{key:"errors:sessionsInitializeInvalid"});this.status="initializing",this.dirty=!1,this.unsubscribeWorkSessions?.(),this.unsubscribeWorkSessions=this.manage.subscribeUpdates(a=>{if(!this.disposed&&this.connection.isCurrent()){if("initializing"===this.status){this.dirty=!0;return}"ready"===this.status&&this.connection.sendPush(e.kM.update,a)}}),this.unsubscribeAppRuntime?.(),this.unsubscribeAppRuntime=this.appRuntime.subscribe(a=>{if(!this.disposed&&this.connection.isCurrent()){if("initializing"===this.status){this.dirty=!0;return}"ready"===this.status&&this.connection.sendPush(f.R.update,a)}});try{let c,d;do if(this.dirty=!1,c=await this.manage.listWorkSessions(),d=this.appRuntime.readSnapshot(),this.disposed||!this.connection.isCurrent())return;while(this.dirty);let e={...c,appRuntime:d};this.status="ready",this.connection.sendSuccess(b,a.head.requestId,e),console.info("[Pi Desk][WorkSessionSocket] 工作会话初始化完成",{clientId:this.connection.clientId,connectionId:this.connection.connectionId,workSessionCount:e.workSessions.length,notificationCount:e.appRuntime.notifications.length,pluginStateCount:Object.keys(e.appRuntime.plugins).length})}catch(c){this.status="new",this.unsubscribeWorkSessions?.(),this.unsubscribeWorkSessions=null,this.unsubscribeAppRuntime?.(),this.unsubscribeAppRuntime=null,console.error("[Pi Desk][WorkSessionSocket] 工作会话初始化失败",{clientId:this.connection.clientId,connectionId:this.connection.connectionId,errorName:c instanceof Error?c.name:"UnknownError"}),this.connection.sendError(b.path,a.head.requestId,500,"工作会话初始化失败",{key:"errors:sessionsInitializeFailed"})}}async acknowledgeCompleted(a){let b=e.kM.acknowledgeCompleted,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"工作会话完成确认参数无效",{key:"errors:completionAckInvalid"});try{await this.manage.acknowledgeCompleted(c.data.workId),this.connection.sendSuccess(b,a.head.requestId,{workId:c.data.workId})}catch(d){let c=d instanceof g.XM;this.connection.sendError(b.path,a.head.requestId,c?404:500,c?"工作会话不存在":"确认工作会话完成状态失败",{key:c?"errors:sessionMissing":"errors:completionAckFailed"})}}}d()}catch(a){d(a)}})},48317:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{k:()=>j});var e=c(68623),f=c(47574),g=c(23272),h=a([f]);function i(a){return JSON.stringify([a.workId,a.sessionId,a.branchId])}f=(h.then?(await h)():h)[0];class j{constructor(a,b){this.connection=a,this.manage=b,this.subscriptions=new Map,this.disposed=!1,this.releaseSources=b.subscribeMessageEvents(a=>{"source_invalidated"===a.type&&this.release(i(a.source))}),this.routes=[{path:e.H.subscribe.path,access:"ready",handle:async a=>this.subscribe(a)},{path:e.H.unsubscribe.path,access:"ready",handle:async a=>this.unsubscribe(a)},{path:e.H.respond.path,access:"ready",handle:async a=>this.respond(a)}]}dispose(){if(!this.disposed)for(let a of(this.disposed=!0,this.releaseSources(),this.subscriptions.keys()))this.release(a)}subscribe(a){if(this.disposed||!this.connection.isCurrent())return;let b=e.H.subscribe,c=b.inputSchema.safeParse(a.body);if(!c.success)return this.invalid(a);try{let{source:d}=c.data,f=this.manage.getNativeUi(d),g=i(d);this.release(g),this.subscriptions.set(g,f.subscribe(a=>{!this.disposed&&this.connection.isCurrent()&&this.connection.sendPush(e.H.event,{source:d,event:a})})),this.connection.sendSuccess(b,a.head.requestId,f.snapshot())}catch(b){this.fail(a,b)}}unsubscribe(a){if(this.disposed||!this.connection.isCurrent())return;let b=e.H.unsubscribe,c=b.inputSchema.safeParse(a.body);if(!c.success)return this.invalid(a);this.release(i(c.data.source)),this.connection.sendSuccess(b,a.head.requestId,{})}respond(a){if(this.disposed||!this.connection.isCurrent())return;let b=e.H.respond,c=b.inputSchema.safeParse(a.body);if(!c.success)return this.invalid(a);try{this.manage.getNativeUi(c.data.source).respond(c.data.response),this.connection.sendSuccess(b,a.head.requestId,{})}catch(b){this.fail(a,b)}}release(a){this.subscriptions.get(a)?.(),this.subscriptions.delete(a)}invalid(a){this.connection.sendError(a.head.path,a.head.requestId,400,"插件交互参数无效")}fail(a,b){let c=b instanceof f.dM?409:b instanceof g.H?b.code:500,d=b instanceof f.dM?"工作会话来源已变化":b instanceof Error?b.message:"插件交互失败";500===c&&console.error("[Pi Desk][NativeUI] 请求失败",{path:a.head.path,message:d}),this.connection.sendError(a.head.path,a.head.requestId,c,d)}}d()}catch(a){d(a)}})},50857:(a,b,c)=>{"use strict";c.d(b,{rn:()=>m});var d=c(59473),e=c(96089),f=c(69779),g=c(2002);let h=d.Ik({source:e.R,taskId:f.mQ.nullable()}).strict(),i=d.Ik({snapshot:f.ui.nullable()}).strict(),j=d.Ik({source:e.R,taskId:f.mQ}).strict(),k=d.Ik({}).strict(),l=d.Ik({source:e.R,taskId:f.mQ,event:f.gm}).strict(),m=Object.freeze({detailWatch:(0,g.Vc)({path:"task-center/detail-watch",inputSchema:h,outputSchema:i}),interrupt:(0,g.Vc)({path:"task-center/interrupt",inputSchema:j,outputSchema:k}),detailEvent:(0,g._G)({path:"task-center/detail-event",bodySchema:l})})},54133:(a,b,c)=>{"use strict";c.d(b,{c:()=>n});var d=c(59473),e=c(2002);let f=d.Ik({}).strict(),g=d.Yj().trim().min(1).max(128),h=d.Yj().max(32768),i=d.Ik({url:h,label:h.optional()}).strict(),j=d.Ik({provider:g,name:h,loggedIn:d.zM(),conflict:d.Yj().nullable()}).strict(),k=d.Ik({id:d.Yj().uuid(),type:d.k5(["text","secret","select","manual_code"]),message:h,placeholder:h.optional(),options:d.YO(d.Ik({id:h,label:h,description:h.optional()}).strict()).optional()}).strict(),l=d.gM("type",[d.Ik({type:d.eu("auth_url"),url:h,instructions:h.optional()}).strict(),d.Ik({type:d.eu("device_code"),userCode:h,verificationUri:h}).strict(),d.Ik({type:d.eu("info"),message:h,links:d.YO(i).optional()}).strict(),d.Ik({type:d.eu("progress"),message:h}).strict()]),m=d.Ik({loginId:d.Yj().uuid(),provider:g,status:d.k5(["running","completed","cancelled","error"]),notice:l.nullable(),prompt:k.nullable(),message:d.Yj().nullable()}).strict(),n=Object.freeze({list:(0,e.Vc)({path:"model-auth/list",inputSchema:f,outputSchema:d.Ik({providers:d.YO(j)}).strict()}),start:(0,e.Vc)({path:"model-auth/start",inputSchema:d.Ik({loginId:d.Yj().uuid(),provider:g}).strict(),outputSchema:f}),respond:(0,e.Vc)({path:"model-auth/respond",inputSchema:d.Ik({loginId:d.Yj().uuid(),promptId:d.Yj().uuid(),value:h}).strict(),outputSchema:f}),cancel:(0,e.Vc)({path:"model-auth/cancel",inputSchema:d.Ik({loginId:d.Yj().uuid()}).strict(),outputSchema:f}),logout:(0,e.Vc)({path:"model-auth/logout",inputSchema:d.Ik({provider:g}).strict(),outputSchema:f}),state:(0,e._G)({path:"model-auth/state",bodySchema:m})})},54997:(a,b,c)=>{"use strict";c.d(b,{cx:()=>j});var d=c(59473),e=c(96089),f=c(2002),g=c(24187);let h=d.gM("scope",[d.Ik({scope:d.eu("global")}).strict(),d.Ik({scope:d.eu("session"),source:e.R}).strict()]),i=d.Ik({pluginName:g.tv,target:h,event:g.f7,data:g.Dz}).strict(),j=(0,f._G)({path:"plugins/push",bodySchema:i})},59587:(a,b,c)=>{"use strict";c.d(b,{Jz:()=>g,bm:()=>n,iT:()=>i,sd:()=>j});var d=c(59473),e=c(2002),f=c(24187);let g=d.Yj().min(32).max(128).regex(/^[A-Za-z0-9_-]+$/),h="/api/plugins/host-runtime/v1",i=Object.freeze({imports:Object.freeze({react:`${h}/base.js`,"react/jsx-runtime":`${h}/base.js`,"react/jsx-dev-runtime":`${h}/base.js`,"react-dom":`${h}/base.js`,"react-dom/client":`${h}/base.js`,"@jetcrab/pi-desk-sdk/react/base":`${h}/base.js`,"@jetcrab/pi-desk-sdk/react/markdown":`${h}/markdown.js`})}),j=d.eu("v1"),k=d.Ik({pluginName:f.tv,url:d.Yj().regex(/^\/api\/plugins\/browser-resources\/[A-Za-z0-9_-]{32,128}\/entry\.js$/,"Browser Entry URL 无效")}).strict(),l=d.Ik({}).strict(),m=d.Ik({entries:d.YO(k)}).strict(),n=Object.freeze({list:(0,e.Vc)({path:"plugins/browser-entries/list",inputSchema:l,outputSchema:m})})},63461:(a,b,c)=>{"use strict";c.d(b,{D:()=>m});var d=c(59473),e=c(2002),f=c(9050);let g=d.Yj().uuid(),h=d.Ik({}).strict(),i=d.Ik({terminalId:g,cwd:d.Yj().min(1),shell:d.Yj().min(1),title:d.Yj().max(512),status:d.k5(["running","exited"]),exitCode:d.ai().int().nullable()}).strict(),j=d.Ik({terminals:d.YO(i).max(32)}).strict(),k=Object.freeze({list:(0,e.Vc)({path:"terminals/list",inputSchema:h,outputSchema:j}),create:(0,e.Vc)({path:"terminals/create",inputSchema:d.Ik({cwd:d.Yj().min(1).max(32768).optional()}).strict(),outputSchema:i}),remove:(0,e.Vc)({path:"terminals/remove",inputSchema:d.Ik({terminalId:g}).strict(),outputSchema:h}),watch:(0,e.Vc)({path:"terminals/watch",inputSchema:d.Ik({terminalId:g.nullable()}).strict(),outputSchema:d.Ik({snapshot:f.CR.nullable()}).strict()}),unwatch:(0,e.Vc)({path:"terminals/unwatch",inputSchema:d.Ik({terminalId:g}).strict(),outputSchema:h}),input:(0,e.Vc)({path:"terminals/input",inputSchema:d.Ik({terminalId:g,data:d.Yj().min(1).max(f.Oi)}).strict(),outputSchema:h}),activate:(0,e.Vc)({path:"terminals/activate",inputSchema:d.Ik({terminalId:g,...f.XV}).strict(),outputSchema:h}),resize:(0,e.Vc)({path:"terminals/resize",inputSchema:d.Ik({terminalId:g,...f.XV}).strict(),outputSchema:h}),update:(0,e._G)({path:"terminals/update",bodySchema:j}),event:(0,e._G)({path:"terminals/event",bodySchema:d.Ik({terminalId:g,event:f.ED}).strict()})});var l=c(83977);class m{constructor(a,b,c){this.connection=a,this.manage=b,this.isReady=c,this.disposed=!1,this.unsubscribeList=null,this.watches=new Map,this.watchTail=Promise.resolve(),this.routes=[this.route(k.list,()=>(this.unsubscribeList||(this.unsubscribeList=this.manage.subscribeList(a=>{if(!this.active())return;let b=new Set(a.map(a=>a.terminalId));for(let a of this.watches.keys())b.has(a)||this.releaseWatch(a);this.connection.sendPush(k.update,{terminals:a})})),{terminals:this.manage.list()})),this.route(k.create,({cwd:a})=>this.manage.create(a)),this.route(k.remove,async({terminalId:a})=>(await this.manage.remove(a),{})),{path:k.watch.path,access:"ready",handle:a=>this.enqueueWatch(()=>this.watch(a))},{path:k.unwatch.path,access:"ready",handle:a=>this.enqueueWatch(()=>this.unwatch(a))},this.route(k.input,async({terminalId:a,data:b})=>(await this.manage.input(a,b),{})),this.route(k.activate,async({terminalId:a,cols:b,rows:c})=>(await this.manage.activate(a,this.connection.connectionId,b,c),this.active()||this.manage.releaseOwner(this.connection.connectionId),{})),this.route(k.resize,async({terminalId:a,cols:b,rows:c})=>(await this.manage.resize(a,this.connection.connectionId,b,c),{}))]}dispose(){this.disposed||(this.disposed=!0,this.unsubscribeList?.(),this.unsubscribeList=null,this.releaseAllWatches(),this.manage.releaseOwner(this.connection.connectionId))}active(){return!this.disposed&&this.connection.isCurrent()&&this.isReady()}route(a,b){return{path:a.path,access:"ready",handle:async c=>{if(!this.active())return;let d=a.inputSchema.safeParse(c.body);if(!d.success)return void this.connection.sendError(a.path,c.head.requestId,400,"终端请求参数无效");try{let e=b(d.data),f=e instanceof Promise?await e:e;this.active()&&this.connection.sendSuccess(a,c.head.requestId,f)}catch(a){this.sendError(c,a)}}}}enqueueWatch(a){let b=this.watchTail.then(a);return this.watchTail=b.catch(()=>void 0),b}async watch(a){if(!this.active())return;let b=k.watch,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"终端观察参数无效");if(null===c.data.terminalId){this.releaseAllWatches(),this.connection.sendSuccess(b,a.head.requestId,{snapshot:null});return}if(this.releaseWatch(c.data.terminalId),this.watches.size>=32)return void this.sendError(a,new l.l$(429,"终端观察已达 32 个上限"));let d={id:c.data.terminalId,dispose:null,events:[],bytes:0,syncing:!0,overflowed:!1,rebuilding:!1,timer:null};this.watches.set(d.id,d);try{await this.prepareSnapshot(d,c=>{this.connection.sendSuccess(b,a.head.requestId,{snapshot:c})})}catch(b){this.watches.get(d.id)===d&&this.releaseWatch(d.id),this.sendError(a,b)}}async unwatch(a){if(!this.active())return;let b=k.unwatch,c=b.inputSchema.safeParse(a.body);c.success?(this.releaseWatch(c.data.terminalId),this.connection.sendSuccess(b,a.head.requestId,{})):this.connection.sendError(b.path,a.head.requestId,400,"终端观察参数无效")}valid(a){return this.watches.get(a.id)===a&&this.active()}async prepareSnapshot(a,b){a.rebuilding=!0,a.syncing=!0;try{for(;this.valid(a);){a.dispose?.(),a.dispose=null,a.events=[],a.bytes=0,a.overflowed=!1;let c=await this.manage.watch(a.id,b=>this.acceptEvent(a,b));if(!this.valid(a))return void c.dispose();if(a.dispose=c.dispose,!a.overflowed){b(c.snapshot),a.syncing=!1,this.scheduleDrain(a);return}}}finally{a.rebuilding=!1}}acceptEvent(a,b){if(!this.valid(a)||a.overflowed)return;let c=this.eventBytes(b);if(a.bytes+c>524288||a.events.length>=128){a.overflowed=!0,a.syncing=!0,a.events=[],a.bytes=0,console.warn("[Pi Desk][TerminalSocket] 观察队列溢出,重建快照",{terminalId:a.id,connectionId:this.connection.connectionId}),a.rebuilding||this.enqueueWatch(async()=>{if(this.valid(a))try{await this.prepareSnapshot(a,b=>{this.connection.sendPush(k.event,{terminalId:a.id,event:{type:"snapshot",snapshot:b}})})}catch(b){console.error("[Pi Desk][TerminalSocket] 快照重建失败",{terminalId:a.id,error:b}),this.valid(a)&&(this.releaseWatch(a.id),this.connection.close(1011,"终端画面无法同步"))}});return}a.events.push(b),a.bytes+=c,a.syncing||this.scheduleDrain(a)}scheduleDrain(a){this.valid(a)&&!a.syncing&&!a.timer&&a.events.length&&(a.timer=setTimeout(()=>{if(a.timer=null,this.valid(a)&&!a.syncing){for(let b=0;b<4&&a.events.length&&this.valid(a);b+=1){let b=a.events.shift();a.bytes-=this.eventBytes(b),this.connection.sendPush(k.event,{terminalId:a.id,event:b})}this.scheduleDrain(a)}},8))}eventBytes(a){return"output"===a.type?Buffer.byteLength(a.data):"snapshot"===a.type?Buffer.byteLength(a.snapshot.data):32}releaseWatch(a){let b=this.watches.get(a);b&&(this.watches.delete(a),b.dispose?.(),b.timer&&clearTimeout(b.timer),b.events=[],b.bytes=0)}releaseAllWatches(){for(let a of this.watches.keys())this.releaseWatch(a)}sendError(a,b){if(this.active()){if(b instanceof l.l$)return void this.connection.sendError(a.head.path,a.head.requestId,b.code,b.message);console.error("[Pi Desk][TerminalSocket] 终端请求失败",{path:a.head.path,connectionId:this.connection.connectionId,error:b}),this.connection.sendError(a.head.path,a.head.requestId,500,"终端操作失败")}}}},63578:(a,b,c)=>{"use strict";c.d(b,{V:()=>g});var d=c(77598),e=c(2002),f=c(37968);class g{constructor(a,b){this.clientId=a,this.socket=b,this.connectionId=(0,d.randomUUID)(),this.inFlightRequestIds=new Set,this.requestHandler=null,this.closeListener=null,this.heartbeat=null,this.alive=!0,this.current=!0,this.started=!1,this.disposed=!1,this.handleHeartbeat=()=>{this.alive?(this.alive=!1,this.socket.ping()):this.terminate()},this.handlePong=()=>{this.alive=!0},this.handleMessage=(a,b)=>{let c;if(!this.current)return;if(b)return void this.socket.close(1003,"仅支持文本 JSON 消息");try{c=JSON.parse(Array.isArray(a)?Buffer.concat(a).toString("utf8"):a instanceof ArrayBuffer?Buffer.from(a).toString("utf8"):a.toString("utf8"))}catch{this.socket.close(1007,"JSON 格式无效");return}let d=e.tU.safeParse(c);if(!d.success)return void this.socket.close(1008,"消息信封或方向无效");let f=d.data.head.requestId;if(this.inFlightRequestIds.has(f))return void this.sendError(d.data.head.path,f,409,"requestId 正在处理中",{key:"common:duplicateRequest"});if(this.inFlightRequestIds.size>=32)return void this.sendError(d.data.head.path,f,429,"当前连接并发请求过多",{key:"common:tooManyRequests"});let g=this.requestHandler;g?(this.inFlightRequestIds.add(f),g(d.data).catch(a=>{console.error("[Pi Desk][AppSocketConnection] 请求处理失败",{clientId:this.clientId,connectionId:this.connectionId,path:d.data.head.path,errorName:a instanceof Error?a.name:"UnknownError"}),this.sendError(d.data.head.path,f,500,"服务端请求处理失败",{key:"common:serverRequestFailed"})}).finally(()=>{this.inFlightRequestIds.delete(f)})):this.sendError(d.data.head.path,f,503,"应用 WebSocket 尚未就绪",{key:"common:socketUnavailable"})},this.handleClose=(a,b)=>{let c={code:a,reason:b.toString("utf8")},d=this.closeListener;this.dispose();try{d?.(c)}catch(a){console.error("[Pi Desk][AppSocketConnection] 关闭监听器执行失败",{clientId:this.clientId,connectionId:this.connectionId,errorName:a instanceof Error?a.name:"UnknownError"})}finally{this.resolveClosed(c)}},this.handleError=a=>{console.error("[Pi Desk][AppSocketConnection] 连接错误",{clientId:this.clientId,connectionId:this.connectionId,errorName:a.name,message:a.message})},this.closedPromise=new Promise(a=>{this.resolveClosed=a})}start(a,b){if(this.started)throw Error("AppSocket connection has already started");this.started=!0,this.requestHandler=a,this.closeListener=b,this.heartbeat=setInterval(this.handleHeartbeat,3e4),this.socket.on("pong",this.handlePong),this.socket.on("message",this.handleMessage),this.socket.on("close",this.handleClose),this.socket.on("error",this.handleError)}isCurrent(){return this.current&&!this.disposed}sendSuccess(a,b,c){this.sendJson(e.hE.parse({head:{op:"resp",path:a.path,requestId:b},body:{code:0,msg:"",data:a.outputSchema.parse(c)}}))}sendError(a,b,c,d,f){this.sendJson(e.hE.parse({head:{op:"resp",path:a,requestId:b},body:{code:c,msg:d,data:null,...f?{i18n:f}:{}}}))}sendPush(a,b){this.sendJson(e.Od.parse({head:{op:"push",path:a.path},body:a.bodySchema.parse(b)}))}supersede(){!this.disposed&&this.current&&(this.current=!1,this.socket.close(e.P9,"连接已被替换"))}close(a=1e3,b="连接已关闭"){if(!this.disposed){if(this.current=!1,this.socket.readyState===f.kb.OPEN)return void this.socket.close(a,b);this.socket.readyState!==f.kb.CLOSED&&this.socket.terminate()}}terminate(){this.disposed||(this.current=!1,this.socket.terminate())}waitForClose(){return this.closedPromise}sendJson(a){if(this.isCurrent()&&this.socket.readyState===f.kb.OPEN){if(this.socket.bufferedAmount>0x2000000)return void this.terminate();try{this.socket.send(JSON.stringify(a))}catch{this.terminate()}}}dispose(){this.disposed||(this.disposed=!0,this.current=!1,this.heartbeat&&clearInterval(this.heartbeat),this.heartbeat=null,this.inFlightRequestIds.clear(),this.requestHandler=null,this.closeListener=null,this.socket.off("pong",this.handlePong),this.socket.off("message",this.handleMessage),this.socket.off("close",this.handleClose),this.socket.off("error",this.handleError))}}},68623:(a,b,c)=>{"use strict";c.d(b,{H:()=>j});var d=c(59473),e=c(96089),f=c(67062),g=c(2002);let h=d.Ik({source:e.R}).strict(),i=d.Ik({}).strict(),j=Object.freeze({subscribe:(0,g.Vc)({path:"pi/ui/subscribe",inputSchema:h,outputSchema:f.P}),unsubscribe:(0,g.Vc)({path:"pi/ui/unsubscribe",inputSchema:h,outputSchema:i}),respond:(0,g.Vc)({path:"pi/ui/respond",inputSchema:h.extend({response:f.YB}).strict(),outputSchema:i}),event:(0,g._G)({path:"pi/ui/event",bodySchema:h.extend({event:f.Z$}).strict()})})},69779:(a,b,c)=>{"use strict";c.d(b,{Ld:()=>A,NN:()=>y,VQ:()=>z,gm:()=>w,mQ:()=>j,n0:()=>x,ui:()=>u});var d=c(59473),e=c(96089),f=c(89409),g=c(610),h=c(83905),i=c(2364);let j=d.Yj().trim().min(1).max(200),k=d.Yj().trim().min(1).max(100).nullable(),l=d.Yj().trim().min(1).max(100).nullable(),m=d.Yj().trim().min(1).max(200),n=d.Ik({label:d.Yj().trim().min(1).max(64),value:d.Yj().trim().min(1).max(500)}).strict(),o=d.Yj().trim().min(1).max(300).nullable(),p=d.k5(["running","completed","failed","stopped","interrupted"]),q=d.Ik({taskId:j,taskKind:k,taskType:l,title:m,info:d.YO(n).max(12),status:p,activity:o,startedAt:i.k,endedAt:i.k.nullable()}).strict().superRefine((a,b)=>{"running"===a.status&&null!==a.endedAt&&b.addIssue({code:"custom",message:"running task requires endedAt=null",path:["endedAt"]}),"running"!==a.status&&null===a.endedAt&&b.addIssue({code:"custom",message:"terminal task requires endedAt",path:["endedAt"]})});d.Ik({tasks:d.YO(q)}).strict().superRefine((a,b)=>{let c=new Set;for(let[d,e]of a.tasks.entries())c.has(e.taskId)&&b.addIssue({code:"custom",message:"taskId values must be unique",path:["tasks",d,"taskId"]}),c.add(e.taskId)});let r=d.Ik({kind:d.eu("text"),text:d.Yj(),truncated:d.zM()}).strict(),s=f.RX.extend({kind:d.eu("conversation"),truncated:d.zM()}).strict(),t=d.KC([d.ch(),r,s]),u=d.Ik({taskId:j,canInterrupt:d.zM(),body:t}).strict(),v=g.mv,w=d.KC([d.Ik({type:d.eu("snapshot"),snapshot:u}).strict(),d.Ik({type:d.eu("text_append"),text:d.Yj().min(1)}).strict(),d.Ik({type:d.eu("conversation_event"),event:v}).strict(),d.Ik({type:d.eu("unavailable")}).strict()]),x=d.Ik({source:e.R,taskId:j,entryId:h.Rv}).strict(),y=f.XM,z=x.extend({imageIndex:d.ai().int().nonnegative()}).strict(),A=f.y0},73952:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{p:()=>j});var e=c(50857),f=c(36559),g=c(47574),h=a([f,g]);function i(a,b){return a.workId===b.workId&&a.sessionId===b.sessionId&&a.branchId===b.branchId}[f,g]=h.then?(await h)():h;class j{constructor(a,b,c){this.connection=a,this.manage=b,this.taskCenter=c,this.currentWatch=null,this.pendingWatch=null,this.operationTail=Promise.resolve(),this.disposed=!1,this.unsubscribeSources=this.manage.subscribeMessageEvents(a=>this.handleSourceEvent(a)),this.routes=Object.freeze([{path:e.rn.detailWatch.path,access:"ready",handle:a=>this.enqueue(()=>this.watch(a))},{path:e.rn.interrupt.path,access:"ready",handle:a=>this.interrupt(a)}])}dispose(){this.disposed||(this.disposed=!0,this.unsubscribeSources(),this.pendingWatch=null,this.releaseCurrentWatch())}enqueue(a){let b=this.operationTail.then(a,a);return this.operationTail=b.then(()=>void 0,()=>void 0),b}async watch(a){let b=e.rn.detailWatch,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"任务详情参数无效");if(this.releaseCurrentWatch(),null===c.data.taskId)return void this.connection.sendSuccess(b,a.head.requestId,{snapshot:null});let d={source:c.data.source,invalidated:!1};this.pendingWatch=d;try{let e=await this.createStableWatch(c.data.source,c.data.taskId);if(this.disposed||!this.connection.isCurrent())return void e.observation.release();if(d.invalidated)throw e.observation.release(),new g.dM(d.source);this.currentWatch=e,this.connection.sendSuccess(b,a.head.requestId,{snapshot:e.observation.snapshot}),e.status="ready",this.flushQueuedEvents(e),console.info("[Pi Desk][TaskCenterSocket] 任务详情观察完成",{clientId:this.connection.clientId,workId:e.source.workId,taskId:e.taskId})}catch(c){this.sendTaskError(b.path,a.head.requestId,c,"任务详情初始化失败")}finally{this.pendingWatch===d&&(this.pendingWatch=null)}}async createStableWatch(a,b){for(;;){let c=[],d={state:null},e=await this.taskCenter.watchDetail(a,b,a=>{let b=d.state;if(!b||this.currentWatch!==b||this.disposed){c.length<128&&c.push(a);return}this.handleDetailEvent(b,a)}),f={source:a,taskId:b,observation:e,status:"syncing",queuedEvents:c,overflowed:c.length>=128};if(d.state=f,!f.overflowed)return f;e.release()}}handleDetailEvent(a,b){if(this.currentWatch===a&&!this.disposed&&this.connection.isCurrent()){if("syncing"===a.status){if(a.queuedEvents.length>=128){a.queuedEvents.length=0,a.overflowed=!0;return}a.queuedEvents.push(b);return}this.connection.sendPush(e.rn.detailEvent,{source:a.source,taskId:a.taskId,event:b}),"unavailable"===b.type&&this.releaseCurrentWatch()}}flushQueuedEvents(a){if(this.currentWatch===a){if(a.overflowed)return void this.connection.close(1011,"任务详情同步队列溢出");for(let b of a.queuedEvents.splice(0))if(this.connection.sendPush(e.rn.detailEvent,{source:a.source,taskId:a.taskId,event:b}),"unavailable"===b.type)return void this.releaseCurrentWatch()}}async interrupt(a){let b=e.rn.interrupt,c=b.inputSchema.safeParse(a.body);if(!c.success)return void this.connection.sendError(b.path,a.head.requestId,400,"任务打断参数无效");try{await this.taskCenter.interrupt(c.data.source,c.data.taskId),this.connection.sendSuccess(b,a.head.requestId,{})}catch(c){this.sendTaskError(b.path,a.head.requestId,c,"打断任务失败")}}sendTaskError(a,b,c,d){c instanceof g.dM?this.connection.sendError(a,b,409,"工作会话来源已变化"):c instanceof f.x4?this.connection.sendError(a,b,404,"任务不存在"):c instanceof f.o3?this.connection.sendError(a,b,409,"任务当前不可打断"):c instanceof f.Y3?this.connection.sendError(a,b,409,"任务不支持该详情"):c instanceof f.qc?this.connection.sendError(a,b,404,"任务消息不存在"):(console.warn("[Pi Desk][TaskCenterSocket] 任务操作失败",{path:a,errorName:c instanceof Error?c.name:"UnknownError",message:c instanceof Error?c.message:d}),this.connection.sendError(a,b,500,d))}handleSourceEvent(a){if("source_invalidated"!==a.type)return;this.pendingWatch&&i(this.pendingWatch.source,a.source)&&(this.pendingWatch.invalidated=!0);let b=this.currentWatch;b&&i(b.source,a.source)&&(this.connection.sendPush(e.rn.detailEvent,{source:b.source,taskId:b.taskId,event:{type:"unavailable"}}),this.releaseCurrentWatch())}releaseCurrentWatch(){let a=this.currentWatch;this.currentWatch=null,a?.observation.release()}}d()}catch(a){d(a)}})},77712:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{K:()=>j});var e=c(36559),f=c(47574),g=c(23054),h=c(72498),i=a([e,f,g,h]);function j(){if(!globalThis.__piDeskTaskCenterRuntime){let a=(0,g.JJ)();globalThis.__piDeskTaskCenterRuntime=new e.rt(async b=>{let c=await a.getWorkSession(b.workId);if(!c||c.sessionId!==b.sessionId||c.branchId!==b.branchId)throw new f.dM(b);return(0,h.ls)(b.sessionId)})}return globalThis.__piDeskTaskCenterRuntime}[e,f,g,h]=i.then?(await i)():i,d()}catch(a){d(a)}})},83977:(a,b,c)=>{"use strict";c.d(b,{l$:()=>n,yd:()=>w});var d=c(77598),e=c(76760),f=c(9050),g=c(31421),h=c(51455),i=c(73024),j=c(48161);let k=(0,c(57975).promisify)(g.execFile),{createRequire:l}=process.getBuiltinModule("module"),m=l((0,e.join)(process.cwd(),"package.json"));class n extends Error{constructor(a,b){super(b),this.code=a,this.name="L4TerminalError"}}async function o(a){try{return await (0,h.access)(a,"win32"===process.platform?i.constants.F_OK:i.constants.X_OK),(await (0,h.stat)(a)).isFile()}catch{return!1}}async function p(a){let b=a??(0,j.homedir)();if(!(0,e.isAbsolute)(b))throw new n(400,"终端目录必须是绝对路径");try{if(!(await (0,h.stat)(b)).isDirectory())throw Error("not a directory")}catch{throw new n(400,"终端目录不存在或不是目录")}let c="/bin/sh",d=[];if("win32"===process.platform){let a=(process.env.PATH??"").split(e.delimiter).map(a=>(0,e.join)(a.replace(/^"|"$/g,""),"pwsh.exe"));for(let b of(a.push((0,e.join)(process.env.ProgramFiles??"C:/Program Files","PowerShell/7/pwsh.exe")),c=(0,e.join)(process.env.SystemRoot??"C:/Windows","System32/WindowsPowerShell/v1.0/powershell.exe"),a))if((0,e.isAbsolute)(b)&&await o(b)){c=b;break}d.push("-NoLogo","-NoProfile")}else process.env.SHELL&&(0,e.isAbsolute)(process.env.SHELL)&&await o(process.env.SHELL)&&(c=process.env.SHELL);if(!await o(c))throw new n(503,"没有可用的终端 Shell");return{cwd:b,file:c,args:d,shell:(0,e.basename)(c)}}class q{constructor(a,b,c){this.stopped=null,this.exited=!1,this.earlyInputBytes=0;try{const d=m("node-pty/package.json").version;if("1.1.0"!==d)throw Error(`不支持的 node-pty 版本:${d}`);if("win32"===process.platform&&18309>Number((0,j.release)().split(".")[2]))throw Error("系统 Windows 版本不支持稳定 ConPTY");const e=m("node-pty");if(this.pty=e.spawn(a.file,a.args,{cwd:a.cwd,cols:b,rows:c,name:"xterm-256color",env:{...process.env,TERM:"xterm-256color"},useConpty:!0,useConptyDll:!1}),"win32"===process.platform){const a=this.pty._agent;if(!a._useConpty||a._useConptyDll)throw Error("终端需要系统 ConPTY");this.workerExit=new Promise((b,c)=>{a._conoutSocketWorker._worker.once("exit",()=>b()),a._conoutSocketWorker._worker.once("error",c)}),this.workerExit.catch(()=>void 0)}else this.workerExit=null;this.processExit=new Promise(a=>{let b=this.pty.onExit(()=>{this.exited=!0,b.dispose(),a()})}),this.released=this.processExit.then(()=>this.releaseNative()),this.released.catch(a=>console.error("[Pi Desk][Terminal] 原生资源释放失败",{pid:this.pty.pid,error:a}))}catch(a){throw console.error("[Pi Desk][Terminal] PTY 加载或启动失败",{message:a instanceof Error?a.message:String(a)}),new n(503,"终端原生依赖不可用或 Shell 启动失败")}}write(a){if(this.exited)throw new n(409,"终端已经退出");let b="win32"===process.platform?this.pty:null;if(b?._isReady&&(this.earlyInputBytes=0),(b?b._agent._inSocket.writableLength+this.earlyInputBytes:this.pty._writeStream._writeQueue.reduce((a,b)=>a+b.buffer.length-b.offset,0))+Buffer.byteLength(a)>65536)throw new n(429,"终端输入缓冲已满");this.checkDeferredCapacity(),b&&!b._isReady&&(this.earlyInputBytes+=Buffer.byteLength(a)),this.pty.write(function(a){let b=[],c=0;for(let d of a.matchAll(/\x1b\[M[\x00-\xff]{3}/g)){let e=d.index;e>c&&b.push(Buffer.from(a.slice(c,e),"utf8")),b.push(Buffer.from(d[0],"latin1")),c=e+d[0].length}return 0===c?Buffer.from(a,"utf8"):(c<a.length&&b.push(Buffer.from(a.slice(c),"utf8")),Buffer.concat(b))}(a))}resize(a,b){this.checkDeferredCapacity(),this.pty.resize(a,b)}checkDeferredCapacity(){if("win32"===process.platform&&this.pty._deferreds.length>=256)throw new n(429,"终端初始化操作队列已满")}stop(){return this.stopped||(this.stopped=this.stopTree()),this.stopped}async stopTree(){let a,b=performance.now();if(!this.exited)if("win32"===process.platform)try{await k("taskkill.exe",["/PID",String(this.pty.pid),"/T","/F"],{windowsHide:!0,timeout:4e3,maxBuffer:65536})}catch(a){if(this.logStopFailure("终止进程树",b,a),!this.exited)throw a}else{let{stdout:a}=await k("ps",["-eo","pid=,ppid="],{timeout:2e3,maxBuffer:2097152}),b=a.trim().split("\n").map(a=>a.trim().split(/\s+/).map(Number)),c=new Set([this.pty.pid]),d=[],e=!0;for(;e;)for(let[a,f]of(e=!1,b))c.has(f)&&!c.has(a)&&(c.add(a),d.push(a),e=!0);for(let a of d.reverse())this.killUnix(a);this.killUnix(-this.pty.pid),this.pty.kill("SIGKILL")}let c=performance.now();try{await Promise.race([this.processExit,new Promise((b,c)=>{a=setTimeout(()=>c(Error("Shell 退出等待超时")),4e3)})])}catch(a){throw this.logStopFailure("等待 Shell 退出",b,a),a}finally{a&&clearTimeout(a)}let d=performance.now();await this.released,console.info("[Pi Desk][Terminal] 原生终端停止完成",{pid:this.pty.pid,terminateMs:Math.round(c-b),exitMs:Math.round(d-c),releaseMs:Math.round(performance.now()-d),totalMs:Math.round(performance.now()-b)})}logStopFailure(a,b,c){let d=null;try{process.kill(this.pty.pid,0),d=!0}catch(a){"ESRCH"===a.code&&(d=!1)}console.error("[Pi Desk][Terminal] 终端停止阶段失败",{pid:this.pty.pid,stage:a,elapsedMs:Math.round(performance.now()-b),processAlive:d,ptyExited:this.exited,nativeExitCode:"win32"===process.platform?this.pty._agent.exitCode??null:null,error:c})}killUnix(a){try{process.kill(a,"SIGKILL")}catch(a){if("ESRCH"!==a.code)throw a}}async releaseNative(){if("win32"!==process.platform)return;let a=this.pty._agent;a._inSocket.destroy(),a._outSocket.destroy(),a._conoutSocketWorker.dispose(),await this.workerExit}}class r{frame(a){let b=this.pending+a,c=0;for(let a=this.pending.length;a<b.length;a+=1){let d=b.charCodeAt(a);24===d||26===d?this.state="ground":"ground"===this.state?27===d?this.state="escape":155===d?this.state="csi":[144,152,157,158,159].includes(d)&&(this.osc=157===d,this.state="string"):"escape"===this.state?91===d?this.state="csi":[80,88,93,94,95].includes(d)?(this.osc=93===d,this.state="string"):d>=48&&d<=126&&(this.state="ground"):"csi"===this.state?27===d?this.state="escape":d>=64&&d<=126&&(this.state="ground"):"string"===this.state?156===d||this.osc&&7===d?this.state="ground":27===d&&(this.state="string-escape"):"string-escape"===this.state&&(92===d?this.state="ground":27!==d&&(this.state="string")),"ground"===this.state&&(c=a+1)}if(this.pending=b.slice(c),Buffer.byteLength(this.pending)>1048576)throw new n(429,"终端控制序列超出缓冲上限");return b.slice(0,c)}dispose(){this.pending=""}constructor(){this.pending="",this.state="ground",this.osc=!1}}let{createRequire:s}=process.getBuiltinModule("module"),t=s((0,e.join)(process.cwd(),"package.json"));class u{constructor(a,b,c,d){this.terminalId=a,this.onExit=c,this.framing=new r,this.listeners=new Set,this.tail=Promise.resolve(),this.queueBytes=0,this.operations=0,this.paused=!1,this.ended=!1,this.failed=!1,this.disposed=!1,this.disposing=null,this.ownerId=null,this.pendingActivations=new Set;try{const a=t("@xterm/headless"),b=t("@xterm/addon-serialize");this.screen=new a.Terminal({cols:100,rows:28,scrollback:f.XZ,allowProposedApi:!0,windowOptions:{pushTitle:!0,popTitle:!0}}),this.serializer=new b.SerializeAddon,this.screen.loadAddon(this.serializer)}catch(b){throw console.error("[Pi Desk][Terminal] 权威屏幕加载失败",{terminalId:a,error:b}),new n(503,"终端屏幕依赖不可用")}try{this.child=new q(b,this.screen.cols,this.screen.rows),console.info("[Pi Desk][Terminal] PTY 已启动",{terminalId:a,pid:this.child.pty.pid})}catch(a){throw this.screen.dispose(),a}this.subscriptions=[this.screen.onTitleChange(a=>{this.disposed||d(a)}),this.screen.onData(a=>{if(!this.ended&&!this.disposed&&!this.failed)try{this.child.write(a)}catch(a){this.fail(a)}}),this.child.pty.onData(a=>this.acceptOutput(a)),this.child.pty.onExit(({exitCode:b})=>{this.ended=!0,this.ownerId=null,this.enqueue(async()=>{await this.child.released,this.disposed||(this.emit({type:"exit",exitCode:b}),this.onExit(b),console.info("[Pi Desk][Terminal] Shell 已退出",{terminalId:a,exitCode:b}))},!1).catch(a=>this.fail(a))})]}watch(a){return this.enqueue(async()=>{if(this.ensureAvailable(),this.listeners.size>=64)throw new n(429,"终端观察连接过多");let b=this.snapshot();return this.listeners.add(a),{snapshot:b,dispose:()=>{this.listeners.delete(a)}}})}input(a){return!a||Buffer.byteLength(a)>f.Oi?Promise.reject(new n(400,"终端输入必须为 1~16KiB UTF-8")):this.enqueue(async()=>{this.ensureRunning(),this.child.write(a)})}activate(a,b,c){let d={ownerId:a,released:!1};return this.pendingActivations.add(d),this.enqueue(async()=>{this.ensureRunning(),d.released||(this.validateDimensions(b,c),this.resizeScreen(b,c),this.ownerId=a)}).finally(()=>{this.pendingActivations.delete(d)})}resize(a,b,c){return this.enqueue(async()=>{this.ensureAvailable(),this.ownerId!==a||this.ended||(this.validateDimensions(b,c),this.resizeScreen(b,c))})}releaseOwner(a){for(let b of(this.ownerId===a&&(this.ownerId=null),this.pendingActivations))b.ownerId===a&&(b.released=!0)}dispose(){return this.disposing||(this.disposing=this.disposeRuntime()),this.disposing}async disposeRuntime(){this.disposed=!0,this.ownerId=null,this.listeners.clear(),this.paused&&this.child.pty.resume();try{await this.child.stop(),await this.tail}finally{for(let a of this.subscriptions)a.dispose();this.framing.dispose(),this.screen.dispose()}}acceptOutput(a){let b;if(this.disposed||this.failed)return;try{if(Buffer.byteLength(a)>1048576)throw new n(429,"PTY 单批输出超限");b=this.framing.frame(a)}catch(a){this.fail(a);return}if(!b)return;let c=Buffer.byteLength(b);this.queueBytes+c>1048576||this.operations>=256?this.fail(new n(429,"PTY 解析队列溢出")):(this.queueBytes+=c,!this.paused&&this.queueBytes>=262144&&(this.paused=!0,this.child.pty.pause()),this.enqueue(async()=>{try{if(this.disposed)return;for(let a of function(a,b=16384){let c=[],d=0,e=0;for(let f=0;f<a.length;){let g=a.codePointAt(f),h=g<=127?1:g<=2047?2:g<=65535?3:4;e+h>b&&(c.push(a.slice(d,f)),d=f,e=0),e+=h,f+=g>65535?2:1}return d<a.length&&c.push(a.slice(d)),c}(b))await new Promise(b=>this.screen.write(a,b)),this.emit({type:"output",data:a})}finally{this.queueBytes-=c,this.paused&&this.queueBytes<=65536&&!this.disposed&&(this.paused=!1,this.child.pty.resume())}},!1).catch(a=>this.fail(a)))}enqueue(a,b=!0){if(b&&this.operations>=256)return Promise.reject(new n(429,"终端操作队列已满"));this.operations+=1;let c=this.tail.then(a);return this.tail=c.then(()=>void 0,()=>void 0).finally(()=>{this.operations-=1}),c}snapshot(){let a=f.XZ;for(;;){let b=this.serializer.serialize({scrollback:a});if(Buffer.byteLength(b)<=f.I1)return{cols:this.screen.cols,rows:this.screen.rows,data:b};if(0===a)throw new n(429,"终端当前画面超过快照上限");a=Math.floor(a/2)}}resizeScreen(a,b){(this.screen.cols!==a||this.screen.rows!==b)&&(this.child.resize(a,b),this.screen.resize(a,b),this.emit({type:"resize",cols:a,rows:b}))}validateDimensions(a,b){if(!Number.isInteger(a)||!Number.isInteger(b)||a<2||a>f.xb||b<2||b>f.tu)throw new n(400,"终端尺寸必须为 2~400 列、2~200 行")}ensureAvailable(){if(this.disposed)throw new n(503,"终端正在关闭")}ensureRunning(){if(this.ensureAvailable(),this.ended||this.failed)throw new n(409,"终端已经退出")}emit(a){for(let b of this.listeners)try{b(a)}catch(a){this.listeners.delete(b),console.warn("[Pi Desk][Terminal] 释放失败的观察者",{terminalId:this.terminalId,error:a})}}fail(a){this.failed||this.disposed||(this.failed=!0,console.error("[Pi Desk][Terminal] 终端处理失败,结束目标进程",{terminalId:this.terminalId,error:a}),this.paused&&(this.paused=!1,this.child.pty.resume()),this.child.stop().catch(a=>console.error("[Pi Desk][Terminal] 结束失败",{terminalId:this.terminalId,error:a})))}}class v{create(a){let b=performance.now();return this.enqueue(async()=>{let c=performance.now();if(this.ensureOpen(),this.list().filter(a=>"running"===a.status).length+this.releases.size>=16)throw new n(429,"运行中或尚未完成清理的终端已达 16 个上限");let e=await p(a),f=performance.now();this.ensureOpen();let g=(0,d.randomUUID)(),h=new u(g,e,a=>this.handleExit(g,a),a=>this.handleTitleChange(g,a)),i={terminalId:g,cwd:e.cwd,shell:e.shell,title:"",status:"running",exitCode:null};return this.records.set(g,{summary:i,runtime:h,titleTimer:null}),this.publish(),console.info("[Pi Desk][TerminalManage] 已创建终端",{terminalId:g,cwd:e.cwd,shell:e.shell,queueMs:Math.round(c-b),resolveMs:Math.round(f-c),startMs:Math.round(performance.now()-f),totalMs:Math.round(performance.now()-b)}),{...i}})}list(){return Array.from(this.records.values(),({summary:a})=>({...a}))}subscribeList(a){return this.ensureOpen(),this.listeners.add(a),()=>{this.listeners.delete(a)}}watch(a,b){return this.get(a).runtime.watch(b)}input(a,b){return this.get(a).runtime.input(b)}activate(a,b,c,d){return this.get(a).runtime.activate(b,c,d)}resize(a,b,c,d){return this.get(a).runtime.resize(b,c,d)}releaseOwner(a){for(let b of this.records.values())b.runtime.releaseOwner(a)}remove(a){let b=performance.now();return this.enqueue(async()=>{let c=this.get(a);this.clearTitleTimer(c),this.records.delete(a);let d=this.exitedIds.indexOf(a);-1!==d&&this.exitedIds.splice(d,1),this.release(c),this.publish(),console.info("[Pi Desk][TerminalManage] 已接纳终端关闭",{terminalId:a,elapsedMs:Math.round(performance.now()-b)})})}release(a){let b=a.summary.terminalId,c=performance.now(),d=new Promise(a=>setImmediate(a)).then(()=>a.runtime.dispose());this.releases.set(b,d),d.then(()=>{this.releases.delete(b),console.info("[Pi Desk][TerminalManage] 终端资源已释放",{terminalId:b,elapsedMs:Math.round(performance.now()-c)})},a=>{console.error("[Pi Desk][TerminalManage] 终端资源清理失败",{terminalId:b,elapsedMs:Math.round(performance.now()-c),error:a})})}dispose(){if(!this.disposing){for(let a of(this.closing=!0,this.listeners.clear(),this.records.values()))this.clearTitleTimer(a);this.disposing=this.disposeAll()}return this.disposing}async disposeAll(){await this.tail;let a=await Promise.allSettled([...this.releases.values(),...Array.from(this.records.values(),a=>a.runtime.dispose())]);this.records.clear(),this.releases.clear(),this.exitedIds.length=0;let b=a.filter(a=>"rejected"===a.status);if(b.length)throw console.error("[Pi Desk][TerminalManage] 终端集合释放失败",{errors:b.map(a=>a.reason)}),AggregateError(b.map(a=>a.reason),"终端资源未完全释放")}handleTitleChange(a,b){let c=this.records.get(a);if(!c||this.closing)return;let d=b.replace(/\p{Cc}/gu,"").slice(0,512);c.summary.title!==d&&(c.summary.title=d,c.titleTimer||(c.titleTimer=setTimeout(()=>this.publish(),50)))}clearTitleTimer(a){a.titleTimer&&clearTimeout(a.titleTimer),a.titleTimer=null}handleExit(a,b){let c=this.records.get(a);if(c&&!this.closing&&"exited"!==c.summary.status){for(c.summary={...c.summary,status:"exited",exitCode:b},this.exitedIds.push(a);this.exitedIds.length>16;){let a=this.exitedIds.shift(),b=this.records.get(a);this.records.delete(a),b&&(this.clearTitleTimer(b),this.release(b))}this.publish()}}publish(){if(this.closing)return;for(let a of this.records.values())this.clearTitleTimer(a);let a=this.list();for(let b of this.listeners)try{b(a)}catch(a){this.listeners.delete(b),console.warn("[Pi Desk][TerminalManage] 列表观察失败",{error:a})}}get(a){this.ensureOpen();let b=this.records.get(a);if(!b)throw new n(404,"终端不存在");return b}ensureOpen(){if(this.closing)throw new n(503,"终端服务正在关闭")}enqueue(a){if(this.closing)return Promise.reject(new n(503,"终端服务正在关闭"));if(this.pending>=64)return Promise.reject(new n(429,"终端集合操作队列已满"));this.pending+=1;let b=this.tail.then(a);return this.tail=b.then(()=>void 0,()=>void 0).finally(()=>{this.pending-=1}),b}constructor(){this.records=new Map,this.exitedIds=[],this.releases=new Map,this.listeners=new Set,this.tail=Promise.resolve(),this.pending=0,this.closing=!1,this.disposing=null}}function w(){return globalThis.__piDeskTerminalManage||(globalThis.__piDeskTerminalManage=new v),globalThis.__piDeskTerminalManage}},87016:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{ho:()=>l,uF:()=>i.fA,wT:()=>k});var e=c(20369),f=c(61518),g=c(86166),h=c(494),i=c(30010),j=a([f,g,h,i]);function k(){let a=(0,i.hZ)();if(globalThis.__piDeskModeNamesBinding?.runtime!==a){globalThis.__piDeskModeNamesBinding?.dispose();let b=(0,f.O)(),c=()=>{a.applyInternal({key:"capabilityModes",update:(0,e.HE)(b.read())})};c(),globalThis.__piDeskModeNamesBinding={runtime:a,dispose:b.subscribe(c)}}return a}function l(){globalThis.__piDeskModeNamesBinding?.dispose(),globalThis.__piDeskModeNamesBinding=void 0,(0,g.HM)(),(0,h.UM)(),(0,i.s6)()}[f,g,h,i]=j.then?(await j)():j,d()}catch(a){d(a)}})},87568:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{Y:()=>r});var e=c(82459),f=c(42616),g=c(51071),h=c(16438),i=c(87016),j=c(23054),k=c(13578),l=c(96459),m=c(72498),n=c(77712),o=c(83977),p=c(97416),q=a([e,f,h,i,j,l,m,n,p]);[e,f,h,i,j,l,m,n,p]=q.then?(await q)():q;class s{constructor(){this.sessionsByClientId=new Map,this.manage=(0,j.JJ)(),this.appRuntime=(0,i.wT)(),this.taskCenter=(0,n.K)(),this.terminals=(0,o.yd)(),this.manage.subscribePluginPushEvents(a=>this.pushPlugin(a))}accept(a,b,c){let d=this.sessionsByClientId.get(b),e=new p.k(a,b,(0,g.nV)(c,f.yJ),this.manage,this.appRuntime,this.taskCenter,this.terminals,(a,c)=>{this.sessionsByClientId.get(b)===a&&this.sessionsByClientId.delete(b),console.info("[Pi Desk][AppSocketRuntime] 应用连接已断开",{clientId:b,connectionId:a.connection.connectionId,code:c.code})});this.sessionsByClientId.set(b,e);try{e.start()}catch(a){throw d?this.sessionsByClientId.set(b,d):this.sessionsByClientId.delete(b),e.terminate(),a}d?.supersede()}async closeByAuthToken(a,b,c){let d=[];for(let[e,f]of this.sessionsByClientId)f.authToken===a&&(this.sessionsByClientId.delete(e),f.close(b,c),d.push(f));await Promise.all(d.map(a=>a.waitForClose()))}async closeAll(a,b){let c=[...this.sessionsByClientId.values()];for(let d of(this.sessionsByClientId.clear(),c))d.close(a,b);await Promise.all(c.map(a=>a.waitForClose()))}terminateAll(){let a=[...this.sessionsByClientId.values()];for(let b of(this.sessionsByClientId.clear(),a))b.terminate()}connectionCount(){return this.sessionsByClientId.size}pushPlugin(a){for(let b of this.sessionsByClientId.values())b.pushPlugin(a)}async disposePlugins(){(0,e.Ee)(),(0,h.qE)(),await (0,l.H0)(),(0,k.J)(),(0,i.ho)()}async disposeTerminals(){await this.terminals.dispose()}async disposeWorkSessions(){await (0,m.wz)()}}function r(){return globalThis.__piDeskAppSocketRuntime||(globalThis.__piDeskAppSocketRuntime=new s),globalThis.__piDeskAppSocketRuntime}d()}catch(a){d(a)}})},93750:()=>{},97416:(a,b,c)=>{"use strict";c.a(a,async(a,d)=>{try{c.d(b,{k:()=>q});var e=c(54997),f=c(63578),g=c(27235),h=c(36925),i=c(36262),j=c(48317),k=c(15801),l=c(25588),m=c(73952),n=c(63461),o=c(41935),p=a([g,h,j,k,l,m,o]);[g,h,j,k,l,m,o]=p.then?(await p)():p;class q{constructor(a,b,c,d,e,p,q,r){this.authToken=c,this.onClose=r,this.routes=new Map,this.disposed=!1,this.connection=new f.V(b,a),this.workSessions=new o.G(this.connection,d,e),this.appRuntime=new g.U(this.connection,e),this.chat=new h.T(this.connection,d),this.plugins=new l.c(this.connection,d,()=>this.workSessions.isReady()),this.nativeUi=new j.k(this.connection,d),this.modelAuth=new k.Y(this.connection),this.pluginLogs=new i.m(this.connection),this.taskCenter=new m.p(this.connection,d,p),this.terminals=new n.D(this.connection,q,()=>this.workSessions.isReady()),this.registerRoutes(this.workSessions.routes),this.registerRoutes(this.appRuntime.routes),this.registerRoutes(this.chat.routes),this.registerRoutes(this.plugins.routes),this.registerRoutes(this.nativeUi.routes),this.registerRoutes(this.modelAuth.routes),this.registerRoutes(this.pluginLogs.routes),this.registerRoutes(this.taskCenter.routes),this.registerRoutes(this.terminals.routes)}start(){this.connection.start(a=>this.handleRequest(a),a=>{this.dispose(),this.onClose(this,a)}),console.info("[Pi Desk][AppSocketSession] 应用连接已建立",{clientId:this.connection.clientId,connectionId:this.connection.connectionId})}supersede(){this.disposeControllers(),this.connection.supersede()}close(a,b){this.disposeControllers(),this.connection.close(a,b)}terminate(){this.disposeControllers(),this.connection.terminate()}waitForClose(){return this.connection.waitForClose()}pushPlugin(a){!this.disposed&&this.workSessions.isReady()&&this.connection.sendPush(e.cx,a)}registerRoutes(a){for(let b of a){if(this.routes.has(b.path))throw Error(`Duplicate WebSocket route: ${b.path}`);this.routes.set(b.path,b)}}async handleRequest(a){let b=this.routes.get(a.head.path);b?"ready"!==b.access||this.workSessions.isReady()?await b.handle(a):this.connection.sendError(a.head.path,a.head.requestId,409,"工作会话尚未初始化",{key:"errors:sessionsNotReady"}):this.connection.sendError(a.head.path,a.head.requestId,404,"未知 WebSocket 路径",{key:"errors:socketUnknownPath"})}disposeControllers(){this.plugins.dispose(),this.nativeUi.dispose(),this.modelAuth.dispose(),this.pluginLogs.dispose(),this.taskCenter.dispose(),this.terminals.dispose(),this.chat.dispose(),this.appRuntime.dispose(),this.workSessions.dispose()}dispose(){this.disposed||(this.disposed=!0,this.disposeControllers())}}d()}catch(a){d(a)}})},97824:(a,b,c)=>{"use strict";c.d(b,{dZ:()=>f});var d=c(69779),e=c(18);function f(a,b){if("snapshot"===b.type){var c;return c=b.snapshot,a.taskId!==c.taskId||a.body?.kind!=="conversation"||c.body?.kind!=="conversation"?c:d.ui.parse({...c,body:{kind:"conversation",truncated:c.body.truncated,...(0,e.zR)(a.body,c.body.messages,c.body.temporaryMessages)}})}if("unavailable"===b.type)return null;if("text_append"===b.type){if(a.body?.kind!=="text")throw Error("Text append requires a text task detail snapshot");return{...a,body:{...a.body,text:a.body.text+b.text}}}if(a.body?.kind!=="conversation")throw Error("Conversation event requires a conversation task detail snapshot");return{...a,body:{...(0,e.FR)(a.body,b.event),kind:"conversation",truncated:a.body.truncated}}}},99407:()=>{}};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";exports.id=8584,exports.ids=[8584],exports.modules={193:(a,b,c)=>{c.d(b,{OC:()=>u,Ot:()=>l,Xe:()=>m,ZI:()=>o,_X:()=>q,fg:()=>n,p0:()=>p,p3:()=>s,ry:()=>r,ys:()=>t});var d=c(59473),e=c(63719),f=c(66951),g=c(39792);let h=d.Ik({cwd:d.Yj().trim().min(1).max(4096),workId:d.Yj().trim().min(1).optional()}).strict(),i=h.extend({repositoryRoot:e.rh}),j=h.extend({path:e.eC,imagePreviewMode:e.p$}).superRefine((a,b)=>{a.workId||e._g.safeParse(a.path).success||b.addIssue({code:"custom",path:["path"],message:"独立项目预览只接受根内相对路径"})}),k=d.k5(["file","directory"]),l={path:"/api/project-files/reveal",request:h.extend({path:e.rh,targetType:k.optional()}).refine(a=>""!==a.path||"directory"===a.targetType,"文件路径不能为空"),response:d.Ik({}).strict()},m={path:"/api/project-files/list",request:h.extend({path:e.rh}).strict(),response:e.JH},n={path:"/api/project-files/search",request:h.extend({query:d.Yj().trim().min(1).max(200)}).strict(),response:e.jI},o={path:"/api/project-files/get",request:j,response:e.ih},p={path:"/api/project-git/get",request:h.extend({refresh:d.zM().optional()}).strict(),response:d.Ik({repositories:d.YO(f.u2).max(100)}).strict()},q={path:"/api/project-git-heads/get",request:h,response:d.Ik({repositories:d.YO(f.yl).max(f.y2)}).strict()},r={path:"/api/project-git-branches/list",request:i.strict(),response:g.WW},s={path:"/api/project-git-log/list",request:i.extend(g.co.shape).strict(),response:g.yw},t={path:"/api/project-git-changes/list",request:i.extend(g.ph.shape).strict(),response:g.T8},u={path:"/api/project-git-diff/get",request:i.extend({path:e._g,comparison:g.xv.optional()}).strict(),response:g.lw}},8127:(a,b,c)=>{c.d(b,{m:()=>f});var d=c(52913),e=c(8602);function f(a){if(a instanceof Error&&"WorkSessionNotFoundError"===a.name)return(0,e.e)(404,"工作会话不存在",{key:"errors:sessionMissing"});if(a instanceof Error&&"WorkSessionProjectChangedError"===a.name)return(0,e.e)(409,"工作会话项目已变化",{key:"errors:projectChanged"});switch((0,d.C$)(a)){case"project-not-found":return(0,e.e)(404,"项目目录不存在",{key:"errors:projectMissing"});case"not-repository":return(0,e.e)(404,"Git 仓库不存在",{key:"errors:repositoryMissing"});case"outside-project":return(0,e.e)(403,"Git 目标不在当前项目目录内",{key:"errors:gitOutsideProject"});case"invalid-ref":return(0,e.e)(400,a instanceof Error?a.message:"Git 分支无效");case"scan-limit":return(0,e.e)(413,a instanceof Error?a.message:"Git 仓库过大");case"operation-failed":return(0,e.e)(409,a instanceof Error?a.message:"Git 操作失败");case"read-failed":return(0,e.e)(500,"读取 Git 仓库失败",{key:"errors:gitReadFailed"});case null:return null}}},8584:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{Cx:()=>n,Dk:()=>r,Ql:()=>m,bF:()=>o,gF:()=>k,jP:()=>s,u:()=>q,u8:()=>l,uP:()=>p});var e=c(193),f=c(60351),g=c(52913),h=c(17911),i=c(11420),j=a([f,i]);[f,i]=j.then?(await j)():j;let k=(0,i.G)(e.Xe,a=>(0,f.cv)(a.cwd,a.path)),l=(0,i.G)(e.fg,a=>(0,f.wZ)(a.cwd,a.query)),m=(0,i.G)(e.ZI,a=>(0,f.dy)(a.cwd,a.path,a.imagePreviewMode)),n=(0,i.G)(e.p0,a=>(0,g.ib)(a.cwd,a.refresh)),o=(0,i.G)(e._X,a=>(0,g.hg)(a.cwd)),p=(0,i.G)(e.ry,a=>(0,h.Wf)(a.cwd,a.repositoryRoot)),q=(0,i.G)(e.p3,a=>(0,h.wZ)(a.cwd,a.repositoryRoot,a)),r=(0,i.G)(e.ys,a=>(0,h.rQ)(a.cwd,a.repositoryRoot,a)),s=(0,i.G)(e.OC,a=>(0,h.ji)(a.cwd,a.repositoryRoot,a.path,a.comparison));d()}catch(a){d(a)}})},11420:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{G:()=>l});var e=c(76760),f=c(23054),g=c(8602),h=c(52913),i=c(61371),j=c(8127),k=a([f,i]);function l(a,b){return async c=>{let d;try{d=await c.json()}catch{return(0,g.e)(400,"项目请求 JSON 格式无效",{key:"errors:projectJsonInvalid"})}let k=a.request.safeParse(d);if(!k.success)return(0,g.e)(400,"项目请求参数无效",{key:"errors:projectInputInvalid"});let l=k.data;if(!(0,e.isAbsolute)(l.cwd)||l.cwd.includes("\0"))return(0,g.e)(400,"项目目录必须是绝对路径",{key:"errors:projectCwdAbsolute"});try{if(l.workId){let a=
|
|
1
|
+
"use strict";exports.id=8584,exports.ids=[8584],exports.modules={193:(a,b,c)=>{c.d(b,{OC:()=>u,Ot:()=>l,Xe:()=>m,ZI:()=>o,_X:()=>q,fg:()=>n,p0:()=>p,p3:()=>s,ry:()=>r,ys:()=>t});var d=c(59473),e=c(63719),f=c(66951),g=c(39792);let h=d.Ik({cwd:d.Yj().trim().min(1).max(4096),workId:d.Yj().trim().min(1).optional()}).strict(),i=h.extend({repositoryRoot:e.rh}),j=h.extend({path:e.eC,imagePreviewMode:e.p$}).superRefine((a,b)=>{a.workId||e._g.safeParse(a.path).success||b.addIssue({code:"custom",path:["path"],message:"独立项目预览只接受根内相对路径"})}),k=d.k5(["file","directory"]),l={path:"/api/project-files/reveal",request:h.extend({path:e.rh,targetType:k.optional()}).refine(a=>""!==a.path||"directory"===a.targetType,"文件路径不能为空"),response:d.Ik({}).strict()},m={path:"/api/project-files/list",request:h.extend({path:e.rh}).strict(),response:e.JH},n={path:"/api/project-files/search",request:h.extend({query:d.Yj().trim().min(1).max(200)}).strict(),response:e.jI},o={path:"/api/project-files/get",request:j,response:e.ih},p={path:"/api/project-git/get",request:h.extend({refresh:d.zM().optional()}).strict(),response:d.Ik({repositories:d.YO(f.u2).max(100)}).strict()},q={path:"/api/project-git-heads/get",request:h,response:d.Ik({repositories:d.YO(f.yl).max(f.y2)}).strict()},r={path:"/api/project-git-branches/list",request:i.strict(),response:g.WW},s={path:"/api/project-git-log/list",request:i.extend(g.co.shape).strict(),response:g.yw},t={path:"/api/project-git-changes/list",request:i.extend(g.ph.shape).strict(),response:g.T8},u={path:"/api/project-git-diff/get",request:i.extend({path:e._g,comparison:g.xv.optional()}).strict(),response:g.lw}},8127:(a,b,c)=>{c.d(b,{m:()=>f});var d=c(52913),e=c(8602);function f(a){if(a instanceof Error&&"WorkSessionNotFoundError"===a.name)return(0,e.e)(404,"工作会话不存在",{key:"errors:sessionMissing"});if(a instanceof Error&&"WorkSessionProjectChangedError"===a.name)return(0,e.e)(409,"工作会话项目已变化",{key:"errors:projectChanged"});switch((0,d.C$)(a)){case"project-not-found":return(0,e.e)(404,"项目目录不存在",{key:"errors:projectMissing"});case"not-repository":return(0,e.e)(404,"Git 仓库不存在",{key:"errors:repositoryMissing"});case"outside-project":return(0,e.e)(403,"Git 目标不在当前项目目录内",{key:"errors:gitOutsideProject"});case"invalid-ref":return(0,e.e)(400,a instanceof Error?a.message:"Git 分支无效");case"scan-limit":return(0,e.e)(413,a instanceof Error?a.message:"Git 仓库过大");case"operation-failed":return(0,e.e)(409,a instanceof Error?a.message:"Git 操作失败");case"read-failed":return(0,e.e)(500,"读取 Git 仓库失败",{key:"errors:gitReadFailed"});case null:return null}}},8584:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{Cx:()=>n,Dk:()=>r,Ql:()=>m,bF:()=>o,gF:()=>k,jP:()=>s,u:()=>q,u8:()=>l,uP:()=>p});var e=c(193),f=c(60351),g=c(52913),h=c(17911),i=c(11420),j=a([f,i]);[f,i]=j.then?(await j)():j;let k=(0,i.G)(e.Xe,a=>(0,f.cv)(a.cwd,a.path)),l=(0,i.G)(e.fg,a=>(0,f.wZ)(a.cwd,a.query)),m=(0,i.G)(e.ZI,a=>(0,f.dy)(a.cwd,a.path,a.imagePreviewMode)),n=(0,i.G)(e.p0,a=>(0,g.ib)(a.cwd,a.refresh)),o=(0,i.G)(e._X,a=>(0,g.hg)(a.cwd)),p=(0,i.G)(e.ry,a=>(0,h.Wf)(a.cwd,a.repositoryRoot)),q=(0,i.G)(e.p3,a=>(0,h.wZ)(a.cwd,a.repositoryRoot,a)),r=(0,i.G)(e.ys,a=>(0,h.rQ)(a.cwd,a.repositoryRoot,a)),s=(0,i.G)(e.OC,a=>(0,h.ji)(a.cwd,a.repositoryRoot,a.path,a.comparison));d()}catch(a){d(a)}})},11420:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{G:()=>l});var e=c(76760),f=c(23054),g=c(8602),h=c(52913),i=c(61371),j=c(8127),k=a([f,i]);function l(a,b){return async c=>{let d;try{d=await c.json()}catch{return(0,g.e)(400,"项目请求 JSON 格式无效",{key:"errors:projectJsonInvalid"})}let k=a.request.safeParse(d);if(!k.success)return(0,g.e)(400,"项目请求参数无效",{key:"errors:projectInputInvalid"});let l=k.data;if(!(0,e.isAbsolute)(l.cwd)||l.cwd.includes("\0"))return(0,g.e)(400,"项目目录必须是绝对路径",{key:"errors:projectCwdAbsolute"});try{let c;if(l.workId){let a=(0,f.JJ)(),b=await a.getWorkSession(l.workId);if(!b)return(0,g.e)(404,"工作会话不存在",{key:"errors:sessionMissing"});let d=a.getProjectPreviewContext(b,l.cwd);if(!d)return(0,g.e)(409,"工作会话项目已变化或预览目录未登记",{key:"errors:projectChanged"});l.cwd=d.cwd,c=d.isCurrent}let d=await b(l);if(c&&!c())return(0,g.e)(409,"工作会话项目已变化",{key:"errors:projectChanged"});return(0,g.n)(a.response.parse(d))}catch(b){if(console.warn("[Pi Desk][Project] 项目请求失败",{path:a.path,cwd:l.cwd,workId:l.workId,error:b instanceof Error?b.message:String(b)}),"read-failed"===(0,h.C$)(b))return(0,g.e)(500,b instanceof Error?b.message:"读取 Git 失败",b instanceof Error?void 0:{key:"errors:gitReadOperationFailed"});return(0,i.g)(b)??(0,j.m)(b)??(0,g.e)(500,"项目操作失败",{key:"errors:projectOperationFailed"})}}}[f,i]=k.then?(await k)():k,d()}catch(a){d(a)}})},17911:(a,b,c)=>{c.d(b,{ji:()=>u,Wf:()=>t,rQ:()=>s,wZ:()=>r});var d=c(63719),e=c(52913),f=c(96956),g=c(29671),h=c(39792),i=c(85224);let j="%H%x00%P%x00%an%x00%ct%x00%D%x00%s";async function k(a,b){let c=await (0,f.R)(a,b);if(0!==c.code)throw new g.q("read-failed",`读取 Git 失败:${c.stderr.trim().slice(0,1200)}`);return c.stdout}async function l(a,b){if(h.xi.parse(b),b.startsWith("refs/")&&0!==(await (0,f.R)(a,["check-ref-format",b])).code)throw new g.q("invalid-ref","Git 引用名称无效");let c=await (0,f.R)(a,["rev-parse","--verify","--end-of-options",`${b}^{commit}`]);if(0===c.code)return h.aD.parse(c.stdout.trim());if("HEAD"===b){let b=await (0,f.R)(a,["symbolic-ref","-q","HEAD"]);if(0===b.code&&1===(await (0,f.R)(a,["show-ref","--verify","--quiet",b.stdout.trim()])).code)return null}throw new g.q("invalid-ref",`Git 版本不存在或对象不可读:${b}`)}function m(a){if(6!==a.length||!Number.isFinite(Number(a[3])))throw new g.q("read-failed","Git 提交记录格式无效");return{oid:h.aD.parse(a[0]),parents:a[1]?a[1].split(" ").map(a=>h.aD.parse(a)):[],author:a[2],timestampMs:1e3*Number(a[3]),refs:a[4]?a[4].split(", "):[],subject:a[5]}}async function n(a,b){let c=(await k(a,["show","-s","--no-show-signature","--decorate=short",`--format=${j}%x00%B`,b,"--"])).split("\0");if(7!==c.length)throw new g.q("read-failed","Git 提交详情格式无效");return{...m(c.slice(0,6)),message:c[6].trimEnd()}}async function o(a,b,c){if(!b)return null;let d=await k(a,["--literal-pathspecs","ls-tree","-z",b,"--",c]);if(!d)return null;let e=d.split("\0").find(a=>a.slice(a.indexOf(" ")+1)===c);if(!e)return null;let[f,i,j]=e.slice(0,e.indexOf(" ")).split(" ");if(!f||!i||!j)throw new g.q("read-failed","Git 树对象格式无效");return{mode:f,type:i,oid:h.aD.parse(j)}}async function p(a,b){if(!b)return{kind:"text",content:""};let c=Number((await k(a,["cat-file","-s",b.oid])).trim());if(!Number.isSafeInteger(c)||c<0)throw new g.q("read-failed","Git 文件大小无效");if(c>d.NL)return{kind:"too_large"};let e=await (0,f.U)(a,["cat-file","blob",b.oid]);if(0!==e.code)throw new g.q("read-failed","Git 文件对象不可读");if(e.stdout.length>d.NL)return{kind:"too_large"};let h=(0,i.X)(e.stdout);return null===h?{kind:"binary"}:{kind:"text",content:h}}async function q(a,b,c){await l(a,c.targetCommit),c.baseCommit&&await l(a,c.baseCommit);let d=c.oldPath??b,[e,f]=await Promise.all([o(a,c.baseCommit,d),o(a,c.targetCommit,b)]);if(!e&&!f)throw new g.q("invalid-ref","文件不在指定的任一版本中");if(e&&"blob"!==e.type||f&&"blob"!==f.type||e&&f&&e.mode.slice(0,3)!==f.mode.slice(0,3)){let a=a=>a?`${a.type} \xb7 ${a.mode}
|
|
2
2
|
${a.oid}`:"不存在";return{kind:"metadata",original:a(e),modified:a(f)}}let[h,i]=await Promise.all([p(a,e),p(a,f)]);return"too_large"===h.kind||"too_large"===i.kind?{kind:"too_large"}:"text"!==h.kind||"text"!==i.kind?{kind:"binary"}:{kind:"text",original:{path:d,content:h.content},modified:{path:b,content:i.content}}}async function r(a,b,c){let d=await (0,e.H$)(a,b),f=await l(d,c.tip),h=c.exclude?await l(d,c.exclude):null;if(!f)return{tip:f,exclude:h,items:[],hasMore:!1,truncated:!1};let i=(await k(d,["log","-z","--topo-order","--no-show-signature","--decorate=short","--max-count=20001",`--format=${j}`,f,...h?[`^${h}`]:[],"--"])).split("\0");if(""===i.at(-1)&&i.pop(),i.length%6!=0)throw new g.q("read-failed","Git 提交列表格式无效");let n=[];for(let a=0;a<Math.min(i.length,12e4);a+=6)n.push(m(i.slice(a,a+6)));let o=c.query.toLocaleLowerCase(),p=c.author?.toLocaleLowerCase(),q=n.filter(a=>(!p||a.author.toLocaleLowerCase().includes(p))&&(!o||a.subject.toLocaleLowerCase().includes(o)||a.oid.includes(o))),r=(c.page.index-1)*c.page.size;return{tip:f,exclude:h,items:q.slice(r,r+c.page.size),hasMore:r+c.page.size<q.length,truncated:i.length>12e4}}async function s(a,b,c){let h,i,j,m=await (0,e.H$)(a,b),o=null;if("commit"in c.selection){let a=await l(m,c.selection.commit);if(!a)throw new g.q("invalid-ref","当前仓库还没有提交");let b=await n(m,a),d=c.selection.parent??b.parents[0]??null;if(d&&!b.parents.includes(d))throw new g.q("invalid-ref","选择的版本不是该提交的父提交");j=a,h=i=d,o={...b,selectedParent:d}}else{let a=await l(m,c.selection.base),b=await l(m,c.selection.target);if(!a||!b)throw new g.q("invalid-ref","比较分支还没有提交");if(h=a,j=b,i=h,"merge-base"===c.selection.strategy){let a=await (0,f.R)(m,["merge-base","--all",h,j]);if(0!==a.code&&1!==a.code)throw new g.q("read-failed","计算共同祖先失败");let b=a.stdout.trim().split(/\s+/).filter(Boolean);if(1!==b.length){let a="true"===(await k(m,["rev-parse","--is-shallow-repository"])).trim();throw new g.q("invalid-ref",b.length>1?"存在多个最佳共同祖先,请改用两个版本直接比较":a?"浅克隆历史不足,无法确定共同祖先;可改用直接比较":"两个版本没有共同祖先,可改用直接比较")}i=b[0]}}let p=i?["diff","--no-ext-diff","--no-textconv","--find-renames","--name-status","-z",i,j,"--"]:["diff-tree","--root","--no-commit-id","-r","--no-ext-diff","--no-textconv","--find-renames","--name-status","-z",j,"--"],q=(await k(m,p)).split("\0");""===q.at(-1)&&q.pop();let r=[];for(let a=0;a<q.length;){let b=q[a++],c=q[a++],e=b.startsWith("R")||b.startsWith("C"),f=e?q[a++]:c;if(!f||!d._g.safeParse(f).success||e&&!d._g.safeParse(c).success)throw new g.q("read-failed","变更包含无法展示的文件路径");let h="R"===b[0]?"renamed":"A"===b[0]||"C"===b[0]?"added":"D"===b[0]?"deleted":"T"===b[0]?"type-changed":"modified";if(r.push({path:f,oldPath:"R"===b[0]?c:null,status:h}),r.length>5e4)break}let s=(c.page.index-1)*c.page.size,t=r.slice(0,5e4);return{comparison:{base:h,target:j,original:i},commit:o,items:t.slice(s,s+c.page.size),hasMore:s+c.page.size<t.length,truncated:r.length>5e4}}async function t(a,b){let c=await (0,e.o9)(a,b);if("branch"!==c.head.type)return{...c,upstream:null};let d=await (0,e.H$)(a,b),g=(await k(d,["for-each-ref","--format=%(upstream)",`refs/heads/${c.head.name}`])).trim();if(!g)return{...c,upstream:null};let h=await (0,f.R)(d,["rev-list","--left-right","--count",`HEAD...${g}`,"--"]),[i,j]=h.stdout.trim().split(/\s+/).map(Number);return{...c,upstream:{ref:g,ahead:0===h.code&&Number.isSafeInteger(i)?i:null,behind:0===h.code&&Number.isSafeInteger(j)?j:null}}}async function u(a,b,c,d){return d?q(await (0,e.H$)(a,b),c,d):(0,e.bv)(a,b,c)}},39792:(a,b,c)=>{c.d(b,{T8:()=>q,WW:()=>r,aD:()=>g,co:()=>m,lw:()=>s,ph:()=>p,xi:()=>h,xv:()=>k,yw:()=>n});var d=c(59473),e=c(63719),f=c(66951);let g=d.Yj().regex(/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/),h=d.KC([g,d.eu("HEAD"),d.Yj().max(1024).regex(/^refs\/(?:heads|remotes)\/[^\0\r\n]+$/)]).refine(a=>!a.includes("..")&&!a.endsWith("/"),"Git 版本无效"),i=d.KC([d.Ik({commit:h,parent:g.optional()}).strict(),d.Ik({base:h,target:h,strategy:d.k5(["merge-base","direct"])}).strict()]),j=d.Ik({base:g.nullable(),target:g,original:g.nullable()}).strict(),k=d.Ik({baseCommit:g.nullable(),targetCommit:g,oldPath:e._g.optional()}).strict(),l=d.Ik({oid:g,parents:d.YO(g),subject:d.Yj(),author:d.Yj(),timestampMs:d.ai().int(),refs:d.YO(d.Yj())}).strict(),m=d.Ik({tip:h,exclude:h.optional(),query:d.Yj().trim().max(200).default(""),author:d.Yj().trim().max(200).optional(),page:d.Ik({index:d.ai().int().min(1).max(2e3),size:d.ai().int().min(1).max(100)}).strict()}).strict(),n=d.Ik({tip:g.nullable(),exclude:g.nullable(),items:d.YO(l),hasMore:d.zM(),truncated:d.zM()}).strict(),o=d.Ik({path:e._g,oldPath:e._g.nullable(),status:d.k5(["added","modified","deleted","renamed","type-changed"])}).strict(),p=d.Ik({selection:i,page:d.Ik({index:d.ai().int().min(1).max(5e4),size:d.ai().int().min(1).max(500)}).strict()}).strict(),q=d.Ik({comparison:j,commit:l.extend({message:d.Yj(),selectedParent:g.nullable()}).nullable(),items:d.YO(o),hasMore:d.zM(),truncated:d.zM()}).strict(),r=f.gf.extend({upstream:d.Ik({ref:d.Yj(),ahead:d.ai().int().nonnegative().nullable(),behind:d.ai().int().nonnegative().nullable()}).strict().nullable()}).strict(),s=d.KC([f.FJ,d.Ik({kind:d.eu("metadata"),original:d.Yj(),modified:d.Yj()}).strict()])},61371:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{g:()=>h});var e=c(60351),f=c(8602),g=a([e]);function h(a){if(a instanceof Error&&"WorkSessionNotFoundError"===a.name)return(0,f.e)(404,"工作会话不存在",{key:"errors:sessionMissing"});if(a instanceof Error&&"WorkSessionProjectChangedError"===a.name)return(0,f.e)(409,"工作会话项目已变化",{key:"errors:projectChanged"});switch((0,e.Vp)(a)){case"not-found":return(0,f.e)(404,"文件或目录不存在",{key:"errors:fileMissing"});case"not-directory":return(0,f.e)(400,"目标不是目录",{key:"errors:notDirectory"});case"not-file":return(0,f.e)(400,"目标不是文件",{key:"errors:notFile"});case"outside-project":return(0,f.e)(403,"目标不在当前项目目录内",{key:"errors:outsideProject"});case"text-too-large":return(0,f.e)(413,"文本文件超过 5MB,暂不支持在线预览",{key:"errors:textTooLarge"});case"image-too-large":return(0,f.e)(413,"图片过大,暂不支持在线预览",{key:"errors:imageTooLarge"});case"unsupported":return(0,f.e)(415,"当前文件类型不支持在线预览",{key:"errors:previewUnsupported"});case"read-failed":return(0,f.e)(500,"读取项目文件失败",{key:"errors:fileReadFailed"});case"reveal-failed":return(0,f.e)(500,"打开所在文件夹失败",{key:"errors:revealFailed"});case null:return null}}e=(g.then?(await g)():g)[0],d()}catch(a){d(a)}})}};
|