@wendongfly/myhi 1.3.182 → 1.3.184
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/myhi.js +873 -873
- package/dist/chat.html +81 -14
- package/dist/index.html +19 -0
- package/dist/index.js +4 -4
- package/dist/index.min.js +2 -2
- package/package.json +1 -1
package/dist/index.min.js
CHANGED
|
@@ -373,7 +373,7 @@ Content-Length: `+C+`\r
|
|
|
373
373
|
`,{mode:384})}catch{}}function loadAudit(E,p=500){if(!E)return[];try{return(0,external_fs_.readFileSync)(auditPath(E),"utf8").trim().split(`
|
|
374
374
|
`).filter(Boolean).slice(-p).map((r=>{try{return JSON.parse(r)}catch{return null}})).filter(Boolean)}catch{return[]}}function buildPseudonymizer(E,p){const l=getProjectGuard(E),r=p&&p.byVal?p:newMap();if(!l.enabled)return{enabled:!1,level:l.level,map:r,size:Object.keys(r.byVal).length,pseudonymize:i=>({text:i,count:0}),restore:i=>i};const e=LEVELS[l.level]||LEVELS[DEFAULT_LEVEL],s={};for(const[i,a]of Object.entries(r.byVal))s[a.ph]=i;function u(i,a){if(r.byVal[i])return r.byVal[i].ph;r.counters[a]=(r.counters[a]||0)+1;const t=`\u3010${a}_${r.counters[a]}\u3011`;return r.byVal[i]={ph:t,type:a},s[t]=i,t}function h(i){if(typeof i!="string"||!i||i.length>2e5)return{text:i,count:0};const a=[];e.pii&&a.push(...PII);const t=e.dict?l.entities:[];e.amount&&a.push(...AMOUNT);for(const v of a){const m=i.match(v.re);if(m)for(const b of m)r.byVal[b]||u(b,v.type)}for(const v of t)v.name&&i.includes(v.name)&&!r.byVal[v.name]&&u(v.name,v.type||"\u4E3B\u4F53");const n=Object.keys(r.byVal).filter((v=>i.includes(v)));n.sort(((v,m)=>m.length-v.length));let f=i,d=0;const c={};for(const v of n)if(f.includes(v)){const m=r.byVal[v].type;f=f.split(v).join(r.byVal[v].ph),d++,c[m]=(c[m]||0)+1}return{text:f,count:d,byType:c}}function o(i){return typeof i!="string"||!i||i.indexOf("\u3010")<0?i:i.replace(PLACEHOLDER_RE,(a=>s[a]!==void 0?s[a]:a))}return{enabled:!0,level:l.level,map:r,size:Object.keys(r.byVal).length,pseudonymize:h,restore:o}}const CONFIG_DIR=(0,external_path_.join)((0,external_os_.homedir)(),".myhi"),INBOX_FILE=(0,external_path_.join)(CONFIG_DIR,"inbox.json"),MAX_DRAFTS=500,MAX_TEXT=2e4;function loadDrafts(){try{const E=JSON.parse((0,external_fs_.readFileSync)(INBOX_FILE,"utf8"));return Array.isArray(E)?E:[]}catch{return[]}}function saveDrafts(E){try{(0,external_fs_.mkdirSync)(CONFIG_DIR,{recursive:!0});const p=INBOX_FILE+".tmp";return(0,external_fs_.writeFileSync)(p,JSON.stringify(E,null,2),{mode:384}),(0,external_fs_.renameSync)(p,INBOX_FILE),!0}catch(p){return console.error("[inbox] \u5199\u5165\u5931\u8D25:",p.message),!1}}function projectNameOf(E){if(!E)return"";const p=String(E).replace(/\\/g,"/").split("/").filter(Boolean);return p[p.length-1]||""}function normAttach(E){return Array.isArray(E)?E.filter((p=>p&&typeof p.path=="string"&&p.path)).slice(0,10).map((p=>({path:p.path,name:p.name||p.path.split("/").pop()}))):[]}function listDrafts({sessionId:E,owner:p,includeAll:l=!0}={}){let r=loadDrafts();return E&&(r=r.filter((e=>e.sessionId===E))),p&&!l&&(r=r.filter((e=>!e.owner||e.owner===p))),r.sort(((e,s)=>(s.createdAt||0)-(e.createdAt||0)))}function countBySession(){const E={};for(const p of loadDrafts())p.sessionId&&(E[p.sessionId]=(E[p.sessionId]||0)+1);return E}function addDraft(E={},p=null){const l=String(E.text||"").slice(0,MAX_TEXT),r=normAttach(E.images),e=normAttach(E.files);if(!l.trim()&&!r.length&&!e.length)throw new Error("\u8349\u7A3F\u5185\u5BB9\u4E3A\u7A7A");if(!E.sessionId)throw new Error("\u8349\u7A3F\u5FC5\u987B\u5F52\u5C5E\u4E00\u4E2A\u4F1A\u8BDD");const s=typeof E.clientKey=="string"&&E.clientKey?E.clientKey.slice(0,64):null;if(s){const i=loadDrafts().find((a=>a.clientKey===s));if(i)return i}const u=p?.cwd||E.cwd||"",h={id:(0,external_crypto_.randomUUID)(),clientKey:s,text:l,images:r,files:e,sessionId:E.sessionId,claudeSessionId:p?.claudeSessionId||E.claudeSessionId||null,sessionTitle:p?.title||E.sessionTitle||"(\u672A\u77E5\u4EFB\u52A1)",cwd:u,projectName:projectNameOf(u),owner:E.owner||p?.owner||null,autoSend:!!E.autoSend,source:E.source||"manual",createdAt:Date.now(),updatedAt:Date.now()},o=loadDrafts();for(o.push(h);o.length>MAX_DRAFTS;)o.shift();return saveDrafts(o),h}function updateDraft(E,p={},l=null){const r=loadDrafts(),e=r.findIndex((u=>u.id===E));if(e<0)return null;const s=r[e];return typeof p.text=="string"&&(s.text=p.text.slice(0,MAX_TEXT)),typeof p.autoSend=="boolean"&&(s.autoSend=p.autoSend),p.images&&(s.images=normAttach(p.images)),p.files&&(s.files=normAttach(p.files)),p.sessionId&&p.sessionId!==s.sessionId&&(s.sessionId=p.sessionId,s.claudeSessionId=l?.claudeSessionId||null,s.sessionTitle=l?.title||p.sessionTitle||s.sessionTitle,s.cwd=l?.cwd||p.cwd||s.cwd,s.projectName=projectNameOf(s.cwd)),s.updatedAt=Date.now(),r[e]=s,saveDrafts(r),s}function removeDraft(E){const p=loadDrafts(),l=p.filter((r=>r.id!==E));return l.length===p.length?!1:(saveDrafts(l),!0)}function rebindDrafts(E=[]){const p=new Map;for(const s of E)s.claudeSessionId&&p.set(s.claudeSessionId,s);const l=new Set(E.map((s=>s.id))),r=loadDrafts();let e=0;for(const s of r){if(l.has(s.sessionId)||!s.claudeSessionId)continue;const u=p.get(s.claudeSessionId);!u||u.id===s.sessionId||(s.sessionId=u.id,s.sessionTitle=u.title||s.sessionTitle,s.cwd=u.cwd||s.cwd,s.projectName=projectNameOf(s.cwd),e++)}return e&&saveDrafts(r),e}function syncSessionTitle(E,p){const l=loadDrafts();let r=!1;for(const e of l)e.sessionId===E&&e.sessionTitle!==p&&(e.sessionTitle=p,r=!0);r&&saveDrafts(l)}function buildDraftPrompt(E){const p=(E.text||"").trim(),l=E.images?.[0],r=E.files?.[0];return l?`\u7528\u6237\u4E0A\u4F20\u4E86\u4E00\u5F20\u56FE\u7247\uFF0C\u8DEF\u5F84\u662F ${l.path}\uFF0C\u8BF7\u7528 Read \u5DE5\u5177\u8BFB\u53D6\u8FD9\u5F20\u56FE\u7247\u3002\u7528\u6237\u7684\u8981\u6C42\u662F\uFF1A${p||"\u63CF\u8FF0\u56FE\u7247\u5185\u5BB9"}`:r?`\u7528\u6237\u4E0A\u4F20\u4E86\u4E00\u4E2A\u4E34\u65F6\u6587\u4EF6\u7528\u4E8E\u672C\u6B21\u5206\u6790\uFF08\u4E0D\u5728\u9879\u76EE\u6587\u4EF6\u6811\u91CC\uFF09\uFF0C\u8DEF\u5F84\u662F ${r.path}\uFF08\u539F\u6587\u4EF6\u540D ${r.name}\uFF09\uFF0C\u8BF7\u7528\u5408\u9002\u7684\u5DE5\u5177\uFF08\u5982 Read\uFF09\u8BFB\u53D6\u5E76\u5206\u6790\u5B83\u3002\u7528\u6237\u7684\u8981\u6C42\u662F\uFF1A${p||"\u5206\u6790\u8FD9\u4E2A\u6587\u4EF6"}`:p}function nextAutoSendDraft(E){return E&&loadDrafts().filter((l=>l.sessionId===E&&l.autoSend)).sort(((l,r)=>(l.createdAt||0)-(r.createdAt||0)))[0]||null}function draftDisplayText(E){const p=(E.text||"").trim(),l=E.images?.[0],r=E.files?.[0];return l?`\u{1F4F7} ${p||"\u5206\u6790\u56FE\u7247"}`:r?`\u{1F4CE} ${r.name}${p?" "+p:""}`:p}let _launcher=null;function resolveWinLauncherFromCmd(E){try{const p=(0,external_fs_.readFileSync)(E,"utf8"),l=(0,external_path_.dirname)(E),r=s=>s.trim().replace(/%~?dp0%?/gi,l+"\\").replace(/\\{2,}/g,"\\");let e=p.match(/"?([^"\r\n]*claude\.exe)"?/i);if(e){const s=r(e[1]);if((0,external_fs_.existsSync)(s))return{command:s,preArgs:[]}}if(e=p.match(/"?([^"\r\n]*\.js)"?\s+%\*/i),e){const s=r(e[1]);if((0,external_fs_.existsSync)(s))return{command:process.execPath,preArgs:[s]}}}catch{}return null}function winLauncherFromPath(E){if(/\.exe$/i.test(E))return{command:E,preArgs:[]};if(/\.cmd$/i.test(E)){const p=resolveWinLauncherFromCmd(E);return p||{command:process.env.ComSpec||"cmd.exe",preArgs:["/c",E]}}return{command:E,preArgs:[]}}function findClaude(){if(_launcher)return _launcher;const E=process.platform==="win32"?[(0,external_path_.join)((0,external_os_.homedir)(),".claude","local","node_modules","@anthropic-ai","claude-code","bin","claude.exe"),(0,external_path_.join)((0,external_os_.homedir)(),"AppData","Roaming","npm","node_modules","@anthropic-ai","claude-code","bin","claude.exe"),(0,external_path_.join)((0,external_os_.homedir)(),".claude","local","claude.cmd"),(0,external_path_.join)((0,external_os_.homedir)(),"AppData","Roaming","npm","claude.cmd")]:["/usr/bin/claude","/usr/local/bin/claude",(0,external_path_.join)((0,external_os_.homedir)(),".claude","local","claude"),(0,external_path_.join)((0,external_os_.homedir)(),".npm-global","bin","claude"),(0,external_path_.join)((0,external_os_.homedir)(),".local","bin","claude")],p=r=>process.platform==="win32"?winLauncherFromPath(r):{command:r,preArgs:[]},l=r=>console.log(`[agent] ${r} claude:`,_launcher.command,..._launcher.preArgs.length?[_launcher.preArgs[_launcher.preArgs.length-1]]:[]);for(const r of E)if((0,external_fs_.existsSync)(r))return _launcher=p(r),l("\u627E\u5230"),_launcher;try{const r=process.platform==="win32"?"where claude.cmd":"which claude",e=(0,external_child_process_namespaceObject.execSync)(r,{timeout:5e3,stdio:"pipe"}).toString().trim().split(`
|
|
375
375
|
`)[0].trim();if(e)return _launcher=p(e),l("which \u627E\u5230"),_launcher}catch{}return console.warn("[agent] \u672A\u627E\u5230 claude \u53EF\u6267\u884C\u6587\u4EF6\uFF0C\u56DE\u9000\u5230 PATH \u67E5\u627E"),_launcher=process.platform==="win32"?{command:process.env.ComSpec||"cmd.exe",preArgs:["/c","claude"]}:{command:"claude",preArgs:[]},_launcher}function resetClaudeLauncher(){_launcher=null}function getClaudeVersion(){return new Promise((E=>{let p;try{p=findClaude()}catch{return E(null)}let l="",r=!1;const e=h=>{r||(r=!0,E(h))};let s;try{s=(0,external_child_process_namespaceObject.spawn)(p.command,[...p.preArgs,"--version"],{stdio:["ignore","pipe","pipe"]})}catch{return e(null)}const u=setTimeout((()=>{try{s.kill()}catch{}e(null)}),1e4);s.stdout.on("data",(h=>{l+=h.toString()})),s.on("error",(()=>{clearTimeout(u),e(null)})),s.on("close",(()=>{clearTimeout(u);const h=l.match(/(\d+\.\d+\.\d+)/);e(h?{version:h[1],raw:l.trim()}:null)}))}))}const BASE64_STRIP_THRESHOLD=5*1024;function stripHeavyPayload(E){if(E==null||typeof E!="object")return E;if(Array.isArray(E))return E.map(stripHeavyPayload);const p={};for(const[l,r]of Object.entries(E))typeof r=="string"&&r.length>BASE64_STRIP_THRESHOLD&&(l==="data"||l==="url"&&r.startsWith("data:"))?p[l]=`[STRIPPED_BASE64_${r.length}_CHARS]`:p[l]=stripHeavyPayload(r);return p}const LOOP_POISON_PHRASES=["could not be processed and was removed","image exceeds","image dimensions exceed"],LOOP_MAX_POISON_HITS=2,POISON_MAX_NOTICE_LEN=4e3,LOOP_MAX_IDENTICAL_CALLS=3,LOOP_MAX_TURN_TOOLCALLS=120,LOOP_MAX_AUTO_RECOVER=2,IMAGE_NUDGE_STEP=15,STALL_WATCHDOG_MS=Number(process.env.MYHI_STALL_WATCHDOG_MS)||240*1e3,STALL_CHECK_INTERVAL_MS=30*1e3,RELAY_DELAY_MS=Number(process.env.MYHI_RELAY_DELAY_MS)||3e3,FOLLOW_UP_DEFAULT_MS=900*1e3,FOLLOW_UP_MAX=5,FOLLOW_UP_PROMPT="\u3010\u81EA\u52A8\u8DDF\u8FDB\xB7\u7CFB\u7EDF\u89E6\u53D1\u3011\u8BF7\u68C0\u67E5\u5F53\u524D\u6B63\u5728\u8FDB\u884C\u7684\u540E\u53F0\u4EFB\u52A1\u6216\u4E0A\u4E00\u6B65\u64CD\u4F5C\u7684\u8FDB\u5EA6\uFF1A\u6709\u65B0\u8FDB\u5C55\u5C31\u7B80\u8981\u6C47\u62A5\uFF1B\u4ECD\u5728\u8FDB\u884C\u5C31\u8BF4\u660E\u8FD8\u5728\u8DD1\u3001\u9884\u8BA1\u8FD8\u9700\u591A\u4E45\uFF1B\u82E5\u5DF2\u3010\u5168\u90E8\u5B8C\u6210\u3011\uFF0C\u8BF7\u6C47\u603B\u6700\u7EC8\u7ED3\u679C\uFF0C\u5E76\u5728\u56DE\u590D\u6700\u540E\u5355\u72EC\u4E00\u884C\u53EA\u5199 [\u8DDF\u8FDB\u5B8C\u6210]\uFF08\u7CFB\u7EDF\u636E\u6B64\u505C\u6B62\u81EA\u52A8\u8DDF\u8FDB\uFF09\u3002\u4E0D\u8981\u91CD\u590D\u5DF2\u6C47\u62A5\u8FC7\u7684\u5185\u5BB9\u3002",MYHI_SYSTEM_PROMPT=["\u56FE\u7247\u4E0E\u622A\u56FE\u5904\u7406\u7EA6\u675F\uFF08\u91CD\u8981\uFF0C\u7528\u4E8E\u907F\u514D API \u56FE\u7247\u9519\u8BEF\u4E0E\u6B7B\u5FAA\u73AF\uFF09\uFF1A","1. \u622A\u56FE\u4F18\u5148\u53EA\u622A\u5F53\u524D\u89C6\u53E3\uFF0C\u4E0D\u8981\u6574\u9875\u957F\u622A\u56FE\uFF1B\u56FE\u7247\u957F\u8FB9\u5C3D\u91CF \u22641568px\u3001\u9AD8\u5EA6\u4E0D\u8981\u8D85\u8FC7 8000px\uFF0C\u5426\u5219\u4F1A\u88AB API \u62D2\u7EDD\u3002",'2. \u82E5\u51FA\u73B0 "an image ... could not be processed and was removed" \u6216\u56FE\u7247\u88AB\u79FB\u9664\u7684\u9519\u8BEF\uFF0C\u8BF4\u660E\u8BE5\u56FE\u7247\u5DF2\u4E0D\u53EF\u7528\uFF0C'," \u4E0D\u8981\u7528 Read \u53CD\u590D\u91CD\u65B0\u8BFB\u53D6\u5B83\uFF1B\u8BF7\u57FA\u4E8E\u5DF2\u6709\u6587\u5B57\u4FE1\u606F\u7EE7\u7EED\uFF0C\u5FC5\u8981\u65F6\u8BF7\u7528\u6237\u91CD\u65B0\u4E0A\u4F20\u4E00\u5F20\u66F4\u5C0F\u7684\u622A\u56FE\u3002","3. \u540C\u4E00\u4E2A\u5DE5\u5177\u7528\u5B8C\u5168\u76F8\u540C\u7684\u53C2\u6570\u8FDE\u7EED\u5931\u8D25\u65F6\uFF0C\u4E0D\u8981\u539F\u6837\u91CD\u8BD5\uFF0C\u6362\u65B9\u6CD5\u6216\u8DF3\u8FC7\u3002","",'\u6267\u884C\u6A21\u5F0F\u7EA6\u675F\uFF08\u91CD\u8981\uFF09\uFF1A\u672C\u4F1A\u8BDD\u662F\u65E0\u4EBA\u503C\u5B88\u81EA\u52A8\u6267\u884C\u6A21\u5F0F\uFF0C\u6CA1\u6709"\u8BA1\u5212\u6A21\u5F0F"/"\u9000\u51FA\u8BA1\u5212"/\u5BA1\u6279\u5F39\u7A97/\u786E\u8BA4\u6309\u94AE/\u6587\u4EF6\u7F16\u8F91\u6388\u6743\u8FD9\u7C7B\u4EA4\u4E92\u3002','\u4F60\u60F3\u597D\u65B9\u6848\u5C31\u76F4\u63A5\u7528\u5DE5\u5177\u6267\u884C\uFF0C\u7EDD\u4E0D\u8981\u8BF4"\u7B49\u5F85\u6279\u51C6""\u8BF7\u70B9\u51FB\u786E\u8BA4\u6309\u94AE""\u6B63\u5728\u7B49\u5F85\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F""\u9700\u8981\u4F60\u6388\u6743"\u4E4B\u7C7B\u7684\u8BDD\u2014\u2014',"\u90A3\u4E9B UI \u5728\u8FD9\u91CC\u4E0D\u5B58\u5728\uFF0C\u8BF4\u4E86\u53EA\u4F1A\u8BA9\u4EFB\u52A1\u6C38\u4E45\u5361\u4F4F\u3002\u82E5\u67D0\u4E2A\u5DE5\u5177\u62A5\u6743\u9650/\u6388\u6743\u9519\u8BEF\uFF0C\u76F4\u63A5\u57FA\u4E8E\u73B0\u72B6\u7EE7\u7EED\u6216\u6362\u505A\u6CD5\uFF0C\u4E0D\u8981\u7A7A\u7B49\u7528\u6237\u70B9\u6309\u94AE\u3002","","\u6740\u8FDB\u7A0B\u7EA6\u675F\uFF08\u91CD\u8981\uFF0C\u4E8B\u5173\u672C\u4F1A\u8BDD\u5B58\u6D3B\uFF09\uFF1A\u6258\u7BA1\u4F60\u7684 myhi \u81EA\u5DF1\u5C31\u662F\u4E00\u4E2A node \u8FDB\u7A0B\uFF0C\u4F60\u662F\u5B83\u7684\u5B50\u8FDB\u7A0B\u3002","\u7EDD\u5BF9\u7981\u6B62\u6309\u300C\u8FDB\u7A0B\u540D\u300D\u6279\u91CF\u6740\u8FDB\u7A0B\uFF1Ataskkill /F /IM node.exe\u3001pkill node\u3001killall node\u3001Stop-Process -Name node \u5168\u90FD\u7981\u6B62\u2014\u2014","\u5B83\u4EEC\u4F1A\u628A myhi \u8FDE\u540C\u672C\u4F1A\u8BDD\u4E00\u8D77\u6740\u6B7B\uFF0C\u5DE5\u5177\u7ED3\u679C\u518D\u4E5F\u5199\u4E0D\u56DE\u6765\uFF0C\u8FD9\u6761\u547D\u4EE4\u4F1A\u6C38\u8FDC\u505C\u5728\u672A\u5B8C\u6210\u72B6\u6001\uFF0C","\u4E0B\u6B21 --resume \u53C8\u88AB\u91CD\u653E\u3001\u518D\u6740\u4E00\u6B21\uFF0C\u5F62\u6210\u65E0\u9650\u81EA\u6740\u5FAA\u73AF\uFF08\u771F\u5B9E\u53D1\u751F\u8FC7\uFF09\u3002","\u8981\u91CD\u542F\u67D0\u4E2A\u670D\u52A1\uFF0C\u5FC5\u987B\u7CBE\u786E\u5B9A\u4F4D\u90A3\u4E00\u4E2A\u8FDB\u7A0B\uFF1A\u5148\u6309\u5B83\u76D1\u542C\u7684\u7AEF\u53E3\u67E5 PID\uFF0C\u518D\u6309 PID \u6740\u3002","Windows: netstat -ano | findstr :<\u7AEF\u53E3> \u7136\u540E taskkill /F /PID <pid>\uFF1BLinux: lsof -ti:<\u7AEF\u53E3> | xargs -r kill\u3002","\u540C\u7406\uFF0C\u4E0D\u8981\u987A\u624B rm -rf \u6570\u636E\u76EE\u5F55/\u4E0A\u4F20\u76EE\u5F55\uFF0C\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u5220\u3002","","\u5B50\u4EE3\u7406\uFF08Task \u5DE5\u5177\uFF09\u4F7F\u7528\u5EFA\u8BAE\uFF1A\u9047\u5230\u300C\u5927\u8303\u56F4\u4EE3\u7801\u68C0\u7D22 / \u591A\u6587\u4EF6\u5BA1\u8BA1 / \u53EF\u5E76\u884C\u7684\u72EC\u7ACB\u5B50\u4EFB\u52A1 / \u9700\u8981\u6D77\u91CF\u8BFB\u53D6\u4F46\u53EA\u56DE\u7ED3\u8BBA\u300D\u8FD9\u7C7B\u91CD\u6D3B\uFF0C","\u4F18\u5148\u7528 Task \u5DE5\u5177\u8D77\u5B50\u4EE3\u7406\u53BB fan-out\u2014\u2014\u628A\u4E2D\u95F4\u8FC7\u7A0B\u9694\u79BB\u5728\u5B50\u4E0A\u4E0B\u6587\u91CC\u3001\u53EA\u628A\u7ED3\u8BBA\u6536\u56DE\u4E3B\u7EBF\uFF0C\u65E2\u7701\u4E3B\u4E0A\u4E0B\u6587\u53C8\u66F4\u5FEB\u3002","\u5B50\u4EE3\u7406\u5185\u90E8\u7684\u5DE5\u5177\u8C03\u7528\u4E0D\u4F1A\u6491\u7206\u4E3B\u7EBF\u7684\u5355\u8F6E\u5DE5\u5177\u9884\u7B97\uFF08\u5DF2\u8C41\u514D\uFF09\uFF0C\u653E\u5FC3\u7528\uFF1B\u4F46\u7B80\u5355\u7684\u5355\u6587\u4EF6\u5C0F\u6539\u52A8\u76F4\u63A5\u81EA\u5DF1\u505A\uFF0C\u4E0D\u5FC5\u8D77\u5B50\u4EE3\u7406\u3002"].join(`
|
|
376
|
-
`),VALID_PERMISSION_MODES=new Set(["bypassPermissions","plan","acceptEdits"]);function normalizePermissionMode(E){return E==="bypass"?"bypassPermissions":VALID_PERMISSION_MODES.has(E)?E:"bypassPermissions"}class AgentSession extends external_events_.EventEmitter{constructor(p,l={}){super(),this.id=p,this.createdAt=l.createdAt||new Date().toISOString(),this.title=l.title||"claude",this.cwd=l.cwd||process.env.MYHI_CWD||process.cwd(),this.tags=Array.isArray(l.tags)?l.tags:[],this.firstUserText=l.firstUserText||"",this.permissionMode=normalizePermissionMode(l.permissionMode),this.owner=l.owner||null,this.userDir=l.userDir||null,this.claudeSessionId=l.resumeSessionId||null,this.mode="agent",this.alive=!0,this._viewers=new Set,this._viewerNames=new Map,this.controlHolder=null,this.controlHolderName=null,this.lastInputTime=null,this._proc=null,this._busy=!1,this._interrupted=!1,this._buffer="",this._pendingResolve=null,this._pendingReject=null,this._keepAliveTimer=null,this._history=[],this._loopSigCounts=new Map,this._loopPoisonHits=0,this._loopTurnToolCalls=0,this._loopTripped=!1,this._loopAutoRecover=0,this._pendingSteer=null,this._followEnabled=!1,this._followIntervalMs=FOLLOW_UP_DEFAULT_MS,this._followMax=FOLLOW_UP_MAX,this._followCount=0,this._followTimer=null,this._relayTimer=null,this._followStopSignal=!1,this._imageBlockCount=0,this._imageNudgeAt=IMAGE_NUDGE_STEP,this._redactor=null,this._pseudo=null,this._pseudoMap=null,this._lastActivityAt=l.lastActivityAt||0,this._awaitingTool=!1,this._watchdogTimer=null,this._usage={totalCostUSD:0,totalInputTokens:0,totalOutputTokens:0,totalCacheReadTokens:0,totalCacheCreationTokens:0,queryCount:0,rateLimitInfo:null,modelUsage:{},...l.usage||{},modelUsage:{...l.usage?.modelUsage||{}}},this._usageBase=JSON.parse(JSON.stringify(this._usage)),this._procQueryCount=0,this._contextTokens=0,this.claudeSessionId&&this._loadResumedHistory()}_buildEnv(){const p={...process.env};if(delete p.CLAUDECODE,delete p.CLAUDE_CODE_ENTRYPOINT,delete p.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC,this.userDir){const l=(0,external_path_.join)(this.userDir,".gitconfig");(0,external_fs_.existsSync)(l)&&(p.GIT_CONFIG_GLOBAL=l)}try{const l=(0,external_path_.join)((0,external_os_.homedir)(),".myhi","gateway.json");if((0,external_fs_.existsSync)(l)){const r=JSON.parse((0,external_fs_.readFileSync)(l,"utf8"));r.baseUrl&&(p.ANTHROPIC_BASE_URL=r.baseUrl),r.apiKey&&(p.ANTHROPIC_API_KEY=r.apiKey)}}catch{}try{applySecretsToEnv(p,this.cwd)}catch{}return p}_buildArgs(){const p=["--output-format","stream-json","--input-format","stream-json","--verbose"];p.push("--append-system-prompt",MYHI_SYSTEM_PROMPT.replace(/\s*\n\s*/g," ").trim());const l=normalizePermissionMode(this.permissionMode);if(l==="bypassPermissions")p.push("--dangerously-skip-permissions");else if(l==="plan")p.push("--permission-mode","plan"),p.push("--allowedTools","WebSearch"),p.push("--allowedTools","WebFetch");else if(l==="acceptEdits"){p.push("--permission-mode","acceptEdits");const r=["Bash(git *)","Bash(npm *)","Bash(npx *)","Bash(node *)","Bash(ls *)","Bash(cat *)","Bash(mkdir *)","Bash(cp *)","Bash(mv *)","Bash(rm *)","Bash(cd *)","Bash(pwd)","Bash(find *)","Bash(grep *)","Bash(curl *)","Bash(wget *)","Bash(pip *)","Bash(python *)","Bash(python3 *)","Bash(chmod *)","Bash(chown *)","Bash(tar *)","Bash(unzip *)","Bash(zip *)","Bash(sed *)","Bash(awk *)","Bash(head *)","Bash(tail *)","Bash(wc *)","Bash(sort *)","Bash(echo *)","Bash(which *)","Bash(apt *)","Bash(apt-get *)","Bash(docker *)","Bash(ssh *)","Bash(scp *)","Bash(rsync *)","Bash(touch *)","Bash(diff *)","Bash(env *)","Bash(export *)","Bash(source *)","Bash(tee *)","Bash(xargs *)","Bash(du *)","Bash(df *)","Bash(ps *)","Bash(kill *)","Bash(systemctl *)","Bash(journalctl *)","Bash(sudo *)","Task","WebSearch","WebFetch"];for(const e of r)p.push("--allowedTools",e)}return this.modelId&&p.push("--model",this.modelId),this.claudeSessionId&&p.push("--resume",this.claudeSessionId),p}_writeStdin(p){if(!this._proc||!this._proc.stdin?.writable)return!1;try{return this._proc.stdin.write(JSON.stringify(p)+`
|
|
376
|
+
`),VALID_PERMISSION_MODES=new Set(["bypassPermissions","plan","acceptEdits"]);function normalizePermissionMode(E){return E==="bypass"?"bypassPermissions":VALID_PERMISSION_MODES.has(E)?E:"bypassPermissions"}class AgentSession extends external_events_.EventEmitter{constructor(p,l={}){super(),this.id=p,this.createdAt=l.createdAt||new Date().toISOString(),this.title=l.title||"claude",this.cwd=l.cwd||process.env.MYHI_CWD||process.cwd(),this.tags=Array.isArray(l.tags)?l.tags:[],this.firstUserText=l.firstUserText||"",this.permissionMode=normalizePermissionMode(l.permissionMode),this.owner=l.owner||null,this.userDir=l.userDir||null,this.claudeSessionId=l.resumeSessionId||null,this.mode="agent",this.alive=!0,this._viewers=new Set,this._viewerNames=new Map,this.controlHolder=null,this.controlHolderName=null,this.lastInputTime=null,this._proc=null,this._busy=!1,this._interrupted=!1,this._buffer="",this._pendingResolve=null,this._pendingReject=null,this._keepAliveTimer=null,this._history=[],this._loopSigCounts=new Map,this._loopPoisonHits=0,this._loopTurnToolCalls=0,this._loopTripped=!1,this._loopAutoRecover=0,this._pendingSteer=null,this._followEnabled=!1,this._followIntervalMs=FOLLOW_UP_DEFAULT_MS,this._followMax=FOLLOW_UP_MAX,this._followCount=0,this._followTimer=null,this._relayTimer=null,this._followStopSignal=!1,this._imageBlockCount=0,this._imageNudgeAt=IMAGE_NUDGE_STEP,this._redactor=null,this._pseudo=null,this._pseudoMap=null,this._lastActivityAt=l.lastActivityAt||0,this._awaitingTool=!1,this._watchdogTimer=null,this._usage={totalCostUSD:0,totalInputTokens:0,totalOutputTokens:0,totalCacheReadTokens:0,totalCacheCreationTokens:0,queryCount:0,rateLimitInfo:null,modelUsage:{},...l.usage||{},modelUsage:{...l.usage?.modelUsage||{}}},this._usageBase=JSON.parse(JSON.stringify(this._usage)),this._procQueryCount=0,this._contextTokens=0,this.claudeSessionId&&this._loadResumedHistory()}_buildEnv(){const p={...process.env};if(delete p.CLAUDECODE,delete p.CLAUDE_CODE_ENTRYPOINT,delete p.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC,this.userDir){const l=(0,external_path_.join)(this.userDir,".gitconfig");(0,external_fs_.existsSync)(l)&&(p.GIT_CONFIG_GLOBAL=l)}try{const l=(0,external_path_.join)((0,external_os_.homedir)(),".myhi","gateway.json");if((0,external_fs_.existsSync)(l)){const r=JSON.parse((0,external_fs_.readFileSync)(l,"utf8").replace(/^\uFEFF/,""));r.baseUrl&&(p.ANTHROPIC_BASE_URL=r.baseUrl),r.apiKey&&(p.ANTHROPIC_API_KEY=r.apiKey)}}catch{}try{applySecretsToEnv(p,this.cwd)}catch{}return p}_buildArgs(){const p=["--output-format","stream-json","--input-format","stream-json","--verbose"];p.push("--append-system-prompt",MYHI_SYSTEM_PROMPT.replace(/\s*\n\s*/g," ").trim());const l=normalizePermissionMode(this.permissionMode);if(l==="bypassPermissions")p.push("--dangerously-skip-permissions");else if(l==="plan")p.push("--permission-mode","plan"),p.push("--allowedTools","WebSearch"),p.push("--allowedTools","WebFetch");else if(l==="acceptEdits"){p.push("--permission-mode","acceptEdits");const r=["Bash(git *)","Bash(npm *)","Bash(npx *)","Bash(node *)","Bash(ls *)","Bash(cat *)","Bash(mkdir *)","Bash(cp *)","Bash(mv *)","Bash(rm *)","Bash(cd *)","Bash(pwd)","Bash(find *)","Bash(grep *)","Bash(curl *)","Bash(wget *)","Bash(pip *)","Bash(python *)","Bash(python3 *)","Bash(chmod *)","Bash(chown *)","Bash(tar *)","Bash(unzip *)","Bash(zip *)","Bash(sed *)","Bash(awk *)","Bash(head *)","Bash(tail *)","Bash(wc *)","Bash(sort *)","Bash(echo *)","Bash(which *)","Bash(apt *)","Bash(apt-get *)","Bash(docker *)","Bash(ssh *)","Bash(scp *)","Bash(rsync *)","Bash(touch *)","Bash(diff *)","Bash(env *)","Bash(export *)","Bash(source *)","Bash(tee *)","Bash(xargs *)","Bash(du *)","Bash(df *)","Bash(ps *)","Bash(kill *)","Bash(systemctl *)","Bash(journalctl *)","Bash(sudo *)","Task","WebSearch","WebFetch"];for(const e of r)p.push("--allowedTools",e)}return this.modelId&&p.push("--model",this.modelId),this.claudeSessionId&&p.push("--resume",this.claudeSessionId),p}_writeStdin(p){if(!this._proc||!this._proc.stdin?.writable)return!1;try{return this._proc.stdin.write(JSON.stringify(p)+`
|
|
377
377
|
`),!0}catch{return!1}}_spawnProcess(){this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null);const p=findClaude(),l=this._buildArgs(),r=this._buildEnv();this._usageBase=JSON.parse(JSON.stringify(this._usage)),this._procQueryCount=0;const e=p.command,s=[...p.preArgs,...l];console.log(`[agent] \u542F\u52A8\u6301\u4E45\u8FDB\u7A0B: ${e} ${p.preArgs.join(" ")} (\u4F1A\u8BDD: ${this.claudeSessionId||"\u65B0\u5EFA"})`),this._proc=(0,external_child_process_namespaceObject.spawn)(e,s,{cwd:this.cwd,env:r,stdio:["pipe","pipe","pipe"]}),this._buffer="",this._proc.stdout.on("data",(h=>{this._buffer+=h.toString();const o=this._buffer.split(`
|
|
378
378
|
`);this._buffer=o.pop()||"";for(const i of o){const a=i.replace(/\r$/,"");if(a)try{const t=JSON.parse(a);this._handleMessage(t)}catch{a.trim()&&(this.emit("agent:message",{type:"system",subtype:"info",message:a.trim()}),this._checkDeathLoop({type:"system",_raw:a}))}}}));const u=[/connectors are disabled because/i];this._proc.stderr.on("data",(h=>{const o=h.toString().trim();if(!o||o.includes("Warning:")||o.includes("DeprecationWarning"))return;const i=o.split(`
|
|
379
379
|
`).map((t=>t.trim())).filter(Boolean),a=i.filter((t=>!u.some((n=>n.test(t)))));i.length>a.length&&console.log(`[agent:stderr][benign] \u541E\u6389 ${i.length-a.length} \u6761\u826F\u6027\u63D0\u793A`),a.length&&(console.error("[agent:stderr]",a.join(`
|
|
@@ -388,7 +388,7 @@ Content-Length: `+C+`\r
|
|
|
388
388
|
`)),{type:"tool_result",id:r.tool_use_id||"",text:clipText(s),timestamp:p.timestamp}}const e=l.find((s=>s.type==="text"))?.text||"";return e?{type:"user",content:clipText(e),timestamp:p.timestamp}:null}return null}if(p.type==="assistant"&&p.message?.content){const l=stripHeavyPayload(p.message);if(Array.isArray(l.content))for(const r of l.content)r?.type==="thinking"&&typeof r.thinking=="string"&&(r.thinking=clipText(r.thinking,4e3)),r?.type==="tool_use"&&r.input&&(r.input=clipStrings(r.input));return{type:"assistant",message:l,timestamp:p.timestamp}}return p.type==="result"?{type:"result",total_cost_usd:p.costUSD||p.total_cost_usd,timestamp:p.timestamp}:null}function readTranscript(E,{offset:p=0,limit:l=0}={}){const r=findTranscriptPath(E);if(!r)return{ok:!1,messages:[],total:0,hasMore:!1};let e;try{e=(0,external_fs_.readFileSync)(r,"utf8").split(`
|
|
389
389
|
`).filter(Boolean)}catch{return{ok:!1,messages:[],total:0,hasMore:!1}}const s=[];for(const i of e){const a=parseTranscriptLine(i);a&&s.push(a)}const u=s.length,h=Math.max(0,u-Math.max(0,p)),o=Math.max(0,l>0?h-l:0);return{ok:!0,messages:s.slice(o,h),total:u,hasMore:o>0}}const execAsync=(0,external_util_.promisify)(external_child_process_namespaceObject.exec),server_dirname=(0,external_path_.dirname)((0,external_url_.fileURLToPath)(import.meta.url));let PORT=parseInt(process.env.PORT,10)||12300;const PORT_EXPLICIT=!!process.env.PORT,server_configDir=(0,external_path_.join)((0,external_os_.homedir)(),".myhi");(0,external_fs_.mkdirSync)(server_configDir,{recursive:!0});let httpsServer=null,httpServer=null;function getOrCreateCert(){const E=(0,external_path_.join)(server_configDir,"cert.pem"),p=(0,external_path_.join)(server_configDir,"key.pem");if((0,external_fs_.existsSync)(E)&&(0,external_fs_.existsSync)(p))try{return{cert:(0,external_fs_.readFileSync)(E),key:(0,external_fs_.readFileSync)(p)}}catch{}try{const l=selfsigned.generate([{name:"commonName",value:"myhi"}],{days:3650,keySize:2048});return(0,external_fs_.writeFileSync)(E,l.cert,"utf8"),(0,external_fs_.writeFileSync)(p,l.private,"utf8"),console.log("[myhi] \u81EA\u7B7E\u540D HTTPS \u8BC1\u4E66\u5DF2\u751F\u6210"),{cert:l.cert,key:l.private}}catch{}try{return(0,external_child_process_namespaceObject.execSync)(`openssl req -x509 -newkey rsa:2048 -keyout "${p}" -out "${E}" -days 3650 -nodes -subj "/CN=myhi"`,{stdio:"pipe",timeout:1e4}),{cert:(0,external_fs_.readFileSync)(E),key:(0,external_fs_.readFileSync)(p)}}catch(l){return console.warn(`[myhi] \u751F\u6210 HTTPS \u8BC1\u4E66\u5931\u8D25: ${l.message?.split(`
|
|
390
390
|
`)[0]||l}`),null}}const pidFile=(0,external_path_.join)(server_configDir,"server.pid"),daemonPidFile=(0,external_path_.join)(server_configDir,"daemon.pid"),IS_DAEMON_CHILD=!!process.env.MYHI_DAEMON;function killOldProcess(E,p){let l=!1;try{process.kill(E,0),l=!0}catch{}if(!l)return!0;console.log(`[myhi] \u68C0\u6D4B\u5230\u5DF2\u8FD0\u884C\u7684${p} (PID ${E})\uFF0C\u6B63\u5728\u505C\u6B62...`);try{process.platform==="win32"?(0,external_child_process_namespaceObject.execSync)(`taskkill /PID ${E} /F /T`,{stdio:"pipe",timeout:5e3}):process.kill(E,"SIGTERM")}catch{}const r=Date.now()+5e3;for(;Date.now()<r;){try{process.kill(E,0)}catch{return!0}const s=Date.now()+200;for(;Date.now()<s;);}let e=!1;try{process.kill(E,0),e=!0}catch{}return!e}(function E(){try{const p=parseInt((0,external_fs_.readFileSync)(daemonPidFile,"utf8").trim(),10);if(p&&p!==process.pid&&p!==parseInt(process.env.MYHI_DAEMON_PID||"0",10)){let l=!1;try{process.kill(p,0),l=!0}catch{}if(l&&!IS_DAEMON_CHILD){console.log("[myhi] \u68C0\u6D4B\u5230\u540E\u53F0 daemon \u5728\u8FD0\u884C\uFF0C\u5148\u505C\u6B62..."),killOldProcess(p,"daemon")||(console.error("[myhi] \u65E0\u6CD5\u505C\u6B62 daemon\uFF0C\u8BF7\u5148\u8FD0\u884C: myhi stop"),process.exit(1));try{(0,external_fs_.unlinkSync)(daemonPidFile)}catch{}}}}catch{}if(!IS_DAEMON_CHILD)try{const p=parseInt((0,external_fs_.readFileSync)(pidFile,"utf8").trim(),10);p&&p!==process.pid&&(killOldProcess(p,"\u5B9E\u4F8B")||(console.error(`[myhi] \u65E0\u6CD5\u505C\u6B62\u65E7\u8FDB\u7A0B (PID ${p})\uFF0C\u8BF7\u624B\u52A8\u6267\u884C\uFF1A`),console.error(" myhi stop"),console.error(` \u6216: ${process.platform==="win32"?`taskkill /PID ${p} /F`:`kill -9 ${p}`}`),process.exit(1)))}catch{}(0,external_fs_.writeFileSync)(pidFile,String(process.pid))})();function cleanupPid(){try{parseInt((0,external_fs_.readFileSync)(pidFile,"utf8").trim(),10)===process.pid&&(0,external_fs_.unlinkSync)(pidFile)}catch{}}function gracefulShutdown(){try{if(typeof manager<"u"){try{manager.persist()}catch{}for(const E of manager.listSessions())try{E.kill()}catch{}}}catch{}cleanupPid()}process.on("exit",cleanupPid),process.on("SIGTERM",(()=>{gracefulShutdown(),process.exit(0)})),process.on("SIGINT",(()=>{gracefulShutdown(),process.exit(0)}));const RECOVERABLE_ERRNO=new Set(["ECONNRESET","EPIPE","ECONNABORTED","ETIMEDOUT","ENOENT","EBUSY","EACCES","EPERM","EISDIR","ERR_STREAM_PREMATURE_CLOSE","ERR_STREAM_DESTROYED","ERR_HTTP_HEADERS_SENT"]);process.on("uncaughtException",(E=>{if(RECOVERABLE_ERRNO.has(E?.code)){console.error(`[myhi] \u5DF2\u5FFD\u7565\u53EF\u6062\u590D\u5F02\u5E38(${E.code}):`,E.message);return}console.error("[myhi] \u672A\u6355\u83B7\u5F02\u5E38:",E.message),gracefulShutdown(),process.exit(1)})),process.on("unhandledRejection",(E=>{console.error("[myhi] \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD:",E)}));function readOrCreate(E,p){try{if((0,external_fs_.existsSync)(E))return(0,external_fs_.readFileSync)(E,"utf8").trim()}catch{}const l=p();return(0,external_fs_.writeFileSync)(E,l,{mode:384}),l}const TOKEN=readOrCreate((0,external_path_.join)(server_configDir,"token"),(()=>(0,external_crypto_.randomBytes)(16).toString("hex")));let PASSWORD=readOrCreate((0,external_path_.join)(server_configDir,"password"),(()=>String(Math.floor(1e3+Math.random()*9e3))));loadRoles(),loadUsers();let activeUser=null;const userSessions=new Map;userSessions.set(TOKEN,{role:"admin",name:"\u7BA1\u7406\u5458",permanent:!0});const SESSION_MAX_AGE=10080*60*1e3;setInterval((()=>{const E=Date.now();for(const[p,l]of userSessions)l.permanent||(!l.lastUsed||E-l.lastUsed>SESSION_MAX_AGE)&&userSessions.delete(p)}),3600*1e3);function getTailscaleIP(){try{return(0,external_child_process_namespaceObject.execSync)("tailscale ip -4",{timeout:3e3,stdio:"pipe"}).toString().trim().split(`
|
|
391
|
-
`)[0]}catch{}try{if(process.platform==="win32"){const E=(0,external_child_process_namespaceObject.execSync)("route print 0.0.0.0",{timeout:3e3,stdio:"pipe"}).toString().match(/0\.0\.0\.0\s+0\.0\.0\.0\s+\S+\s+(\d+\.\d+\.\d+\.\d+)/);if(E)return E[1]}else try{const E=(0,external_child_process_namespaceObject.execSync)("ip route get 1.1.1.1",{timeout:3e3,stdio:"pipe"}).toString().match(/src\s+(\d+\.\d+\.\d+\.\d+)/);if(E)return E[1]}catch{const E=(0,external_child_process_namespaceObject.execSync)("route -n get default 2>/dev/null || route -n 2>/dev/null",{timeout:3e3,stdio:"pipe"}).toString(),p=E.match(/interface:\s*(\S+)/i)||E.match(/0\.0\.0\.0\s+(\d+\.\d+\.\d+\.\d+)/);if(p){const l=(0,external_os_.networkInterfaces)()[p[1]];if(l){const r=l.find((e=>e.family==="IPv4"&&!e.internal));if(r)return r.address}if(/^\d+\.\d+\.\d+\.\d+$/.test(p[1]))return p[1]}}}catch{}for(const E of Object.values((0,external_os_.networkInterfaces)()))for(const p of E)if(p.family==="IPv4"&&!p.internal)return p.address;return"localhost"}function parseCookies(E=""){const p={};for(const l of E.split(";")){const r=l.indexOf("=");r>0&&(p[l.slice(0,r).trim()]=l.slice(r+1).trim())}return p}const SESSION_COOKIE="myhi_sid",COOKIE_OPTS_BASE="HttpOnly; SameSite=Strict; Path=/; Max-Age=31536000";function cookieOpts(E){return E?.secure||E?.headers?.["x-forwarded-proto"]==="https"?COOKIE_OPTS_BASE+"; Secure":COOKIE_OPTS_BASE}function setSessionCookie(E,p,l){E.setHeader("Set-Cookie",`${SESSION_COOKIE}=${p||TOKEN}; ${cookieOpts(l)}`)}function getSessionToken(E){return parseCookies(E)[SESSION_COOKIE]||null}function hasValidSession(E){const p=getSessionToken(E);if(p&&userSessions.has(p)){const l=userSessions.get(p);return l&&(l.lastUsed=Date.now()),!0}return!1}function getUserInfo(E){const p=getSessionToken(E);return p?userSessions.get(p):null}const app=express();app.set("trust proxy",!0),app.use(((E,p,l)=>{p.setHeader("Referrer-Policy","no-referrer"),p.setHeader("X-Content-Type-Options","nosniff"),l()}));function _hostFromConfig(){try{const E=JSON.parse((0,external_fs_.readFileSync)((0,external_path_.join)(server_configDir,"config.json"),"utf8")).host;return typeof E=="string"&&E?E:null}catch{return null}}function _configString(E){try{const p=JSON.parse((0,external_fs_.readFileSync)((0,external_path_.join)(server_configDir,"config.json"),"utf8"))[E];return typeof p=="string"&&p?p:null}catch{return null}}const HOST=process.env.HOST||_hostFromConfig()||"0.0.0.0";function _httpOnlyFromConfig(){try{return!!JSON.parse((0,external_fs_.readFileSync)((0,external_path_.join)(server_configDir,"config.json"),"utf8")).httpOnly}catch{return!1}}const _tlsOpts=process.env.MYHI_NO_HTTPS||_httpOnlyFromConfig()?null:getOrCreateCert();_tlsOpts?(httpsServer=(0,external_https_.createServer)(_tlsOpts,app),httpServer=(0,external_http_.createServer)(((E,p)=>{const l=(E.headers.host||"").replace(/:\d+$/,"");p.writeHead(301,{Location:`https://${l}:${PORT}${E.url}`}),p.end()}))):(console.warn("[myhi] TLS \u4E0D\u53EF\u7528\uFF0C\u4EE5 HTTP \u6A21\u5F0F\u8FD0\u884C\uFF08\u9EA6\u514B\u98CE/\u6444\u50CF\u5934\u7B49\u6D4F\u89C8\u5668\u5B89\u5168\u529F\u80FD\u53D7\u9650\uFF09"),httpServer=(0,external_http_.createServer)(app));for(const E of[httpsServer,httpServer])E&&(E.keepAliveTimeout=72e3,E.headersTimeout=76e3);const _corsAllowed=/^https?:\/\/(localhost|127\.0\.0\.1|\[::1\]|10\.\d+\.\d+\.\d+|172\.(1[6-9]|2\d|3[01])\.\d+\.\d+|192\.168\.\d+\.\d+|100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\.\d+\.\d+)(:\d+)?$/,io=new Server({serveClient:!1,cors:{origin:(E,p)=>{if(!E||_corsAllowed.test(E))return p(null,!0);p(new Error("CORS \u4E0D\u5141\u8BB8\u6B64\u6765\u6E90"),!1)},credentials:!0},transports:["websocket","polling"],pingTimeout:6e4,pingInterval:25e3,upgradeTimeout:3e4,maxHttpBufferSize:5e6});httpsServer?io.attach(httpsServer):io.attach(httpServer);const manager=new SessionManager,AUTO_ATTACH=process.env.MYHI_AUTO_ATTACH!=="0",_autoSpawned=new Set;function spawnLocalTerminal(E,p){if(!AUTO_ATTACH||_autoSpawned.has(E)||!process.env.DISPLAY&&process.platform==="linux")return;_autoSpawned.add(E);const l=__nccwpck_require__.ab+"attach.js",r=process.execPath,e=p||"myhi";if(process.platform==="win32"){const s=`"${r}" "${l}" ${E}`,u=(0,external_child_process_namespaceObject.spawn)("wt.exe",["-w","0","new-tab","--title",e,"--","cmd","/k",s],{detached:!0,stdio:"ignore"});u.unref(),u.on("error",(h=>{console.warn("[attach] wt.exe \u5931\u8D25\uFF0C\u56DE\u9000\u5230 cmd:",h.message),(0,external_child_process_namespaceObject.spawn)("cmd.exe",["/c","start",`"${e}"`,"cmd","/k",s],{detached:!0,stdio:"ignore"}).unref()}))}else if(process.platform==="darwin"){const s=`tell application "Terminal" to do script "${r} ${l} ${E}"`;(0,external_child_process_namespaceObject.spawn)("osascript",["-e",s],{detached:!0,stdio:"ignore"}).unref()}else{const s=`${r} "${l}" ${E}`;for(const[u,h]of[["gnome-terminal",["--","bash","-c",`${s}; exec bash`]],["xterm",["-title",e,"-e",s]],["konsole",["--new-tab","-e",s]]]){const o=(0,external_child_process_namespaceObject.spawn)(u,h,{detached:!0,stdio:"ignore"});o.unref(),o.on("error",(()=>{}));break}}}const uploadDir=(0,external_path_.join)(server_configDir,"uploads");(0,external_fs_.mkdirSync)(uploadDir,{recursive:!0});function checkAuth(E,p,l){const r=E.query.token;if(r&&(r===TOKEN||userSessions.has(r))){const e=userSessions.get(r);if(e?.onetime){userSessions.delete(r);const h=(0,external_crypto_.randomBytes)(16).toString("hex");userSessions.set(h,{role:e.role,name:e.name,lastUsed:Date.now()}),setSessionCookie(p,h,E)}else setSessionCookie(p,r===TOKEN?TOKEN:r,E);const s=Object.keys(E.query).filter((h=>h!=="token")),u=E.path+(s.length?"?"+new URLSearchParams(Object.fromEntries(Object.entries(E.query).filter((([h])=>h!=="token")))):"");return p.redirect(u)}if(hasValidSession(E.headers.cookie)){if(isExclusiveMode()&&activeUser){const e=getSessionToken(E.headers.cookie);if(e!==TOKEN){const s=userSessions.get(e);if(!s||s.name!==activeUser.name)return p.setHeader("Set-Cookie",`${SESSION_COOKIE}=; HttpOnly; SameSite=Strict; Path=/; Max-Age=0`),p.redirect("/login")}}return l()}p.redirect("/login")}const _require=(0,external_module_namespaceObject.createRequire)(import.meta.url);function pkgDirSafe(E){try{return(0,external_path_.dirname)(_require.resolve(`${E}/package.json`))}catch{return null}}const libDir=(0,external_path_.join)(server_dirname,"lib"),staticOpts={maxAge:864e5};app.use("/lib/xterm",express.static(pkgDirSafe("xterm")||(0,external_path_.join)(libDir,"xterm"),staticOpts)),app.use("/lib/xterm-fit",express.static(pkgDirSafe("xterm-addon-fit")||(0,external_path_.join)(libDir,"xterm-fit"),staticOpts)),app.use("/lib/xterm-links",express.static(pkgDirSafe("xterm-addon-web-links")||(0,external_path_.join)(libDir,"xterm-links"),staticOpts)),app.use("/sio-client",express.static((0,external_path_.join)(server_dirname,"client-dist"),{maxAge:"1h",index:!1,setHeaders:(E,p)=>{p.endsWith(".js")&&E.setHeader("Content-Type","application/javascript; charset=utf-8")}})),app.get("/manifest.json",((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"manifest.json")))),app.get("/icon.png",((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"icon.png")))),app.get("/icon.svg",((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"icon.svg"))));const _loginAttempts=new Map,LOGIN_MAX_ATTEMPTS=5,LOGIN_LOCKOUT_MS=300*1e3;function checkLoginRate(E){const p=Date.now(),l=_loginAttempts.get(E);return!l||p>l.resetAt?!0:l.count<LOGIN_MAX_ATTEMPTS}function recordLoginFailure(E){const p=Date.now(),l=_loginAttempts.get(E);!l||p>l.resetAt?_loginAttempts.set(E,{count:1,resetAt:p+LOGIN_LOCKOUT_MS}):l.count++}function clearLoginFailures(E){_loginAttempts.delete(E)}setInterval((()=>{const E=Date.now();for(const[p,l]of _loginAttempts)E>l.resetAt&&_loginAttempts.delete(p)}),600*1e3),app.get("/login",((E,p)=>{p.sendFile((0,external_path_.join)(server_dirname,"login.html"))})),app.post("/login",express.urlencoded({extended:!1}),((E,p)=>{const l=E.ip;if(!checkLoginRate(l))return p.redirect("/login?error=locked");loadRoles(),loadUsers();const r=E.body?.password,e=E.query.from,s=e&&e.startsWith("/")&&!e.startsWith("//")?e:"/";if(hasUsers()){const h=lookupUser(r);if(!h)return recordLoginFailure(l),p.redirect("/login?error=1");if(isExclusiveMode()&&activeUser&&activeUser.name!==h.name)return p.redirect("/login?error=occupied&user="+encodeURIComponent(activeUser.name));clearLoginFailures(l);const o=(0,external_crypto_.randomBytes)(16).toString("hex");return userSessions.set(o,{role:"operator",name:h.name,dir:h.dir,lastUsed:Date.now()}),isExclusiveMode()&&(activeUser?activeUser.tokens.add(o):activeUser={name:h.name,dir:h.dir,tokens:new Set([o]),loginAt:Date.now()}),setSessionCookie(p,o,E),console.log(`[\u767B\u5F55] ${h.name} \u767B\u5F55\uFF08${isExclusiveMode()?"\u72EC\u5360":"\u5171\u4EAB"}\u6A21\u5F0F\uFF09`),p.redirect(s)}const u=lookupPassword(r);if(u){clearLoginFailures(l);const h=(0,external_crypto_.randomBytes)(16).toString("hex");return userSessions.set(h,{role:u.role,name:u.name,lastUsed:Date.now()}),setSessionCookie(p,h,E),p.redirect(s)}if(r===PASSWORD){clearLoginFailures(l);const h=(0,external_crypto_.randomBytes)(16).toString("hex");return userSessions.set(h,{role:"admin",name:"\u7BA1\u7406\u5458",lastUsed:Date.now()}),setSessionCookie(p,h,E),p.redirect(s)}recordLoginFailure(l),p.redirect("/login?error=1")})),app.post("/logout",((E,p)=>{const l=getSessionToken(E.headers.cookie);l&&(activeUser&&activeUser.tokens.has(l)&&(activeUser.tokens.delete(l),activeUser.tokens.size===0?(console.log(`[\u9000\u51FA] ${activeUser.name} \u5168\u90E8\u8BBE\u5907\u9000\u51FA\uFF0C\u91CA\u653E\u767B\u5F55\u72B6\u6001\uFF08\u4F1A\u8BDD\u4FDD\u7559\uFF09`),activeUser=null):console.log(`[\u9000\u51FA] ${activeUser.name} \u4E00\u4E2A\u8BBE\u5907\u9000\u51FA\uFF08\u5269\u4F59 ${activeUser.tokens.size} \u4E2A\uFF09`)),userSessions.delete(l)),p.setHeader("Set-Cookie",`${SESSION_COOKIE}=; HttpOnly; SameSite=Strict; Path=/; Max-Age=0`),p.redirect("/login")})),app.get("/api/status",((E,p)=>{if(isExclusiveMode()&&activeUser)return p.json({occupied:!0,userName:activeUser.name,releasing:!!_exclusiveReleaseTimer});if(hasUsers()&&!isExclusiveMode()){const l=new Set;for(const[,r]of io.sockets.sockets){if(!r.data.userName||r.data.userName==="\u7BA1\u7406\u5458")continue;const e=r.handshake.headers.cookie;e&&!hasValidSession(e)||l.add(r.data.userName)}return p.json({occupied:!1,onlineUsers:[...l]})}p.json({occupied:!1})})),app.get("/admin",((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"admin.html")))),app.get("/",checkAuth,((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"index.html")))),app.get("/terminal/:id",checkAuth,((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"chat.html")))),app.get("/grid",checkAuth,((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"grid.html")))),app.get("/terminal-raw/:id",checkAuth,((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"terminal.html")))),app.use("/lib",express.static((0,external_path_.join)(server_dirname,"lib"),staticOpts)),app.get("/api/sessions",checkAuth,((E,p)=>{const l=getUserInfo(E.headers.cookie);p.json(manager.list(l?.name,l?.role==="admin"))})),app.get("/api/usage",((E,p)=>{try{const l=manager.listSessions().filter((e=>e.mode==="agent"&&e.alive)).map((e=>({id:e.id,title:e.title,owner:e.owner,usage:e._usage})));let r=null;for(const e of l)if(e.usage?.rateLimitInfo){r=e.usage.rateLimitInfo;break}p.json({rateLimit:r,activeSessions:l})}catch(l){p.status(500).json({error:l.message})}})),app.post("/api/sessions",checkAuth,express.json(),((E,p)=>{const l=getUserInfo(E.headers.cookie),r=manager.create({...E.body,owner:l?.name,userDir:l?.dir});p.status(201).json(r.toJSON())})),app.delete("/api/sessions/:id",checkAuth,((E,p)=>{manager.kill(E.params.id),p.status(204).end()})),app.get("/api/sessions/health",checkAuth,((E,p)=>{const l=getUserInfo(E.headers.cookie),r=manager.listSessions().filter((e=>e.mode==="agent")).filter((e=>!e.owner||!l?.name||e.owner===l.name)).map((e=>({...e.toJSON(),health:getSessionHealth(e.claudeSessionId)})));p.json({ok:!0,sessions:r})})),app.post("/api/sessions/:id/reset",checkAuth,((E,p)=>{const l=manager.get(E.params.id);if(!l||l.mode!=="agent"||typeof l.reset!="function")return p.status(404).json({ok:!1,error:"agent \u4F1A\u8BDD\u4E0D\u5B58\u5728"});l.reset(),l.emit("agent:message",{type:"system",subtype:"info",message:"\u5DF2\u91CD\u5F00\u4E3A\u5E72\u51C0\u4F1A\u8BDD\uFF0C\u4E0B\u6B21\u63D0\u95EE\u5F00\u542F\u5168\u65B0\u5BF9\u8BDD\uFF08\u65E7\u4E0A\u4E0B\u6587\u5DF2\u65AD\u5F00\uFF09"}),broadcastSessions(),p.json({ok:!0})})),app.get("/api/claude-sessions",checkAuth,((E,p)=>{const l=getUserInfo(E.headers.cookie);p.json(listLocalClaudeSessions(l?.dir))})),app.get("/api/agent/history/:sessionId",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l||l.mode!=="agent")return p.status(404).json({ok:!1,error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=l.claudeSessionId;if(!r)return p.json({ok:!0,messages:[],total:0,hasMore:!1});const e=Math.max(0,parseInt(E.query.offset,10)||0),s=Math.min(200,Math.max(1,parseInt(E.query.limit,10)||50)),u=readTranscript(r,{offset:e,limit:s});p.json({ok:!0,messages:u.messages,total:u.total,hasMore:u.hasMore})})),app.get("/api/dirs",checkAuth,((E,p)=>{const l=getUserInfo(E.headers.cookie);if(!l||l.role!=="admin")return p.status(403).json({error:"\u6CA1\u6709\u76EE\u5F55\u6D4F\u89C8\u6743\u9650"});const r=l.dir?(0,external_path_.resolve)((0,external_path_.normalize)(l.dir)):null,e=process.platform==="win32"?"\\":"/";let s=E.query.path||r||process.env.MYHI_CWD||(0,external_os_.homedir)(),u=(0,external_path_.resolve)((0,external_path_.normalize)(s)).replace(/[/\\]+$/,"");process.platform==="win32"&&/^[A-Za-z]:$/.test(u)&&(u+="\\"),r&&!u.startsWith(r)&&(u=r);try{const h=(0,external_fs_.readdirSync)(u,{withFileTypes:!0}).filter((a=>a.isDirectory()&&a.name!==".git")).map((a=>({name:a.name,path:u.replace(/[/\\]+$/,"")+e+a.name}))).sort(((a,t)=>a.name.localeCompare(t.name))),o=(0,external_path_.join)(u,".."),i=!r||(0,external_path_.resolve)((0,external_path_.normalize)(o)).startsWith(r);p.json({current:u,parent:i&&o!==u?o:null,dirs:h,drives:process.platform==="win32"&&!r?"CDEFGHIJKLMNOPQRSTUVWXYZ".split("").map((a=>a+":\\")).filter((a=>{try{return(0,external_fs_.existsSync)(a)}catch{return!1}})):[]})}catch(h){p.status(400).json({error:h.message})}}));function safePath(E,p){const l=(0,external_path_.resolve)((0,external_path_.normalize)(E)),r=(0,external_path_.resolve)((0,external_path_.normalize)((0,external_path_.join)(E,p||"")));if(r!==l&&!r.startsWith(l+external_path_.sep))return null;try{const e=(0,external_fs_.realpathSync)(l),s=(0,external_fs_.existsSync)(r)?(0,external_fs_.realpathSync)(r):r;if(s!==e&&!s.startsWith(e+external_path_.sep))return null}catch{}return r}function walkFiles(E,p,l=[],r=0,e=[],s=!1,u=1/0){if(r>20||l.length>=u)return l;let h;try{h=(0,external_fs_.readdirSync)(E,{withFileTypes:!0})}catch{return l}for(const o of h){if(o.name===".git"||e.includes(o.name))continue;if(l.length>=u)return l;const i=(0,external_path_.join)(E,o.name),a=p?p+"/"+o.name:o.name;try{const t=(0,external_fs_.lstatSync)(i);if(t.isSymbolicLink())continue;t.isDirectory()?(s&&l.push({name:a,dir:!0,mtime:t.mtimeMs}),walkFiles(i,a,l,r+1,e,s,u)):t.isFile()&&l.push({name:a,size:t.size,mtime:t.mtimeMs})}catch{}}return l}function fileHash(E){return new Promise(((p,l)=>{const r=(0,external_crypto_.createHash)("sha256"),e=(0,external_fs_.createReadStream)(E);e.on("data",(s=>r.update(s))),e.on("end",(()=>p(r.digest("hex")))),e.on("error",l)}))}app.get("/api/files/:sessionId",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=E.query.path||"",e=safePath(l.cwd,r);if(!e)return p.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});try{if(!(0,external_fs_.statSync)(e).isDirectory())return p.status(400).json({error:"\u4E0D\u662F\u76EE\u5F55"});const s=(0,external_fs_.readdirSync)(e,{withFileTypes:!0}).filter((o=>o.name!==".git")).map((o=>{const i=(0,external_path_.join)(e,o.name);try{const a=(0,external_fs_.lstatSync)(i);return a.isSymbolicLink()?null:{name:o.name,isDir:a.isDirectory(),size:a.isFile()?a.size:void 0,mtime:a.mtimeMs}}catch{return null}})).filter(Boolean).sort(((o,i)=>i.isDir-o.isDir||o.name.localeCompare(i.name))),u=r?r.replace(/\\/g,"/"):"",h=u.includes("/")?u.slice(0,u.lastIndexOf("/")):u?"":null;p.json({ok:!0,cwd:l.cwd,path:u,parent:h,entries:s})}catch(s){p.status(500).json({error:s.message})}}));const atRootsFile=(0,external_path_.join)(server_configDir,"atreferences.json");function loadAtRoots(){try{const E=JSON.parse((0,external_fs_.readFileSync)(atRootsFile,"utf8")).roots;return Array.isArray(E)?E.filter((p=>typeof p=="string"&&p.trim())):[]}catch{return[]}}app.get("/api/atroots",checkAuth,((E,p)=>p.json({ok:!0,roots:loadAtRoots()}))),app.put("/api/atroots",checkAuth,express.json(),((E,p)=>{const l=(Array.isArray(E.body?.roots)?E.body.roots:[]).filter((r=>typeof r=="string"&&r.trim())).map((r=>r.trim())).slice(0,10);for(const r of l)try{if(!(0,external_fs_.statSync)(r).isDirectory())return p.status(400).json({error:"\u4E0D\u662F\u76EE\u5F55: "+r})}catch{return p.status(400).json({error:"\u76EE\u5F55\u4E0D\u5B58\u5728: "+r})}(0,external_fs_.writeFileSync)(atRootsFile,JSON.stringify({roots:l},null,2)),p.json({ok:!0,roots:l})})),app.get("/api/files/:sessionId/search",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=String(E.query.q||"").trim().toLowerCase();try{let e=walkFiles(l.cwd,"",[],0,["node_modules"],!0).map((s=>({name:s.name,dir:!!s.dir,mtime:s.mtime})));for(const s of loadAtRoots())try{if(!(0,external_fs_.existsSync)(s))continue;const u=s.replace(/[\\/]+$/,"");for(const h of walkFiles(u,"",[],0,["node_modules"],!0,3e3))e.push({name:(u+"/"+h.name).replace(/\\/g,"/"),dir:!!h.dir,mtime:h.mtime,abs:!0})}catch{}r&&(e=e.filter((s=>s.name.toLowerCase().includes(r)))),e.sort(((s,u)=>(u.mtime||0)-(s.mtime||0))),p.json({ok:!0,files:e.slice(0,50).map((s=>({name:s.name,dir:!!s.dir,abs:!!s.abs})))})}catch(e){p.status(500).json({error:e.message})}})),app.get("/api/files/:sessionId/download",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=E.query.path;if(!r)return p.status(400).json({error:"\u7F3A\u5C11 path \u53C2\u6570"});const e=safePath(l.cwd,r);if(!e)return p.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});let s;try{s=(0,external_fs_.statSync)(e)}catch{return p.status(404).json({error:"\u6587\u4EF6\u4E0D\u5B58\u5728"})}if(!s.isFile())return p.status(400).json({error:"\u4E0D\u662F\u6587\u4EF6"});const u=r.split("/").pop();p.setHeader("Content-Disposition",`attachment; filename*=UTF-8''${encodeURIComponent(u)}`),p.sendFile(e,{dotfiles:"allow",acceptRanges:!0},(h=>{if(!h)return;const o=h.code||"";["ECONNABORTED","EPIPE","ECONNRESET"].includes(o)||p.writableEnded||(console.warn("[files] \u4E0B\u8F7D\u5931\u8D25:",r,o||h.message),p.headersSent?p.destroy():p.status(500).json({error:"\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: "+(o||h.message)}))}))})),app.post("/api/files/:sessionId/upload",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=(E.query.path||"").replace(/\\/g,"/"),e=safePath(l.cwd,r);if(!e)return p.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});(0,external_fs_.mkdirSync)(e,{recursive:!0}),multer({storage:multer.diskStorage({destination:(s,u,h)=>{u.originalname=Buffer.from(u.originalname,"latin1").toString("utf8");const o=u.originalname.includes("/")?u.originalname.slice(0,u.originalname.lastIndexOf("/")):"",i=o?(0,external_path_.join)(e,o):e,a=(0,external_path_.resolve)((0,external_path_.normalize)(i)),t=(0,external_path_.resolve)((0,external_path_.normalize)(l.cwd));if(a!==t&&!a.startsWith(t+external_path_.sep))return h(new Error("\u8DEF\u5F84\u8D8A\u754C"));(0,external_fs_.mkdirSync)(i,{recursive:!0}),h(null,i)},filename:(s,u,h)=>{const o=u.originalname.includes("/")?u.originalname.slice(u.originalname.lastIndexOf("/")+1):u.originalname;h(null,o)}}),limits:{fileSize:500*1024*1024}}).array("files",100)(E,p,(s=>{if(s)return p.status(400).json({error:s.message});if(!E.files?.length)return p.status(400).json({error:"\u6CA1\u6709\u6587\u4EF6"});const u=E.files.map((h=>({name:h.originalname,size:h.size,path:(0,external_path_.resolve)(h.path).replace(/\\/g,"/")})));io.emit("files:changed",{sessionId:l.id}),p.json({ok:!0,files:u})}))})),app.delete("/api/files/:sessionId",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=E.query.path;if(!r)return p.status(400).json({error:"\u7F3A\u5C11 path \u53C2\u6570"});const e=safePath(l.cwd,r);if(!e)return p.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});if((0,external_path_.resolve)((0,external_path_.normalize)(e))===(0,external_path_.resolve)((0,external_path_.normalize)(l.cwd)))return p.status(403).json({error:"\u4E0D\u80FD\u5220\u9664\u4F1A\u8BDD\u6839\u76EE\u5F55"});try{(0,external_fs_.statSync)(e).isDirectory()?(0,external_fs_.rmSync)(e,{recursive:!0}):(0,external_fs_.unlinkSync)(e),io.emit("files:changed",{sessionId:l.id}),p.json({ok:!0})}catch(s){p.status(500).json({error:s.message})}})),app.get("/api/files/:sessionId/manifest",checkAuth,(async(E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=E.query.path||"",e=safePath(l.cwd,r);if(!e)return p.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});try{const s=walkFiles(e,""),u=[];for(const h of s){if(h.size>=50*1024*1024){u.push(h);continue}try{const o=await fileHash((0,external_path_.join)(e,h.name));u.push({...h,hash:o})}catch{u.push(h)}}p.json({ok:!0,cwd:l.cwd,path:r,files:u})}catch(s){p.status(500).json({error:s.message})}}));const EDITABLE_EXTS=new Set(["md","markdown","txt","log","json","jsonc","json5","yml","yaml","toml","ini","cfg","conf","env","properties","editorconfig","csv","tsv","xml","svg","html","htm","css","scss","less","js","mjs","cjs","jsx","ts","mts","cts","tsx","vue","svelte","py","pyi","sh","bash","zsh","ps1","psm1","bat","cmd","sql","java","kt","kts","groovy","gradle","c","h","cpp","hpp","cc","cxx","cs","go","rs","rb","php","swift","lua","dart","proto","graphql","cmake","dockerfile","gitignore"]),EDIT_MAX_BYTES=2*1024*1024;function normRelPath(E){return String(E||"").replace(/\\/g,"/").replace(/^\/+/,"")}function editableTarget(E,p){const l=normRelPath(p);if(!l)return{error:"\u7F3A\u5C11 path",code:400};const r=safePath(E.cwd,l);if(!r)return{error:"\u8DEF\u5F84\u8D8A\u754C",code:403};const e=(l.split("/").pop().match(/\.([A-Za-z0-9]+)$/)||[])[1]?.toLowerCase()||"";return EDITABLE_EXTS.has(e)?{rel:l,target:r}:{error:"\u8BE5\u7C7B\u578B\u6587\u4EF6\u4E0D\u652F\u6301\u5728\u7EBF\u7F16\u8F91\uFF0C\u8BF7\u7528\u4E0B\u8F7D",code:415}}function looksBinary(E){const p=Math.min(E.length,8192);for(let l=0;l<p;l++)if(E[l]===0)return!0;return!1}app.get("/api/files/:sessionId/content",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=editableTarget(l,E.query.path);if(r.error)return p.status(r.code).json({error:r.error});let e;try{e=(0,external_fs_.statSync)(r.target)}catch{return p.status(404).json({error:"\u6587\u4EF6\u4E0D\u5B58\u5728"})}if(!e.isFile())return p.status(400).json({error:"\u4E0D\u662F\u6587\u4EF6"});if(e.size>EDIT_MAX_BYTES)return p.status(413).json({error:"\u6587\u4EF6\u8D85\u8FC7 2MB\uFF0C\u4EC5\u652F\u6301\u4E0B\u8F7D"});let s;try{s=(0,external_fs_.readFileSync)(r.target)}catch(u){return p.status(500).json({error:"\u8BFB\u53D6\u5931\u8D25: "+(u.code||u.message)})}if(looksBinary(s))return p.status(415).json({error:"\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u4EC5\u652F\u6301\u4E0B\u8F7D"});p.json({ok:!0,path:r.rel,name:r.rel.split("/").pop(),content:s.toString("utf8"),mtime:e.mtimeMs,size:e.size,md:/\.(md|markdown)$/i.test(r.rel)})})),app.put("/api/files/:sessionId/content",checkAuth,express.json({limit:"4mb"}),((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{content:r,baseMtime:e,force:s}=E.body||{};if(typeof r!="string")return p.status(400).json({error:"\u7F3A\u5C11\u5185\u5BB9"});if(Buffer.byteLength(r,"utf8")>EDIT_MAX_BYTES)return p.status(413).json({error:"\u5185\u5BB9\u8D85\u8FC7 2MB"});const u=editableTarget(l,E.body.path);if(u.error)return p.status(u.code).json({error:u.error});let h;try{h=(0,external_fs_.statSync)(u.target)}catch{return p.status(404).json({error:"\u6587\u4EF6\u5DF2\u88AB\u5220\u9664\uFF0C\u65E0\u6CD5\u4FDD\u5B58"})}if(!h.isFile())return p.status(400).json({error:"\u4E0D\u662F\u6587\u4EF6"});if(!s&&typeof e=="number"&&Math.abs(h.mtimeMs-e)>300)return p.status(409).json({error:"conflict",mtime:h.mtimeMs});const o=u.target+".myhi-edit-"+Date.now();try{try{(0,external_fs_.writeFileSync)(o,r,"utf8"),(0,external_fs_.renameSync)(o,u.target)}catch{try{(0,external_fs_.rmSync)(o,{force:!0})}catch{}(0,external_fs_.writeFileSync)(u.target,r,"utf8")}}catch(a){const t=["EBUSY","EPERM","EACCES"].includes(a.code);return console.warn("[files] \u4FDD\u5B58\u5931\u8D25:",u.rel,a.code||a.message),p.status(500).json({error:t?"\u6587\u4EF6\u88AB\u5176\u5B83\u7A0B\u5E8F\u5360\u7528\uFF08AI \u53EF\u80FD\u6B63\u5728\u5199\u5165\uFF09\uFF0C\u7A0D\u540E\u518D\u8BD5":"\u4FDD\u5B58\u5931\u8D25: "+(a.code||a.message)})}let i=Date.now();try{i=(0,external_fs_.statSync)(u.target).mtimeMs}catch{}io.emit("files:changed",{sessionId:l.id}),p.json({ok:!0,mtime:i})})),app.get("/api/me",checkAuth,((E,p)=>{const l=getUserInfo(E.headers.cookie);p.json({name:l?.name||"\u7528\u6237",role:l?.role||"admin",exclusive:isExclusiveMode(),hasUsers:hasUsers(),dir:l?.dir||null,defaultRoot:l?.dir||process.env.MYHI_CWD||process.cwd(),skMode:(process.env.MYHI_SK_MODE||_configString("skMode")||"expert").toLowerCase()==="normal"?"normal":"expert"})}));const gatewayFile=(0,external_path_.join)(server_configDir,"gateway.json");function loadGateway(){try{return JSON.parse((0,external_fs_.readFileSync)(gatewayFile,"utf8"))}catch{return{baseUrl:"",apiKey:""}}}app.get("/api/gateway",checkAdminAuth,((E,p)=>{const l=loadGateway();p.json({baseUrl:l.baseUrl||"",apiKey:l.apiKey?l.apiKey.length>12?l.apiKey.slice(0,6)+"***"+l.apiKey.slice(-4):"***":"",hasKey:!!l.apiKey})})),app.post("/api/gateway",checkAdminAuth,express.json(),((E,p)=>{const{baseUrl:l,apiKey:r}=E.body||{},e=loadGateway(),s={baseUrl:typeof l=="string"?l.trim():e.baseUrl,apiKey:!r||r.includes("***")?e.apiKey:r.trim()};try{(0,external_fs_.mkdirSync)(server_configDir,{recursive:!0}),(0,external_fs_.writeFileSync)(gatewayFile,JSON.stringify(s,null,2),{mode:384}),p.json({ok:!0})}catch(u){p.status(500).json({error:u.message})}})),app.get("/api/secrets",checkAdminAuth,((E,p)=>{try{p.json(secretsOverview())}catch(l){p.status(500).json({error:l.message})}})),app.post("/api/secrets",checkAdminAuth,express.json(),((E,p)=>{const{name:l,value:r,type:e,scope:s,cwd:u}=E.body||{},h=upsertSecret({name:l,value:r,type:e,scope:s,cwd:u});if(h.error)return p.status(400).json(h);p.json(h)})),app.delete("/api/secrets",checkAdminAuth,express.json(),((E,p)=>{const{name:l,scope:r,cwd:e}=E.body||{};if(!l)return p.status(400).json({error:"\u7F3A\u5C11 name"});try{p.json(deleteSecret({name:l,scope:r,cwd:e}))}catch(s){p.status(500).json({error:s.message})}})),app.get("/api/session/:id/secrets",checkAuth,((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});p.json({cwd:l.cwd,project:listSecrets("project",l.cwd),global:listSecrets("global")})})),app.post("/api/session/:id/secrets",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:r,value:e,type:s}=E.body||{},u=upsertSecret({name:r,value:e,type:s,scope:"project",cwd:l.cwd});if(u.error)return p.status(400).json(u);p.json(u)})),app.delete("/api/session/:id/secrets",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:r}=E.body||{};if(!r)return p.status(400).json({error:"\u7F3A\u5C11 name"});p.json(deleteSecret({name:r,scope:"project",cwd:l.cwd}))})),app.post("/api/session/:id/secrets/bulk",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=upsertManyProject(l.cwd,(E.body||{}).text||"");if(r.error)return p.status(400).json(r);p.json(r)})),app.get("/api/session/:id/guard",checkAuth,((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=getProjectGuard(l.cwd);p.json({cwd:l.cwd,enabled:r.enabled,level:r.level,entities:r.entities})})),app.put("/api/session/:id/guard",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{enabled:r,level:e}=E.body||{},s=setProjectGuard(l.cwd,{enabled:r,level:e});if(s.error)return p.status(400).json(s);p.json(s)})),app.post("/api/session/:id/guard/entity",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:r,type:e}=E.body||{},s=upsertEntity(l.cwd,{name:r,type:e});if(s.error)return p.status(400).json(s);p.json(s)})),app.delete("/api/session/:id/guard/entity",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:r}=E.body||{};if(!r)return p.status(400).json({error:"\u7F3A\u5C11 name"});p.json(deleteEntity(l.cwd,r))})),app.post("/api/session/:id/guard/bulk",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=upsertManyEntities(l.cwd,(E.body||{}).text||"");if(r.error)return p.status(400).json(r);p.json(r)})),app.get("/api/session/:id/guard/audit",checkAuth,((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=l.claudeSessionId||E.params.id;p.json({entries:loadAudit(r)})})),app.get("/api/session/:id/followup",checkAuth,((E,p)=>{const l=manager.get(E.params.id);if(!l||typeof l.followUpState!="function")return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728\u6216\u975E AI \u4F1A\u8BDD"});p.json(l.followUpState())})),app.put("/api/session/:id/followup",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l||typeof l.setFollowUp!="function")return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728\u6216\u975E AI \u4F1A\u8BDD"});const{enabled:r,intervalMinutes:e}=E.body||{};p.json(l.setFollowUp({enabled:r,intervalMinutes:e}))}));function maybeKickRelay(E){try{if(!E?.autoSend)return;const p=manager.get(E.sessionId);p&&typeof p._maybeRelayDraft=="function"&&p.alive&&!p.isBusy&&p._maybeRelayDraft()}catch{}}app.get("/api/inbox",checkAuth,((E,p)=>{const l=getUserInfo(E.headers.cookie),{sessionId:r}=E.query;try{try{rebindDrafts(manager.listSessions())}catch{}const e=new Set(manager.list(l?.name,l?.role==="admin").map((o=>o.id))),s=listDrafts({sessionId:r||void 0}).filter((o=>e.has(o.sessionId)||o.owner&&o.owner===l?.name)),u={};for(const o of s)u[o.sessionId]=(u[o.sessionId]||0)+1;const h=new Set(manager.listSessions().map((o=>o.id)));p.json({drafts:s.map((o=>({...o,sessionAlive:h.has(o.sessionId)}))),counts:u})}catch(e){p.status(500).json({error:e.message})}})),app.post("/api/inbox",checkAuth,express.json({limit:"1mb"}),((E,p)=>{const l=getUserInfo(E.headers.cookie),r=E.body||{},e=r.sessionId?manager.get(r.sessionId):null;try{const s=addDraft({...r,owner:r.owner||l?.name||null},e);maybeKickRelay(s),p.json({ok:!0,draft:s})}catch(s){p.status(400).json({error:s.message})}})),app.put("/api/inbox/:id",checkAuth,express.json({limit:"1mb"}),((E,p)=>{const l=E.body||{},r=l.sessionId?manager.get(l.sessionId):null,e=updateDraft(E.params.id,l,r);if(!e)return p.status(404).json({error:"\u8349\u7A3F\u4E0D\u5B58\u5728"});maybeKickRelay(e),p.json({ok:!0,draft:e})})),app.delete("/api/inbox/:id",checkAuth,((E,p)=>{if(!removeDraft(E.params.id))return p.status(404).json({error:"\u8349\u7A3F\u4E0D\u5B58\u5728"});p.json({ok:!0})}));function _spawnOpen(E,p,l=process.platform==="win32"){return new Promise((r=>{try{const e=(0,external_child_process_namespaceObject.spawn)(E,p,{detached:!0,stdio:"ignore",shell:l});e.on("error",(s=>{console.warn("[open-folder]",E,"\u5931\u8D25:",s.message),r(!1)})),e.unref(),setTimeout((()=>r(!0)),300)}catch(e){console.warn("[open-folder] spawn \u5F02\u5E38:",e.message),r(!1)}}))}app.post("/api/session/:id/open-folder",checkAuth,(async(E,p)=>{const l=manager.get(E.params.id);if(!l?.cwd)return p.status(404).json({error:"\u4F1A\u8BDD\u6216\u76EE\u5F55\u4E0D\u5B58\u5728"});if(!(0,external_fs_.existsSync)(l.cwd))return p.status(400).json({error:"\u76EE\u5F55\u4E0D\u5B58\u5728\uFF08\u53EF\u80FD\u88AB\u79FB\u52A8/\u5220\u9664\uFF09: "+l.cwd});let r=l.cwd;if(process.platform==="win32"){r=r.replace(/\//g,"\\");let s=await _spawnOpen("explorer.exe",[r]);s||(s=await _spawnOpen("cmd.exe",["/c","start","",r]));const u=r.split("\\").filter(Boolean).pop()||"";if(u){const h=`$f='${u.replace(/'/g,"''")}'; 1..12 | ForEach-Object { Start-Sleep -Milliseconds 350; if ((New-Object -ComObject WScript.Shell).AppActivate($f)) { break } }`;_spawnOpen("powershell.exe",["-NoProfile","-ExecutionPolicy","Bypass","-Command",h],!1)}return console.log("[open-folder]",r,s?"\u5DF2\u62C9\u8D77":"\u5931\u8D25"),p.json({ok:s,cwd:r})}const e=process.platform==="darwin"?await _spawnOpen("open",[r]):await _spawnOpen("xdg-open",[r]);p.json({ok:e,cwd:r})}));function getPkgVersion(){for(const E of["../package.json","./package.json","package.json"])try{const p=JSON.parse((0,external_fs_.readFileSync)((0,external_path_.join)(server_dirname,E),"utf8")).version;if(p&&p!=="0.0.0")return p}catch{}return"0.0.0"}const PKG_VERSION=getPkgVersion();let _latestVersion=null,_lastVersionCheck=0;const VERSION_CHECK_INTERVAL=600*1e3;async function checkLatestVersion(){const E=Date.now();if(_latestVersion&&E-_lastVersionCheck<VERSION_CHECK_INTERVAL)return _latestVersion;try{const p=await fetch("https://registry.npmjs.org/@wendongfly/myhi/latest",{headers:{Accept:"application/json"},signal:AbortSignal.timeout(8e3)});p.ok&&(_latestVersion=(await p.json()).version,_lastVersionCheck=E)}catch{}return _latestVersion}app.get("/api/version",(async(E,p)=>{const l=getPkgVersion(),r=await checkLatestVersion();p.json({current:l,latest:r||l,updateAvailable:r&&r!==l})}));function isSystemd(){return process.platform==="linux"&&(process.env.INVOCATION_ID||process.env.JOURNAL_STREAM)}function getNpmUpgradeCmd(){const E="--registry https://registry.npmjs.org";return process.platform==="win32"?`npm.cmd install -g @wendongfly/myhi@latest ${E}`:`npm install -g @wendongfly/myhi@latest ${E}`}function restartService(){if(process.send)process.send({type:"restart"});else if(isSystemd())try{(0,external_child_process_namespaceObject.spawn)("sudo",["systemctl","restart","myhi.service"],{detached:!0,stdio:"ignore"}).unref()}catch{}else process.exit(0)}app.get("/api/server-config",checkAuth,((E,p)=>{const l=process.env.ASR_URL||(()=>{try{return JSON.parse((0,external_fs_.readFileSync)((0,external_path_.join)((0,external_os_.homedir)(),".myhi","asr.json"),"utf8")).url}catch{return""}})();p.json({asrUrl:l||""})})),app.post("/api/server-config",checkAuth,express.json(),((E,p)=>{const{asrUrl:l}=E.body||{},r=(0,external_path_.join)((0,external_os_.homedir)(),".myhi","asr.json");try{const e=(l||"").trim();(0,external_fs_.writeFileSync)(r,JSON.stringify({url:e},null,2),"utf8"),p.json({ok:!0})}catch(e){p.status(500).json({error:e.message})}}));const shortHostname=()=>((0,external_os_.hostname)()||"").split(".")[0];function machineName(){return(process.env.MYHI_NAME||_configString("name")||shortHostname()||"myhi").trim()}app.get("/api/machine-name",checkAuth,((E,p)=>{p.json({name:machineName(),hostname:shortHostname(),fromEnv:!!process.env.MYHI_NAME})})),app.post("/api/machine-name",checkAuth,express.json(),((E,p)=>{const l=getUserInfo(E.headers.cookie);if(l&&l.role!=="admin")return p.status(403).json({error:"\u4EC5\u7BA1\u7406\u5458\u53EF\u4FEE\u6539\u673A\u5668\u540D"});const r=String(E.body?.name??"").trim().slice(0,32),e=(0,external_path_.join)(server_configDir,"config.json");try{let s={};try{s=JSON.parse((0,external_fs_.readFileSync)(e,"utf8"))}catch{}r?s.name=r:delete s.name,(0,external_fs_.writeFileSync)(e,JSON.stringify(s,null,2),"utf8"),p.json({ok:!0,name:machineName()})}catch(s){p.status(500).json({error:s.message})}})),app.post("/api/restart",checkAuth,((E,p)=>{p.json({ok:!0}),setTimeout((()=>restartService()),300)})),app.post("/api/update",checkAuth,(async(E,p)=>{try{await execAsync(getNpmUpgradeCmd(),{encoding:"utf8",timeout:12e4}),console.log("[myhi] \u5347\u7EA7\u5B8C\u6210"),p.json({ok:!0,message:"\u5347\u7EA7\u5B8C\u6210\uFF0C\u670D\u52A1\u5C06\u81EA\u52A8\u91CD\u542F..."}),setTimeout((()=>restartService()),500)}catch(l){const r=(l.stderr||l.stdout||l.message||"").split(`
|
|
391
|
+
`)[0]}catch{}try{if(process.platform==="win32"){const E=(0,external_child_process_namespaceObject.execSync)("route print 0.0.0.0",{timeout:3e3,stdio:"pipe"}).toString().match(/0\.0\.0\.0\s+0\.0\.0\.0\s+\S+\s+(\d+\.\d+\.\d+\.\d+)/);if(E)return E[1]}else try{const E=(0,external_child_process_namespaceObject.execSync)("ip route get 1.1.1.1",{timeout:3e3,stdio:"pipe"}).toString().match(/src\s+(\d+\.\d+\.\d+\.\d+)/);if(E)return E[1]}catch{const E=(0,external_child_process_namespaceObject.execSync)("route -n get default 2>/dev/null || route -n 2>/dev/null",{timeout:3e3,stdio:"pipe"}).toString(),p=E.match(/interface:\s*(\S+)/i)||E.match(/0\.0\.0\.0\s+(\d+\.\d+\.\d+\.\d+)/);if(p){const l=(0,external_os_.networkInterfaces)()[p[1]];if(l){const r=l.find((e=>e.family==="IPv4"&&!e.internal));if(r)return r.address}if(/^\d+\.\d+\.\d+\.\d+$/.test(p[1]))return p[1]}}}catch{}for(const E of Object.values((0,external_os_.networkInterfaces)()))for(const p of E)if(p.family==="IPv4"&&!p.internal)return p.address;return"localhost"}function parseCookies(E=""){const p={};for(const l of E.split(";")){const r=l.indexOf("=");r>0&&(p[l.slice(0,r).trim()]=l.slice(r+1).trim())}return p}const SESSION_COOKIE="myhi_sid",COOKIE_OPTS_BASE="HttpOnly; SameSite=Strict; Path=/; Max-Age=31536000";function cookieOpts(E){return E?.secure||E?.headers?.["x-forwarded-proto"]==="https"?COOKIE_OPTS_BASE+"; Secure":COOKIE_OPTS_BASE}function setSessionCookie(E,p,l){E.setHeader("Set-Cookie",`${SESSION_COOKIE}=${p||TOKEN}; ${cookieOpts(l)}`)}function getSessionToken(E){return parseCookies(E)[SESSION_COOKIE]||null}function hasValidSession(E){const p=getSessionToken(E);if(p&&userSessions.has(p)){const l=userSessions.get(p);return l&&(l.lastUsed=Date.now()),!0}return!1}function getUserInfo(E){const p=getSessionToken(E);return p?userSessions.get(p):null}const app=express();app.set("trust proxy",!0),app.use(((E,p,l)=>{p.setHeader("Referrer-Policy","no-referrer"),p.setHeader("X-Content-Type-Options","nosniff"),l()}));function _readConfig(){try{return JSON.parse((0,external_fs_.readFileSync)((0,external_path_.join)(server_configDir,"config.json"),"utf8").replace(/^\uFEFF/,""))||{}}catch{return{}}}function _configString(E){const p=_readConfig()[E];return typeof p=="string"&&p?p:null}const HOST=process.env.HOST||_configString("host")||"0.0.0.0",_tlsOpts=process.env.MYHI_NO_HTTPS||_readConfig().httpOnly?null:getOrCreateCert();_tlsOpts?(httpsServer=(0,external_https_.createServer)(_tlsOpts,app),httpServer=(0,external_http_.createServer)(((E,p)=>{const l=(E.headers.host||"").replace(/:\d+$/,"");p.writeHead(301,{Location:`https://${l}:${PORT}${E.url}`}),p.end()}))):(console.warn("[myhi] TLS \u4E0D\u53EF\u7528\uFF0C\u4EE5 HTTP \u6A21\u5F0F\u8FD0\u884C\uFF08\u9EA6\u514B\u98CE/\u6444\u50CF\u5934\u7B49\u6D4F\u89C8\u5668\u5B89\u5168\u529F\u80FD\u53D7\u9650\uFF09"),httpServer=(0,external_http_.createServer)(app));for(const E of[httpsServer,httpServer])E&&(E.keepAliveTimeout=72e3,E.headersTimeout=76e3);const _corsAllowed=/^https?:\/\/(localhost|127\.0\.0\.1|\[::1\]|10\.\d+\.\d+\.\d+|172\.(1[6-9]|2\d|3[01])\.\d+\.\d+|192\.168\.\d+\.\d+|100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\.\d+\.\d+)(:\d+)?$/,io=new Server({serveClient:!1,cors:{origin:(E,p)=>{if(!E||_corsAllowed.test(E))return p(null,!0);p(new Error("CORS \u4E0D\u5141\u8BB8\u6B64\u6765\u6E90"),!1)},credentials:!0},transports:["websocket","polling"],pingTimeout:6e4,pingInterval:25e3,upgradeTimeout:3e4,maxHttpBufferSize:5e6});httpsServer?io.attach(httpsServer):io.attach(httpServer);const manager=new SessionManager,AUTO_ATTACH=process.env.MYHI_AUTO_ATTACH!=="0",_autoSpawned=new Set;function spawnLocalTerminal(E,p){if(!AUTO_ATTACH||_autoSpawned.has(E)||!process.env.DISPLAY&&process.platform==="linux")return;_autoSpawned.add(E);const l=__nccwpck_require__.ab+"attach.js",r=process.execPath,e=p||"myhi";if(process.platform==="win32"){const s=`"${r}" "${l}" ${E}`,u=(0,external_child_process_namespaceObject.spawn)("wt.exe",["-w","0","new-tab","--title",e,"--","cmd","/k",s],{detached:!0,stdio:"ignore"});u.unref(),u.on("error",(h=>{console.warn("[attach] wt.exe \u5931\u8D25\uFF0C\u56DE\u9000\u5230 cmd:",h.message),(0,external_child_process_namespaceObject.spawn)("cmd.exe",["/c","start",`"${e}"`,"cmd","/k",s],{detached:!0,stdio:"ignore"}).unref()}))}else if(process.platform==="darwin"){const s=`tell application "Terminal" to do script "${r} ${l} ${E}"`;(0,external_child_process_namespaceObject.spawn)("osascript",["-e",s],{detached:!0,stdio:"ignore"}).unref()}else{const s=`${r} "${l}" ${E}`;for(const[u,h]of[["gnome-terminal",["--","bash","-c",`${s}; exec bash`]],["xterm",["-title",e,"-e",s]],["konsole",["--new-tab","-e",s]]]){const o=(0,external_child_process_namespaceObject.spawn)(u,h,{detached:!0,stdio:"ignore"});o.unref(),o.on("error",(()=>{}));break}}}const uploadDir=(0,external_path_.join)(server_configDir,"uploads");(0,external_fs_.mkdirSync)(uploadDir,{recursive:!0});function checkAuth(E,p,l){const r=E.query.token;if(r&&(r===TOKEN||userSessions.has(r))){const e=userSessions.get(r);if(e?.onetime){userSessions.delete(r);const h=(0,external_crypto_.randomBytes)(16).toString("hex");userSessions.set(h,{role:e.role,name:e.name,lastUsed:Date.now()}),setSessionCookie(p,h,E)}else setSessionCookie(p,r===TOKEN?TOKEN:r,E);const s=Object.keys(E.query).filter((h=>h!=="token")),u=E.path+(s.length?"?"+new URLSearchParams(Object.fromEntries(Object.entries(E.query).filter((([h])=>h!=="token")))):"");return p.redirect(u)}if(hasValidSession(E.headers.cookie)){if(isExclusiveMode()&&activeUser){const e=getSessionToken(E.headers.cookie);if(e!==TOKEN){const s=userSessions.get(e);if(!s||s.name!==activeUser.name)return p.setHeader("Set-Cookie",`${SESSION_COOKIE}=; HttpOnly; SameSite=Strict; Path=/; Max-Age=0`),p.redirect("/login")}}return l()}p.redirect("/login")}const _require=(0,external_module_namespaceObject.createRequire)(import.meta.url);function pkgDirSafe(E){try{return(0,external_path_.dirname)(_require.resolve(`${E}/package.json`))}catch{return null}}const libDir=(0,external_path_.join)(server_dirname,"lib"),staticOpts={maxAge:864e5};app.use("/lib/xterm",express.static(pkgDirSafe("xterm")||(0,external_path_.join)(libDir,"xterm"),staticOpts)),app.use("/lib/xterm-fit",express.static(pkgDirSafe("xterm-addon-fit")||(0,external_path_.join)(libDir,"xterm-fit"),staticOpts)),app.use("/lib/xterm-links",express.static(pkgDirSafe("xterm-addon-web-links")||(0,external_path_.join)(libDir,"xterm-links"),staticOpts)),app.use("/sio-client",express.static((0,external_path_.join)(server_dirname,"client-dist"),{maxAge:"1h",index:!1,setHeaders:(E,p)=>{p.endsWith(".js")&&E.setHeader("Content-Type","application/javascript; charset=utf-8")}})),app.get("/manifest.json",((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"manifest.json")))),app.get("/icon.png",((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"icon.png")))),app.get("/icon.svg",((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"icon.svg"))));const _loginAttempts=new Map,LOGIN_MAX_ATTEMPTS=5,LOGIN_LOCKOUT_MS=300*1e3;function checkLoginRate(E){const p=Date.now(),l=_loginAttempts.get(E);return!l||p>l.resetAt?!0:l.count<LOGIN_MAX_ATTEMPTS}function recordLoginFailure(E){const p=Date.now(),l=_loginAttempts.get(E);!l||p>l.resetAt?_loginAttempts.set(E,{count:1,resetAt:p+LOGIN_LOCKOUT_MS}):l.count++}function clearLoginFailures(E){_loginAttempts.delete(E)}setInterval((()=>{const E=Date.now();for(const[p,l]of _loginAttempts)E>l.resetAt&&_loginAttempts.delete(p)}),600*1e3),app.get("/login",((E,p)=>{p.sendFile((0,external_path_.join)(server_dirname,"login.html"))})),app.post("/login",express.urlencoded({extended:!1}),((E,p)=>{const l=E.ip;if(!checkLoginRate(l))return p.redirect("/login?error=locked");loadRoles(),loadUsers();const r=E.body?.password,e=E.query.from,s=e&&e.startsWith("/")&&!e.startsWith("//")?e:"/";if(hasUsers()){const h=lookupUser(r);if(!h)return recordLoginFailure(l),p.redirect("/login?error=1");if(isExclusiveMode()&&activeUser&&activeUser.name!==h.name)return p.redirect("/login?error=occupied&user="+encodeURIComponent(activeUser.name));clearLoginFailures(l);const o=(0,external_crypto_.randomBytes)(16).toString("hex");return userSessions.set(o,{role:"operator",name:h.name,dir:h.dir,lastUsed:Date.now()}),isExclusiveMode()&&(activeUser?activeUser.tokens.add(o):activeUser={name:h.name,dir:h.dir,tokens:new Set([o]),loginAt:Date.now()}),setSessionCookie(p,o,E),console.log(`[\u767B\u5F55] ${h.name} \u767B\u5F55\uFF08${isExclusiveMode()?"\u72EC\u5360":"\u5171\u4EAB"}\u6A21\u5F0F\uFF09`),p.redirect(s)}const u=lookupPassword(r);if(u){clearLoginFailures(l);const h=(0,external_crypto_.randomBytes)(16).toString("hex");return userSessions.set(h,{role:u.role,name:u.name,lastUsed:Date.now()}),setSessionCookie(p,h,E),p.redirect(s)}if(r===PASSWORD){clearLoginFailures(l);const h=(0,external_crypto_.randomBytes)(16).toString("hex");return userSessions.set(h,{role:"admin",name:"\u7BA1\u7406\u5458",lastUsed:Date.now()}),setSessionCookie(p,h,E),p.redirect(s)}recordLoginFailure(l),p.redirect("/login?error=1")})),app.post("/logout",((E,p)=>{const l=getSessionToken(E.headers.cookie);l&&(activeUser&&activeUser.tokens.has(l)&&(activeUser.tokens.delete(l),activeUser.tokens.size===0?(console.log(`[\u9000\u51FA] ${activeUser.name} \u5168\u90E8\u8BBE\u5907\u9000\u51FA\uFF0C\u91CA\u653E\u767B\u5F55\u72B6\u6001\uFF08\u4F1A\u8BDD\u4FDD\u7559\uFF09`),activeUser=null):console.log(`[\u9000\u51FA] ${activeUser.name} \u4E00\u4E2A\u8BBE\u5907\u9000\u51FA\uFF08\u5269\u4F59 ${activeUser.tokens.size} \u4E2A\uFF09`)),userSessions.delete(l)),p.setHeader("Set-Cookie",`${SESSION_COOKIE}=; HttpOnly; SameSite=Strict; Path=/; Max-Age=0`),p.redirect("/login")})),app.get("/api/status",((E,p)=>{if(isExclusiveMode()&&activeUser)return p.json({occupied:!0,userName:activeUser.name,releasing:!!_exclusiveReleaseTimer});if(hasUsers()&&!isExclusiveMode()){const l=new Set;for(const[,r]of io.sockets.sockets){if(!r.data.userName||r.data.userName==="\u7BA1\u7406\u5458")continue;const e=r.handshake.headers.cookie;e&&!hasValidSession(e)||l.add(r.data.userName)}return p.json({occupied:!1,onlineUsers:[...l]})}p.json({occupied:!1})})),app.get("/admin",((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"admin.html")))),app.get("/",checkAuth,((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"index.html")))),app.get("/terminal/:id",checkAuth,((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"chat.html")))),app.get("/grid",checkAuth,((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"grid.html")))),app.get("/terminal-raw/:id",checkAuth,((E,p)=>p.sendFile((0,external_path_.join)(server_dirname,"terminal.html")))),app.use("/lib",express.static((0,external_path_.join)(server_dirname,"lib"),staticOpts)),app.get("/api/sessions",checkAuth,((E,p)=>{const l=getUserInfo(E.headers.cookie);p.json(manager.list(l?.name,l?.role==="admin"))})),app.get("/api/usage",((E,p)=>{try{const l=manager.listSessions().filter((e=>e.mode==="agent"&&e.alive)).map((e=>({id:e.id,title:e.title,owner:e.owner,usage:e._usage})));let r=null;for(const e of l)if(e.usage?.rateLimitInfo){r=e.usage.rateLimitInfo;break}p.json({rateLimit:r,activeSessions:l})}catch(l){p.status(500).json({error:l.message})}})),app.post("/api/sessions",checkAuth,express.json(),((E,p)=>{const l=getUserInfo(E.headers.cookie),r=manager.create({...E.body,owner:l?.name,userDir:l?.dir});p.status(201).json(r.toJSON())})),app.delete("/api/sessions/:id",checkAuth,((E,p)=>{manager.kill(E.params.id),p.status(204).end()})),app.get("/api/sessions/health",checkAuth,((E,p)=>{const l=getUserInfo(E.headers.cookie),r=manager.listSessions().filter((e=>e.mode==="agent")).filter((e=>!e.owner||!l?.name||e.owner===l.name)).map((e=>({...e.toJSON(),health:getSessionHealth(e.claudeSessionId)})));p.json({ok:!0,sessions:r})})),app.post("/api/sessions/:id/reset",checkAuth,((E,p)=>{const l=manager.get(E.params.id);if(!l||l.mode!=="agent"||typeof l.reset!="function")return p.status(404).json({ok:!1,error:"agent \u4F1A\u8BDD\u4E0D\u5B58\u5728"});l.reset(),l.emit("agent:message",{type:"system",subtype:"info",message:"\u5DF2\u91CD\u5F00\u4E3A\u5E72\u51C0\u4F1A\u8BDD\uFF0C\u4E0B\u6B21\u63D0\u95EE\u5F00\u542F\u5168\u65B0\u5BF9\u8BDD\uFF08\u65E7\u4E0A\u4E0B\u6587\u5DF2\u65AD\u5F00\uFF09"}),broadcastSessions(),p.json({ok:!0})})),app.get("/api/claude-sessions",checkAuth,((E,p)=>{const l=getUserInfo(E.headers.cookie);p.json(listLocalClaudeSessions(l?.dir))})),app.get("/api/agent/history/:sessionId",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l||l.mode!=="agent")return p.status(404).json({ok:!1,error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=l.claudeSessionId;if(!r)return p.json({ok:!0,messages:[],total:0,hasMore:!1});const e=Math.max(0,parseInt(E.query.offset,10)||0),s=Math.min(200,Math.max(1,parseInt(E.query.limit,10)||50)),u=readTranscript(r,{offset:e,limit:s});p.json({ok:!0,messages:u.messages,total:u.total,hasMore:u.hasMore})})),app.get("/api/dirs",checkAuth,((E,p)=>{const l=getUserInfo(E.headers.cookie);if(!l||l.role!=="admin")return p.status(403).json({error:"\u6CA1\u6709\u76EE\u5F55\u6D4F\u89C8\u6743\u9650"});const r=l.dir?(0,external_path_.resolve)((0,external_path_.normalize)(l.dir)):null,e=process.platform==="win32"?"\\":"/";let s=E.query.path||r||process.env.MYHI_CWD||(0,external_os_.homedir)(),u=(0,external_path_.resolve)((0,external_path_.normalize)(s)).replace(/[/\\]+$/,"");process.platform==="win32"&&/^[A-Za-z]:$/.test(u)&&(u+="\\"),r&&!u.startsWith(r)&&(u=r);try{const h=(0,external_fs_.readdirSync)(u,{withFileTypes:!0}).filter((a=>a.isDirectory()&&a.name!==".git")).map((a=>({name:a.name,path:u.replace(/[/\\]+$/,"")+e+a.name}))).sort(((a,t)=>a.name.localeCompare(t.name))),o=(0,external_path_.join)(u,".."),i=!r||(0,external_path_.resolve)((0,external_path_.normalize)(o)).startsWith(r);p.json({current:u,parent:i&&o!==u?o:null,dirs:h,drives:process.platform==="win32"&&!r?"CDEFGHIJKLMNOPQRSTUVWXYZ".split("").map((a=>a+":\\")).filter((a=>{try{return(0,external_fs_.existsSync)(a)}catch{return!1}})):[]})}catch(h){p.status(400).json({error:h.message})}}));function safePath(E,p){const l=(0,external_path_.resolve)((0,external_path_.normalize)(E)),r=(0,external_path_.resolve)((0,external_path_.normalize)((0,external_path_.join)(E,p||"")));if(r!==l&&!r.startsWith(l+external_path_.sep))return null;try{const e=(0,external_fs_.realpathSync)(l),s=(0,external_fs_.existsSync)(r)?(0,external_fs_.realpathSync)(r):r;if(s!==e&&!s.startsWith(e+external_path_.sep))return null}catch{}return r}function walkFiles(E,p,l=[],r=0,e=[],s=!1,u=1/0){if(r>20||l.length>=u)return l;let h;try{h=(0,external_fs_.readdirSync)(E,{withFileTypes:!0})}catch{return l}for(const o of h){if(o.name===".git"||e.includes(o.name))continue;if(l.length>=u)return l;const i=(0,external_path_.join)(E,o.name),a=p?p+"/"+o.name:o.name;try{const t=(0,external_fs_.lstatSync)(i);if(t.isSymbolicLink())continue;t.isDirectory()?(s&&l.push({name:a,dir:!0,mtime:t.mtimeMs}),walkFiles(i,a,l,r+1,e,s,u)):t.isFile()&&l.push({name:a,size:t.size,mtime:t.mtimeMs})}catch{}}return l}function fileHash(E){return new Promise(((p,l)=>{const r=(0,external_crypto_.createHash)("sha256"),e=(0,external_fs_.createReadStream)(E);e.on("data",(s=>r.update(s))),e.on("end",(()=>p(r.digest("hex")))),e.on("error",l)}))}app.get("/api/files/:sessionId",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=E.query.path||"",e=safePath(l.cwd,r);if(!e)return p.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});try{if(!(0,external_fs_.statSync)(e).isDirectory())return p.status(400).json({error:"\u4E0D\u662F\u76EE\u5F55"});const s=(0,external_fs_.readdirSync)(e,{withFileTypes:!0}).filter((o=>o.name!==".git")).map((o=>{const i=(0,external_path_.join)(e,o.name);try{const a=(0,external_fs_.lstatSync)(i);return a.isSymbolicLink()?null:{name:o.name,isDir:a.isDirectory(),size:a.isFile()?a.size:void 0,mtime:a.mtimeMs}}catch{return null}})).filter(Boolean).sort(((o,i)=>i.isDir-o.isDir||o.name.localeCompare(i.name))),u=r?r.replace(/\\/g,"/"):"",h=u.includes("/")?u.slice(0,u.lastIndexOf("/")):u?"":null;p.json({ok:!0,cwd:l.cwd,path:u,parent:h,entries:s})}catch(s){p.status(500).json({error:s.message})}}));const atRootsFile=(0,external_path_.join)(server_configDir,"atreferences.json");function loadAtRoots(){try{const E=JSON.parse((0,external_fs_.readFileSync)(atRootsFile,"utf8")).roots;return Array.isArray(E)?E.filter((p=>typeof p=="string"&&p.trim())):[]}catch{return[]}}app.get("/api/atroots",checkAuth,((E,p)=>p.json({ok:!0,roots:loadAtRoots()}))),app.put("/api/atroots",checkAuth,express.json(),((E,p)=>{const l=(Array.isArray(E.body?.roots)?E.body.roots:[]).filter((r=>typeof r=="string"&&r.trim())).map((r=>r.trim())).slice(0,10);for(const r of l)try{if(!(0,external_fs_.statSync)(r).isDirectory())return p.status(400).json({error:"\u4E0D\u662F\u76EE\u5F55: "+r})}catch{return p.status(400).json({error:"\u76EE\u5F55\u4E0D\u5B58\u5728: "+r})}(0,external_fs_.writeFileSync)(atRootsFile,JSON.stringify({roots:l},null,2)),p.json({ok:!0,roots:l})})),app.get("/api/files/:sessionId/search",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=String(E.query.q||"").trim().toLowerCase();try{let e=walkFiles(l.cwd,"",[],0,["node_modules"],!0).map((a=>({name:a.name,dir:!!a.dir,mtime:a.mtime})));for(const a of loadAtRoots())try{if(!(0,external_fs_.existsSync)(a))continue;const t=a.replace(/[\\/]+$/,"");for(const n of walkFiles(t,"",[],0,["node_modules"],!0,3e3))e.push({name:(t+"/"+n.name).replace(/\\/g,"/"),dir:!!n.dir,mtime:n.mtime,abs:!0})}catch{}r&&(e=e.filter((a=>a.name.toLowerCase().includes(r))));const s=a=>{if(!r)return 0;const t=a.name.slice(a.name.lastIndexOf("/")+1).toLowerCase();return t.startsWith(r)?0:t.includes(r)?1:2},u=(a,t)=>s(a)-s(t)||(t.mtime||0)-(a.mtime||0),h=e.filter((a=>!a.abs)).sort(u),o=e.filter((a=>a.abs)).sort(u),i=Math.min(o.length,Math.max(15,50-h.length));e=[...h.slice(0,50-i),...o.slice(0,i)],p.json({ok:!0,files:e.map((a=>({name:a.name,dir:!!a.dir,abs:!!a.abs})))})}catch(e){p.status(500).json({error:e.message})}})),app.get("/api/files/:sessionId/at-browse",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=loadAtRoots(),e=E.query.root===void 0||E.query.root==="",s=e?-1:parseInt(E.query.root,10),u=String(E.query.path||"").replace(/\\/g,"/").replace(/^\/+|\/+$/g,"");if(!e&&(isNaN(s)||s<-1||s>=r.length))return p.status(400).json({error:"\u76EE\u5F55\u4E0D\u5B58\u5728"});const h=s===-1?l.cwd:r[s].replace(/[\\/]+$/,""),o=safePath(s===-1?l.cwd:r[s],u);if(!o)return p.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});const i=a=>s===-1?a:(h+(a?"/"+a:"")).replace(/\\/g,"/");try{const a=(0,external_fs_.readdirSync)(o,{withFileTypes:!0}).filter((t=>t.name!==".git")).map((t=>{try{const n=(0,external_fs_.lstatSync)((0,external_path_.join)(o,t.name));if(n.isSymbolicLink()||!(n.isDirectory()||n.isFile()))return null;const f=u?u+"/"+t.name:t.name;return{name:i(f),label:t.name,rel:f,dir:n.isDirectory(),abs:s!==-1}}catch{return null}})).filter(Boolean).sort(((t,n)=>n.dir-t.dir||t.label.localeCompare(n.label,"zh"))).slice(0,300);p.json({ok:!0,root:e?null:s,path:u,self:i(u),entries:a,roots:e?r.map(((t,n)=>({i:n,name:t.replace(/\\/g,"/").replace(/\/+$/,""),label:t.replace(/[\\/]+$/,"").split(/[\\/]/).pop()||t}))):[]})}catch(a){p.status(500).json({error:a.message})}})),app.get("/api/files/:sessionId/download",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=E.query.path;if(!r)return p.status(400).json({error:"\u7F3A\u5C11 path \u53C2\u6570"});const e=safePath(l.cwd,r);if(!e)return p.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});let s;try{s=(0,external_fs_.statSync)(e)}catch{return p.status(404).json({error:"\u6587\u4EF6\u4E0D\u5B58\u5728"})}if(!s.isFile())return p.status(400).json({error:"\u4E0D\u662F\u6587\u4EF6"});const u=r.split("/").pop();p.setHeader("Content-Disposition",`attachment; filename*=UTF-8''${encodeURIComponent(u)}`),p.sendFile(e,{dotfiles:"allow",acceptRanges:!0},(h=>{if(!h)return;const o=h.code||"";["ECONNABORTED","EPIPE","ECONNRESET"].includes(o)||p.writableEnded||(console.warn("[files] \u4E0B\u8F7D\u5931\u8D25:",r,o||h.message),p.headersSent?p.destroy():p.status(500).json({error:"\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: "+(o||h.message)}))}))})),app.post("/api/files/:sessionId/upload",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=(E.query.path||"").replace(/\\/g,"/"),e=safePath(l.cwd,r);if(!e)return p.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});(0,external_fs_.mkdirSync)(e,{recursive:!0}),multer({storage:multer.diskStorage({destination:(s,u,h)=>{u.originalname=Buffer.from(u.originalname,"latin1").toString("utf8");const o=u.originalname.includes("/")?u.originalname.slice(0,u.originalname.lastIndexOf("/")):"",i=o?(0,external_path_.join)(e,o):e,a=(0,external_path_.resolve)((0,external_path_.normalize)(i)),t=(0,external_path_.resolve)((0,external_path_.normalize)(l.cwd));if(a!==t&&!a.startsWith(t+external_path_.sep))return h(new Error("\u8DEF\u5F84\u8D8A\u754C"));(0,external_fs_.mkdirSync)(i,{recursive:!0}),h(null,i)},filename:(s,u,h)=>{const o=u.originalname.includes("/")?u.originalname.slice(u.originalname.lastIndexOf("/")+1):u.originalname;h(null,o)}}),limits:{fileSize:500*1024*1024}}).array("files",100)(E,p,(s=>{if(s)return p.status(400).json({error:s.message});if(!E.files?.length)return p.status(400).json({error:"\u6CA1\u6709\u6587\u4EF6"});const u=E.files.map((h=>({name:h.originalname,size:h.size,path:(0,external_path_.resolve)(h.path).replace(/\\/g,"/")})));io.emit("files:changed",{sessionId:l.id}),p.json({ok:!0,files:u})}))})),app.delete("/api/files/:sessionId",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=E.query.path;if(!r)return p.status(400).json({error:"\u7F3A\u5C11 path \u53C2\u6570"});const e=safePath(l.cwd,r);if(!e)return p.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});if((0,external_path_.resolve)((0,external_path_.normalize)(e))===(0,external_path_.resolve)((0,external_path_.normalize)(l.cwd)))return p.status(403).json({error:"\u4E0D\u80FD\u5220\u9664\u4F1A\u8BDD\u6839\u76EE\u5F55"});try{(0,external_fs_.statSync)(e).isDirectory()?(0,external_fs_.rmSync)(e,{recursive:!0}):(0,external_fs_.unlinkSync)(e),io.emit("files:changed",{sessionId:l.id}),p.json({ok:!0})}catch(s){p.status(500).json({error:s.message})}})),app.get("/api/files/:sessionId/manifest",checkAuth,(async(E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=E.query.path||"",e=safePath(l.cwd,r);if(!e)return p.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});try{const s=walkFiles(e,""),u=[];for(const h of s){if(h.size>=50*1024*1024){u.push(h);continue}try{const o=await fileHash((0,external_path_.join)(e,h.name));u.push({...h,hash:o})}catch{u.push(h)}}p.json({ok:!0,cwd:l.cwd,path:r,files:u})}catch(s){p.status(500).json({error:s.message})}}));const EDITABLE_EXTS=new Set(["md","markdown","txt","log","json","jsonc","json5","yml","yaml","toml","ini","cfg","conf","env","properties","editorconfig","csv","tsv","xml","svg","html","htm","css","scss","less","js","mjs","cjs","jsx","ts","mts","cts","tsx","vue","svelte","py","pyi","sh","bash","zsh","ps1","psm1","bat","cmd","sql","java","kt","kts","groovy","gradle","c","h","cpp","hpp","cc","cxx","cs","go","rs","rb","php","swift","lua","dart","proto","graphql","cmake","dockerfile","gitignore"]),EDIT_MAX_BYTES=2*1024*1024;function normRelPath(E){return String(E||"").replace(/\\/g,"/").replace(/^\/+/,"")}function editableTarget(E,p){const l=normRelPath(p);if(!l)return{error:"\u7F3A\u5C11 path",code:400};const r=safePath(E.cwd,l);if(!r)return{error:"\u8DEF\u5F84\u8D8A\u754C",code:403};const e=(l.split("/").pop().match(/\.([A-Za-z0-9]+)$/)||[])[1]?.toLowerCase()||"";return EDITABLE_EXTS.has(e)?{rel:l,target:r}:{error:"\u8BE5\u7C7B\u578B\u6587\u4EF6\u4E0D\u652F\u6301\u5728\u7EBF\u7F16\u8F91\uFF0C\u8BF7\u7528\u4E0B\u8F7D",code:415}}function looksBinary(E){const p=Math.min(E.length,8192);for(let l=0;l<p;l++)if(E[l]===0)return!0;return!1}app.get("/api/files/:sessionId/content",checkAuth,((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=editableTarget(l,E.query.path);if(r.error)return p.status(r.code).json({error:r.error});let e;try{e=(0,external_fs_.statSync)(r.target)}catch{return p.status(404).json({error:"\u6587\u4EF6\u4E0D\u5B58\u5728"})}if(!e.isFile())return p.status(400).json({error:"\u4E0D\u662F\u6587\u4EF6"});if(e.size>EDIT_MAX_BYTES)return p.status(413).json({error:"\u6587\u4EF6\u8D85\u8FC7 2MB\uFF0C\u4EC5\u652F\u6301\u4E0B\u8F7D"});let s;try{s=(0,external_fs_.readFileSync)(r.target)}catch(u){return p.status(500).json({error:"\u8BFB\u53D6\u5931\u8D25: "+(u.code||u.message)})}if(looksBinary(s))return p.status(415).json({error:"\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u4EC5\u652F\u6301\u4E0B\u8F7D"});p.json({ok:!0,path:r.rel,name:r.rel.split("/").pop(),content:s.toString("utf8"),mtime:e.mtimeMs,size:e.size,md:/\.(md|markdown)$/i.test(r.rel)})})),app.put("/api/files/:sessionId/content",checkAuth,express.json({limit:"4mb"}),((E,p)=>{const l=manager.get(E.params.sessionId);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{content:r,baseMtime:e,force:s}=E.body||{};if(typeof r!="string")return p.status(400).json({error:"\u7F3A\u5C11\u5185\u5BB9"});if(Buffer.byteLength(r,"utf8")>EDIT_MAX_BYTES)return p.status(413).json({error:"\u5185\u5BB9\u8D85\u8FC7 2MB"});const u=editableTarget(l,E.body.path);if(u.error)return p.status(u.code).json({error:u.error});let h;try{h=(0,external_fs_.statSync)(u.target)}catch{return p.status(404).json({error:"\u6587\u4EF6\u5DF2\u88AB\u5220\u9664\uFF0C\u65E0\u6CD5\u4FDD\u5B58"})}if(!h.isFile())return p.status(400).json({error:"\u4E0D\u662F\u6587\u4EF6"});if(!s&&typeof e=="number"&&Math.abs(h.mtimeMs-e)>300)return p.status(409).json({error:"conflict",mtime:h.mtimeMs});const o=u.target+".myhi-edit-"+Date.now();try{try{(0,external_fs_.writeFileSync)(o,r,"utf8"),(0,external_fs_.renameSync)(o,u.target)}catch{try{(0,external_fs_.rmSync)(o,{force:!0})}catch{}(0,external_fs_.writeFileSync)(u.target,r,"utf8")}}catch(a){const t=["EBUSY","EPERM","EACCES"].includes(a.code);return console.warn("[files] \u4FDD\u5B58\u5931\u8D25:",u.rel,a.code||a.message),p.status(500).json({error:t?"\u6587\u4EF6\u88AB\u5176\u5B83\u7A0B\u5E8F\u5360\u7528\uFF08AI \u53EF\u80FD\u6B63\u5728\u5199\u5165\uFF09\uFF0C\u7A0D\u540E\u518D\u8BD5":"\u4FDD\u5B58\u5931\u8D25: "+(a.code||a.message)})}let i=Date.now();try{i=(0,external_fs_.statSync)(u.target).mtimeMs}catch{}io.emit("files:changed",{sessionId:l.id}),p.json({ok:!0,mtime:i})})),app.get("/api/me",checkAuth,((E,p)=>{const l=getUserInfo(E.headers.cookie);p.json({name:l?.name||"\u7528\u6237",role:l?.role||"admin",exclusive:isExclusiveMode(),hasUsers:hasUsers(),dir:l?.dir||null,defaultRoot:l?.dir||process.env.MYHI_CWD||process.cwd(),desktop:hasDesktop(),skMode:(process.env.MYHI_SK_MODE||_configString("skMode")||"expert").toLowerCase()==="normal"?"normal":"expert"})}));const gatewayFile=(0,external_path_.join)(server_configDir,"gateway.json");function loadGateway(){try{return JSON.parse((0,external_fs_.readFileSync)(gatewayFile,"utf8").replace(/^\uFEFF/,""))}catch{return{baseUrl:"",apiKey:""}}}app.get("/api/gateway",checkAdminAuth,((E,p)=>{const l=loadGateway();p.json({baseUrl:l.baseUrl||"",apiKey:l.apiKey?l.apiKey.length>12?l.apiKey.slice(0,6)+"***"+l.apiKey.slice(-4):"***":"",hasKey:!!l.apiKey})})),app.post("/api/gateway",checkAdminAuth,express.json(),((E,p)=>{const{baseUrl:l,apiKey:r}=E.body||{},e=loadGateway(),s={baseUrl:typeof l=="string"?l.trim():e.baseUrl,apiKey:!r||r.includes("***")?e.apiKey:r.trim()};try{(0,external_fs_.mkdirSync)(server_configDir,{recursive:!0}),(0,external_fs_.writeFileSync)(gatewayFile,JSON.stringify(s,null,2),{mode:384}),p.json({ok:!0})}catch(u){p.status(500).json({error:u.message})}})),app.get("/api/secrets",checkAdminAuth,((E,p)=>{try{p.json(secretsOverview())}catch(l){p.status(500).json({error:l.message})}})),app.post("/api/secrets",checkAdminAuth,express.json(),((E,p)=>{const{name:l,value:r,type:e,scope:s,cwd:u}=E.body||{},h=upsertSecret({name:l,value:r,type:e,scope:s,cwd:u});if(h.error)return p.status(400).json(h);p.json(h)})),app.delete("/api/secrets",checkAdminAuth,express.json(),((E,p)=>{const{name:l,scope:r,cwd:e}=E.body||{};if(!l)return p.status(400).json({error:"\u7F3A\u5C11 name"});try{p.json(deleteSecret({name:l,scope:r,cwd:e}))}catch(s){p.status(500).json({error:s.message})}})),app.get("/api/session/:id/secrets",checkAuth,((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});p.json({cwd:l.cwd,project:listSecrets("project",l.cwd),global:listSecrets("global")})})),app.post("/api/session/:id/secrets",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:r,value:e,type:s}=E.body||{},u=upsertSecret({name:r,value:e,type:s,scope:"project",cwd:l.cwd});if(u.error)return p.status(400).json(u);p.json(u)})),app.delete("/api/session/:id/secrets",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:r}=E.body||{};if(!r)return p.status(400).json({error:"\u7F3A\u5C11 name"});p.json(deleteSecret({name:r,scope:"project",cwd:l.cwd}))})),app.post("/api/session/:id/secrets/bulk",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=upsertManyProject(l.cwd,(E.body||{}).text||"");if(r.error)return p.status(400).json(r);p.json(r)})),app.get("/api/session/:id/guard",checkAuth,((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=getProjectGuard(l.cwd);p.json({cwd:l.cwd,enabled:r.enabled,level:r.level,entities:r.entities})})),app.put("/api/session/:id/guard",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{enabled:r,level:e}=E.body||{},s=setProjectGuard(l.cwd,{enabled:r,level:e});if(s.error)return p.status(400).json(s);p.json(s)})),app.post("/api/session/:id/guard/entity",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:r,type:e}=E.body||{},s=upsertEntity(l.cwd,{name:r,type:e});if(s.error)return p.status(400).json(s);p.json(s)})),app.delete("/api/session/:id/guard/entity",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:r}=E.body||{};if(!r)return p.status(400).json({error:"\u7F3A\u5C11 name"});p.json(deleteEntity(l.cwd,r))})),app.post("/api/session/:id/guard/bulk",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=upsertManyEntities(l.cwd,(E.body||{}).text||"");if(r.error)return p.status(400).json(r);p.json(r)})),app.get("/api/session/:id/guard/audit",checkAuth,((E,p)=>{const l=manager.get(E.params.id);if(!l)return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const r=l.claudeSessionId||E.params.id;p.json({entries:loadAudit(r)})})),app.get("/api/session/:id/followup",checkAuth,((E,p)=>{const l=manager.get(E.params.id);if(!l||typeof l.followUpState!="function")return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728\u6216\u975E AI \u4F1A\u8BDD"});p.json(l.followUpState())})),app.put("/api/session/:id/followup",checkAuth,express.json(),((E,p)=>{const l=manager.get(E.params.id);if(!l||typeof l.setFollowUp!="function")return p.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728\u6216\u975E AI \u4F1A\u8BDD"});const{enabled:r,intervalMinutes:e}=E.body||{};p.json(l.setFollowUp({enabled:r,intervalMinutes:e}))}));function maybeKickRelay(E){try{if(!E?.autoSend)return;const p=manager.get(E.sessionId);p&&typeof p._maybeRelayDraft=="function"&&p.alive&&!p.isBusy&&p._maybeRelayDraft()}catch{}}app.get("/api/inbox",checkAuth,((E,p)=>{const l=getUserInfo(E.headers.cookie),{sessionId:r}=E.query;try{try{rebindDrafts(manager.listSessions())}catch{}const e=new Set(manager.list(l?.name,l?.role==="admin").map((o=>o.id))),s=listDrafts({sessionId:r||void 0}).filter((o=>e.has(o.sessionId)||o.owner&&o.owner===l?.name)),u={};for(const o of s)u[o.sessionId]=(u[o.sessionId]||0)+1;const h=new Set(manager.listSessions().map((o=>o.id)));p.json({drafts:s.map((o=>({...o,sessionAlive:h.has(o.sessionId)}))),counts:u})}catch(e){p.status(500).json({error:e.message})}})),app.post("/api/inbox",checkAuth,express.json({limit:"1mb"}),((E,p)=>{const l=getUserInfo(E.headers.cookie),r=E.body||{},e=r.sessionId?manager.get(r.sessionId):null;try{const s=addDraft({...r,owner:r.owner||l?.name||null},e);maybeKickRelay(s),p.json({ok:!0,draft:s})}catch(s){p.status(400).json({error:s.message})}})),app.put("/api/inbox/:id",checkAuth,express.json({limit:"1mb"}),((E,p)=>{const l=E.body||{},r=l.sessionId?manager.get(l.sessionId):null,e=updateDraft(E.params.id,l,r);if(!e)return p.status(404).json({error:"\u8349\u7A3F\u4E0D\u5B58\u5728"});maybeKickRelay(e),p.json({ok:!0,draft:e})})),app.delete("/api/inbox/:id",checkAuth,((E,p)=>{if(!removeDraft(E.params.id))return p.status(404).json({error:"\u8349\u7A3F\u4E0D\u5B58\u5728"});p.json({ok:!0})}));function _spawnOpen(E,p,l=process.platform==="win32"){return new Promise((r=>{try{const e=(0,external_child_process_namespaceObject.spawn)(E,p,{detached:!0,stdio:"ignore",shell:l});e.on("error",(s=>{console.warn("[open-folder]",E,"\u5931\u8D25:",s.message),r(!1)})),e.unref(),setTimeout((()=>r(!0)),300)}catch(e){console.warn("[open-folder] spawn \u5F02\u5E38:",e.message),r(!1)}}))}let _desktopFailed=!1;function hasDesktop(){return _desktopFailed?!1:process.platform==="linux"?!!(process.env.DISPLAY||process.env.WAYLAND_DISPLAY):!0}let _winSessionId;function winSessionId(){return _winSessionId!==void 0?Promise.resolve(_winSessionId):new Promise((E=>{(0,external_child_process_namespaceObject.execFile)("tasklist",["/FI",`PID eq ${process.pid}`,"/FO","CSV","/NH"],{windowsHide:!0,timeout:5e3},((p,l)=>{const r=!p&&String(l).match(/^"[^"]*","\d+","[^"]*","(\d+)"/m);_winSessionId=r?Number(r[1]):null,E(_winSessionId)}))}))}function _schtasks(E){return new Promise((p=>(0,external_child_process_namespaceObject.execFile)("schtasks",E,{windowsHide:!0,timeout:1e4},((l,r,e)=>{l&&console.warn("[open-folder] schtasks",E[0],"\u5931\u8D25:",String(e||l.message).trim()),p(!l)}))))}async function openFolderViaTask(E){const p="myhi-open-folder",l=await _schtasks(["/Create","/TN",p,"/TR",`explorer.exe "${E.endsWith("\\")?E+".":E}"`,"/SC","ONCE","/ST","00:00","/IT","/F"]),r=l&&await _schtasks(["/Run","/TN",p]);return l&&setTimeout((()=>_schtasks(["/Delete","/TN",p,"/F"])),5e3),r}app.post("/api/session/:id/open-folder",checkAuth,(async(E,p)=>{const l=manager.get(E.params.id);if(!l?.cwd)return p.status(404).json({error:"\u4F1A\u8BDD\u6216\u76EE\u5F55\u4E0D\u5B58\u5728"});if(!(0,external_fs_.existsSync)(l.cwd))return p.status(400).json({error:"\u76EE\u5F55\u4E0D\u5B58\u5728\uFF08\u53EF\u80FD\u88AB\u79FB\u52A8/\u5220\u9664\uFF09: "+l.cwd});let r=l.cwd;if(process.platform==="win32"){if(r=r.replace(/\//g,"\\").replace(/(?<!^[A-Za-z]:)\\+$/,""),await winSessionId()===0){const h=await openFolderViaTask(r);return h||(_desktopFailed=!0),console.log("[open-folder]",r,h?"\u5DF2\u901A\u8FC7\u8BA1\u5212\u4EFB\u52A1\u5728\u684C\u9762\u6253\u5F00\uFF08myhi \u8FD0\u884C\u5728 Session 0\uFF09":"\u5931\u8D25\uFF08Session 0 \u4E14\u8BA1\u5212\u4EFB\u52A1\u4E0D\u53EF\u7528\uFF09"),p.json(h?{ok:h,cwd:r,via:"task"}:{ok:!1,cwd:r,error:"myhi \u8FD0\u884C\u5728\u6CA1\u6709\u684C\u9762\u7684\u540E\u53F0\u4F1A\u8BDD\u91CC\uFF08\u591A\u534A\u662F\u901A\u8FC7 SSH \u8FDC\u7A0B\u542F\u52A8/\u91CD\u542F\u7684\uFF09\uFF0C\u5F00\u4E0D\u51FA\u7A97\u53E3\u3002\u8BF7\u5728\u8FD9\u53F0\u7535\u8111\u684C\u9762\u4E0A\u6253\u5F00\u547D\u4EE4\u884C\u6267\u884C myhi restart"})}let s=await _spawnOpen("explorer.exe",[r],!1);s||(s=await _spawnOpen("cmd.exe",["/c","start","",r]));const u=r.split("\\").filter(Boolean).pop()||"";if(u){const h=`$f='${u.replace(/'/g,"''")}'; 1..12 | ForEach-Object { Start-Sleep -Milliseconds 350; if ((New-Object -ComObject WScript.Shell).AppActivate($f)) { break } }`;_spawnOpen("powershell.exe",["-NoProfile","-ExecutionPolicy","Bypass","-Command",h],!1)}return console.log("[open-folder]",r,s?"\u5DF2\u62C9\u8D77":"\u5931\u8D25"),p.json({ok:s,cwd:r})}if(!hasDesktop())return p.json({ok:!1,cwd:r,error:"\u8FD9\u53F0\u670D\u52A1\u5668\u6CA1\u6709\u684C\u9762\u73AF\u5883\uFF08\u540E\u53F0\u670D\u52A1\u6A21\u5F0F\uFF09\uFF0C\u5F39\u4E0D\u51FA\u6587\u4EF6\u5939\u7A97\u53E3\uFF0C\u8BF7\u7528\u6587\u4EF6\u9762\u677F\u6D4F\u89C8/\u4E0B\u8F7D"});const e=process.platform==="darwin"?await _spawnOpen("open",[r]):await _spawnOpen("xdg-open",[r]);p.json({ok:e,cwd:r})}));function getPkgVersion(){for(const E of["../package.json","./package.json","package.json"])try{const p=JSON.parse((0,external_fs_.readFileSync)((0,external_path_.join)(server_dirname,E),"utf8")).version;if(p&&p!=="0.0.0")return p}catch{}return"0.0.0"}const PKG_VERSION=getPkgVersion();let _latestVersion=null,_lastVersionCheck=0;const VERSION_CHECK_INTERVAL=600*1e3;async function checkLatestVersion(){const E=Date.now();if(_latestVersion&&E-_lastVersionCheck<VERSION_CHECK_INTERVAL)return _latestVersion;try{const p=await fetch("https://registry.npmjs.org/@wendongfly/myhi/latest",{headers:{Accept:"application/json"},signal:AbortSignal.timeout(8e3)});p.ok&&(_latestVersion=(await p.json()).version,_lastVersionCheck=E)}catch{}return _latestVersion}app.get("/api/version",(async(E,p)=>{const l=getPkgVersion(),r=await checkLatestVersion();p.json({current:l,latest:r||l,updateAvailable:r&&r!==l})}));function isSystemd(){return process.platform==="linux"&&(process.env.INVOCATION_ID||process.env.JOURNAL_STREAM)}function getNpmUpgradeCmd(){const E="--registry https://registry.npmjs.org";return process.platform==="win32"?`npm.cmd install -g @wendongfly/myhi@latest ${E}`:`npm install -g @wendongfly/myhi@latest ${E}`}function restartService(){if(process.send)process.send({type:"restart"});else if(isSystemd())try{(0,external_child_process_namespaceObject.spawn)("sudo",["systemctl","restart","myhi.service"],{detached:!0,stdio:"ignore"}).unref()}catch{}else process.exit(0)}app.get("/api/server-config",checkAuth,((E,p)=>{const l=process.env.ASR_URL||(()=>{try{return JSON.parse((0,external_fs_.readFileSync)((0,external_path_.join)((0,external_os_.homedir)(),".myhi","asr.json"),"utf8")).url}catch{return""}})();p.json({asrUrl:l||""})})),app.post("/api/server-config",checkAuth,express.json(),((E,p)=>{const{asrUrl:l}=E.body||{},r=(0,external_path_.join)((0,external_os_.homedir)(),".myhi","asr.json");try{const e=(l||"").trim();(0,external_fs_.writeFileSync)(r,JSON.stringify({url:e},null,2),"utf8"),p.json({ok:!0})}catch(e){p.status(500).json({error:e.message})}}));const shortHostname=()=>((0,external_os_.hostname)()||"").split(".")[0];function machineName(){return(process.env.MYHI_NAME||_configString("name")||shortHostname()||"myhi").trim()}app.get("/api/machine-name",checkAuth,((E,p)=>{p.json({name:machineName(),hostname:shortHostname(),fromEnv:!!process.env.MYHI_NAME})})),app.post("/api/machine-name",checkAuth,express.json(),((E,p)=>{const l=getUserInfo(E.headers.cookie);if(l&&l.role!=="admin")return p.status(403).json({error:"\u4EC5\u7BA1\u7406\u5458\u53EF\u4FEE\u6539\u673A\u5668\u540D"});const r=String(E.body?.name??"").trim().slice(0,32),e=(0,external_path_.join)(server_configDir,"config.json");try{const s=_readConfig();r?s.name=r:delete s.name,(0,external_fs_.writeFileSync)(e,JSON.stringify(s,null,2),"utf8"),p.json({ok:!0,name:machineName()})}catch(s){p.status(500).json({error:s.message})}})),app.post("/api/restart",checkAuth,((E,p)=>{p.json({ok:!0}),setTimeout((()=>restartService()),300)})),app.post("/api/update",checkAuth,(async(E,p)=>{try{await execAsync(getNpmUpgradeCmd(),{encoding:"utf8",timeout:12e4}),console.log("[myhi] \u5347\u7EA7\u5B8C\u6210"),p.json({ok:!0,message:"\u5347\u7EA7\u5B8C\u6210\uFF0C\u670D\u52A1\u5C06\u81EA\u52A8\u91CD\u542F..."}),setTimeout((()=>restartService()),500)}catch(l){const r=(l.stderr||l.stdout||l.message||"").split(`
|
|
392
392
|
`).filter((e=>e.trim())).slice(-5).join(`
|
|
393
393
|
`);console.error("[myhi] \u5347\u7EA7\u5931\u8D25:",r),p.status(500).json({ok:!1,error:`npm install \u5931\u8D25\uFF1A
|
|
394
394
|
`+r+`
|
package/package.json
CHANGED