@wendongfly/myhi 1.3.89 → 1.3.90
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/dist/chat.html +20 -2
- package/dist/index.js +1 -1
- package/dist/index.min.js +1 -1
- package/package.json +1 -1
package/dist/index.min.js
CHANGED
|
@@ -416,7 +416,7 @@ ${f}
|
|
|
416
416
|
3. \u8BED\u8A00\u81EA\u7136\u6D41\u7545\uFF0C\u4E0D\u9700\u8981\u5206\u6761\u5217\u9879\uFF0C\u4FDD\u6301\u8FDE\u8D2F\u6BB5\u843D
|
|
417
417
|
4. \u4FDD\u7559\u6240\u6709\u5177\u4F53\u7684\u6570\u5B57\u3001\u540D\u79F0\u7B49\u5173\u952E\u4FE1\u606F
|
|
418
418
|
|
|
419
|
-
\u53EA\u8F93\u51FA\u6574\u7406\u540E\u7684\u6587\u5B57\uFF0C\u4E0D\u9700\u8981\u4EFB\u4F55\u89E3\u91CA\u6216\u6807\u9898\u3002\u5FC5\u987B\u7528\u4E2D\u6587\u8F93\u51FA\u3002`;try{const t=await new Promise(((c,l)=>{let m="",o="";const i=process.platform==="win32"?(0,external_fs_.existsSync)((0,external_path_.join)((0,external_os_.homedir)(),"AppData","Roaming","npm","claude.cmd"))?(0,external_path_.join)((0,external_os_.homedir)(),"AppData","Roaming","npm","claude.cmd"):(0,external_path_.join)((0,external_os_.homedir)(),".claude","local","claude.cmd"):"claude",n=process.platform==="win32"?process.env.ComSpec||"cmd.exe":i,e=process.platform==="win32"?["/c",i,"--print"]:["--print"],r=(0,external_child_process_namespaceObject.spawn)(n,e,{stdio:["pipe","pipe","pipe"],env:{...process.env,NO_COLOR:"1"},timeout:9e4});r.stdin.write(s,"utf8"),r.stdin.end(),r.stdout.on("data",(u=>{m+=u.toString()})),r.stderr.on("data",(u=>{o+=u.toString()})),r.on("close",(u=>{u!==0&&!m.trim()?l(new Error(o||`exit ${u}`)):c(m.trim())})),r.on("error",l)}));_.json({requirement:t})}catch(t){_.status(500).json({error:t.message})}})),app.get("/qr/:sessionId",checkAuth,(async(T,_)=>{const f=getTailscaleIP(),s=(0,external_crypto_.randomBytes)(16).toString("hex");userSessions.set(s,{role:"admin",name:"\u626B\u7801\u7528\u6237",onetime:!0,lastUsed:Date.now()});const c=`${httpsServer?"https":"http"}://${f}:${PORT}/terminal/${T.params.sessionId}?token=${s}`;try{const l=await lib.toString(c,{type:"svg"});_.setHeader("Content-Type","image/svg+xml"),_.send(l)}catch(l){_.status(500).send(l.message)}})),io.use(((T,_)=>{const f=T.handshake.headers.cookie;if(hasValidSession(f)){const t=getUserInfo(f);return T.data.role=t?.role||"admin",T.data.userName=t?.name||"\u7528\u6237",T.data.dir=t?.dir||null,_()}const s=T.handshake.auth?.password;if(s){loadUsers();const t=lookupUser(s);if(t)return T.data.role="operator",T.data.userName=t.name,T.data.dir=t.dir,_()}if((T.handshake.auth?.token||T.handshake.query?.token)===TOKEN)return T.data.role="admin",T.data.userName="\u7BA1\u7406\u5458",_();_(new Error("\u672A\u6388\u6743"))}));const EXCLUSIVE_RELEASE_DELAY=120*1e3;let _exclusiveReleaseTimer=null;function checkExclusiveRelease(){if(!isExclusiveMode()||!activeUser)return;let T=!1;for(const[,_]of io.sockets.sockets)if(_.data.userName===activeUser.name){T=!0;break}if(T){_exclusiveReleaseTimer&&(clearTimeout(_exclusiveReleaseTimer),_exclusiveReleaseTimer=null);return}_exclusiveReleaseTimer||(_exclusiveReleaseTimer=setTimeout((()=>{if(_exclusiveReleaseTimer=null,!!activeUser){for(const[,_]of io.sockets.sockets)if(_.data.userName===activeUser.name)return;console.log(`[\u72EC\u5360] ${activeUser.name} \u5DF2\u79BB\u7EBF\u8D85\u65F6\uFF0C\u91CA\u653E\u767B\u5F55\u72B6\u6001\uFF08\u4F1A\u8BDD\u4FDD\u7559\uFF09`);for(const _ of activeUser.tokens)userSessions.delete(_);activeUser=null}}),EXCLUSIVE_RELEASE_DELAY))}let _broadcastTimer=null;function broadcastSessions(){_broadcastTimer||(_broadcastTimer=setTimeout((()=>{_broadcastTimer=null;for(const[,T]of io.sockets.sockets)T.emit("sessions",manager.list(T.data.userName,T.data.role==="admin"))}),100))}io.on("connection",(T=>{const _=T.handshake.address?.replace("::ffff:","")||"?";console.log(`[\u8FDE\u63A5] ${T.data.userName}(${T.data.role}) \u4ECE ${_} \u63A5\u5165 id=${T.id}`),_exclusiveReleaseTimer&&activeUser&&T.data.userName===activeUser.name&&(clearTimeout(_exclusiveReleaseTimer),_exclusiveReleaseTimer=null);let f=null,s=null,t=null,c=null,l=null;function m(){f&&(f.isController(T.id)&&(f.releaseControl(),io.emit("control-changed",{sessionId:f.id,holder:null,holderName:null})),f.removeViewer(T.id),s&&f.off("data",s),t&&f.off("agent:message",t),c&&f.off("agent:busy",c),l&&f.off("agent:error",l),s=null,t=null,c=null,l=null)}T.on("join",(o=>{const i=manager.get(o);if(!i){T.emit("error",{message:`\u4F1A\u8BDD ${o} \u672A\u627E\u5230`});return}const n=f?.id===o;if(m(),f=i,f.addViewer(T.id,T.data.userName),i.mode==="agent"?(t=e=>T.emit("agent:message",e),f.on("agent:message",t),c=e=>T.emit("agent:busy",e),f.on("agent:busy",c),l=e=>T.emit("agent:error",e),f.on("agent:error",l)):(s=e=>T.emit("output",e),f.on("data",s),f.once("exit",(e=>{T.emit("session-exit",{code:e}),s&&f?.off("data",s)})),spawnLocalTerminal(o,i.title)),console.log(`[\u52A0\u5165] ${T.data.userName} \u52A0\u5165\u4F1A\u8BDD "${i.title}" (${o}) \u6A21\u5F0F=${i.mode||"pty"}${n?" [\u91CD\u65B0\u8BA2\u9605]":""}`),T.emit("joined",{...i.toJSON(),role:T.data.role}),!n){if(i.mode==="agent")i._history?.length&&T.emit("agent:history",i._history);else if(i._scrollback?.length){const e=i._scrollback;if(e.length<=4096)T.emit("output",e);else{let r=0;(function u(){r>=e.length||(T.emit("output",e.slice(r,r+4096)),r+=4096,setImmediate(u))})()}}}broadcastSessions()})),T.on("disconnect",(()=>{console.log(`[\u65AD\u5F00] ${T.data.userName} \u79BB\u5F00\u4F1A\u8BDD "${f?.title||"?"}" id=${T.id}`),m(),broadcastSessions(),checkExclusiveRelease(),manager.persist()})),T.on("agent:query",(async({prompt:o}={})=>{if(!f||f.mode!=="agent"){T.emit("agent:error",{message:"\u5F53\u524D\u4E0D\u662F Agent \u6A21\u5F0F\u4F1A\u8BDD"});return}if(!f.isController(T.id)){T.emit("control-denied",{reason:"\u4F60\u6CA1\u6709\u5F53\u524D\u4F1A\u8BDD\u7684\u63A7\u5236\u6743"});return}if(f.isBusy){T.emit("agent:error",{message:"\u6B63\u5728\u5904\u7406\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u5B8C\u6210"});return}try{await f.query(o)}catch(i){console.error("[agent:query] \u9519\u8BEF:",i.message);try{T.connected&&T.emit("agent:error",{message:i.message})}catch{}}})),T.on("agent:interrupt",(()=>{!f||f.mode!=="agent"||f.interrupt()})),T.on("create-agent",((o,i)=>{if(!hasPermission(T.data.role,"operator")){typeof i=="function"&&i({ok:!1,error:"\u6CA1\u6709\u521B\u5EFA\u4F1A\u8BDD\u7684\u6743\u9650"});return}if(T.data.dir){const e=(0,external_path_.resolve)((0,external_path_.normalize)(T.data.dir)),r=o?.cwd?(0,external_path_.resolve)((0,external_path_.normalize)(o.cwd)):null;if(r&&r!==e&&!r.startsWith(e+external_path_.sep)){typeof i=="function"&&i({ok:!1,error:"\u4E0D\u80FD\u5728\u7ED1\u5B9A\u76EE\u5F55\u4E4B\u5916\u521B\u5EFA\u4F1A\u8BDD"});return}r||(o={...o,cwd:e})}const n=o?.cwd||process.env.MYHI_CWD||process.cwd();if(!(0,external_fs_.existsSync)(n))try{(0,external_fs_.mkdirSync)(n,{recursive:!0}),console.log(`[\u521B\u5EFA] \u81EA\u52A8\u521B\u5EFA\u76EE\u5F55: ${n}`)}catch(e){typeof i=="function"&&i({ok:!1,error:`\u521B\u5EFA\u76EE\u5F55\u5931\u8D25: ${e.message}`});return}try{const e=manager.createAgent({...o,owner:T.data.userName,userDir:T.data.dir});console.log(`[\u4F1A\u8BDD] ${T.data.userName} \u521B\u5EFA Agent \u4F1A\u8BDD "${e.title}" (${e.id})`),broadcastSessions(),typeof i=="function"&&i({ok:!0,session:e.toJSON()})}catch(e){typeof i=="function"&&i({ok:!1,error:e.message})}})),T.on("input",(o=>{if(!(o==null||!f)&&f.mode!=="agent"){if(!f.isController(T.id)){T.emit("control-denied",{reason:"\u4F60\u6CA1\u6709\u5F53\u524D\u4F1A\u8BDD\u7684\u63A7\u5236\u6743"});return}f.lastInputTime=Date.now(),f.write(o)}})),T.on("take-control",(({sessionId:o}={})=>{const i=o?manager.get(o):f;if(i){if(!hasPermission(T.data.role,"operator")){T.emit("control-denied",{reason:"\u4F60\u7684\u89D2\u8272\u6CA1\u6709\u63A7\u5236\u6743\u9650"});return}if(i.controlHolder&&i.controlHolder!==T.id){const n=i.controlHolderName===T.data.userName;if(T.data.role!=="admin"&&!n){T.emit("control-denied",{reason:"\u5176\u4ED6\u7528\u6237\u6B63\u5728\u63A7\u5236\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u91CA\u653E"});return}}i.takeControl(T.id,T.data.userName),console.log(`[\u63A7\u5236] ${T.data.userName} \u83B7\u53D6\u4F1A\u8BDD "${i.title}" \u7684\u63A7\u5236\u6743`),io.emit("control-changed",{sessionId:i.id,holder:T.id,holderName:T.data.userName})}})),T.on("release-control",(({sessionId:o}={})=>{const i=o?manager.get(o):f;!i||!i.isController(T.id)||(console.log(`[\u63A7\u5236] ${T.data.userName} \u91CA\u653E\u4F1A\u8BDD "${i.title}" \u7684\u63A7\u5236\u6743`),i.releaseControl(),io.emit("control-changed",{sessionId:i.id,holder:null,holderName:null}))})),T.on("set-mode",(({sessionId:o,mode:i}={})=>{const n=o?manager.get(o):f;if(n){if(n.mode==="agent"&&n.setPermissionMode){n.setPermissionMode(i);const e=n.permissionMode;e!==i&&console.log(`[\u6A21\u5F0F] set-mode \u6536\u5230\u65E0\u6548\u6A21\u5F0F "${i}"\uFF0C\u5DF2\u5F52\u4E00\u5316\u4E3A ${e}`),console.log(`[\u6A21\u5F0F] ${T.data.userName} \u5207\u6362\u4F1A\u8BDD "${n.title}" \u4E3A ${e}`),io.emit("mode-changed",{sessionId:n.id,mode:e})}else n.permissionMode=i,io.emit("mode-changed",{sessionId:n.id,mode:i});manager.persist()}})),T.on("rename",(({sessionId:o,title:i}={})=>{const n=o?manager.get(o):f;!n||!i||(n.title=i,io.emit("session-renamed",{sessionId:n.id,title:i}),broadcastSessions(),manager.persist())})),T.on("resize",(({cols:o,rows:i})=>f?.resize(o,i))),T.on("list",(()=>T.emit("sessions",manager.list(T.data.userName,T.data.role==="admin")))),T.on("dirs",((o,i)=>{if(typeof i!="function")return;const n=T.data.dir?(0,external_path_.resolve)((0,external_path_.normalize)(T.data.dir)):null,e=process.platform==="win32"?"\\":"/";let r=(o||n||process.env.MYHI_CWD||(0,external_os_.homedir)()).replace(/[/\\]+$/,"")||(0,external_os_.homedir)();process.platform==="win32"&&/^[A-Za-z]:$/.test(r)&&(r+="\\");const u=(0,external_path_.resolve)((0,external_path_.normalize)(r));n&&u!==n&&!u.startsWith(n+e)&&(r=n);try{const p=(0,external_fs_.readdirSync)(r,{withFileTypes:!0}).filter((g=>g.isDirectory()&&g.name!==".git")).map((g=>({name:g.name,path:r.replace(/[/\\]+$/,"")+e+g.name}))).sort(((g,b)=>g.name.localeCompare(b.name))),a=(0,external_path_.join)(r,".."),v=(0,external_path_.resolve)((0,external_path_.normalize)(a)),h=!n||v===n||v.startsWith(n+e);i({ok:!0,current:r,parent:h&&a!==r?a:null,dirs:p})}catch(p){i({ok:!1,error:p.message})}})),T.on("create",((o,i)=>{if(!hasPermission(T.data.role,"operator")){typeof i=="function"&&i({ok:!1,error:"\u6CA1\u6709\u521B\u5EFA\u4F1A\u8BDD\u7684\u6743\u9650"});return}if(T.data.dir){const e=(0,external_path_.resolve)((0,external_path_.normalize)(T.data.dir)),r=o?.cwd?(0,external_path_.resolve)((0,external_path_.normalize)(o.cwd)):null;if(r&&r!==e&&!r.startsWith(e+external_path_.sep)){typeof i=="function"&&i({ok:!1,error:"\u4E0D\u80FD\u5728\u7ED1\u5B9A\u76EE\u5F55\u4E4B\u5916\u521B\u5EFA\u4F1A\u8BDD"});return}r||(o={...o,cwd:e})}const n=o?.cwd||process.env.MYHI_CWD||process.cwd();if(!(0,external_fs_.existsSync)(n))try{(0,external_fs_.mkdirSync)(n,{recursive:!0}),console.log(`[\u521B\u5EFA] \u81EA\u52A8\u521B\u5EFA\u76EE\u5F55: ${n}`)}catch(e){typeof i=="function"&&i({ok:!1,error:`\u521B\u5EFA\u76EE\u5F55\u5931\u8D25: ${e.message}`});return}try{const e=manager.create({...o,owner:T.data.userName,userDir:T.data.dir});console.log(`[\u4F1A\u8BDD] ${T.data.userName} \u521B\u5EFA PTY \u4F1A\u8BDD "${e.title}" (${e.id})`),broadcastSessions(),typeof i=="function"&&i({ok:!0,session:e.toJSON()})}catch(e){console.error("[\u521B\u5EFA] PTY \u542F\u52A8\u5931\u8D25:",e.message),typeof i=="function"&&i({ok:!1,error:e.message})}})),T.on("kill",(o=>{if(!hasPermission(T.data.role,"operator")){T.emit("error",{message:"\u6CA1\u6709\u5220\u9664\u4F1A\u8BDD\u7684\u6743\u9650"});return}console.log(`[\u4F1A\u8BDD] ${T.data.userName} \u5220\u9664\u4F1A\u8BDD ${o}`),manager.kill(o),_autoSpawned.delete(o),broadcastSessions()})),T.on("kick-user",(({socketId:o,sessionId:i}={},n)=>{if(!hasPermission(T.data.role,"admin")){typeof n=="function"&&n({ok:!1,error:"\u6CA1\u6709\u8E22\u51FA\u7528\u6237\u7684\u6743\u9650"});return}const e=io.sockets.sockets.get(o);if(!e){typeof n=="function"&&n({ok:!1,error:"\u76EE\u6807\u7528\u6237\u4E0D\u5728\u7EBF"});return}const r=e.data.userName||"\u672A\u77E5";console.log(`[\u8E22\u51FA] ${T.data.userName} \u8E22\u51FA\u4E86\u7528\u6237 ${r} (${o})`),e.emit("kicked",{reason:`\u4F60\u5DF2\u88AB\u7BA1\u7406\u5458 ${T.data.userName} \u8E22\u51FA`}),e.disconnect(!0),typeof n=="function"&&n({ok:!0,name:r})})),T.on("list-viewers",(({sessionId:o}={},i)=>{if(typeof i!="function")return;const n=o?manager.get(o):f;if(!n){i({ok:!1,error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});return}const e=[];for(const r of n._viewers){const u=io.sockets.sockets.get(r);u&&e.push({socketId:r,userName:u.data.userName||"\u672A\u77E5",role:u.data.role||"viewer",isController:n.controlHolder===r})}i({ok:!0,viewers:e})}))}));const CONTROL_TIMEOUT=300*1e3;setInterval((()=>{for(const T of manager.listSessions()){T.controlHolder&&(!io.sockets.sockets.get(T.controlHolder)||T.lastInputTime&&Date.now()-T.lastInputTime>CONTROL_TIMEOUT)&&(T.releaseControl(),io.emit("control-changed",{sessionId:T.id,holder:null,holderName:null}));for(const _ of T._viewers)io.sockets.sockets.has(_)||T.removeViewer(_)}}),60*1e3);function showStartupInfo(){PORT=(httpsServer||httpServer).address()?.port||PORT;const _=getTailscaleIP(),s=`${httpsServer?"https":"http"}://${_}:${PORT}`;console.log(`
|
|
419
|
+
\u53EA\u8F93\u51FA\u6574\u7406\u540E\u7684\u6587\u5B57\uFF0C\u4E0D\u9700\u8981\u4EFB\u4F55\u89E3\u91CA\u6216\u6807\u9898\u3002\u5FC5\u987B\u7528\u4E2D\u6587\u8F93\u51FA\u3002`;try{const t=await new Promise(((c,l)=>{let m="",o="";const i=process.platform==="win32"?(0,external_fs_.existsSync)((0,external_path_.join)((0,external_os_.homedir)(),"AppData","Roaming","npm","claude.cmd"))?(0,external_path_.join)((0,external_os_.homedir)(),"AppData","Roaming","npm","claude.cmd"):(0,external_path_.join)((0,external_os_.homedir)(),".claude","local","claude.cmd"):"claude",n=process.platform==="win32"?process.env.ComSpec||"cmd.exe":i,e=process.platform==="win32"?["/c",i,"--print"]:["--print"],r=(0,external_child_process_namespaceObject.spawn)(n,e,{stdio:["pipe","pipe","pipe"],env:{...process.env,NO_COLOR:"1"},timeout:9e4});r.stdin.write(s,"utf8"),r.stdin.end(),r.stdout.on("data",(u=>{m+=u.toString()})),r.stderr.on("data",(u=>{o+=u.toString()})),r.on("close",(u=>{u!==0&&!m.trim()?l(new Error(o||`exit ${u}`)):c(m.trim())})),r.on("error",l)}));_.json({requirement:t})}catch(t){_.status(500).json({error:t.message})}})),app.get("/qr/:sessionId",checkAuth,(async(T,_)=>{const f=getTailscaleIP(),s=(0,external_crypto_.randomBytes)(16).toString("hex");userSessions.set(s,{role:"admin",name:"\u626B\u7801\u7528\u6237",onetime:!0,lastUsed:Date.now()});const c=`${httpsServer?"https":"http"}://${f}:${PORT}/terminal/${T.params.sessionId}?token=${s}`;try{const l=await lib.toString(c,{type:"svg"});_.setHeader("Content-Type","image/svg+xml"),_.send(l)}catch(l){_.status(500).send(l.message)}})),io.use(((T,_)=>{const f=T.handshake.headers.cookie;if(hasValidSession(f)){const t=getUserInfo(f);return T.data.role=t?.role||"admin",T.data.userName=t?.name||"\u7528\u6237",T.data.dir=t?.dir||null,_()}const s=T.handshake.auth?.password;if(s){loadUsers();const t=lookupUser(s);if(t)return T.data.role="operator",T.data.userName=t.name,T.data.dir=t.dir,_()}if((T.handshake.auth?.token||T.handshake.query?.token)===TOKEN)return T.data.role="admin",T.data.userName="\u7BA1\u7406\u5458",_();_(new Error("\u672A\u6388\u6743"))}));const EXCLUSIVE_RELEASE_DELAY=120*1e3;let _exclusiveReleaseTimer=null;function checkExclusiveRelease(){if(!isExclusiveMode()||!activeUser)return;let T=!1;for(const[,_]of io.sockets.sockets)if(_.data.userName===activeUser.name){T=!0;break}if(T){_exclusiveReleaseTimer&&(clearTimeout(_exclusiveReleaseTimer),_exclusiveReleaseTimer=null);return}_exclusiveReleaseTimer||(_exclusiveReleaseTimer=setTimeout((()=>{if(_exclusiveReleaseTimer=null,!!activeUser){for(const[,_]of io.sockets.sockets)if(_.data.userName===activeUser.name)return;console.log(`[\u72EC\u5360] ${activeUser.name} \u5DF2\u79BB\u7EBF\u8D85\u65F6\uFF0C\u91CA\u653E\u767B\u5F55\u72B6\u6001\uFF08\u4F1A\u8BDD\u4FDD\u7559\uFF09`);for(const _ of activeUser.tokens)userSessions.delete(_);activeUser=null}}),EXCLUSIVE_RELEASE_DELAY))}let _broadcastTimer=null;function broadcastSessions(){_broadcastTimer||(_broadcastTimer=setTimeout((()=>{_broadcastTimer=null;for(const[,T]of io.sockets.sockets)T.emit("sessions",manager.list(T.data.userName,T.data.role==="admin"))}),100))}io.on("connection",(T=>{const _=T.handshake.address?.replace("::ffff:","")||"?";console.log(`[\u8FDE\u63A5] ${T.data.userName}(${T.data.role}) \u4ECE ${_} \u63A5\u5165 id=${T.id}`),_exclusiveReleaseTimer&&activeUser&&T.data.userName===activeUser.name&&(clearTimeout(_exclusiveReleaseTimer),_exclusiveReleaseTimer=null);let f=null,s=null,t=null,c=null,l=null;function m(){f&&(f.isController(T.id)&&(f.releaseControl(),io.emit("control-changed",{sessionId:f.id,holder:null,holderName:null})),f.removeViewer(T.id),s&&f.off("data",s),t&&f.off("agent:message",t),c&&f.off("agent:busy",c),l&&f.off("agent:error",l),s=null,t=null,c=null,l=null)}T.on("join",(o=>{const i=manager.get(o);if(!i){T.emit("error",{message:`\u4F1A\u8BDD ${o} \u672A\u627E\u5230`});return}const n=f?.id===o;if(m(),f=i,f.addViewer(T.id,T.data.userName),i.mode==="agent"?(t=e=>T.emit("agent:message",e),f.on("agent:message",t),c=e=>T.emit("agent:busy",e),f.on("agent:busy",c),l=e=>T.emit("agent:error",e),f.on("agent:error",l)):(s=e=>T.emit("output",e),f.on("data",s),f.once("exit",(e=>{T.emit("session-exit",{code:e}),s&&f?.off("data",s)})),spawnLocalTerminal(o,i.title)),console.log(`[\u52A0\u5165] ${T.data.userName} \u52A0\u5165\u4F1A\u8BDD "${i.title}" (${o}) \u6A21\u5F0F=${i.mode||"pty"}${n?" [\u91CD\u65B0\u8BA2\u9605]":""}`),T.emit("joined",{...i.toJSON(),role:T.data.role}),!n){if(i.mode==="agent")i._history?.length&&T.emit("agent:history",i._history);else if(i._scrollback?.length){const e=i._scrollback;if(e.length<=4096)T.emit("output",e);else{let r=0;(function u(){r>=e.length||(T.emit("output",e.slice(r,r+4096)),r+=4096,setImmediate(u))})()}}}broadcastSessions()})),T.on("disconnect",(()=>{console.log(`[\u65AD\u5F00] ${T.data.userName} \u79BB\u5F00\u4F1A\u8BDD "${f?.title||"?"}" id=${T.id}`),m(),broadcastSessions(),checkExclusiveRelease(),manager.persist()})),T.on("agent:query",(async({prompt:o}={})=>{if(!f||f.mode!=="agent"){T.emit("agent:error",{message:"\u5F53\u524D\u4E0D\u662F Agent \u6A21\u5F0F\u4F1A\u8BDD"});return}if(!f.isController(T.id)){T.emit("control-denied",{reason:"\u4F60\u6CA1\u6709\u5F53\u524D\u4F1A\u8BDD\u7684\u63A7\u5236\u6743"});return}if(f.isBusy){T.emit("agent:error",{message:"\u6B63\u5728\u5904\u7406\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u5B8C\u6210"});return}f.lastInputTime=Date.now();try{await f.query(o)}catch(i){console.error("[agent:query] \u9519\u8BEF:",i.message);try{T.connected&&T.emit("agent:error",{message:i.message})}catch{}}})),T.on("agent:interrupt",(()=>{!f||f.mode!=="agent"||(f.isController(T.id)&&(f.lastInputTime=Date.now()),f.interrupt())})),T.on("create-agent",((o,i)=>{if(!hasPermission(T.data.role,"operator")){typeof i=="function"&&i({ok:!1,error:"\u6CA1\u6709\u521B\u5EFA\u4F1A\u8BDD\u7684\u6743\u9650"});return}if(T.data.dir){const e=(0,external_path_.resolve)((0,external_path_.normalize)(T.data.dir)),r=o?.cwd?(0,external_path_.resolve)((0,external_path_.normalize)(o.cwd)):null;if(r&&r!==e&&!r.startsWith(e+external_path_.sep)){typeof i=="function"&&i({ok:!1,error:"\u4E0D\u80FD\u5728\u7ED1\u5B9A\u76EE\u5F55\u4E4B\u5916\u521B\u5EFA\u4F1A\u8BDD"});return}r||(o={...o,cwd:e})}const n=o?.cwd||process.env.MYHI_CWD||process.cwd();if(!(0,external_fs_.existsSync)(n))try{(0,external_fs_.mkdirSync)(n,{recursive:!0}),console.log(`[\u521B\u5EFA] \u81EA\u52A8\u521B\u5EFA\u76EE\u5F55: ${n}`)}catch(e){typeof i=="function"&&i({ok:!1,error:`\u521B\u5EFA\u76EE\u5F55\u5931\u8D25: ${e.message}`});return}try{const e=manager.createAgent({...o,owner:T.data.userName,userDir:T.data.dir});console.log(`[\u4F1A\u8BDD] ${T.data.userName} \u521B\u5EFA Agent \u4F1A\u8BDD "${e.title}" (${e.id})`),broadcastSessions(),typeof i=="function"&&i({ok:!0,session:e.toJSON()})}catch(e){typeof i=="function"&&i({ok:!1,error:e.message})}})),T.on("input",(o=>{if(!(o==null||!f)&&f.mode!=="agent"){if(!f.isController(T.id)){T.emit("control-denied",{reason:"\u4F60\u6CA1\u6709\u5F53\u524D\u4F1A\u8BDD\u7684\u63A7\u5236\u6743"});return}f.lastInputTime=Date.now(),f.write(o)}})),T.on("take-control",(({sessionId:o}={})=>{const i=o?manager.get(o):f;if(i){if(!hasPermission(T.data.role,"operator")){T.emit("control-denied",{reason:"\u4F60\u7684\u89D2\u8272\u6CA1\u6709\u63A7\u5236\u6743\u9650"});return}if(i.controlHolder&&i.controlHolder!==T.id){const n=i.controlHolderName===T.data.userName;if(T.data.role!=="admin"&&!n){T.emit("control-denied",{reason:"\u5176\u4ED6\u7528\u6237\u6B63\u5728\u63A7\u5236\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u91CA\u653E"});return}}i.takeControl(T.id,T.data.userName),console.log(`[\u63A7\u5236] ${T.data.userName} \u83B7\u53D6\u4F1A\u8BDD "${i.title}" \u7684\u63A7\u5236\u6743`),io.emit("control-changed",{sessionId:i.id,holder:T.id,holderName:T.data.userName})}})),T.on("release-control",(({sessionId:o}={})=>{const i=o?manager.get(o):f;!i||!i.isController(T.id)||(console.log(`[\u63A7\u5236] ${T.data.userName} \u91CA\u653E\u4F1A\u8BDD "${i.title}" \u7684\u63A7\u5236\u6743`),i.releaseControl(),io.emit("control-changed",{sessionId:i.id,holder:null,holderName:null}))})),T.on("set-mode",(({sessionId:o,mode:i}={})=>{const n=o?manager.get(o):f;if(n){if(n.mode==="agent"&&n.setPermissionMode){n.setPermissionMode(i);const e=n.permissionMode;e!==i&&console.log(`[\u6A21\u5F0F] set-mode \u6536\u5230\u65E0\u6548\u6A21\u5F0F "${i}"\uFF0C\u5DF2\u5F52\u4E00\u5316\u4E3A ${e}`),console.log(`[\u6A21\u5F0F] ${T.data.userName} \u5207\u6362\u4F1A\u8BDD "${n.title}" \u4E3A ${e}`),io.emit("mode-changed",{sessionId:n.id,mode:e})}else n.permissionMode=i,io.emit("mode-changed",{sessionId:n.id,mode:i});manager.persist()}})),T.on("rename",(({sessionId:o,title:i}={})=>{const n=o?manager.get(o):f;!n||!i||(n.title=i,io.emit("session-renamed",{sessionId:n.id,title:i}),broadcastSessions(),manager.persist())})),T.on("resize",(({cols:o,rows:i})=>f?.resize(o,i))),T.on("list",(()=>T.emit("sessions",manager.list(T.data.userName,T.data.role==="admin")))),T.on("dirs",((o,i)=>{if(typeof i!="function")return;const n=T.data.dir?(0,external_path_.resolve)((0,external_path_.normalize)(T.data.dir)):null,e=process.platform==="win32"?"\\":"/";let r=(o||n||process.env.MYHI_CWD||(0,external_os_.homedir)()).replace(/[/\\]+$/,"")||(0,external_os_.homedir)();process.platform==="win32"&&/^[A-Za-z]:$/.test(r)&&(r+="\\");const u=(0,external_path_.resolve)((0,external_path_.normalize)(r));n&&u!==n&&!u.startsWith(n+e)&&(r=n);try{const p=(0,external_fs_.readdirSync)(r,{withFileTypes:!0}).filter((g=>g.isDirectory()&&g.name!==".git")).map((g=>({name:g.name,path:r.replace(/[/\\]+$/,"")+e+g.name}))).sort(((g,b)=>g.name.localeCompare(b.name))),a=(0,external_path_.join)(r,".."),v=(0,external_path_.resolve)((0,external_path_.normalize)(a)),h=!n||v===n||v.startsWith(n+e);i({ok:!0,current:r,parent:h&&a!==r?a:null,dirs:p})}catch(p){i({ok:!1,error:p.message})}})),T.on("create",((o,i)=>{if(!hasPermission(T.data.role,"operator")){typeof i=="function"&&i({ok:!1,error:"\u6CA1\u6709\u521B\u5EFA\u4F1A\u8BDD\u7684\u6743\u9650"});return}if(T.data.dir){const e=(0,external_path_.resolve)((0,external_path_.normalize)(T.data.dir)),r=o?.cwd?(0,external_path_.resolve)((0,external_path_.normalize)(o.cwd)):null;if(r&&r!==e&&!r.startsWith(e+external_path_.sep)){typeof i=="function"&&i({ok:!1,error:"\u4E0D\u80FD\u5728\u7ED1\u5B9A\u76EE\u5F55\u4E4B\u5916\u521B\u5EFA\u4F1A\u8BDD"});return}r||(o={...o,cwd:e})}const n=o?.cwd||process.env.MYHI_CWD||process.cwd();if(!(0,external_fs_.existsSync)(n))try{(0,external_fs_.mkdirSync)(n,{recursive:!0}),console.log(`[\u521B\u5EFA] \u81EA\u52A8\u521B\u5EFA\u76EE\u5F55: ${n}`)}catch(e){typeof i=="function"&&i({ok:!1,error:`\u521B\u5EFA\u76EE\u5F55\u5931\u8D25: ${e.message}`});return}try{const e=manager.create({...o,owner:T.data.userName,userDir:T.data.dir});console.log(`[\u4F1A\u8BDD] ${T.data.userName} \u521B\u5EFA PTY \u4F1A\u8BDD "${e.title}" (${e.id})`),broadcastSessions(),typeof i=="function"&&i({ok:!0,session:e.toJSON()})}catch(e){console.error("[\u521B\u5EFA] PTY \u542F\u52A8\u5931\u8D25:",e.message),typeof i=="function"&&i({ok:!1,error:e.message})}})),T.on("kill",(o=>{if(!hasPermission(T.data.role,"operator")){T.emit("error",{message:"\u6CA1\u6709\u5220\u9664\u4F1A\u8BDD\u7684\u6743\u9650"});return}console.log(`[\u4F1A\u8BDD] ${T.data.userName} \u5220\u9664\u4F1A\u8BDD ${o}`),manager.kill(o),_autoSpawned.delete(o),broadcastSessions()})),T.on("kick-user",(({socketId:o,sessionId:i}={},n)=>{if(!hasPermission(T.data.role,"admin")){typeof n=="function"&&n({ok:!1,error:"\u6CA1\u6709\u8E22\u51FA\u7528\u6237\u7684\u6743\u9650"});return}const e=io.sockets.sockets.get(o);if(!e){typeof n=="function"&&n({ok:!1,error:"\u76EE\u6807\u7528\u6237\u4E0D\u5728\u7EBF"});return}const r=e.data.userName||"\u672A\u77E5";console.log(`[\u8E22\u51FA] ${T.data.userName} \u8E22\u51FA\u4E86\u7528\u6237 ${r} (${o})`),e.emit("kicked",{reason:`\u4F60\u5DF2\u88AB\u7BA1\u7406\u5458 ${T.data.userName} \u8E22\u51FA`}),e.disconnect(!0),typeof n=="function"&&n({ok:!0,name:r})})),T.on("list-viewers",(({sessionId:o}={},i)=>{if(typeof i!="function")return;const n=o?manager.get(o):f;if(!n){i({ok:!1,error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});return}const e=[];for(const r of n._viewers){const u=io.sockets.sockets.get(r);u&&e.push({socketId:r,userName:u.data.userName||"\u672A\u77E5",role:u.data.role||"viewer",isController:n.controlHolder===r})}i({ok:!0,viewers:e})}))}));const CONTROL_TIMEOUT=(Number(process.env.MYHI_CONTROL_TIMEOUT)||300)*1e3,CONTROL_SWEEP=Math.min(60*1e3,CONTROL_TIMEOUT);function shouldReleaseIdle(T){if(!T.controlHolder)return!1;if(!io.sockets.sockets.get(T.controlHolder))return!0;if(!T.lastInputTime||Date.now()-T.lastInputTime<=CONTROL_TIMEOUT||T.isBusy)return!1;for(const _ of T._viewers||[])if(_!==T.controlHolder&&io.sockets.sockets.has(_))return!0;return!1}setInterval((()=>{for(const T of manager.listSessions()){shouldReleaseIdle(T)&&(T.releaseControl(),io.emit("control-changed",{sessionId:T.id,holder:null,holderName:null}));for(const _ of T._viewers)io.sockets.sockets.has(_)||T.removeViewer(_)}}),CONTROL_SWEEP);function showStartupInfo(){PORT=(httpsServer||httpServer).address()?.port||PORT;const _=getTailscaleIP(),s=`${httpsServer?"https":"http"}://${_}:${PORT}`;console.log(`
|
|
420
420
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`),console.log(" myhi \u2014 \u57FA\u4E8E Tailscale \u7684 Web \u7EC8\u7AEF"),console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"),console.log(`
|
|
421
421
|
\u5730\u5740: ${s}`),httpsServer&&console.log(` HTTP\u91CD\u5B9A\u5411: http://${_}:${PORT+1} \u2192 HTTPS`),console.log(` \u5BC6\u7801: ${PASSWORD} (\u7F16\u8F91 ~/.myhi/password \u53EF\u4FEE\u6539)`),console.log(`
|
|
422
422
|
\u626B\u63CF\u4E8C\u7EF4\u7801\u5728\u624B\u673A\u4E0A\u6253\u5F00:
|